Fork us on GitHub Follow us on Facebook Follow us on Twitter

Changeset d91488d in mainline


Ignore:
Timestamp:
2018-11-21T09:16:16Z (20 months ago)
Author:
Jiri Svoboda <jiri@…>
Branches:
master
Children:
a91c555
Parents:
0705fc5
git-author:
Jiri Svoboda <jiri@…> (2018-11-20 20:14:06)
git-committer:
Jiri Svoboda <jiri@…> (2018-11-21 09:16:16)
Message:

Fix endless loop in elf_share() walking the wrong B+tree. Fix ELF areas shared to a different address than in the originating task.

Location:
kernel/generic
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • kernel/generic/include/mm/as.h

    r0705fc5 rd91488d  
    179179        /** elf_backend members */
    180180        struct {
     181                uintptr_t elf_base;
    181182                elf_header_t *elf;
    182183                elf_segment_header_t *segment;
  • kernel/generic/src/lib/elf.c

    r0705fc5 rd91488d  
    142142{
    143143        mem_backend_data_t backend_data;
    144         backend_data.elf = elf;
    145         backend_data.segment = entry;
    146144
    147145        if (entry->p_align > 1) {
     
    172170        size_t mem_sz = entry->p_memsz + (entry->p_vaddr - base);
    173171
     172        backend_data.elf_base = base;
     173        backend_data.elf = elf;
     174        backend_data.segment = entry;
     175
    174176        as_area_t *area = as_area_create(as, flags, mem_sz,
    175177            AS_AREA_ATTR_NONE, &elf_backend, &backend_data, &base, 0);
  • kernel/generic/src/mm/backend_elf.c

    r0705fc5 rd91488d  
    9696}
    9797
     98/** Get page number in the task where the ELF page originates from.
     99 *
     100 * The ELF page can be shared to a different address than it originated from,
     101 * but we need the originating address since that corresponds to the ELF's
     102 * virtual addesses.
     103 *
     104 * @param area Area in which the page resides
     105 * @param page Virtual address of the page in @a area
     106 * @return Virtual address of the page in the origin address space
     107 */
     108static uintptr_t elf_orig_page(as_area_t *area, uintptr_t page)
     109{
     110        return page - area->base + area->backend_data.elf_base;
     111}
     112
    98113bool elf_create(as_area_t *area)
    99114{
     
    152167                    btree_node_t, leaf_link);
    153168        } else {
    154                 (void) btree_search(&area->sh_info->pagemap, start_anon, &leaf);
    155                 node = btree_leaf_node_left_neighbour(&area->sh_info->pagemap,
    156                     leaf);
     169                (void) btree_search(&area->used_space, start_anon, &leaf);
     170                node = btree_leaf_node_left_neighbour(&area->used_space, leaf);
    157171                if (!node)
    158172                        node = leaf;
     
    258272        uintptr_t kpage;
    259273        uintptr_t start_anon;
     274        uintptr_t elfpage;
    260275        size_t i;
    261276        bool dirty = false;
     
    265280        assert(IS_ALIGNED(upage, PAGE_SIZE));
    266281
     282        elfpage = elf_orig_page(area, upage);
     283
    267284        if (!as_area_check_access(area, access))
    268285                return AS_PF_FAULT;
    269286
    270         if (upage < ALIGN_DOWN(entry->p_vaddr, PAGE_SIZE))
     287        if (elfpage < ALIGN_DOWN(entry->p_vaddr, PAGE_SIZE))
    271288                return AS_PF_FAULT;
    272289
    273         if (upage >= entry->p_vaddr + entry->p_memsz)
     290        if (elfpage >= entry->p_vaddr + entry->p_memsz)
    274291                return AS_PF_FAULT;
    275292
    276         i = (upage - ALIGN_DOWN(entry->p_vaddr, PAGE_SIZE)) >> PAGE_WIDTH;
     293        i = (elfpage - ALIGN_DOWN(entry->p_vaddr, PAGE_SIZE)) >>
     294            PAGE_WIDTH;
    277295        base = (uintptr_t)
    278296            (((void *) elf) + ALIGN_DOWN(entry->p_offset, PAGE_SIZE));
     
    320338         * mapping.
    321339         */
    322         if (upage >= entry->p_vaddr && upage + PAGE_SIZE <= start_anon) {
     340        if (elfpage >= entry->p_vaddr && elfpage + PAGE_SIZE <= start_anon) {
    323341                /*
    324342                 * Initialized portion of the segment. The memory is backed
    325343                 * directly by the content of the ELF image. Pages are
    326344                 * only copied if the segment is writable so that there
    327                  * can be more instantions of the same memory ELF image
     345                 * can be more instances of the same memory ELF image
    328346                 * used at a time. Note that this could be later done
    329347                 * as COW.
     
    351369                        frame = PTE_GET_FRAME(&pte);
    352370                }
    353         } else if (upage >= start_anon) {
     371        } else if (elfpage >= start_anon) {
    354372                /*
    355373                 * This is the uninitialized portion of the segment.
     
    424442        elf_segment_header_t *entry = area->backend_data.segment;
    425443        uintptr_t start_anon;
     444        uintptr_t elfpage;
    426445
    427446        assert(page_table_locked(area->as));
    428447        assert(mutex_locked(&area->lock));
    429448
    430         assert(page >= ALIGN_DOWN(entry->p_vaddr, PAGE_SIZE));
    431         assert(page < entry->p_vaddr + entry->p_memsz);
     449        elfpage = elf_orig_page(area, page);
     450
     451        assert(elfpage >= ALIGN_DOWN(entry->p_vaddr, PAGE_SIZE));
     452        assert(elfpage < entry->p_vaddr + entry->p_memsz);
    432453
    433454        start_anon = entry->p_vaddr + entry->p_filesz;
    434455
    435         if (page >= entry->p_vaddr && page + PAGE_SIZE <= start_anon) {
     456        if (elfpage >= entry->p_vaddr && elfpage + PAGE_SIZE <= start_anon) {
    436457                if (entry->p_flags & PF_W) {
    437458                        /*
Note: See TracChangeset for help on using the changeset viewer.