Changeset 35a3d950 in mainline


Ignore:
Timestamp:
2012-11-01T18:11:04Z (12 years ago)
Author:
Maurizio Lombardi <m.lombardi85@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
082b7f1
Parents:
a582dff
Message:

mm: implement support to guarded address space areas

Guarded address space areas will have at least one unmapped page at both its ends. This should
prevent overflows from being undetected.

Files:
2 edited

Legend:

Unmodified
Added
Removed
  • abi/include/mm/as.h

    ra582dff r35a3d950  
    3737
    3838/** Address space area flags. */
    39 #define AS_AREA_READ       1
    40 #define AS_AREA_WRITE      2
    41 #define AS_AREA_EXEC       4
    42 #define AS_AREA_CACHEABLE  8
     39#define AS_AREA_READ       0x01
     40#define AS_AREA_WRITE      0x02
     41#define AS_AREA_EXEC       0x04
     42#define AS_AREA_CACHEABLE  0x08
     43#define AS_AREA_GUARD      0x10
    4344
    4445/** Address space area info exported to uspace. */
  • kernel/generic/src/mm/as.c

    ra582dff r35a3d950  
    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);
     
    304305        if (overlaps(addr, P2SZ(count), (uintptr_t) NULL, PAGE_SIZE))
    305306                return false;
    306        
     307
    307308        /*
    308309         * The leaf node is found in O(log n), where n is proportional to
     
    328329                if (area != avoid) {
    329330                        mutex_lock(&area->lock);
     331
     332                        /* If at least one of the two areas are protected
     333                         * by the AS_AREA_GUARD flag then we must be sure
     334                         * that they are separated by at least one unmapped
     335                         * page.
     336                         */
     337                        int const gp = (guarded ||
     338                            (area->flags & AS_AREA_GUARD)) ? 1 : 0;
    330339                       
    331340                        if (overlaps(addr, P2SZ(count), area->base,
     341                            P2SZ(area->pages + gp))) {
     342                                mutex_unlock(&area->lock);
     343                                return false;
     344                        }
     345                       
     346                        mutex_unlock(&area->lock);
     347                }
     348        }
     349       
     350        node = btree_leaf_node_right_neighbour(&as->as_area_btree, leaf);
     351        if (node) {
     352                area = (as_area_t *) node->value[0];
     353               
     354                if (area != avoid) {
     355                        mutex_lock(&area->lock);
     356
     357                        int const gp = (guarded ||
     358                            (area->flags & AS_AREA_GUARD)) ? 1 : 0;
     359                       
     360                        if (overlaps(addr, P2SZ(count + gp), area->base,
    332361                            P2SZ(area->pages))) {
    333362                                mutex_unlock(&area->lock);
     
    339368        }
    340369       
    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        
    358370        /* Second, check the leaf node. */
    359371        btree_key_t i;
     
    365377               
    366378                mutex_lock(&area->lock);
    367                
    368                 if (overlaps(addr, P2SZ(count), area->base,
    369                     P2SZ(area->pages))) {
     379
     380                int const gp = (guarded ||
     381                    (area->flags & AS_AREA_GUARD)) ? 1 : 0;
     382
     383                if (overlaps(addr, P2SZ(count + gp), area->base,
     384                    P2SZ(area->pages + gp))) {
    370385                        mutex_unlock(&area->lock);
    371386                        return false;
     
    392407 * this function.
    393408 *
    394  * @param as    Address space.
    395  * @param bound Lowest address bound.
    396  * @param size  Requested size of the allocation.
     409 * @param as      Address space.
     410 * @param bound   Lowest address bound.
     411 * @param size    Requested size of the allocation.
     412 * @param guarded True if the allocation must be protected by guard pages.
    397413 *
    398414 * @return Address of the beginning of unmapped address space area.
     
    401417 */
    402418NO_TRACE static uintptr_t as_get_unmapped_area(as_t *as, uintptr_t bound,
    403     size_t size)
     419    size_t size, bool guarded)
    404420{
    405421        ASSERT(mutex_locked(&as->lock));
     
    423439        /* First check the bound address itself */
    424440        uintptr_t addr = ALIGN_UP(bound, PAGE_SIZE);
    425         if ((addr >= bound) &&
    426             (check_area_conflicts(as, addr, pages, NULL)))
    427                 return addr;
     441        if (addr >= bound) {
     442                if (guarded) {
     443                        /* Leave an unmapped page between the lower
     444                         * bound and the area's start address.
     445                         */
     446                        addr += P2SZ(1);
     447                }
     448
     449                if (check_area_conflicts(as, addr, pages, guarded, NULL))
     450                        return addr;
     451        }
    428452       
    429453        /* Eventually check the addresses behind each area */
     
    439463                        addr =
    440464                            ALIGN_UP(area->base + P2SZ(area->pages), PAGE_SIZE);
     465
     466                        if (guarded || area->flags & AS_AREA_GUARD) {
     467                                /* We must leave an unmapped page
     468                                 * between the two areas.
     469                                 */
     470                                addr += P2SZ(1);
     471                        }
     472
    441473                        bool avail =
    442474                            ((addr >= bound) && (addr >= area->base) &&
    443                             (check_area_conflicts(as, addr, pages, area)));
     475                            (check_area_conflicts(as, addr, pages, guarded, area)));
    444476                       
    445477                        mutex_unlock(&area->lock);
     
    487519        if ((flags & AS_AREA_EXEC) && (flags & AS_AREA_WRITE))
    488520                return NULL;
     521
     522        bool const guarded = flags & AS_AREA_GUARD;
    489523       
    490524        mutex_lock(&as->lock);
    491525       
    492526        if (*base == (uintptr_t) -1) {
    493                 *base = as_get_unmapped_area(as, bound, size);
     527                *base = as_get_unmapped_area(as, bound, size, guarded);
    494528                if (*base == (uintptr_t) -1) {
    495529                        mutex_unlock(&as->lock);
     
    497531                }
    498532        }
    499        
    500         if (!check_area_conflicts(as, *base, pages, NULL)) {
     533
     534        if (!check_area_conflicts(as, *base, pages, guarded, NULL)) {
    501535                mutex_unlock(&as->lock);
    502536                return NULL;
     
    778812                 * Check for overlaps with other address space areas.
    779813                 */
    780                 if (!check_area_conflicts(as, address, pages, area)) {
     814                bool const guarded = area->flags & AS_AREA_GUARD;
     815                if (!check_area_conflicts(as, address, pages, guarded, area)) {
    781816                        mutex_unlock(&area->lock);
    782817                        mutex_unlock(&as->lock);
Note: See TracChangeset for help on using the changeset viewer.