/* not secure */ void elf_loader(const char * file) { int filelen=0; char * addr = load(file, &filelen); if(!addr) { TRACE("Could not read file"); kernel_freeze(); return; } Elf64_Ehdr *hdr = (Elf64_Ehdr *)addr; if(!elf_check_supported(hdr)) { TRACE("ELF File cannot be loaded"); kernel_freeze(); return; } TRACE("e_entry:%lX e_phnum:%d e_shnum:%d", hdr->e_entry, hdr->e_phnum, hdr->e_shnum); size_t allocsize = 0; for(int i=0; i<hdr->e_phnum; i++) { Elf64_Phdr *seg = elf_segment(hdr, i); #if 0 TRACE("SGMT: type:%X flags:%X offset:%lX vaddr:%lX filesz:%lX memsz:%lX align:%lX", seg->p_type, seg->p_flags, seg->p_offset, seg->p_vaddr, seg->p_filesz, seg->p_memsz, seg->p_align); #endif if(seg->p_type == 1) { allocsize = imax(allocsize, seg->p_vaddr + seg->p_memsz); } } char *prgmp = kernel_calloc(allocsize, 1); //TODO:align this correctly bzero(prgmp, allocsize); if(!prgmp) { TRACE("Malloc failed"); kernel_freeze(); return; } for(int i=0; i<hdr->e_phnum; i++) { Elf64_Phdr *seg = elf_segment(hdr, i); memcpy(prgmp+seg->p_vaddr, addr + seg->p_offset, seg->p_filesz); } size_t pid = kernel_exec((uintptr_t)(prgmp + hdr->e_entry), 0x465); tmp_exec_stuff(pid, (size_t)prgmp, hdr->e_entry, allocsize); }
cap_pair elf_loader_mem(Elf_Env *env, void *p, size_t *minaddr, size_t *maxaddr, size_t *entry) { char *addr = (char *)p; size_t lowaddr = (size_t)(-1); Elf64_Ehdr *hdr = (Elf64_Ehdr *)addr; if(!elf_check_supported(env, hdr)) { ERROR("ELF File cannot be loaded"); return NULL_PAIR; } Elf64_Addr e_entry = hdr->e_entry; TRACE("e_entry:%lX e_phnum:%d e_shnum:%d", hdr->e_entry, hdr->e_phnum, hdr->e_shnum); size_t allocsize = 0; for(int i=0; i<hdr->e_phnum; i++) { Elf64_Phdr *seg = elf_segment(hdr, i); TRACE("SGMT: type:%X flags:%X offset:%lX vaddr:%lX filesz:%lX memsz:%lX align:%lX", seg->p_type, seg->p_flags, seg->p_offset, seg->p_vaddr, seg->p_filesz, seg->p_memsz, seg->p_align); if(seg->p_filesz > seg->p_memsz) { ERROR("Section is larger in file than in memory"); return NULL_PAIR; } if(seg->p_type == PT_LOAD) { size_t bound = seg->p_vaddr + seg->p_memsz; allocsize = umax(allocsize, bound); lowaddr = umin(lowaddr, seg->p_vaddr); TRACE("lowaddr:%lx allocsize:%lx bound:%lx", lowaddr, allocsize, bound); } else if(seg->p_type == PT_GNUSTACK || seg->p_type == PT_PHDR || seg->p_type == PT_GNURELRO) { /* Ignore these headers */ } else { ERROR("Unknown section"); return NULL_PAIR; } } cap_pair pair = env->alloc(allocsize); char *prgmp = pair.data; if(!prgmp) { ERROR("alloc failed"); return NULL_PAIR; } TRACE("Allocated %lx bytes of target memory", allocsize); ENV_PRINT_CAP(env, prgmp); for(int i=0; i<hdr->e_phnum; i++) { Elf64_Phdr *seg = elf_segment(hdr, i); if(seg->p_type == 1) { TRACE("memcpy: [%lx %lx] <-- [%lx %lx] (%lx bytes)", seg->p_vaddr, seg->p_vaddr + seg->p_filesz, seg->p_offset, seg->p_offset + seg->p_filesz, seg->p_filesz); env->memcpy(prgmp+seg->p_vaddr, addr + seg->p_offset, seg->p_filesz); } } env->free(addr); if(minaddr) *minaddr = lowaddr; if(maxaddr) *maxaddr = allocsize; if(entry) *entry = e_entry; return pair; }