📄
字号:
</p> </blockquote></blockquote><p><strong><font FACE="隶书" SIZE="5">三 代码分析(Code analysis)</font></strong></p><blockquote> <blockquote> <p></font><font face="宋体" size="3" color="#000000"> 函数首先定义了一个结构变量:struct linux_binprm bprm,用以存放一些将要被执行的程序的参数值,然后程序调用 open_namei 函数打开文件(。。。。)然后程序检查参数堆栈的设置是否正确.</font><font FACE="宋体" size="3"><font color="#00FF40"><br> </font><font color="#8000FF">/* this function is from file linux/fs/exec.c */ </font><br> </font><font FACE="宋体" COLOR="#007f7f" size="3">/* sys_execve() executes a new program. */ <br> <br> <strong>int do_execve(char * filename, char ** argv, char ** envp, struct pt_regs *regs)<br> { <br> struct linux_binprm bprm;<br> int retval;<br> int i;<br> bprm.p = PAGE_SIZE*MAX_ARG_PAGES-sizeof(void *);<br> <br> /* clear page-table */ <br> for (i=0 ; i<MAX_ARG_PAGES ; i++) <br> bprm.page[i] = 0;<br> retval = open_namei(filename, 0, 0, &bprm.inode, NULL);<br> if (retval) <br> return retval;<br> bprm.filename = filename; <br> bprm.sh_bang = 0;<br> bprm.loader = 0; <br> bprm.exec = 0; <br> bprm.dont_iput = 0;<br> if ((bprm.argc = count(argv)) < 0)<br> return bprm.argc;<br> if ((bprm.envc = count(envp)) < 0) <br> return bprm.envc;<br> retval = prepare_binprm(&bprm); <br> if(retval>=0) {<br> bprm.p = copy_strings(1,&bprm.filename, bprm.page, bprm.p, 2);<br> bprm.exec = bprm.p;<br> bprm.p = copy_strings(bprm.envc,envp,bprm.page, bprm.p,0);<br> </font><font FACE="宋体" size="4" COLOR="#007f7f">bprm.p = copy_strings(bprm.argc,argv,bprm.page, bprm.p,0);<br> if (!bprm.p) <br> retval = -E2BIG; <br> }<br> if(retval>=0)<br> retval = search_binary_handler(&bprm,regs);<br> if(retval>=0) /* execve success */<br> return retval;<br> /* Something went wrong, return the inode and free the argument pages*/<br> if(!bprm.dont_iput) <br> iput(bprm.inode);<br> for (i=0 ; i<MAX_ARG_PAGES ; i++)<br> free_page(bprm.page[i]); <br> return(retval);</font></strong><font FACE="宋体" size="3"></p> </font><font FACE="宋体" COLOR="#007f00" size="4"><p></font><font FACE="宋体" size="4"><font color="#008080"><strong>}</strong></font></p> </font><font FACE="宋体" SIZE="2" COLOR="#7f0000"><p></font><strong><font face="宋体" size="5" color="#000000"> </font><font face="宋体" color="#000000" size="4">如上面的原代码所示:sys_execve 的执行将会被转为函数 do_execve 的执行,此函数共需要 4 个参数:filename, argv,envp,regs.其中filename为所要执行程序的文件名,它必须是一个有效的用户可执行的程序文件,并使该可执行程序有正确的内容。<br> 程序中用到一个重要的数据结构:linux_binprm,此结构在 linux/include/linux/binfmts.h 中有定义如下:</font></strong><font FACE="宋体" SIZE="2" COLOR="#7f0000"></p> </font><p> <img src="dot2.jpg" alt="dot2.bmp (406 bytes)" WIDTH="10" HEIGHT="11"> <font color="#0080C0" face="宋体"><strong><em><big>linux_binprm 结构:</big><br> </em></strong></font><br> <font FACE="宋体" SIZE="2">/*This structure is used to hold the arguments that are used when loading binaries. */</font><br> <font FACE="宋体" size="3">struct linux_binprm{<br> char buf[128];<br> unsigned long page[MAX_ARG_PAGES];<br> unsigned long p;<br> int sh_bang;<br> struct inode * inode;<br> int e_uid, e_gid;<br> int argc, envc;<br> char * filename; /* Name of binary */<br> unsigned long loader, exec;<br> int dont_iput; /* binfmt handler has put inode */<br> };</font></p> <font FACE="宋体" SIZE="3" COLOR="#007f00"><p> </p> <p></font><font color="#000000"><font FACE="宋体" size="3">/*<br> </font><font FACE="宋体" SIZE="2">* </font><font FACE="宋体" size="3">MAX_ARG_PAGES 规定了设定或保存运行程序的参数和框架(或者叫“外壳”)而必 * 须得到的内存页的数量。32 个应该是足够的。<br> *</font><font FACE="宋体" SIZE="2">/<br> </font></font><font FACE="宋体" color="#000000" size="3">#define MAX_ARG_PAGES 32</font><font FACE="宋体" SIZE="2" COLOR="#007f00"></p> </font><font FACE="宋体" SIZE="3" COLOR="#007f00"><p><img src="dot2.jpg" alt="dot2.bmp (278 bytes)" WIDTH="10" HEIGHT="11"></font><em><strong><font FACE="宋体" SIZE="3" color="#0080FF"> </font><font FACE="宋体" color="#0080C0" size="4">pt_regs 结构:</font></strong></em><br> <font FACE="宋体" SIZE="3" COLOR="#007f00"><br> /* this info is in file linux/include/asm/ptrace.h */</font><br> <font FACE="宋体" SIZE="2">/* this struct defines the way the registers are stored on the <br> stack during a system call. */<br> <br> struct pt_regs {<br> long ebx;<br> long ecx;<br> long edx;<br> long esi;<br> long edi;<br> long ebp;<br> long eax;<br> unsigned short ds, __dsu;<br> unsigned short es, __esu;<br> unsigned short fs, __fsu;<br> unsigned short gs, __gsu;<br> long orig_eax; <br> long eip;<br> unsigned short cs, __csu;<br> long eflags;<br> long esp;<br> unsigned short ss, __ssu;<br> };</p> <p></font><font FACE="宋体" size="3"><img src="dot2.jpg" alt="dot2.bmp (278 bytes)" WIDTH="10" HEIGHT="11"> </font><font FACE="宋体" color="#0080C0" size="4"><em><strong>函数 open_namei():</strong></em></font><font FACE="宋体" size="3"></p> <p></font><font FACE="宋体" SIZE="2">/*this function is in file linux/fs/namei.c */</p> </font><blockquote> <font FACE="宋体" SIZE="2"><blockquote> <p><br> * open_namei()<br> *<br> * namei for open - this is in fact almost the whole open-routine.<br> *<br> * Note that the low bits of "flag" aren't the same as in the open<br> * system call - they are 00 - no permissions needed<br> * 01 - read permission needed<br> * 10 - write permission needed<br> * 11 - read/write permissions needed<br> * which is a lot more logical, and also allows the "no perm" needed<br> * for symlinks (where the permissions are checked later). */<br> int open_namei(const char * pathname, int flag, int mode, struct inode ** res_inode, struct inode * base)<br> {<br> <em>const char * basename;<br> int namelen,error;<br> struct inode * dir, *inode;<br> mode &= S_IALLUGO & ~current->fs->umask;<br> mode |= S_IFREG;<br> error = dir_namei(pathname, &namelen, &basename, base, &dir);<br> if (error)<br> return error;<br> if (!namelen) { /* special case: '/usr/' etc */<br> if (flag & 2) {<br> iput(dir);<br> return -EISDIR;<br> }<br> /* thanks to Paul Pluzhnikov for noticing this was missing.. */<br> if ((error = permission(dir,ACC_MODE(flag))) != 0) {<br> iput(dir);<br> return error; <br> }<br> *res_inode=dir;<br> return 0;<br> }<br> dir->i_count++; /* lookup eats the dir */<br> if (flag & O_CREAT) {<br> down(&dir->i_sem);<br> error = lookup(dir, basename, namelen, &inode);<br> if (!error) {<br> if (flag & O_EXCL) {<br>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -