예제 #1
0
파일: PELoader.cpp 프로젝트: dusek/army
    bool load(std::istream &in, Memory& mem, addr_t img_base) {
        if (virt_sz > 0) {
            addr_t sect_addr_va = img_base + virt_addr;
            int prot = get_prot(charac);
            mem.alloc_protect(sect_addr_va , virt_sz, prot | Memory::Write);
            //TODO check for file_sz > virt_sz (explained in spec)
            if (file_sz > 0) {
                std::istream::streampos pos_orig = in.tellg(); 
                if (pos_orig == std::istream::pos_type(std::istream::off_type(-1)))
                    return false;
                in.seekg(file_pos, std::ios_base::beg);
                // TODO is "bad()" the right thing to check?
                if (in.bad())
                    return false;
                char *sect_data = new char[file_sz];
                in.read(sect_data, file_sz);
                if (std::size_t(in.gcount()) < file_sz) {
                    delete[] sect_data;
                    return false;
                }
                // perhaps change "write" interface to accept const char * to
                // avoid this copying madness?
                mem.write(sect_addr_va, std::string(sect_data, file_sz));
                delete[] sect_data;
                if (!(prot & Memory::Write))
                    mem.alloc_protect(sect_addr_va, virt_sz, prot);
                in.seekg(pos_orig);
                if (in.bad())
                    return false;
            }
        }

        return true;
    }
예제 #2
0
void *elf_file_load_ram(int pid, char *pfile) {

    elf64_hdr       *pelf_header;
    elf64_phdr      *prog_hdr;
    void            *seg_addr;
    void            *elf_offset;
    int             ph;
    uintptr_t       start, end;
    int             sizeof_phdrs;
    int             err;

    pelf_header = (elf64_hdr *)pfile;

    if (strncmp((const char *)pelf_header->e_ident, "\x7f" "ELF", 4)) {
        anvil_syslog(0, "Incorrect ELF identifier\n");
        return NULL;
    }

    if (pelf_header->e_ident[4] != 2) {
        anvil_syslog(0, "Elf file is not 64 bit\n");
        return NULL;
    }

    if (pelf_header->e_type != 2) {
        anvil_syslog(0, "Elf file is not executable\n");
        return NULL;
    }

    if (pelf_header->e_phnum > 3) {
        anvil_syslog(0, "Elf file has too many segments\n");
        return NULL;
    }

    //anvil_syslog(0, "Elf OK\n");

    sizeof_phdrs = pelf_header->e_phentsize * pelf_header->e_phnum;

    prog_hdr = (elf64_phdr *)((char *)pelf_header + pelf_header->e_phoff);

    for (ph=0; ph<pelf_header->e_phnum; ++ph) {

        int prot;

        if (prog_hdr->p_type != 1) {
            anvil_syslog(0, "Elf file segment is not loadable\n");
            return NULL;
        }

        prot = get_prot(prog_hdr->p_flags);

        /* We found a loadable segment so create a mapping */
        start = prog_hdr->p_vaddr;
        end = start + prog_hdr->p_memsz;

        start &= ~0xfff;
        end = __PAGEROUND(end);

        if (_Mmap(0, 0, end - start, PROT_READ,
                    MAP_ANON, -1, 0, &seg_addr) != 0) {
            anvil_syslog(0, "Out of memory\n");
            return NULL;
        }

        //anvil_syslog(0, "seg_addr = %016lx\n", seg_addr);

        /* Find where, in the elf image the section is */
        elf_offset = (void *)(pfile + prog_hdr->p_offset);
        //anvil_syslog(0, "File image addr = %08x\n", elf_offset);

        /* The segment is zero filled by the _Mmap system call */
        //anvil_syslog(0, "%016lx %016lx %016lx\n",
        //                seg_addr + prog_hdr->p_vaddr - start,
        //                elf_offset,
        //                prog_hdr->p_filesz);

        memcpy(seg_addr + prog_hdr->p_vaddr - start,
                                elf_offset, prog_hdr->p_filesz);

        //anvil_syslog(0, "_Vmm_send: %d %016lx %016lx %018x\n",
        //        pid, start, seg_addr, end - start);
        _Vmm_send(pid, (void *)start, seg_addr, end - start, prot);

        prog_hdr = (elf64_phdr *)
                ((uint64_t)prog_hdr + pelf_header->e_phentsize);
    }

    return (void *)pelf_header->e_entry;
}
예제 #3
0
int se_virtual_protect(void* address, size_t size, uint32_t prot)
{
    return !mprotect(address, size, (int)get_prot(prot));
}
예제 #4
0
void *elf_file_load(int pid, int fd) {

    elf64_hdr       elf_header;
    elf64_hdr       *pelf_header;
    elf64_phdr      *pprog_hdr;
    void            *seg_addr;
    void            *elf_offset;
    int             ph;
    uintptr_t       start, end;
    int             sizeof_phdrs;
    int             err;
    char            *p;
    char            *interp_name;
    elf64_dyn       *dyn_seg;
    int             ndyn_items;
    int             interp_fd;
    uintptr_t       entry_offs;
    int             prot;


    interp_name = NULL;
    dyn_seg     = NULL;
    entry_offs  = 0;

    if (read(fd, &elf_header, sizeof(elf_header)) != sizeof(elf_header)) {
        anvil_syslog(0, "Bad ELF header\n");
        while (1);
    }

    pelf_header = &elf_header;

    if (strncmp((const char *)pelf_header->e_ident, "\x7f" "ELF", 4)) {
        anvil_syslog(0, "Incorrect ELF identifier\n");
        return NULL;
    }

    if (pelf_header->e_ident[4] != 2) {
        anvil_syslog(0, "Elf file is not 64 bit\n");
        return NULL;
    }

    if (pelf_header->e_type != 2) {
        anvil_syslog(0, "Elf file is not executable\n");
        return NULL;
    }

//    if (pelf_header->e_phnum > 3) {
//        anvil_syslog(0, "Elf file has too many segments\n");
//        return NULL;
//    }

    //anvil_syslog(0, "Elf OK\n");

    sizeof_phdrs = pelf_header->e_phentsize * pelf_header->e_phnum;

    pprog_hdr = (elf64_phdr *)alloca(sizeof_phdrs);
    memset(pprog_hdr, 0, sizeof_phdrs);

    if (pread(fd, pprog_hdr, sizeof_phdrs, elf_header.e_phoff) == -1) {
        anvil_syslog(0, "Bad prog_hdr header\n");
        while (1);
    }

    for (ph=0; ph<pelf_header->e_phnum; ++ph) {

        switch (pprog_hdr->p_type) {

            case PT_LOAD:
                if (pprog_hdr->p_type != 1) {
                    anvil_syslog(0, "Elf file segment is not loadable\n");
                    return NULL;
                }

                prot = get_prot(pprog_hdr->p_flags);

                /* We found a loadable segment so create a mapping */
                start = pprog_hdr->p_vaddr;
                end = start + pprog_hdr->p_memsz;

                start &= ~0xfff;
                end = __PAGEROUND(end);

                //anvil_syslog(0, "\nstart=%016lx end=%016lx\n", start, end);

                /* Make a mapping in the address of the exec-svr */
                if (_Mmap(0, 0, end - start, PROT_READ,
                            MAP_ANON, -1, 0, &seg_addr) != 0) {
                    anvil_syslog(0, "Out of memory\n");
                    return NULL;
                }

                /*
                 * seg_addr (from the mmap call) is the address in the
                 * exec-svr where we will load the section
                 */

                /* Load the segment from the file */
                //anvil_syslog(0, "pread to %016lx %016lx\n", pprog_hdr->p_filesz, pprog_hdr->p_offset);
                if (pread(fd, seg_addr + pprog_hdr->p_vaddr - start, pprog_hdr->p_filesz, pprog_hdr->p_offset) == -1) {
                    anvil_syslog(0, "Bad load of segment\n");
                    while (1);
                }

                /* Send it to the new process space */
                //anvil_syslog(0, "_Vmm_send: %d %016lx %016lx %018x\n",
                //        pid, start, seg_addr, end - start);
                _Vmm_send(pid, (void *)start, seg_addr, end - start, prot);

            break;

            case PT_INTERP:
                /*
                 * Just record the name of the interpreter. We'll load it in
                 * a minute
                 */
                //anvil_syslog(0, "PT_INTERP %d\n", pprog_hdr->p_filesz);
                interp_name = alloca(pprog_hdr->p_filesz + 1);
                if (pread(fd, interp_name, pprog_hdr->p_filesz, pprog_hdr->p_offset) == -1) {
                    anvil_syslog(0, "Bad load of interp\n");
                    while (1);
                }
                interp_name[pprog_hdr->p_filesz] = 0;
                //anvil_syslog(0, "PT_INTERP is %s\n", interp_name);
                break;

            case PT_DYNAMIC:
                /*
                 */
                //anvil_syslog(0, "PT_DYNAMIC\n");
                dyn_seg = alloca(pprog_hdr->p_filesz);
                if (pread(fd, dyn_seg, pprog_hdr->p_filesz, pprog_hdr->p_offset) == -1) {
                    anvil_syslog(0, "Bad load of dyn_seg\n");
                    while (1);
                }
                ndyn_items = pprog_hdr->p_filesz / sizeof(elf64_dyn);
                //anvil_syslog(0, "PT_DYNAMIC %d items\n", ndyn_items);
                /* Now parse the dyn seg */
                while (ndyn_items) {
                    //anvil_syslog(0, " items %d %016lx\n", dyn_seg->d_tag, dyn_seg->d_un.d_ptr);
                    ++dyn_seg;
                    --ndyn_items;
                }
                break;

            case PT_TLS:
//                anvil_syslog(0, "PT_TLS\n");
//                anvil_syslog(0, "p_type %016lx\n",pprog_hdr->p_type);
//                anvil_syslog(0, "p_flags %016lx\n",pprog_hdr->p_flags);
//                anvil_syslog(0, "p_offset %016lx\n",pprog_hdr->p_offset);
//                anvil_syslog(0, "p_vaddr %016lx\n",pprog_hdr->p_vaddr);
//                anvil_syslog(0, "p_paddr %016lx\n",pprog_hdr->p_paddr);
//                anvil_syslog(0, "p_filesz %016lx\n",pprog_hdr->p_filesz);
//                anvil_syslog(0, "p_memsz %016lx\n",pprog_hdr->p_memsz);
//                anvil_syslog(0, "p_align %016lx\n",pprog_hdr->p_align);
                //*ptls_bss_len += pprog_hdr->p_memsz;
                break;

            default:
                anvil_syslog(0, "Unknown Load type %d\n", pprog_hdr->p_type);
            break;
        }

        pprog_hdr = (elf64_phdr *)
                ((uint64_t)pprog_hdr + pelf_header->e_phentsize);
    }

    if (interp_name != NULL) {
        interp_name = "/lib/libc.so";
        //anvil_syslog(0, "Loading interpreter %s\n", interp_name);
        if ((interp_fd = open(interp_name, 0, 0)) == -1) {
            anvil_syslog(0, "Couldn't open interpreter %s\n", interp_name);
            return NULL;
        }

        /*
         * Now load the interpreter into memory. The interpreter should be
         * entirely PIC so we can load it anywhere.
         */

        if (read(interp_fd, &elf_header, sizeof(elf_header)) != sizeof(elf_header)) {
            anvil_syslog(0, "Bad ELF header\n");
            while (1);
        }

        pelf_header = &elf_header;

        if (strncmp((const char *)pelf_header->e_ident, "\x7f" "ELF", 4)) {
            anvil_syslog(0, "Interp: Incorrect ELF identifier\n");
            return NULL;
        }

        if (pelf_header->e_ident[4] != 2) {
            anvil_syslog(0, "Interp: Elf file is not 64 bit\n");
            return NULL;
        }

        if (pelf_header->e_type != 3) {
            anvil_syslog(0, "Interp: Elf file is not a so\n");
            return NULL;
        }

        anvil_syslog(0, "Interp OK\n");

        sizeof_phdrs = pelf_header->e_phentsize * pelf_header->e_phnum;

        pprog_hdr = (elf64_phdr *)alloca(sizeof_phdrs);
        memset(pprog_hdr, 0, sizeof_phdrs);

        if (pread(interp_fd, pprog_hdr, sizeof_phdrs, elf_header.e_phoff) == -1) {
            anvil_syslog(0, "Interp: Bad prog_hdr header\n");
            while (1);
        }

        for (ph=0; ph<pelf_header->e_phnum; ++ph) {

            switch (pprog_hdr->p_type) {

                case PT_LOAD:
                    if (pprog_hdr->p_type != 1) {
                        anvil_syslog(0, "Interp: Elf file segment is not loadable\n");
                        return NULL;
                    }

                    prot = get_prot(pprog_hdr->p_flags);

                    /* We found a loadable segment so create a mapping */
                    start = pprog_hdr->p_vaddr;
                    end = start + pprog_hdr->p_memsz;

                    start &= ~0xfff;
                    end = __PAGEROUND(end);

                    //anvil_syslog(0, "\nstart=%016lx end=%016lx\n", start, end);

                    /* Make a mapping in the address of the exec-svr */
                    if (_Mmap(0, 0, end - start, PROT_EXEC|PROT_READ|PROT_WRITE,
                                MAP_ANON, -1, 0, &seg_addr) != 0) {
                        anvil_syslog(0, "Interp: Out of memory\n");
                        return NULL;
                    }

                    /*
                     * seg_addr (from the mmap call) is the address in the
                     * exec-svr where we will load the section
                     */

                    /* Load the segment from the file */
                    //anvil_syslog(0, "pread to %016lx %016lx\n", pprog_hdr->p_filesz, pprog_hdr->p_offset);
                    if (pread(interp_fd, seg_addr + pprog_hdr->p_vaddr - start, pprog_hdr->p_filesz, pprog_hdr->p_offset) == -1) {
                        anvil_syslog(0, "Interp: Bad load of segment\n");
                        while (1);
                    }

                    /* Send it to the new process space */
                    //anvil_syslog(0, "_Vmm_send: %d %016lx %016lx %018x\n",
                    //        pid, start, seg_addr, end - start);
                    _Vmm_send(pid, (void *)start+0x100000000, seg_addr, end - start, prot);

                break;

                default:
                    anvil_syslog(0, "Unknown Load type %d\n", pprog_hdr->p_type);
                break;
            }

            pprog_hdr = (elf64_phdr *)
                    ((uint64_t)pprog_hdr + pelf_header->e_phentsize);
        }
        entry_offs += 0x100000000;
        close(interp_fd);
    }

    //anvil_syslog(0, "Start address at %016lx\n", elf_header.e_entry+entry_offs);

    return (void *)elf_header.e_entry + entry_offs;
}
예제 #5
0
void load_elf(const char* fn, elf_info* info)
{
  file_t* file = file_open(fn, O_RDONLY, 0);
  if (IS_ERR_VALUE(file))
    goto fail;

  Elf_Ehdr eh;
  ssize_t ehdr_size = file_pread(file, &eh, sizeof(eh), 0);
  if (ehdr_size < (ssize_t)sizeof(eh) ||
      !(eh.e_ident[0] == '\177' && eh.e_ident[1] == 'E' &&
        eh.e_ident[2] == 'L'    && eh.e_ident[3] == 'F'))
    goto fail;

#if __riscv_xlen == 64
  assert(IS_ELF64(eh));
#else
  assert(IS_ELF32(eh));
#endif

#ifndef __riscv_compressed
  assert(!(eh.e_flags & EF_RISCV_RVC));
#endif

  size_t phdr_size = eh.e_phnum * sizeof(Elf_Phdr);
  if (phdr_size > info->phdr_size)
    goto fail;
  ssize_t ret = file_pread(file, (void*)info->phdr, phdr_size, eh.e_phoff);
  if (ret < (ssize_t)phdr_size)
    goto fail;
  info->phnum = eh.e_phnum;
  info->phent = sizeof(Elf_Phdr);
  Elf_Phdr* ph = (typeof(ph))info->phdr;

  // compute highest VA in ELF
  uintptr_t max_vaddr = 0;
  for (int i = 0; i < eh.e_phnum; i++)
    if (ph[i].p_type == PT_LOAD && ph[i].p_memsz)
      max_vaddr = MAX(max_vaddr, ph[i].p_vaddr + ph[i].p_memsz);
  max_vaddr = ROUNDUP(max_vaddr, RISCV_PGSIZE);

  // don't load dynamic linker at 0, else we can't catch NULL pointer derefs
  uintptr_t bias = 0;
  if (eh.e_type == ET_DYN)
    bias = RISCV_PGSIZE;

  info->entry = eh.e_entry + bias;
  int flags = MAP_FIXED | MAP_PRIVATE;
  for (int i = eh.e_phnum - 1; i >= 0; i--) {
    if(ph[i].p_type == PT_LOAD && ph[i].p_memsz) {
      uintptr_t prepad = ph[i].p_vaddr % RISCV_PGSIZE;
      uintptr_t vaddr = ph[i].p_vaddr + bias;
      if (vaddr + ph[i].p_memsz > info->brk_min)
        info->brk_min = vaddr + ph[i].p_memsz;
      int flags2 = flags | (prepad ? MAP_POPULATE : 0);
      int prot = get_prot(ph[i].p_flags);
      if (__do_mmap(vaddr - prepad, ph[i].p_filesz + prepad, prot | PROT_WRITE, flags2, file, ph[i].p_offset - prepad) != vaddr - prepad)
        goto fail;
      memset((void*)vaddr - prepad, 0, prepad);
      if (!(prot & PROT_WRITE))
        if (do_mprotect(vaddr - prepad, ph[i].p_filesz + prepad, prot))
          goto fail;
      size_t mapped = ROUNDUP(ph[i].p_filesz + prepad, RISCV_PGSIZE) - prepad;
      if (ph[i].p_memsz > mapped)
        if (__do_mmap(vaddr + mapped, ph[i].p_memsz - mapped, prot, flags|MAP_ANONYMOUS, 0, 0) != vaddr + mapped)
          goto fail;
    }
  }

  file_decref(file);
  return;

fail:
  panic("couldn't open ELF program: %s!", fn);
}