Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • kernel/generic/src/mm/as.c

    rc4c2406 r57355a40  
    285285/** Check area conflicts with other areas.
    286286 *
    287  * @param as    Address space.
    288  * @param addr  Starting virtual address of the area being tested.
    289  * @param count Number of pages in the area being tested.
    290  * @param avoid Do not touch this area.
     287 * @param as      Address space.
     288 * @param addr    Starting virtual address of the area being tested.
     289 * @param count   Number of pages in the area being tested.
     290 * @param guarded True if the area being tested is protected by guard pages.
     291 * @param avoid   Do not touch this area.
    291292 *
    292293 * @return True if there is no conflict, false otherwise.
     
    294295 */
    295296NO_TRACE static bool check_area_conflicts(as_t *as, uintptr_t addr,
    296     size_t count, as_area_t *avoid)
     297    size_t count, bool guarded, as_area_t *avoid)
    297298{
    298299        ASSERT((addr % PAGE_SIZE) == 0);
    299300        ASSERT(mutex_locked(&as->lock));
     301
     302        /*
     303         * If the addition of the supposed area address and size overflows,
     304         * report conflict.
     305         */
     306        if (overflows_into_positive(addr, P2SZ(count)))
     307                return false;
    300308       
    301309        /*
     
    304312        if (overlaps(addr, P2SZ(count), (uintptr_t) NULL, PAGE_SIZE))
    305313                return false;
    306        
     314
    307315        /*
    308316         * The leaf node is found in O(log n), where n is proportional to
     
    328336                if (area != avoid) {
    329337                        mutex_lock(&area->lock);
    330                        
     338
     339                        /*
     340                         * If at least one of the two areas are protected
     341                         * by the AS_AREA_GUARD flag then we must be sure
     342                         * that they are separated by at least one unmapped
     343                         * page.
     344                         */
     345                        int const gp = (guarded ||
     346                            (area->flags & AS_AREA_GUARD)) ? 1 : 0;
     347                       
     348                        /*
     349                         * The area comes from the left neighbour node, which
     350                         * means that there already are some areas in the leaf
     351                         * node, which in turn means that adding gp is safe and
     352                         * will not cause an integer overflow.
     353                         */
    331354                        if (overlaps(addr, P2SZ(count), area->base,
     355                            P2SZ(area->pages + gp))) {
     356                                mutex_unlock(&area->lock);
     357                                return false;
     358                        }
     359                       
     360                        mutex_unlock(&area->lock);
     361                }
     362        }
     363       
     364        node = btree_leaf_node_right_neighbour(&as->as_area_btree, leaf);
     365        if (node) {
     366                area = (as_area_t *) node->value[0];
     367               
     368                if (area != avoid) {
     369                        int gp;
     370
     371                        mutex_lock(&area->lock);
     372
     373                        gp = (guarded || (area->flags & AS_AREA_GUARD)) ? 1 : 0;
     374                        if (gp && overflows(addr, P2SZ(count))) {
     375                                /*
     376                                 * Guard page not needed if the supposed area
     377                                 * is adjacent to the end of the address space.
     378                                 * We already know that the following test is
     379                                 * going to fail...
     380                                 */
     381                                gp--;
     382                        }
     383                       
     384                        if (overlaps(addr, P2SZ(count + gp), area->base,
    332385                            P2SZ(area->pages))) {
    333386                                mutex_unlock(&area->lock);
     
    339392        }
    340393       
    341         node = btree_leaf_node_right_neighbour(&as->as_area_btree, leaf);
    342         if (node) {
    343                 area = (as_area_t *) node->value[0];
    344                
    345                 if (area != avoid) {
    346                         mutex_lock(&area->lock);
    347                        
    348                         if (overlaps(addr, P2SZ(count), area->base,
    349                             P2SZ(area->pages))) {
    350                                 mutex_unlock(&area->lock);
    351                                 return false;
    352                         }
    353                        
    354                         mutex_unlock(&area->lock);
    355                 }
    356         }
    357        
    358394        /* Second, check the leaf node. */
    359395        btree_key_t i;
    360396        for (i = 0; i < leaf->keys; i++) {
    361397                area = (as_area_t *) leaf->value[i];
     398                int agp;
     399                int gp;
    362400               
    363401                if (area == avoid)
     
    365403               
    366404                mutex_lock(&area->lock);
    367                
    368                 if (overlaps(addr, P2SZ(count), area->base,
    369                     P2SZ(area->pages))) {
     405
     406                gp = (guarded || (area->flags & AS_AREA_GUARD)) ? 1 : 0;
     407                agp = gp;
     408
     409                /*
     410                 * Sanitize the two possible unsigned integer overflows.
     411                 */
     412                if (gp && overflows(addr, P2SZ(count)))
     413                        gp--;
     414                if (agp && overflows(area->base, P2SZ(area->pages)))
     415                        agp--;
     416
     417                if (overlaps(addr, P2SZ(count + gp), area->base,
     418                    P2SZ(area->pages + agp))) {
    370419                        mutex_unlock(&area->lock);
    371420                        return false;
     
    377426        /*
    378427         * So far, the area does not conflict with other areas.
    379          * Check if it doesn't conflict with kernel address space.
     428         * Check if it is contained in the user address space.
    380429         */
    381430        if (!KERNEL_ADDRESS_SPACE_SHADOWED) {
    382                 return !overlaps(addr, P2SZ(count), KERNEL_ADDRESS_SPACE_START,
    383                     KERNEL_ADDRESS_SPACE_END - KERNEL_ADDRESS_SPACE_START);
     431                return iswithin(USER_ADDRESS_SPACE_START,
     432                    (USER_ADDRESS_SPACE_END - USER_ADDRESS_SPACE_START) + 1,
     433                    addr, P2SZ(count));
    384434        }
    385435       
     
    392442 * this function.
    393443 *
    394  * @param as    Address space.
    395  * @param bound Lowest address bound.
    396  * @param size  Requested size of the allocation.
     444 * @param as      Address space.
     445 * @param bound   Lowest address bound.
     446 * @param size    Requested size of the allocation.
     447 * @param guarded True if the allocation must be protected by guard pages.
    397448 *
    398449 * @return Address of the beginning of unmapped address space area.
     
    401452 */
    402453NO_TRACE static uintptr_t as_get_unmapped_area(as_t *as, uintptr_t bound,
    403     size_t size)
     454    size_t size, bool guarded)
    404455{
    405456        ASSERT(mutex_locked(&as->lock));
     
    423474        /* First check the bound address itself */
    424475        uintptr_t addr = ALIGN_UP(bound, PAGE_SIZE);
    425         if ((addr >= bound) &&
    426             (check_area_conflicts(as, addr, pages, NULL)))
    427                 return addr;
     476        if (addr >= bound) {
     477                if (guarded) {
     478                        /* Leave an unmapped page between the lower
     479                         * bound and the area's start address.
     480                         */
     481                        addr += P2SZ(1);
     482                }
     483
     484                if (check_area_conflicts(as, addr, pages, guarded, NULL))
     485                        return addr;
     486        }
    428487       
    429488        /* Eventually check the addresses behind each area */
     
    439498                        addr =
    440499                            ALIGN_UP(area->base + P2SZ(area->pages), PAGE_SIZE);
     500
     501                        if (guarded || area->flags & AS_AREA_GUARD) {
     502                                /* We must leave an unmapped page
     503                                 * between the two areas.
     504                                 */
     505                                addr += P2SZ(1);
     506                        }
     507
    441508                        bool avail =
    442509                            ((addr >= bound) && (addr >= area->base) &&
    443                             (check_area_conflicts(as, addr, pages, area)));
     510                            (check_area_conflicts(as, addr, pages, guarded, area)));
    444511                       
    445512                        mutex_unlock(&area->lock);
     
    481548        if (size == 0)
    482549                return NULL;
    483        
     550
    484551        size_t pages = SIZE2FRAMES(size);
    485552       
     
    487554        if ((flags & AS_AREA_EXEC) && (flags & AS_AREA_WRITE))
    488555                return NULL;
     556
     557        bool const guarded = flags & AS_AREA_GUARD;
    489558       
    490559        mutex_lock(&as->lock);
    491560       
    492561        if (*base == (uintptr_t) -1) {
    493                 *base = as_get_unmapped_area(as, bound, size);
     562                *base = as_get_unmapped_area(as, bound, size, guarded);
    494563                if (*base == (uintptr_t) -1) {
    495564                        mutex_unlock(&as->lock);
     
    497566                }
    498567        }
    499        
    500         if (!check_area_conflicts(as, *base, pages, NULL)) {
     568
     569        if (overflows_into_positive(*base, size))
     570                return NULL;
     571
     572        if (!check_area_conflicts(as, *base, pages, guarded, NULL)) {
    501573                mutex_unlock(&as->lock);
    502574                return NULL;
     
    625697                return ENOENT;
    626698        }
    627        
    628         if (area->backend == &phys_backend) {
    629                 /*
    630                  * Remapping of address space areas associated
    631                  * with memory mapped devices is not supported.
     699
     700        if (!area->backend->is_resizable(area)) {
     701                /*
     702                 * The backend does not support resizing for this area.
    632703                 */
    633704                mutex_unlock(&area->lock);
     
    776847                /*
    777848                 * Growing the area.
     849                 */
     850
     851                if (overflows_into_positive(address, P2SZ(pages)))
     852                        return EINVAL;
     853
     854                /*
    778855                 * Check for overlaps with other address space areas.
    779856                 */
    780                 if (!check_area_conflicts(as, address, pages, area)) {
     857                bool const guarded = area->flags & AS_AREA_GUARD;
     858                if (!check_area_conflicts(as, address, pages, guarded, area)) {
    781859                        mutex_unlock(&area->lock);
    782860                        mutex_unlock(&as->lock);
     
    9791057        }
    9801058       
    981         if ((!src_area->backend) || (!src_area->backend->share)) {
    982                 /*
    983                  * There is no backend or the backend does not
    984                  * know how to share the area.
     1059        if (!src_area->backend->is_shareable(src_area)) {
     1060                /*
     1061                 * The backend does not permit sharing of this area.
    9851062                 */
    9861063                mutex_unlock(&src_area->lock);
     
    20542131{
    20552132        uintptr_t virt = base;
    2056         as_area_t *area = as_area_create(AS, flags, size,
     2133        as_area_t *area = as_area_create(AS, flags | AS_AREA_CACHEABLE, size,
    20572134            AS_AREA_ATTR_NONE, &anon_backend, NULL, &virt, bound);
    20582135        if (area == NULL)
Note: See TracChangeset for help on using the changeset viewer.