Chinaunix首页 | 论坛 | 博客
  • 博客访问: 601379
  • 博文数量: 353
  • 博客积分: 1104
  • 博客等级: 少尉
  • 技术积分: 1457
  • 用 户 组: 普通用户
  • 注册时间: 2008-12-23 23:02
个人简介

1、刚工作时做Linux 流控;后来做安全操作系统;再后来做操作系统加固;现在做TCP 加速。唉!没离开过类Unix!!!但是水平有限。。

文章存档

2015年(80)

2013年(4)

2012年(90)

2011年(177)

2010年(1)

2009年(1)

分类: LINUX

2015-06-05 17:22:15

原文地址:load_elf_binary阅读(2) 作者:ch122633

/*
* Check to see if the section's size will overflow the
* allowed task size. Note that p_filesz must always be
* <= p_memsz so it is only necessary to check p_memsz.
*/
if (BAD_ADDR(k) || elf_ppnt->p_filesz > elf_ppnt->p_memsz ||
   elf_ppnt->p_memsz > TASK_SIZE ||                      判断使用的空间是否小于分配空间
   TASK_SIZE - elf_ppnt->p_memsz < k) {
/* set_brk can never work. Avoid overflows. */
send_sig(SIGKILL, current, 0);
retval = -EINVAL;
goto out_free_dentry;
}


k = elf_ppnt->p_vaddr + elf_ppnt->p_filesz;           段虚拟地址加上段大小就到了段尾


if (k > elf_bss)
elf_bss = k;                                                                   后面接elf_bss
if ((elf_ppnt->p_flags & PF_X) && end_code < k)         ELF 段标志可执行 并且指令段不在K
end_code = k;                                                         指令段后面接段
if (end_data < k)
end_data = k;                                                       数据段连接
k = elf_ppnt->p_vaddr + elf_ppnt->p_memsz;         k又设为内存映像地址末尾
if (k > elf_brk)
elf_brk = k;
}
循环结束

loc->elf_ex.e_entry += load_bias;                      把地址转换成内存地址
elf_bss += load_bias;
elf_brk += load_bias;
start_code += load_bias;
end_code += load_bias;
start_data += load_bias;
end_data += load_bias;


/* Calling set_brk effectively mmaps the pages that we need
* for the bss and break sections.  We must do this before
* mapping in the interpreter, to make sure it doesn't wind
* up getting placed where the bss needs to go.
*/
retval = set_brk(elf_bss, elf_brk);
if (retval) {
send_sig(SIGKILL, current, 0);
goto out_free_dentry;
}
if (likely(elf_bss != elf_brk) && unlikely(padzero(elf_bss))) {
send_sig(SIGSEGV, current, 0);
retval = -EFAULT; /* Nobody gets to see this, but.. */
goto out_free_dentry;
}

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;
}


if (elf_interpreter) {                                                 判断是否需要解释器
unsigned long uninitialized_var(interp_map_addr);


elf_entry = load_elf_interp(&loc->interp_elf_ex,
   interpreter,
   &interp_map_addr,
   load_bias);
if (!IS_ERR((void *)elf_entry)) {
/*
* load_elf_interp() returns relocation
* adjustment
*/                                                                  这个是基地址重定位?
interp_load_addr = elf_entry;
elf_entry += loc->interp_elf_ex.e_entry;
}
if (BAD_ADDR(elf_entry)) {
force_sig(SIGSEGV, current);
retval = IS_ERR((void *)elf_entry) ?
(int)elf_entry : -EINVAL;
goto out_free_dentry;
}
reloc_func_desc = interp_load_addr;


点击(此处)折叠或打开

  1. /* This is much more generalized than the library routine read function,
  2.    so we keep this separate. Technically the library read function
  3.    is only provided so that we can read a.out libraries that have
  4.    an ELF header */

  5. static unsigned long load_elf_interp(struct elfhdr *interp_elf_ex,
  6. struct file *interpreter, unsigned long *interp_map_addr,
  7. unsigned long no_base)
  8. {
  9. struct elf_phdr *elf_phdata;
  10. struct elf_phdr *eppnt;
  11. unsigned long load_addr = 0;
  12. int load_addr_set = 0;
  13. unsigned long last_bss = 0, elf_bss = 0;
  14. unsigned long error = ~0UL;
  15. unsigned long total_size;
  16. int retval, i, size;


  17. /* First of all, some simple consistency checks */
  18. if (interp_elf_ex->e_type != ET_EXEC &&
  19.    interp_elf_ex->e_type != ET_DYN)                   判断是否是可执行文件和共享库,否则goto out
  20. goto out;
  21. if (!elf_check_arch(interp_elf_ex))                   判断头结构
  22. goto out;
  23. if (!interpreter->f_op || !interpreter->f_op->mmap)     f_op是否为脏?     是否有内存映射?
  24. goto out;

  25. /*
  26. * If the size of this structure has changed, then punt, since
  27. * we will be doing the wrong thing.
  28. */
  29. if (interp_elf_ex->e_phentsize != sizeof(struct elf_phdr))     判断项是否和段大小一致
  30. goto out;
  31. if (interp_elf_ex->e_phnum < 1 ||
  32. interp_elf_ex->e_phnum > 65536U / sizeof(struct elf_phdr))    判断是否有程序头个数是否正常1~0xffff
  33. goto out;


  34. /* Now read in all of the header information */
  35. size = sizeof(struct elf_phdr) * interp_elf_ex->e_phnum;         读取头
  36. if (size > ELF_MIN_ALIGN)
  37. goto out;
  38. elf_phdata = kmalloc(size, GFP_KERNEL);                          为其分配空间
  39. if (!elf_phdata)
  40. goto out;

  41. retval = kernel_read(interpreter, interp_elf_ex->e_phoff,
  42.     (char *)elf_phdata,size);
  43. error = -EIO;
  44. if (retval != size) {
  45. if (retval < 0)
  46. error = retval;
  47. goto out_close;
  48. }

  49. total_size = total_mapping_size(elf_phdata, interp_elf_ex->e_phnum);
  50. if (!total_size) {
  51. error = -EINVAL;
  52. goto out_close;
  53. }

  54. eppnt = elf_phdata;
  55. for (i = 0; i < interp_elf_ex->e_phnum; i++, eppnt++) {
  56. if (eppnt->p_type == PT_LOAD) {
  57. int elf_type = MAP_PRIVATE | MAP_DENYWRITE;
  58. int elf_prot = 0;
  59. unsigned long vaddr = 0;
  60. unsigned long k, map_addr;

  61. if (eppnt->p_flags & PF_R)
  62.         elf_prot = PROT_READ;
  63. if (eppnt->p_flags & PF_W)
  64. elf_prot |= PROT_WRITE;
  65. if (eppnt->p_flags & PF_X)
  66. elf_prot |= PROT_EXEC;
  67. vaddr = eppnt->p_vaddr;
  68. if (interp_elf_ex->e_type == ET_EXEC || load_addr_set)
  69. elf_type |= MAP_FIXED;
  70. else if (no_base && interp_elf_ex->e_type == ET_DYN)
  71. load_addr = -vaddr;

  72. map_addr = elf_map(interpreter, load_addr + vaddr,
  73. eppnt, elf_prot, elf_type, total_size);
  74. total_size = 0;
  75. if (!*interp_map_addr)
  76. *interp_map_addr = map_addr;
  77. error = map_addr;
  78. if (BAD_ADDR(map_addr))
  79. goto out_close;

  80. if (!load_addr_set &&
  81.    interp_elf_ex->e_type == ET_DYN) {
  82. load_addr = map_addr - ELF_PAGESTART(vaddr);
  83. load_addr_set = 1;
  84. }

  85. /*
  86. * Check to see if the section's size will overflow the
  87. * allowed task size. Note that p_filesz must always be
  88. * <= p_memsize so it's only necessary to check p_memsz.
  89. */
  90. k = load_addr + eppnt->p_vaddr;
  91. if (BAD_ADDR(k) ||
  92.    eppnt->p_filesz > eppnt->p_memsz ||
  93.    eppnt->p_memsz > TASK_SIZE ||
  94.    TASK_SIZE - eppnt->p_memsz < k) {
  95. error = -ENOMEM;
  96. goto out_close;
  97. }

  98. /*
  99. * Find the end of the file mapping for this phdr, and
  100. * keep track of the largest address we see for this.
  101. */
  102. k = load_addr + eppnt->p_vaddr + eppnt->p_filesz;
  103. if (k > elf_bss)
  104. elf_bss = k;

  105. /*
  106. * Do the same thing for the memory mapping - between
  107. * elf_bss and last_bss is the bss section.
  108. */
  109. k = load_addr + eppnt->p_memsz + eppnt->p_vaddr;
  110. if (k > last_bss)
  111. last_bss = k;
  112. }
  113. }

  114. if (last_bss > elf_bss) {
  115. /*
  116. * Now fill out the bss section. First pad the last page up
  117. * to the page boundary, and then perform a mmap to make sure
  118. * that there are zero-mapped pages up to and including the
  119. * last bss page.
  120. */
  121. if (padzero(elf_bss)) {
  122. error = -EFAULT;
  123. goto out_close;
  124. }

  125. /* What we have mapped so far */
  126. elf_bss = ELF_PAGESTART(elf_bss + ELF_MIN_ALIGN - 1);

  127. /* Map the last of the bss segment */
  128. down_write(&current->mm->mmap_sem);
  129. error = do_brk(elf_bss, last_bss - elf_bss);
  130. up_write(&current->mm->mmap_sem);
  131. if (BAD_ADDR(error))
  132. goto out_close;
  133. }

  134. error = load_addr;

  135. out_close:
  136. kfree(elf_phdata);
  137. out:
  138. return error;
  139. }
allow_write_access(interpreter);        防止其他进程在读入可执行文件期间通过内存映射改变它的内容
fput(interpreter);            递减file文件中的共享计数
kfree(elf_interpreter);        用完释放
} else {
elf_entry = loc->elf_ex.e_entry;
if (BAD_ADDR(elf_entry)) {
force_sig(SIGSEGV, current);
retval = -EINVAL;
goto out_free_dentry;
}
}


kfree(elf_phdata);    释放


set_binfmt(&elf_format);       设置进程的binfmt   ELF格式


#ifdef ARCH_HAS_SETUP_ADDITIONAL_PAGES
retval = arch_setup_additional_pages(bprm, !!elf_interpreter);
if (retval < 0) {
send_sig(SIGKILL, current, 0);
goto out;
}
#endif /* ARCH_HAS_SETUP_ADDITIONAL_PAGES */


install_exec_creds(bprm);
current->flags &= ~PF_FORKNOEXEC;
retval = create_elf_tables(bprm, &loc->elf_ex,
 load_addr, interp_load_addr);
if (retval < 0) {
send_sig(SIGKILL, current, 0);
goto out;
}
/* N.B. passed_fileno might not be initialized? */
current->mm->end_code = end_code;    代码段结束地址
current->mm->start_code = start_code;    代码段起始地址
current->mm->start_data = start_data;    数据段起始地址
current->mm->end_data = end_data;     数据段结束地址
current->mm->start_stack = bprm->p;    栈的起始地址


#ifdef arch_randomize_brk
if ((current->flags & PF_RANDOMIZE) && (randomize_va_space > 1))
current->mm->brk = current->mm->start_brk =
arch_randomize_brk(current->mm);
#endif


if (current->personality & MMAP_PAGE_ZERO) {
/* Why this, you ask???  Well SVr4 maps page 0 as read-only,
  and some applications "depend" upon this behavior.
  Since we do not have the power to recompile these, we
  emulate the SVr4 behavior. Sigh. */
down_write(¤t->mm->mmap_sem);      写信号
error = do_mmap(NULL, 0, PAGE_SIZE, PROT_READ | PROT_EXEC,        访问权限可读可执行
MAP_FIXED | MAP_PRIVATE, 0);        地址固定,私有
up_write(¤t->mm->mmap_sem);         写信号
}


#ifdef ELF_PLAT_INIT
/*
* The ABI may specify that certain registers be set up in special
* ways (on i386 %edx is the address of a DT_FINI function, for
* example.  In addition, it may also specify (eg, PowerPC64 ELF)
* that the e_entry field is the address of the function descriptor
* for the startup routine, rather than the address of the startup
* routine itself.  This macro performs whatever initialization to
* the regs structure is required as well as any relocations to the
* function descriptor entries when executing dynamically links apps.
*/
ELF_PLAT_INIT(regs, reloc_func_desc);
#endif


start_thread(regs, elf_entry, bprm->p);        开始进程
retval = 0;
out:
kfree(loc);
out_ret:
return retval;


/* error cleanup */
out_free_dentry:
allow_write_access(interpreter);
if (interpreter)
fput(interpreter);
out_free_interp:
kfree(elf_interpreter);
out_free_ph:
kfree(elf_phdata);
goto out;
}

阅读(668) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~