分类: LINUX
2015-01-17 16:51:27
原文地址:load_elf_binary阅读(2) 作者:ch122633
static int set_brk(unsigned long start, unsigned long end)
{
start = PAGE_ALIGN(start);
end = PAGE_ALIGN(end);
if (end > start) {
unsigned long addr;
down_write(¤t->mm->mmap_sem);
addr = do_brk(start, end - start);
up_write(¤t->mm->mmap_sem);
if (BAD_ADDR(addr))
return addr;
}
return 0;
}
allow_write_access(interpreter); 防止其他进程在读入可执行文件期间通过内存映射改变它的内容
点击(此处)折叠或打开
- /* This is much more generalized than the library routine read function,
- so we keep this separate. Technically the library read function
- is only provided so that we can read a.out libraries that have
- an ELF header */
- static unsigned long load_elf_interp(struct elfhdr *interp_elf_ex,
- struct file *interpreter, unsigned long *interp_map_addr,
- unsigned long no_base)
- {
- struct elf_phdr *elf_phdata;
- struct elf_phdr *eppnt;
- unsigned long load_addr = 0;
- int load_addr_set = 0;
- unsigned long last_bss = 0, elf_bss = 0;
- unsigned long error = ~0UL;
- unsigned long total_size;
- int retval, i, size;
- /* First of all, some simple consistency checks */
- if (interp_elf_ex->e_type != ET_EXEC &&
- interp_elf_ex->e_type != ET_DYN) 判断是否是可执行文件和共享库,否则goto out
- goto out;
- if (!elf_check_arch(interp_elf_ex)) 判断头结构
- goto out;
- if (!interpreter->f_op || !interpreter->f_op->mmap) f_op是否为脏? 是否有内存映射?
- goto out;
- /*
- * If the size of this structure has changed, then punt, since
- * we will be doing the wrong thing.
- */
- if (interp_elf_ex->e_phentsize != sizeof(struct elf_phdr)) 判断项是否和段大小一致
- goto out;
- if (interp_elf_ex->e_phnum < 1 ||
- interp_elf_ex->e_phnum > 65536U / sizeof(struct elf_phdr)) 判断是否有程序头个数是否正常1~0xffff
- goto out;
- /* Now read in all of the header information */
- size = sizeof(struct elf_phdr) * interp_elf_ex->e_phnum; 读取头
- if (size > ELF_MIN_ALIGN)
- goto out;
- elf_phdata = kmalloc(size, GFP_KERNEL); 为其分配空间
- if (!elf_phdata)
- goto out;
- retval = kernel_read(interpreter, interp_elf_ex->e_phoff,
- (char *)elf_phdata,size);
- error = -EIO;
- if (retval != size) {
- if (retval < 0)
- error = retval;
- goto out_close;
- }
- total_size = total_mapping_size(elf_phdata, interp_elf_ex->e_phnum);
- if (!total_size) {
- error = -EINVAL;
- goto out_close;
- }
- eppnt = elf_phdata;
- for (i = 0; i < interp_elf_ex->e_phnum; i++, eppnt++) {
- if (eppnt->p_type == PT_LOAD) {
- int elf_type = MAP_PRIVATE | MAP_DENYWRITE;
- int elf_prot = 0;
- unsigned long vaddr = 0;
- unsigned long k, map_addr;
- if (eppnt->p_flags & PF_R)
- elf_prot = PROT_READ;
- if (eppnt->p_flags & PF_W)
- elf_prot |= PROT_WRITE;
- if (eppnt->p_flags & PF_X)
- elf_prot |= PROT_EXEC;
- vaddr = eppnt->p_vaddr;
- if (interp_elf_ex->e_type == ET_EXEC || load_addr_set)
- elf_type |= MAP_FIXED;
- else if (no_base && interp_elf_ex->e_type == ET_DYN)
- load_addr = -vaddr;
- map_addr = elf_map(interpreter, load_addr + vaddr,
- eppnt, elf_prot, elf_type, total_size);
- total_size = 0;
- if (!*interp_map_addr)
- *interp_map_addr = map_addr;
- error = map_addr;
- if (BAD_ADDR(map_addr))
- goto out_close;
- if (!load_addr_set &&
- interp_elf_ex->e_type == ET_DYN) {
- load_addr = map_addr - ELF_PAGESTART(vaddr);
- load_addr_set = 1;
- }
- /*
- * Check to see if the section's size will overflow the
- * allowed task size. Note that p_filesz must always be
- * <= p_memsize so it's only necessary to check p_memsz.
- */
- k = load_addr + eppnt->p_vaddr;
- if (BAD_ADDR(k) ||
- eppnt->p_filesz > eppnt->p_memsz ||
- eppnt->p_memsz > TASK_SIZE ||
- TASK_SIZE - eppnt->p_memsz < k) {
- error = -ENOMEM;
- goto out_close;
- }
- /*
- * Find the end of the file mapping for this phdr, and
- * keep track of the largest address we see for this.
- */
- k = load_addr + eppnt->p_vaddr + eppnt->p_filesz;
- if (k > elf_bss)
- elf_bss = k;
- /*
- * Do the same thing for the memory mapping - between
- * elf_bss and last_bss is the bss section.
- */
- k = load_addr + eppnt->p_memsz + eppnt->p_vaddr;
- if (k > last_bss)
- last_bss = k;
- }
- }
- if (last_bss > elf_bss) {
- /*
- * Now fill out the bss section. First pad the last page up
- * to the page boundary, and then perform a mmap to make sure
- * that there are zero-mapped pages up to and including the
- * last bss page.
- */
- if (padzero(elf_bss)) {
- error = -EFAULT;
- goto out_close;
- }
- /* What we have mapped so far */
- elf_bss = ELF_PAGESTART(elf_bss + ELF_MIN_ALIGN - 1);
- /* Map the last of the bss segment */
- down_write(¤t->mm->mmap_sem);
- error = do_brk(elf_bss, last_bss - elf_bss);
- up_write(¤t->mm->mmap_sem);
- if (BAD_ADDR(error))
- goto out_close;
- }
- error = load_addr;
- out_close:
- kfree(elf_phdata);
- out:
- return error;
- }