{"id":594,"date":"2014-10-17T09:01:56","date_gmt":"2014-10-17T09:01:56","guid":{"rendered":"http:\/\/www.selinuxplus.com\/?p=594"},"modified":"2014-10-17T09:01:56","modified_gmt":"2014-10-17T09:01:56","slug":"%e7%94%b1bash%ef%bc%9acve-2014-6271-%e5%ad%a6%e4%b9%a0execve","status":"publish","type":"post","link":"http:\/\/www.selinuxplus.com\/?p=594","title":{"rendered":"\u7531bash\uff1acve-2014-6271 \u5b66\u4e60execve"},"content":{"rendered":"<p>\u6211\u4eec\u5148\u4e86\u89e3\u4e00\u4e0bexecve\uff1a<\/p>\n<pre class=\"lang:default decode:true\">int execve(const char * filename,char * const argv[ ],char * const envp[ ]);<\/pre>\n<p>\u51fd\u6570\u8bf4\u660e\uff1a<br \/>\nexecve()\u7528\u6765\u6267\u884c\u53c2\u6570filename\u5b57\u7b26\u4e32\u6240\u4ee3\u8868\u7684\u6587\u4ef6\u8def\u5f84\uff0c\u7b2c\u4e8c\u4e2a\u53c2\u6570\u7cfb\u5229\u7528\u6570\u7ec4\u6307\u9488\u6765\u4f20\u9012\u7ed9\u6267\u884c\u6587\u4ef6\uff0c\u6700\u540e\u4e00\u4e2a\u53c2\u6570\u5219\u4e3a\u4f20\u9012\u7ed9\u6267\u884c\u6587\u4ef6\u7684\u65b0\u73af\u5883\u53d8\u91cf\u6570\u7ec4\u3002<br \/>\n\u8fd4\u56de\u503c\uff1a<br \/>\n\u5982\u679c\u6267\u884c\u6210\u529f\u5219\u51fd\u6570\u4e0d\u4f1a\u8fd4\u56de\uff0c\u6267\u884c\u5931\u8d25\u5219\u76f4\u63a5\u8fd4\u56de-1\uff0c\u5931\u8d25\u539f\u56e0\u5b58\u4e8eerrno \u4e2d\u3002<br \/>\n\u8fd9\u4e2a\u4ee3\u7801\u4f1a\u6267\u884c\/bin\/sh \u4f7f\u7528\u53c2\u6570-c \u548c env \u3002 \u5728\u5f53\u524d\u7684\u73af\u5883PATH\u4e2d\uff0c\u8fd0\u884cenv\u73af\u5883\u7684\u7a0b\u5e8f\uff0c\u8be5\u73af\u5883\u53d8\u91cf\u5305\u542b\u4e865\u4e2avalues\u3002\u6267\u884c\u540e\u7684 \u7ed3\u679c\u4e3a\uff1a<\/p>\n<pre class=\"lang:default decode:true\">[test@localhost execve-test]$ .\/execve-test \r\nUSER=test\r\nPATH=\/bin:\/usr\/bin\r\nPWD=\/home\/test\/execve-test\r\nTZ=UTC0\r\nSHLVL=1\r\nHOME=\/\r\nLOGNAME=qfong\r\n_=\/bin\/env<\/pre>\n<p>\u8be5\u6bb5\u4e5f\u5305\u542b\u4e86\u201d_\u201d,\u201dSHLVL\u201d,\u201dPWD\u201d\u73af\u5883\u53d8\u91cf\u3002<br \/>\n\u6211\u4eec\u8c03\u8bd5\u4e00\u4e0b\u8be5\u7a0b\u5e8f\u8fd0\u884c\u7684\u4fe1\u606f<\/p>\n<pre class=\"lang:default decode:true\">[root@localhost execve]# cat test.c \r\n#include &lt;unistd.h&gt;\r\n#include &lt;stdio.h&gt;\r\n\r\nint main()\r\n{\r\n\r\n    char *envp[] = {\r\n    \"PATH=\/bin:\/usr\/bin\",\r\n    \"\/usr\/bin\/id=() { \"\r\n    \"echo pwn me twice,shame on me; }; \"\r\n    \"echo pwn me once,shame on you\",\r\n    NULL\r\n    };\r\n    char *argv[] = {\"\/bin\/bash\",NULL};\r\n\r\n    execve(argv[0],argv,envp);\r\n    perror(\"execve\");\r\nreturn 1\r\n}<\/pre>\n<p>\u6d4b\u8bd5\uff1a<\/p>\n<pre class=\"lang:default decode:true\">[root@localhost execve]# .\/a.out \r\npwn me once,shame on you\r\nbash: [: pwn me twice,shame on me: integer expression expected\r\n[root@localhost execve]# \/usr\/bin\/id\r\npwn me twice,shame on me<\/pre>\n<p>\u4f7f\u7528gdb\u8fdb\u884c\u5206\u6790\u4e00\u4e0b<\/p>\n<pre class=\"lang:default decode:true\">[test@localhost execve-test]$ gcc -static -o execve-test-static execve-test.c -O2 \r\n\/bin\/ld: cannot find -lc\r\ncollect2: error: ld returned 1 exit status\r\n\r\n(gdb) disassemble main\r\nDump of assembler code for function main:\r\n   0x0000000000400a60 &lt;+0&gt;:     sub    $0x58,%rsp\r\n   0x0000000000400a64 &lt;+4&gt;:     mov    $0x48e9b0,%edi\r\n   0x0000000000400a69 &lt;+9&gt;:     lea    0x20(%rsp),%rdx\r\n   0x0000000000400a6e &lt;+14&gt;:    mov    %rsp,%rsi\r\n   0x0000000000400a71 &lt;+17&gt;:    movq   $0x48e9b0,(%rsp)\r\n   0x0000000000400a79 &lt;+25&gt;:    movq   $0x48e9b8,0x8(%rsp)\r\n   0x0000000000400a82 &lt;+34&gt;:    movq   $0x48e9bb,0x10(%rsp)\r\n   0x0000000000400a8b &lt;+43&gt;:    movq   $0x0,0x18(%rsp)\r\n   0x0000000000400a94 &lt;+52&gt;:    movq   $0x48e9bf,0x20(%rsp)\r\n   0x0000000000400a9d &lt;+61&gt;:    movq   $0x48e9c6,0x28(%rsp)\r\n   0x0000000000400aa6 &lt;+70&gt;:    movq   $0x48e9d9,0x30(%rsp)\r\n   0x0000000000400aaf &lt;+79&gt;:    movq   $0x48e9e1,0x38(%rsp)\r\n   0x0000000000400ab8 &lt;+88&gt;:    movq   $0x48e9eb,0x40(%rsp)\r\n   0x0000000000400ac1 &lt;+97&gt;:    movq   $0x0,0x48(%rsp)\r\n   0x0000000000400aca &lt;+106&gt;:   callq  0x40ee50 &lt;execve&gt;\r\n   0x0000000000400acf &lt;+111&gt;:   mov    0x2b75ca(%rip),%rcx        # 0x6b80a0 &lt;stderr&gt;\r\n   0x0000000000400ad6 &lt;+118&gt;:   mov    $0x6,%edx\r\n   0x0000000000400adb &lt;+123&gt;:   mov    $0x1,%esi\r\n   0x0000000000400ae0 &lt;+128&gt;:   mov    $0x48e9f9,%edi\r\n   0x0000000000400ae5 &lt;+133&gt;:   callq  0x401820 &lt;fwrite&gt;\r\n   0x0000000000400aea &lt;+138&gt;:   mov    $0xffffffff,%eax\r\n   0x0000000000400aef &lt;+143&gt;:   add    $0x58,%rsp\r\n   0x0000000000400af3 &lt;+147&gt;:   retq   \r\nEnd of assembler dump.\r\n(gdb)\r\n(gdb) printf \"%s\\n\", 0x48e9b0\r\n\/bin\/sh\r\n(gdb) printf \"%s\\n\", 0x48e9b8\r\n-c\r\n(gdb) printf \"%s\\n\", 0x48e9bb\r\nenv\r\n(gdb) printf \"%s\\n\", 0x48e9bf\r\nHOME=\/\r\n(gdb) printf \"%s\\n\", 0x48e9c6\r\nPATH=\/bin:\/usr\/bin\r\n(gdb) printf \"%s\\n\", 0x48e9d9\r\nTZ=UTC0\r\n(gdb) printf \"%s\\n\", 0x48e9e1\r\nUSER=test\r\n(gdb) printf \"%s\\n\", 0x48e9eb\r\nLOGNAME=qfong\r\n(gdb) disassemble 0x40ee50\r\nDump of assembler code for function execve:\r\n   0x000000000040ee50 &lt;+0&gt;:     mov    $0x3b,%eax \/\/0x3b\u4e2d\u65ad\u8c03\u7528\u53f7\r\n   0x000000000040ee55 &lt;+5&gt;:     syscall \r\n   0x000000000040ee57 &lt;+7&gt;:     cmp    $0xfffffffffffff000,%rax\r\n   0x000000000040ee5d &lt;+13&gt;:    ja     0x40ee61 &lt;execve+17&gt;\r\n   0x000000000040ee5f &lt;+15&gt;:    repz retq \r\n   0x000000000040ee61 &lt;+17&gt;:    mov    $0xffffffffffffffc0,%rdx\r\n   0x000000000040ee68 &lt;+24&gt;:    neg    %eax\r\n   0x000000000040ee6a &lt;+26&gt;:    mov    %eax,%fs:(%rdx)\r\n   0x000000000040ee6d &lt;+29&gt;:    or     $0xffffffffffffffff,%rax\r\n   0x000000000040ee71 &lt;+33&gt;:    retq   \r\nEnd of assembler dump.<\/pre>\n<pre class=\"lang:default decode:true\">\t0x48\t0\r\n\t0x40\tLOGNAME=qfong\r\n\t0x38\tUSER=test\r\n\t0x30\tTZ=UTC0\r\n\t0x28\tPATH=\/bin:\/usr\/bin\r\n\t0x20\tHOME=\/\r\n\t0x18\t0\r\n\t0x10\tenv\r\n\t0x8\t-c\r\n%rsp\t0x4006e0\t\/bin\/sh<\/pre>\n<p>Execve\uff08\uff09\u9700\u8981\u5404\u79cd\u53c2\u6570<br \/>\n\u5c06\u6570\u636e\u5b58\u653e\u5728\u5806\u6808\u4e2d\uff0c\u8868\u793a\u8981\u6267\u884c\u7684\u547d\u4ee4\/bin\/sh\u57280x0.\u4f9d\u6b21\u5c06\u53c2\u6570\u5b58\u5165\u5806\u6808\u4e2d\u3002\u7b2c\u4e00\u4e2a\u53c2\u6570\u5fc5\u987b\u662f\u8be5\u7a0b\u5e8f\u7684\u540d\u5b57mov $0x48e9b0,%edi\u3002Edi\u4e3a\u7b2c\u4e00\u53c2\u6570\u5bc4\u5b58\u5668\u3002Rsi\u6307\u5411\u7b2c\u4e8c\u5bc4\u5b58\u5668\u3002<br \/>\n\u5728execve\u6267\u884c\u7a0b\u5e8f\u65f6\uff0c\u6211\u4eec\u9700\u8981\/bin\/sh\u7684\u5b57\u7b26\u4e32\uff0c\u4e00\u4e2a\u6307\u9488\u6307\u5411\u8fd9\u4e2a\u5b57\u7b26\u4e32\uff0c\u548c\u4e00\u4e2a\u6307\u5411\u53c2\u6570\u7684\u6307\u9488\u3002\u6211\u4eec\u53ef\u4ee5\u770b\u5230execve\uff08\uff09\u8c03\u7528\u4e4b\u524d\u7684\u6570\u636e\u8868\u793a\uff0c\u4e00\u4e2a\u6307\u5411\/bin\/sh\u5b57\u7b26\u4e32\u540e\u8ddf\u4e00\u4e2a\u6307\u5411\u53c2\u6570\u7684\u6307\u9488\u6570\u7ec4\uff08\u5806\u6808\u6240\u5728\u7684rsi\u5bc4\u5b58\u5668\uff09\uff0c\u5176\u4ed6\u7684ecx\u548cedx\u5206\u522b\u4e3a\u7b2c\u4e09\u7b2c\u56db\u53c2\u6570\u5bc4\u5b58\u5668\u3002<\/p>\n<p>Execve(name[0],name, envp))<br \/>\nExecve \u662f\u600e\u4e48\u6267\u884c\u7684\u5462\uff1f\u6211\u4eec\u770b\u4e00\u4e0b\u5185\u6838\u91cc\u9762\u7684\u4ee3\u7801\u5b9e\u73b0<\/p>\n<p><a href=\"http:\/\/www.selinuxplus.com\/wp-content\/uploads\/2014\/10\/execve.png\"><img loading=\"lazy\" class=\"aligncenter size-full wp-image-595\" alt=\"execve\" src=\"http:\/\/www.selinuxplus.com\/wp-content\/uploads\/2014\/10\/execve.png\" width=\"828\" height=\"652\" srcset=\"http:\/\/www.selinuxplus.com\/wp-content\/uploads\/2014\/10\/execve.png 828w, http:\/\/www.selinuxplus.com\/wp-content\/uploads\/2014\/10\/execve-300x236.png 300w\" sizes=\"(max-width: 828px) 100vw, 828px\" \/><\/a><br \/>\n\u7ecf\u8fc7\u4e86<\/p>\n<pre class=\"lang:default decode:true \" >sys_execve()  \u2192  do_execve()  \u2192 do_execve_common() \r\n versus compat_sys_execve() \u2192  compat_do_execve() \u2192  do_execve_common() \u8fd9\u4e2a\u8fc7\u7a0b\u3002<\/pre>\n<p>\u53ef\u4ee5\u5206\u6790\u5185\u6838\u7684\u4e00\u6bb5\u4ee3\u7801\uff1a<\/p>\n<pre class=\"lang:default decode:true \" >Fs\/exec.c\r\n1674 SYSCALL_DEFINE3(execve,\r\n1675 \u25b8       \u25b8       const char __user *, filename,\r\n1676 \u25b8       \u25b8       const char __user *const __user *, argv,\r\n1677 \u25b8       \u25b8       const char __user *const __user *, envp)\r\n1678 {\r\n1679 \u25b8       struct filename *path = getname(filename); \/\/\u5c06\u4e00\u4e2a\u53ef\u6267\u884c\u6587\u4ef6\u7684\u540d\u79f0\u88c5\u5165\u5230\u4e00\u4e2a\u65b0\u5206\u914d\u7684\u9875\u9762\u4e2d\u3002\r\n1680 \u25b8       int error = PTR_ERR(path);\r\n1681 \u25b8       if (!IS_ERR(path)) {\r\n1682 \u25b8       \u25b8       error = do_execve(path-&gt;name, argv, envp); \/\/\u6267\u884c\u53ef\u6267\u884c\u6587\u4ef6\r\n1683 \u25b8       \u25b8       putname(path);\r\n1684 \u25b8       }\r\n1685 \u25b8       return error;\r\n1686 }\r\n\u5728\u8fd9\u91cc1674-1677\u8fd9\u6bb5\u4ee3\u7801\u7684SYSCALL_DEFINE3(execve,filename,argv.envp)\u7b49\u540c\u4e8e\uff1a\r\n= SYSCALL_DEFINEx(3,## execve,__VA_ARGS)\r\n= asmlinkage long sys_execve(SC_DECL,(_VA_ARGS__))\u2026\r\n= asmlinkage long sys_execve(filename,argv.envp)\r\n\u53c2\u7167include\/linux\/syscalls.h\r\n176 #define SYSCALL_DEFINE3(name, ...) SYSCALL_DEFINEx(3, _##name, __VA_ARGS__)\r\n\r\n186 #define __SYSCALL_DEFINEx(x, name, ...)\u25b8\u25b8       \u25b8       \u25b8       \u25b8       \\\r\n187 \u25b8       asmlinkage long sys##name(__MAP(x,__SC_DECL,__VA_ARGS__));\u25b8     \\\r\n188 \u25b8       static inline long SYSC##name(__MAP(x,__SC_DECL,__VA_ARGS__));\u25b8 \\\r\n189 \u25b8       asmlinkage long SyS##name(__MAP(x,__SC_LONG,__VA_ARGS__))\u25b8      \\\r\n190 \u25b8       {\u25b8      \u25b8       \u25b8       \u25b8       \u25b8       \u25b8       \u25b8       \u25b8       \\\r\n191 \u25b8       \u25b8       long ret = SYSC##name(__MAP(x,__SC_CAST,__VA_ARGS__));\u25b8 \\\r\n192 \u25b8       \u25b8       __MAP(x,__SC_TEST,__VA_ARGS__);\u25b8\u25b8       \u25b8       \u25b8       \\\r\n193 \u25b8       \u25b8       __PROTECT(x, ret,__MAP(x,__SC_ARGS,__VA_ARGS__));\u25b8      \\\r\n194 \u25b8       \u25b8       return ret;\u25b8    \u25b8       \u25b8       \u25b8       \u25b8       \u25b8       \\\r\n195 \u25b8       }\u25b8      \u25b8       \u25b8       \u25b8       \u25b8       \u25b8       \u25b8       \u25b8       \\\r\n196 \u25b8       SYSCALL_ALIAS(sys##name, SyS##name);\u25b8   \u25b8       \u25b8       \u25b8       \\\r\n197 \u25b8       static inline long SYSC##name(__MAP(x,__SC_DECL,__VA_ARGS__))\r\n198\r\n=&gt;\r\n99 #define __SC_DECL(t, a)\u25b8t a\r\n\r\n\r\ndo_execve code:\r\n1580 int do_execve(const char *filename,\r\n1581 \u25b8       const char __user *const __user *__argv,\r\n1582 \u25b8       const char __user *const __user *__envp)\r\n1583 {\r\n1584 \u25b8       struct user_arg_ptr argv = { .ptr.native = __argv }; \/\/\u5c01\u88c5\u7ed3\u6784\r\n1585 \u25b8       struct user_arg_ptr envp = { .ptr.native = __envp }; \r\n1586 \u25b8       return do_execve_common(filename, argv, envp); \/\/\u8c03\u7528do_execve_common\r\n1587 }\r\n1588\r\n\r\n\r\n1450 \/*\r\n1451  * sys_execve() executes a new program.\r\n1452  *\/\r\n1453 static int do_execve_common(const char *filename,\r\n1454 \u25b8       \u25b8       \u25b8       \u25b8       struct user_arg_ptr argv,\r\n1455 \u25b8       \u25b8       \u25b8       \u25b8       struct user_arg_ptr envp)\r\n1456 {\r\n1457 \u25b8       struct linux_binprm *bprm; \/\/\u4fdd\u5b58\u548c\u8981\u6267\u884c\u7684\u6587\u4ef6\u76f8\u5173\u6570\u636e\r\n1458 \u25b8       struct file *file;\r\n1459 \u25b8       struct files_struct *displaced;\r\n1460 \u25b8       bool clear_in_exec;\r\n1461 \u25b8       int retval;\r\n1462 \u25b8       const struct cred *cred = current_cred();\r\n1463 \r\n1464 \u25b8       \/*\r\n1465 \u25b8        * We move the actual failure in case of RLIMIT_NPROC excess from\r\n1466 \u25b8        * set*uid() to execve() because too many poorly written programs\r\n1467 \u25b8        * don't check setuid() return code.  Here we additionally recheck\r\n1468 \u25b8        * whether NPROC limit is still exceeded.\r\n1469 \u25b8        *\/\r\n1470 \u25b8       if ((current-&gt;flags &amp; PF_NPROC_EXCEEDED) &amp;&amp;\r\n1471 \u25b8           atomic_read(&amp;cred-&gt;user-&gt;processes) &gt; rlimit(RLIMIT_NPROC)) {\r\n1472 \u25b8       \u25b8       retval = -EAGAIN;\r\n1473 \u25b8       \u25b8       goto out_ret;\r\n1474 \u25b8       }\r\n1475 \r\n1476 \u25b8       \/* We're below the limit (still or again), so we don't want to make\r\n1477 \u25b8        * further execve() calls fail. *\/\r\n1478 \u25b8       current-&gt;flags &amp;= ~PF_NPROC_EXCEEDED;\r\n1479 \r\n1480 \u25b8       retval = unshare_files(&amp;displaced);\r\n1481 \u25b8       if (retval)\r\n1482 \u25b8       \u25b8       goto out_ret;\r\n1483 \r\n1484 \u25b8       retval = -ENOMEM;\r\n1485 \u25b8       bprm = kzalloc(sizeof(*bprm), GFP_KERNEL); \/\/\u5728\u5806\u4e0a\u5206\u914d\u4e00\u4e2alinux_binprm\u7ed3\u6784\r\n1486 \u25b8       if (!bprm)\r\n1487 \u25b8       \u25b8       goto out_files;\r\n1488 \r\n1489 \u25b8       retval = prepare_bprm_creds(bprm);\r\n1490 \u25b8       if (retval)\r\n1491 \u25b8       \u25b8       goto out_free;\r\n1492 \r\n1493 \u25b8       retval = check_unsafe_exec(bprm);\r\n1494 \u25b8       if (retval &lt; 0)\r\n1495 \u25b8       \u25b8       goto out_free;\r\n1496 \u25b8       clear_in_exec = retval;\r\n1497 \u25b8       current-&gt;in_execve = 1;\r\n1498 \r\n1499 \u25b8       file = open_exec(filename); \/\/\u8c03\u7528open_exec \u8bfb\u53d6\u53ef\u6267\u884c\u6587\u4ef6\r\n1500 \u25b8       retval = PTR_ERR(file);\r\n1501 \u25b8       if (IS_ERR(file))\r\n1502 \u25b8       \u25b8       goto out_unmark;\r\n1503 \r\n1504 \u25b8       sched_exec(); \/\/\u9009\u62e9\u786e\u5b9a\u6700\u5c0f\u8d1f\u8f7d\u7684cpu\u6267\u884c\uff0c\u5e76\u628a\u5f53\u524dprocess\u8f6c\u79fb\u8fc7\u53bb \r\n1506 \u25b8       bprm-&gt;file = file; \r\n1507 \u25b8       bprm-&gt;filename = filename;\r\n1508 \u25b8       bprm-&gt;interp = filename;\r\n1509 \r\n1510 \u25b8       retval = bprm_mm_init(bprm); \/\/\u8c03\u7528bprm_mm_init \u4e3a\u65b0\u7a0b\u5e8f\u521d\u59cb\u5316\u5185\u5b58\r\n1511 \u25b8       if (retval)\r\n1512 \u25b8       \u25b8       goto out_file;\r\n1513 \r\n1514 \u25b8       bprm-&gt;argc = count(argv, MAX_ARG_STRINGS);\r\n1515 \u25b8       if ((retval = bprm-&gt;argc) &lt; 0)\r\n1516 \u25b8       \u25b8       goto out;\r\n1517 \r\n1518 \u25b8       bprm-&gt;envc = count(envp, MAX_ARG_STRINGS);\r\n1519 \u25b8       if ((retval = bprm-&gt;envc) &lt; 0)\r\n1520 \u25b8       \u25b8       goto out;\r\n1521 \r\n1522 \u25b8       retval = prepare_binprm(bprm); \u586b\u5145bprm\u7ed3\u6784\r\n1523 \u25b8       if (retval &lt; 0)\r\n1524 \u25b8       \u25b8       goto out;\r\n1525 \r\n1526 \u25b8       retval = copy_strings_kernel(1, &amp;bprm-&gt;filename, bprm); \/\/\u62f7\u8d1dfilename\u5230\u65b0\u8fdb\u7a0b\u4e2d\r\n1527 \u25b8       if (retval &lt; 0)\r\n1528 \u25b8       \u25b8       goto out;\r\n1529 \r\n1530 \u25b8       bprm-&gt;exec = bprm-&gt;p;\r\n1531 \u25b8       retval = copy_strings(bprm-&gt;envc, envp, bprm); \/\/\u62f7\u8d1d\u73af\u5883\u53d8\u91cfenvp\u5230\u65b0\u8fdb\u7a0b\u4e2d\r\n\r\n1532 \u25b8       if (retval &lt; 0)\r\n1533 \u25b8       \u25b8       goto out;\r\n1534\r\n1535 \u25b8       retval = copy_strings(bprm-&gt;argc, argv, bprm); \/\/\u62f7\u8d1d\u53c2\u6570argv\u5230\u65b0\u8fdb\u7a0b\u4e2d\r\n1536 \u25b8       if (retval &lt; 0)\r\n1537 \u25b8       \u25b8       goto out;\r\n1538 \r\n1539 \u25b8       retval = search_binary_handler(bprm); \/\/\u8be5\u51fd\u6570\u5f0f\u5bf9formats\u94fe\u8868\u8fdb\u884c\u626b\u63cf\uff0c\u5e76\u5c1d\u8bd5\u6bcf\u4e2aload_binary\u51fd\u6570\uff0c\u5982\u679c\u6210\u529f\u52a0\u8f7d\u4e86\u6587\u4ef6\u7684\u6267\u884c\u683c\u5f0f\uff0c\u5bf9formats\u7684\u626b\u63cf\u7ec8\u6b62\r\n1540 \u25b8       if (retval &lt; 0)\r\n1541 \u25b8       \u25b8       goto out;\r\n1542 \r\n1543 \u25b8       \/* execve succeeded *\/\r\n1544 \u25b8       current-&gt;fs-&gt;in_exec = 0;\r\n1545 \u25b8       current-&gt;in_execve = 0;\r\n1546 \u25b8       acct_update_integrals(current);\r\n1547 \u25b8       task_numa_free(current);\r\n1548 \u25b8       free_bprm(bprm); \/\/\u91ca\u653ebprm \u7ed3\u6784\r\n1549 \u25b8       if (displaced)\r\n1550 \u25b8       \u25b8       put_files_struct(displaced);\r\n1551 \u25b8       return retval;\r\n1552 \r\n1553 out:\r\n1554 \u25b8       if (bprm-&gt;mm) {\r\n1555 \u25b8       \u25b8       acct_arg_size(bprm, 0);\r\n1556 \u25b8       \u25b8       mmput(bprm-&gt;mm);\r\n1557 \u25b8       }\r\n1558 \r\n1559 out_file:\r\n1560 \u25b8       if (bprm-&gt;file) {\r\n1561 \u25b8       \u25b8       allow_write_access(bprm-&gt;file);\r\n1562 \u25b8       \u25b8       fput(bprm-&gt;file);\r\n1563 \u25b8       }\r\n1564 \r\n1565 out_unmark:\r\n1566 \u25b8       if (clear_in_exec)\r\n1567 \u25b8       \u25b8       current-&gt;fs-&gt;in_exec = 0;\r\n1568 \u25b8       current-&gt;in_execve = 0;\r\n1569 \r\n1570 out_free:\r\n1571 \u25b8       free_bprm(bprm);\r\n1572 \r\n1573 out_files:\r\n1574 \u25b8       if (displaced)\r\n1575 \u25b8       \u25b8       reset_files_struct(displaced);\r\n1576 out_ret:\r\n1577 \u25b8       return retval;\r\n1578 }\r\n1579\r\n\r\nload_elf_binary\u51fd\u6570\uff0c\u8be5\u51fd\u6570\u4f4d\u4e8efs\/binfmt_elf.c\u4e2d\r\n569 static int load_elf_binary(struct linux_binprm *bprm)\r\n 570 {\r\n 571 \u25b8       struct file *interpreter = NULL; \/* to shut gcc up *\/\r\n 572  \u25b8      unsigned long load_addr = 0, load_bias = 0;\r\n 573 \u25b8       int load_addr_set = 0;\r\n 574 \u25b8       char * elf_interpreter = NULL;\r\n 575 \u25b8       unsigned long error;\r\n 576 \u25b8       struct elf_phdr *elf_ppnt, *elf_phdata;\r\n 577 \u25b8       unsigned long elf_bss, elf_brk;\r\n 578 \u25b8       int retval, i;\r\n 579 \u25b8       unsigned int size;\r\n 580 \u25b8       unsigned long elf_entry;\r\n 581 \u25b8       unsigned long interp_load_addr = 0;\r\n 582 \u25b8       unsigned long start_code, end_code, start_data, end_data;\r\n 583 \u25b8       unsigned long reloc_func_desc __maybe_unused = 0;\r\n 584 \u25b8       int executable_stack = EXSTACK_DEFAULT;\r\n 585 \u25b8       unsigned long def_flags = 0;\r\n 586 \u25b8       struct pt_regs *regs = current_pt_regs();\r\n 587 \u25b8       struct {\r\n 588 \u25b8       \u25b8       struct elfhdr elf_ex;\r\n 589 \u25b8       \u25b8       struct elfhdr interp_elf_ex;\r\n 590 \u25b8       } *loc;\r\n 591 \r\n 592 \u25b8       loc = kmalloc(sizeof(*loc), GFP_KERNEL);\r\n 593 \u25b8       if (!loc) {\r\n 594 \u25b8       \u25b8       retval = -ENOMEM;\r\n 595 \u25b8       \u25b8       goto out_ret;\r\n 596 \u25b8       }\r\n 597 \u25b8       \r\n 598 \u25b8       \/* Get the exec-header *\/\r\n             \/\/\u8bfb\u53d6\u53ef\u6267\u884c\u6587\u4ef6\u7684\u9996\u90e8\uff0c\u9996\u90e8\u63cf\u8ff0\u7a0b\u5e8f\u7684\u6bb5\u548c\u6240\u9700 \u7684\u5171\u4eab\u5e93\r\n 599 \u25b8       loc-&gt;elf_ex = *((struct elfhdr *)bprm-&gt;buf);\r\n 600\r\n600 \r\n 601 \u25b8       retval = -ENOEXEC;\r\n 602 \u25b8       \/* First of all, some simple consistency checks *\/ \r\n             \/\/\u4e00\u81f4\u6027\u68c0\u6d4b\r\n 603 \u25b8       if (memcmp(loc-&gt;elf_ex.e_ident, ELFMAG, SELFMAG) != 0)\r\n 604 \u25b8       \u25b8       goto out;\r\n 605 \r\n 606 \u25b8       if (loc-&gt;elf_ex.e_type != ET_EXEC &amp;&amp; loc-&gt;elf_ex.e_type != ET_DYN)\r\n 607 \u25b8       \u25b8       goto out;\r\n 608 \u25b8       if (!elf_check_arch(&amp;loc-&gt;elf_ex))\r\n 609 \u25b8       \u25b8       goto out;\r\n 610 \u25b8       if (!bprm-&gt;file-&gt;f_op || !bprm-&gt;file-&gt;f_op-&gt;mmap)\r\n 611 \u25b8       \u25b8       goto out;\r\n 612 \r\n 613 \u25b8       \/* Now read in all of the header information *\/\r\n              \/\/\u8bfb\u53d6\u6240\u6709\u7684\u9996\u90e8\u4fe1\u606f\r\n 614 \u25b8       if (loc-&gt;elf_ex.e_phentsize != sizeof(struct elf_phdr))\r\n 615 \u25b8       \u25b8       goto out;\r\n 616 \u25b8       if (loc-&gt;elf_ex.e_phnum &lt; 1 ||\r\n 617 \u25b8        \u25b8      loc-&gt;elf_ex.e_phnum &gt; 65536U \/ sizeof(struct elf_phdr))\r\n 618 \u25b8       \u25b8       goto out;\r\n 619 \u25b8       size = loc-&gt;elf_ex.e_phnum * sizeof(struct elf_phdr);\r\n 620 \u25b8       retval = -ENOMEM;\r\n 621 \u25b8       elf_phdata = kmalloc(size, GFP_KERNEL);\r\n 622 \u25b8       if (!elf_phdata)\r\n 623 \u25b8       \u25b8       goto out;\r\n 624 \r\n 625 \u25b8       retval = kernel_read(bprm-&gt;file, loc-&gt;elf_ex.e_phoff,\r\n 626 \u25b8       \u25b8       \u25b8            (char *)elf_phdata, size);\r\n 627 \u25b8       if (retval != size) {\r\n 628 \u25b8       \u25b8       if (retval &gt;= 0)\r\n 629 \u25b8       \u25b8       \u25b8       retval = -EIO;\r\n 630 \u25b8       \u25b8       goto out_free_ph;\r\n 631 \u25b8       }\r\n632 \r\n 633 \u25b8       elf_ppnt = elf_phdata;\r\n 634 \u25b8       elf_bss = 0;\r\n 635 \u25b8       elf_brk = 0;\r\n 636 \r\n 637 \u25b8       start_code = ~0UL;\r\n 638 \u25b8       end_code = 0;\r\n 639 \u25b8       start_data = 0;\r\n 640 \u25b8       end_data = 0;\r\n 641         \/\/\u4ece\u53ef\u6267\u884c\u6587\u4ef6\u4e2d\u786e\u5b9a\u52a8\u6001\u94fe\u63a5\u7a0b\u5e8f\u7684\u8def\u5f84\u540d\u3002\u5e76\u7528\u5b83\u6765\u786e\u5b9a\u5171\u4eab\u5e93\u7684\u4f4d\u7f6e\uff0c\u5e76\u628a\u4ed6\u4eec\u6620\u5c04\u5230\u5185\u5b58\u3002\r\n 642 \u25b8       for (i = 0; i &lt; loc-&gt;elf_ex.e_phnum; i++) {\r\n 643 \u25b8       \u25b8       if (elf_ppnt-&gt;p_type == PT_INTERP) {\r\n 644 \u25b8       \u25b8       \u25b8       \/* This is the program interpreter used for\r\n 645 \u25b8       \u25b8       \u25b8        * shared libraries - for now assume that this\r\n 646 \u25b8       \u25b8       \u25b8        * is an a.out format binary\r\n 647 \u25b8       \u25b8       \u25b8        *\/\r\n 648 \u25b8       \u25b8       \u25b8       retval = -ENOEXEC;\r\n 649 \u25b8       \u25b8       \u25b8       if (elf_ppnt-&gt;p_filesz &gt; PATH_MAX ||\u25ab\r\n 650 \u25b8       \u25b8       \u25b8           elf_ppnt-&gt;p_filesz &lt; 2)\r\n 651 \u25b8       \u25b8       \u25b8       \u25b8       goto out_free_ph;\r\n 652 \r\n 653 \u25b8       \u25b8       \u25b8       retval = -ENOMEM;\r\n 654 \u25b8       \u25b8       \u25b8       elf_interpreter = kmalloc(elf_ppnt-&gt;p_filesz,\r\n 655 \u25b8       \u25b8       \u25b8       \u25b8       \u25b8       \u25b8         GFP_KERNEL);\r\n 656 \u25b8       \u25b8       \u25b8       if (!elf_interpreter)\r\n 657 \u25b8       \u25b8       \u25b8       \u25b8       goto out_free_ph;\r\n 658 \r\n 659 \u25b8       \u25b8       \u25b8       retval = kernel_read(bprm-&gt;file, elf_ppnt-&gt;p_offset,\r\n 660 \u25b8       \u25b8       \u25b8       \u25b8       \u25b8            elf_interpreter,\r\n 661 \u25b8       \u25b8       \u25b8       \u25b8       \u25b8            elf_ppnt-&gt;p_filesz);\r\n 662 \u25b8       \u25b8       \u25b8       if (retval != elf_ppnt-&gt;p_filesz) {\r\n 663 \u25b8       \u25b8       \u25b8       \u25b8       if (retval &gt;= 0)\r\n 664 \u25b8       \u25b8       \u25b8       \u25b8       \u25b8       retval = -EIO;\r\n 665 \u25b8       \u25b8       \u25b8       \u25b8       goto out_free_interp;\r\n 666 \u25b8       \u25b8       \u25b8       }\r\n667 \u25b8       \u25b8       \u25b8       \/* make sure path is NULL terminated *\/\r\n 668 \u25b8       \u25b8       \u25b8       retval = -ENOEXEC;\r\n 669 \u25b8       \u25b8       \u25b8       if (elf_interpreter[elf_ppnt-&gt;p_filesz - 1] != '\\0')\r\n 670 \u25b8       \u25b8       \u25b8       \u25b8       goto out_free_interp;\r\n 671 \r\n 672 \u25b8       \u25b8       \u25b8       interpreter = open_exec(elf_interpreter);\r\n 673 \u25b8       \u25b8       \u25b8       retval = PTR_ERR(interpreter);\r\n 674 \u25b8       \u25b8       \u25b8       if (IS_ERR(interpreter))\r\n 675 \u25b8       \u25b8       \u25b8       \u25b8       goto out_free_interp;\r\n 676 \r\n 677 \u25b8       \u25b8       \u25b8       \/*\r\n 678 \u25b8       \u25b8       \u25b8        * If the binary is not readable then enforce\r\n 679 \u25b8       \u25b8       \u25b8        * mm-&gt;dumpable = 0 regardless of the interpreter's\r\n 680 \u25b8       \u25b8       \u25b8        * permissions.\r\n 681 \u25b8       \u25b8       \u25b8        *\/\r\n 682 \u25b8       \u25b8       \u25b8       would_dump(bprm, interpreter);\r\n 683 \r\n 684 \u25b8       \u25b8       \u25b8       retval = kernel_read(interpreter, 0, bprm-&gt;buf,\r\n 685 \u25b8       \u25b8       \u25b8       \u25b8       \u25b8            BINPRM_BUF_SIZE);\r\n 686 \u25b8       \u25b8       \u25b8       if (retval != BINPRM_BUF_SIZE) {\r\n 687 \u25b8       \u25b8       \u25b8       \u25b8       if (retval &gt;= 0)\r\n 688 \u25b8       \u25b8       \u25b8       \u25b8       \u25b8       retval = -EIO;\r\n 689 \u25b8       \u25b8       \u25b8       \u25b8       goto out_free_dentry;\r\n 690 \u25b8       \u25b8       \u25b8       }\r\n 691 \r\n 692 \u25b8       \u25b8       \u25b8       \/* Get the exec headers *\/\r\n 693 \u25b8       \u25b8       \u25b8       loc-&gt;interp_elf_ex = *((struct elfhdr *)bprm-&gt;buf);\r\n 694 \u25b8       \u25b8       \u25b8       break;\r\n 695 \u25b8       \u25b8       }\r\n 696 \u25b8       \u25b8       elf_ppnt++;\r\n 697 \u25b8       }\r\n698 \r\n 699 \u25b8       elf_ppnt = elf_phdata;\r\n 700 \u25b8       for (i = 0; i &lt; loc-&gt;elf_ex.e_phnum; i++, elf_ppnt++)\r\n 701 \u25b8       \u25b8       if (elf_ppnt-&gt;p_type == PT_GNU_STACK) {\r\n 702 \u25b8       \u25b8       \u25b8       if (elf_ppnt-&gt;p_flags &amp; PF_X)\r\n 703 \u25b8       \u25b8       \u25b8       \u25b8       executable_stack = EXSTACK_ENABLE_X;\r\n 704 \u25b8       \u25b8       \u25b8       else\r\n 705 \u25b8       \u25b8       \u25b8       \u25b8       executable_stack = EXSTACK_DISABLE_X;\r\n 706 \u25b8       \u25b8       \u25b8       break;\r\n 707 \u25b8       \u25b8       }\r\n 708 \r\n 709 \u25b8       \/* Some simple consistency checks for the interpreter *\/\r\n             \/\/\u5bf9\u52a8\u6001\u94fe\u63a5\u5e93\u6267\u884c\u4e00\u81f4\u6027\u68c0\u6d4b\r\n 710 \u25b8       if (elf_interpreter) {\r\n 711 \u25b8       \u25b8       retval = -ELIBBAD;\r\n 712 \u25b8       \u25b8       \/* Not an ELF interpreter *\/\r\n 713 \u25b8       \u25b8       if (memcmp(loc-&gt;interp_elf_ex.e_ident, ELFMAG, SELFMAG) != 0)\r\n 714 \u25b8       \u25b8       \u25b8       goto out_free_dentry;\r\n 715 \u25b8       \u25b8       \/* Verify the interpreter has a valid arch *\/\r\n 716 \u25b8       \u25b8       if (!elf_check_arch(&amp;loc-&gt;interp_elf_ex))\r\n 717 \u25b8       \u25b8       \u25b8       goto out_free_dentry;\r\n 718 \u25b8       }\r\n 719 \r\n 720 \u25b8       \/* Flush all traces of the currently running executable *\/\r\n              \/\/\u91ca\u653e\u5f53\u524d\u8fd0\u884c\u7684\u53ef\u6267\u884c\u6587\u4ef6\u5360\u7528\u7684\u6240\u6709\u8d44\u6e90\r\n 721 \u25b8       retval = flush_old_exec(bprm);\r\n 722 \u25b8       if (retval)\r\n 723 \u25b8       \u25b8       goto out_free_dentry;\r\n 724 \r\n 725 \u25b8       \/* OK, This is the point of no return *\/\r\n 726 \u25b8       current-&gt;mm-&gt;def_flags = def_flags;\r\n 727 \r\n 728 \u25b8       \/* Do this immediately, since STACK_TOP as used in setup_arg_pages\r\n 729 \u25b8          may depend on the personality.  *\/\r\n 730 \u25b8       SET_PERSONALITY(loc-&gt;elf_ex);\r\n731 \u25b8       if (elf_read_implies_exec(loc-&gt;elf_ex, executable_stack))\r\n 732 \u25b8       \u25b8       current-&gt;personality |= READ_IMPLIES_EXEC;\r\n 733 \r\n 734 \u25b8       if (!(current-&gt;personality &amp; ADDR_NO_RANDOMIZE) &amp;&amp; randomize_va_space)\r\n 735 \u25b8       \u25b8       current-&gt;flags |= PF_RANDOMIZE;\r\n 736 \r\n 737 \u25b8       setup_new_exec(bprm);\r\n 738 \r\n 739 \u25b8       \/* Do this so that we can load the interpreter, if need be.  We will\r\n 740 \u25b8          change some of these later *\/\r\n 741 \u25b8       current-&gt;mm-&gt;free_area_cache = current-&gt;mm-&gt;mmap_base;\r\n 742 \u25b8       current-&gt;mm-&gt;cached_hole_size = 0;\r\n            \/\/\u4e3a\u8fdb\u7a0b\u7684\u7528\u6237\u6001\u5806\u6808\u5206\u914d\u4e00\u4e2a\u65b0\u7684\u7ebf\u6027\u533a\u63cf\u8ff0\u7b26\uff0c\u5e76\u628a\u90a3\u4e2a\u7ebf\u6027\u533a\u63d2\u5165\u5230\u8fdb\u7a0b\u7684\u5730\u5740\u7a7a\u95f4\u3002\r\n 743 \u25b8       retval = setup_arg_pages(bprm, randomize_stack_top(STACK_TOP),\r\n 744 \u25b8       \u25b8       \u25b8       \u25b8        executable_stack);\r\n 745 \u25b8       if (retval &lt; 0) {\r\n 746 \u25b8       \u25b8       send_sig(SIGKILL, current, 0);\r\n 747 \u25b8       \u25b8       goto out_free_dentry;\r\n 748 \u25b8       }\r\n 749 \u25b8       \r\n 750 \u25b8       current-&gt;mm-&gt;start_stack = bprm-&gt;p;\r\n 751 \r\n 752 \u25b8       \/* Now we do a little grungy work by mmapping the ELF image into\r\n 753 \u25b8          the correct location in memory. *\/\r\n            \/\/\u5c06ELF\u955c\u50cf\u6587\u4ef6\u6620\u5c04\u5230\u5185\u5b58\u4e2d\u6b63\u786e\u7684\u4f4d\u7f6e\r\n 754 \u25b8       for(i = 0, elf_ppnt = elf_phdata;\r\n 755 \u25b8           i &lt; loc-&gt;elf_ex.e_phnum; i++, elf_ppnt++) {\r\n 756 \u25b8       \u25b8       int elf_prot = 0, elf_flags;\r\n 757 \u25b8       \u25b8       unsigned long k, vaddr;\r\n 758 \r\n 759 \u25b8       \u25b8       if (elf_ppnt-&gt;p_type != PT_LOAD)\r\n 760 \u25b8       \u25b8       \u25b8       continue;\r\n 761 \r\n 762 \u25b8       \u25b8       if (unlikely (elf_brk &gt; elf_bss)) {\r\n 763 \u25b8       \u25b8       \u25b8       unsigned long nbyte;\r\n764 \u25b8       \u25ab\u25ab\u25ab\u25ab\u25ab\u25ab\u25ab\u25ab\u25ab\u25ab\u25ab\u25ab\r\n 765 \u25b8       \u25b8       \u25b8       \/* There was a PT_LOAD segment with p_memsz &gt; p_filesz\r\n 766 \u25b8       \u25b8       \u25b8          before this one. Map anonymous pages, if needed,\r\n 767 \u25b8       \u25b8       \u25b8          and clear the area.  *\/\r\n 768 \u25b8       \u25b8       \u25b8       retval = set_brk(elf_bss + load_bias,\r\n 769 \u25b8       \u25b8       \u25b8       \u25b8       \u25b8        elf_brk + load_bias);\r\n 770 \u25b8       \u25b8       \u25b8       if (retval) {\r\n 771 \u25b8       \u25b8       \u25b8       \u25b8       send_sig(SIGKILL, current, 0);\r\n 772 \u25b8       \u25b8       \u25b8       \u25b8       goto out_free_dentry;\r\n 773 \u25b8       \u25b8       \u25b8       }\r\n 774 \u25b8       \u25b8       \u25b8       nbyte = ELF_PAGEOFFSET(elf_bss);\r\n 775 \u25b8       \u25b8       \u25b8       if (nbyte) {\r\n 776 \u25b8       \u25b8       \u25b8       \u25b8       nbyte = ELF_MIN_ALIGN - nbyte;\r\n 777 \u25b8       \u25b8       \u25b8       \u25b8       if (nbyte &gt; elf_brk - elf_bss)\r\n 778 \u25b8       \u25b8       \u25b8       \u25b8       \u25b8       nbyte = elf_brk - elf_bss;\r\n 779 \u25b8       \u25b8       \u25b8       \u25b8       if (clear_user((void __user *)elf_bss +\r\n 780 \u25b8       \u25b8       \u25b8       \u25b8       \u25b8       \u25b8       \u25b8       load_bias, nbyte)) {\r\n 781 \u25b8       \u25b8       \u25b8       \u25b8       \u25b8       \/*\r\n 782 \u25b8       \u25b8       \u25b8       \u25b8       \u25b8        * This bss-zeroing can fail if the ELF\r\n 783 \u25b8       \u25b8       \u25b8       \u25b8       \u25b8        * file specifies odd protections. So\r\n 784 \u25b8       \u25b8       \u25b8       \u25b8       \u25b8        * we don't check the return value\r\n 785 \u25b8       \u25b8       \u25b8       \u25b8       \u25b8        *\/\r\n 786 \u25b8       \u25b8       \u25b8       \u25b8       }\r\n 787 \u25b8       \u25b8       \u25b8       }\r\n 788 \u25b8       \u25b8       }\r\n 789 \r\n 790 \u25b8       \u25b8       if (elf_ppnt-&gt;p_flags &amp; PF_R)\r\n 791 \u25b8       \u25b8       \u25b8       elf_prot |= PROT_READ;\r\n 792 \u25b8       \u25b8       if (elf_ppnt-&gt;p_flags &amp; PF_W)\r\n 793 \u25b8       \u25b8       \u25b8       elf_prot |= PROT_WRITE;\r\n 794 \u25b8       \u25b8       if (elf_ppnt-&gt;p_flags &amp; PF_X)\r\n 795 \u25b8       \u25b8       \u25b8       elf_prot |= PROT_EXEC;\r\n796 \r\n 797 \u25b8       \u25b8       elf_flags = MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE;\r\n 798 \r\n 799 \u25b8       \u25b8       vaddr = elf_ppnt-&gt;p_vaddr;\r\n 800 \u25b8       \u25b8       if (loc-&gt;elf_ex.e_type == ET_EXEC || load_addr_set) {\r\n 801 \u25b8       \u25b8       \u25b8       elf_flags |= MAP_FIXED;\r\n 802 \u25b8       \u25b8       } else if (loc-&gt;elf_ex.e_type == ET_DYN) {\r\n 803 \u25b8       \u25b8       \u25b8       \/* Try and get dynamic programs out of the way of the\r\n 804 \u25b8       \u25b8       \u25b8        * default mmap base, as well as whatever program they\r\n 805 \u25b8       \u25b8       \u25b8        * might try to exec.  This is because the brk will\r\n 806 \u25b8       \u25b8       \u25b8        * follow the loader, and is not movable.  *\/\r\n 807 #ifdef CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE\r\n 808 \u25b8       \u25b8       \u25b8       \/* Memory randomization might have been switched off\r\n 809 \u25b8       \u25b8       \u25b8        * in runtime via sysctl or explicit setting of\r\n 810 \u25b8       \u25b8       \u25b8        * personality flags.\r\n 811 \u25b8       \u25b8       \u25b8        * If that is the case, retain the original non-zero\r\n 812 \u25b8       \u25b8       \u25b8        * load_bias value in order to establish proper\r\n 813 \u25b8       \u25b8       \u25b8        * non-randomized mappings.\r\n 814 \u25b8       \u25b8       \u25b8        *\/\r\n 815 \u25b8       \u25b8       \u25b8       if (current-&gt;flags &amp; PF_RANDOMIZE)\r\n 816 \u25b8       \u25b8       \u25b8       \u25b8       load_bias = 0;\r\n 817 \u25b8       \u25b8       \u25b8       else\r\n 818 \u25b8       \u25b8       \u25b8       \u25b8       load_bias = ELF_PAGESTART(ELF_ET_DYN_BASE - vaddr);\r\n 819 #else\r\n 820 \u25b8       \u25b8       \u25b8       load_bias = ELF_PAGESTART(ELF_ET_DYN_BASE - vaddr);\r\n 821 #endif\r\n 822 \u25b8       \u25b8       }\r\n 823\r\n824 \u25b8       \u25b8       error = elf_map(bprm-&gt;file, load_bias + vaddr, elf_ppnt,\r\n 825 \u25b8       \u25b8       \u25b8       \u25b8       elf_prot, elf_flags, 0);\r\n 826 \u25b8       \u25b8       if (BAD_ADDR(error)) {\r\n 827 \u25b8       \u25b8       \u25b8       send_sig(SIGKILL, current, 0);\r\n 828 \u25b8       \u25b8       \u25b8       retval = IS_ERR((void *)error) ?\r\n 829 \u25b8       \u25b8       \u25b8       \u25b8       PTR_ERR((void*)error) : -EINVAL;\r\n 830 \u25b8       \u25b8       \u25b8       goto out_free_dentry;\r\n 831 \u25b8       \u25b8       }\r\n 832 \r\n 833 \u25b8       \u25b8       if (!load_addr_set) {\r\n 834 \u25b8       \u25b8       \u25b8       load_addr_set = 1;\r\n 835 \u25b8       \u25b8       \u25b8       load_addr = (elf_ppnt-&gt;p_vaddr - elf_ppnt-&gt;p_offset);\r\n 836 \u25b8       \u25b8       \u25b8       if (loc-&gt;elf_ex.e_type == ET_DYN) {\r\n 837 \u25b8       \u25b8       \u25b8       \u25b8       load_bias += error -\r\n 838 \u25b8       \u25b8       \u25b8       \u25b8                    ELF_PAGESTART(load_bias + vaddr);\r\n 839 \u25b8       \u25b8       \u25b8       \u25b8       load_addr += load_bias;\r\n 840 \u25b8       \u25b8       \u25b8       \u25b8       reloc_func_desc = load_bias;\r\n 841 \u25b8       \u25b8       \u25b8       }\r\n 842 \u25b8       \u25b8       }\r\n 843 \u25b8       \u25b8       k = elf_ppnt-&gt;p_vaddr;\r\n 844 \u25b8       \u25b8       if (k &lt; start_code)\r\n 845 \u25b8       \u25b8       \u25b8       start_code = k;\r\n 846 \u25b8       \u25b8       if (start_data &lt; k)\r\n 847 \u25b8       \u25b8       \u25b8       start_data = k;\r\n 848 \r\n 849 \u25b8       \u25b8       \/*\r\n 850 \u25b8       \u25b8        * Check to see if the section's size will overflow the\r\n 851 \u25b8       \u25b8        * allowed task size. Note that p_filesz must always be\r\n 852 \u25b8       \u25b8        * &lt;= p_memsz so it is only necessary to check p_memsz.\r\n 853 \u25b8       \u25b8        *\/\r\n 854 \u25b8       \u25b8       if (BAD_ADDR(k) || elf_ppnt-&gt;p_filesz &gt; elf_ppnt-&gt;p_memsz ||\r\n 855 \u25b8       \u25b8           elf_ppnt-&gt;p_memsz &gt; TASK_SIZE ||\r\n 856 \u25b8       \u25b8           TASK_SIZE - elf_ppnt-&gt;p_memsz &lt; k) {\r\n857 \u25b8       \u25b8       \u25b8       \/* set_brk can never work. Avoid overflows. *\/\r\n 858 \u25b8       \u25b8       \u25b8       send_sig(SIGKILL, current, 0);\r\n 859 \u25b8       \u25b8       \u25b8       retval = -EINVAL;\r\n 860 \u25b8       \u25b8       \u25b8       goto out_free_dentry;\r\n 861 \u25b8       \u25b8       }\r\n 862 \r\n 863 \u25b8       \u25b8       k = elf_ppnt-&gt;p_vaddr + elf_ppnt-&gt;p_filesz;\r\n 864 \r\n 865 \u25b8       \u25b8       if (k &gt; elf_bss)\r\n 866 \u25b8       \u25b8       \u25b8       elf_bss = k;\r\n 867 \u25b8       \u25b8       if ((elf_ppnt-&gt;p_flags &amp; PF_X) &amp;&amp; end_code &lt; k)\r\n 868 \u25b8       \u25b8       \u25b8       end_code = k;\r\n 869 \u25b8       \u25b8       if (end_data &lt; k)\r\n 870 \u25b8       \u25b8       \u25b8       end_data = k;\r\n 871 \u25b8       \u25b8       k = elf_ppnt-&gt;p_vaddr + elf_ppnt-&gt;p_memsz;\r\n 872 \u25b8       \u25b8       if (k &gt; elf_brk)\r\n 873 \u25b8       \u25b8       \u25b8       elf_brk = k;\r\n 874 \u25b8       }\r\n 875 \r\n 876 \u25b8       loc-&gt;elf_ex.e_entry += load_bias;\r\n 877 \u25b8       elf_bss += load_bias;\r\n 878 \u25b8       elf_brk += load_bias;\r\n 879 \u25b8       start_code += load_bias;\r\n 880 \u25b8       end_code += load_bias;\r\n 881 \u25b8       start_data += load_bias;\r\n 882 \u25b8       end_data += load_bias;\r\n 883 \r\n 884 \u25b8       \/* Calling set_brk effectively mmaps the pages that we need\r\n 885 \u25b8        * for the bss and break sections.  We must do this before\r\n 886 \u25b8        * mapping in the interpreter, to make sure it doesn't wind\r\n 887 \u25b8        * up getting placed where the bss needs to go.\r\n 888 \u25b8        *\/\r\n890 \u25b8       if (retval) {\r\n 891 \u25b8       \u25b8       send_sig(SIGKILL, current, 0);\r\n 892 \u25b8       \u25b8       goto out_free_dentry;\r\n 893 \u25b8       }\r\n 894 \u25b8       if (likely(elf_bss != elf_brk) &amp;&amp; unlikely(padzero(elf_bss))) {\r\n 895 \u25b8       \u25b8       send_sig(SIGSEGV, current, 0);\r\n 896 \u25b8       \u25b8       retval = -EFAULT; \/* Nobody gets to see this, but.. *\/\r\n 897 \u25b8       \u25b8       goto out_free_dentry;\r\n 898 \u25b8       }\r\n 899          \/\/\u8c03\u7528\u4e00\u4e2a\u52a8\u6001\u94fe\u63a5\u7a0b\u5e8f\u7684\u51fd\u6570\uff0c\u5982\u679c\u52a8\u6001\u94fe\u63a5\u7a0b\u5e8f\u662felf\u53ef\u6267\u884c\u7684\uff0c\u8c03\u7528load_elf_interp(\u52a8\u6001\u94fe\u63a5\u7a0b\u5e8f)\r\n 900 \u25b8       if (elf_interpreter) {\r\n 901 \u25b8       \u25b8       unsigned long interp_map_addr = 0;\r\n 902 \r\n 903 \u25b8       \u25b8       elf_entry = load_elf_interp(&amp;loc-&gt;interp_elf_ex,\r\n 904 \u25b8       \u25b8       \u25b8       \u25b8       \u25b8           interpreter,\r\n 905 \u25b8       \u25b8       \u25b8       \u25b8       \u25b8           &amp;interp_map_addr,\r\n 906 \u25b8       \u25b8       \u25b8       \u25b8       \u25b8           load_bias);\r\n 907 \u25b8       \u25b8       if (!IS_ERR((void *)elf_entry)) {\r\n 908 \u25b8       \u25b8       \u25b8       \/*\r\n 909 \u25b8       \u25b8       \u25b8        * load_elf_interp() returns relocation\r\n 910 \u25b8       \u25b8       \u25b8        * adjustment\r\n 911 \u25b8       \u25b8       \u25b8        *\/\r\n 912 \u25b8       \u25b8       \u25b8       interp_load_addr = elf_entry;\r\n 913 \u25b8       \u25b8       \u25b8       elf_entry += loc-&gt;interp_elf_ex.e_entry;\r\n 914 \u25b8       \u25b8       }\r\n 915 \u25b8       \u25b8       if (BAD_ADDR(elf_entry)) {\r\n 916 \u25b8       \u25b8       \u25b8       force_sig(SIGSEGV, current);\r\n 917 \u25b8       \u25b8       \u25b8       retval = IS_ERR((void *)elf_entry) ?\r\n 918 \u25b8       \u25b8       \u25b8       \u25b8       \u25b8       (int)elf_entry : -EINVAL;\r\n 919 \u25b8       \u25b8       \u25b8       goto out_free_dentry;\r\n 920 \u25b8       \u25b8       }\r\n 921 \u25b8       \u25b8       reloc_func_desc = interp_load_addr;\r\n 922\r\n923 \u25b8       \u25b8       allow_write_access(interpreter);\r\n 924 \u25b8       \u25b8       fput(interpreter);\r\n 925 \u25b8       \u25b8       kfree(elf_interpreter);\r\n 926 \u25b8       } else {\r\n 927 \u25b8       \u25b8       elf_entry = loc-&gt;elf_ex.e_entry;\r\n 928 \u25b8       \u25b8       if (BAD_ADDR(elf_entry)) {\r\n 929 \u25b8       \u25b8       \u25b8       force_sig(SIGSEGV, current);\r\n 930 \u25b8       \u25b8       \u25b8       retval = -EINVAL;\r\n 931 \u25b8       \u25b8       \u25b8       goto out_free_dentry;\r\n 932 \u25b8       \u25b8       }\r\n 933 \u25b8       }\r\n 934 \r\n 935 \u25b8       kfree(elf_phdata);\r\n 936         \/\/\u628a\u53ef\u6267\u884c\u683c\u5f0f\u7684linux_binfmt\u5bf9\u8c61\u5730\u5740\u5b58\u653e\u5728\u8fdb\u7a0b\u63cf\u8ff0\u7b26binfmt\u5b57\u6bb5\u4e2d\r\n 937 \u25b8       set_binfmt(&amp;elf_format);\r\n 938 \r\n 939 #ifdef ARCH_HAS_SETUP_ADDITIONAL_PAGES\r\n 940 \u25b8       retval = arch_setup_additional_pages(bprm, !!elf_interpreter);\r\n 941 \u25b8       if (retval &lt; 0) {\r\n 942 \u25b8       \u25b8       send_sig(SIGKILL, current, 0);\r\n 943 \u25b8       \u25b8       goto out;\r\n 944 \u25b8       }\r\n 945 #endif \/* ARCH_HAS_SETUP_ADDITIONAL_PAGES *\/\r\n 946 \r\n 947 \u25b8       install_exec_creds(bprm);\r\n 948 \u25b8       retval = create_elf_tables(bprm, &amp;loc-&gt;elf_ex,\r\n 949 \u25b8       \u25b8       \u25b8         load_addr, interp_load_addr);\r\n 950 \u25b8       if (retval &lt; 0) {\r\n 951 \u25b8       \u25b8       send_sig(SIGKILL, current, 0);\r\n952 \u25b8       \u25b8       goto out;\r\n 953 \u25b8       }\r\n 954 \u25b8       \/* N.B. passed_fileno might not be initialized? *\/\r\n 955 \u25b8       current-&gt;mm-&gt;end_code = end_code;\r\n 956 \u25b8       current-&gt;mm-&gt;start_code = start_code;\r\n 957 \u25b8       current-&gt;mm-&gt;start_data = start_data;\r\n 958 \u25b8       current-&gt;mm-&gt;end_data = end_data;\r\n 959 \u25b8       current-&gt;mm-&gt;start_stack = bprm-&gt;p;\r\n 960 \r\n 961 #ifdef arch_randomize_brk\r\n 962 \u25b8       if ((current-&gt;flags &amp; PF_RANDOMIZE) &amp;&amp; (randomize_va_space &gt; 1)) {\r\n 963 \u25b8       \u25b8       current-&gt;mm-&gt;brk = current-&gt;mm-&gt;start_brk =\r\n 964 \u25b8       \u25b8       \u25b8       arch_randomize_brk(current-&gt;mm);\r\n 965 #ifdef CONFIG_COMPAT_BRK\r\n 966 \u25b8       \u25b8       current-&gt;brk_randomized = 1;\r\n 967 #endif\r\n 968 \u25b8       }\r\n 969 #endif\r\n 970 \r\n 971 \u25b8       if (current-&gt;personality &amp; MMAP_PAGE_ZERO) {\r\n 972 \u25b8       \u25b8       \/* Why this, you ask???  Well SVr4 maps page 0 as read-only,\r\n 973 \u25b8       \u25b8          and some applications \"depend\" upon this behavior.\r\n 974 \u25b8       \u25b8          Since we do not have the power to recompile these, we\r\n 975 \u25b8       \u25b8          emulate the SVr4 behavior. Sigh. *\/\r\n 976 \u25b8       \u25b8       error = vm_mmap(NULL, 0, PAGE_SIZE, PROT_READ | PROT_EXEC,\r\n 977 \u25b8       \u25b8       \u25b8       \u25b8       MAP_FIXED | MAP_PRIVATE, 0);\r\n 978 \u25b8       }\r\n 979 \r\n 980 #ifdef ELF_PLAT_INIT\r\n981 \u25b8       \/*\r\n 982 \u25b8        * The ABI may specify that certain registers be set up in special\r\n 983 \u25b8        * ways (on i386 %edx is the address of a DT_FINI function, for\r\n 984 \u25b8        * example.  In addition, it may also specify (eg, PowerPC64 ELF)\r\n 985 \u25b8        * that the e_entry field is the address of the function descriptor\r\n 986 \u25b8        * for the startup routine, rather than the address of the startup\r\n 987 \u25b8        * routine itself.  This macro performs whatever initialization to\r\n 988 \u25b8        * the regs structure is required as well as any relocations to the\r\n 989 \u25b8        * function descriptor entries when executing dynamically links apps.\r\n 990 \u25b8        *\/\r\n 991 \u25b8       ELF_PLAT_INIT(regs, reloc_func_desc);\r\n 992 #endif\r\n 993 \r\n 994 \u25b8       start_thread(regs, elf_entry, bprm-&gt;p);\r\n 995 \u25b8       retval = 0;\r\n 996 out:\r\n 997 \u25b8       kfree(loc);\r\n 998 out_ret:\r\n 999 \u25b8       return retval;\r\n1000 \r\n1001 \u25b8       \/* error cleanup *\/\r\n1002 out_free_dentry:\r\n1003 \u25b8       allow_write_access(interpreter);\r\n1004 \u25b8       if (interpreter)\r\n1005 \u25b8       \u25b8       fput(interpreter);\r\n1006 out_free_interp:\r\n1007 \u25b8       kfree(elf_interpreter);\r\n1008 out_free_ph:\r\n1009 \u25b8       kfree(elf_phdata);\r\n1010 \u25b8       goto out;\r\n1011 }\r\n<\/pre>\n<p>\u9644\u5f55\uff1a<br \/>\nX86-64\u4e2d\uff0c\u6240\u6709\u5bc4\u5b58\u5668\u90fd\u662f64\u4f4d\uff0c\u76f8\u5bf932\u4f4d\u7684x86\u6765\u8bf4\uff0c\u6807\u8bc6\u7b26\u53d1\u751f\u4e86\u53d8\u5316\uff0c\u6bd4\u5982\uff1a\u4ece\u539f\u6765\u7684%ebp\u53d8\u6210\u4e86%rbp\u3002\u4e3a\u4e86\u5411\u540e\u517c\u5bb9\u6027\uff0c%ebp\u4f9d\u7136\u53ef\u4ee5\u4f7f\u7528\uff0c\u4e0d\u8fc7\u6307\u5411\u4e86%rbp\u7684\u4f4e32\u4f4d\u3002<br \/>\nX86-64\u5bc4\u5b58\u5668\u7684\u53d8\u5316\uff0c\u4e0d\u4ec5\u4f53\u73b0\u5728\u4f4d\u6570\u4e0a\uff0c\u66f4\u52a0\u4f53\u73b0\u5728\u5bc4\u5b58\u5668\u6570\u91cf\u4e0a\u3002\u65b0\u589e\u52a0\u5bc4\u5b58\u5668%r8\u5230%r15\u3002\u52a0\u4e0ax86\u7684\u539f\u67098\u4e2a\uff0c\u4e00\u517116\u4e2a\u5bc4\u5b58\u5668\u3002<br \/>\n\u521a\u521a\u8bf4\u5230\uff0c\u5bc4\u5b58\u5668\u96c6\u6210\u5728CPU\u4e0a\uff0c\u5b58\u53d6\u901f\u5ea6\u6bd4\u5b58\u50a8\u5668\u5feb\u597d\u51e0\u4e2a\u6570\u91cf\u7ea7\uff0c\u5bc4\u5b58\u5668\u591a\u4e86\uff0cGCC\u5c31\u53ef\u4ee5\u66f4\u591a\u7684\u4f7f\u7528\u5bc4\u5b58\u5668\uff0c\u66ff\u6362\u4e4b\u524d\u7684\u5b58\u50a8\u5668\u5806\u6808\u4f7f\u7528\uff0c\u4ece\u800c\u5927\u5927\u63d0\u5347\u6027\u80fd\u3002<br \/>\n\u8ba9\u5bc4\u5b58\u5668\u4e3a\u5df1\u6240\u7528\uff0c\u5c31\u5f97\u4e86\u89e3\u5b83\u4eec\u7684\u7528\u9014\uff0c\u8fd9\u4e9b\u7528\u9014\u90fd\u6d89\u53ca\u51fd\u6570\u8c03\u7528\uff0cX86-64\u670916\u4e2a64\u4f4d\u5bc4\u5b58\u5668\uff0c\u5206\u522b\u662f\uff1a%rax\uff0c%rbx\uff0c%rcx\uff0c%rdx\uff0c%esi\uff0c%edi\uff0c%rbp\uff0c%rsp\uff0c%r8\uff0c%r9\uff0c%r10\uff0c%r11\uff0c%r12\uff0c%r13\uff0c%r14\uff0c%r15\u3002\u5176\u4e2d\uff1a<br \/>\n\u2022\t%rax \u4f5c\u4e3a\u51fd\u6570\u8fd4\u56de\u503c\u4f7f\u7528\u3002<br \/>\n\u2022\t%rsp \u6808\u6307\u9488\u5bc4\u5b58\u5668\uff0c\u6307\u5411\u6808\u9876<br \/>\n\u2022\t%rdi\uff0c%rsi\uff0c%rdx\uff0c%rcx\uff0c%r8\uff0c%r9 \u7528\u4f5c\u51fd\u6570\u53c2\u6570\uff0c\u4f9d\u6b21\u5bf9\u5e94\u7b2c1\u53c2\u6570\uff0c\u7b2c2\u53c2\u6570\u3002\u3002\u3002<br \/>\n\u2022\t%rbx\uff0c%rbp\uff0c%r12\uff0c%r13\uff0c%14\uff0c%15 \u7528\u4f5c\u6570\u636e\u5b58\u50a8\uff0c\u9075\u5faa\u88ab\u8c03\u7528\u8005\u4f7f\u7528\u89c4\u5219\uff0c\u7b80\u5355\u8bf4\u5c31\u662f\u968f\u4fbf\u7528\uff0c\u8c03\u7528\u5b50\u51fd\u6570\u4e4b\u524d\u8981\u5907\u4efd\u5b83\uff0c\u4ee5\u9632\u4ed6\u88ab\u4fee\u6539<br \/>\n\u2022\t%r10\uff0c%r11 \u7528\u4f5c\u6570\u636e\u5b58\u50a8\uff0c\u9075\u5faa\u8c03\u7528\u8005\u4f7f\u7528\u89c4\u5219\uff0c\u7b80\u5355\u8bf4\u5c31\u662f\u4f7f\u7528\u4e4b\u524d\u8981\u5148\u4fdd\u5b58\u539f\u503c<br \/>\n<a href=\"http:\/\/www.selinuxplus.com\/wp-content\/uploads\/2014\/10\/x86-64\u5bc4\u5b58\u56682.png\"><img loading=\"lazy\" src=\"http:\/\/www.selinuxplus.com\/wp-content\/uploads\/2014\/10\/x86-64\u5bc4\u5b58\u56682.png\" alt=\"x86-64\u5bc4\u5b58\u56682\" width=\"1004\" height=\"1520\" class=\"aligncenter size-full wp-image-596\" srcset=\"http:\/\/www.selinuxplus.com\/wp-content\/uploads\/2014\/10\/x86-64\u5bc4\u5b58\u56682.png 1004w, http:\/\/www.selinuxplus.com\/wp-content\/uploads\/2014\/10\/x86-64\u5bc4\u5b58\u56682-198x300.png 198w, http:\/\/www.selinuxplus.com\/wp-content\/uploads\/2014\/10\/x86-64\u5bc4\u5b58\u56682-676x1024.png 676w\" sizes=\"(max-width: 1004px) 100vw, 1004px\" \/><\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u6211\u4eec\u5148\u4e86\u89e3\u4e00\u4e0bexecve\uff1a int execve&hellip;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[103,5],"tags":[17,128,129],"_links":{"self":[{"href":"http:\/\/www.selinuxplus.com\/index.php?rest_route=\/wp\/v2\/posts\/594"}],"collection":[{"href":"http:\/\/www.selinuxplus.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.selinuxplus.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.selinuxplus.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/www.selinuxplus.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=594"}],"version-history":[{"count":2,"href":"http:\/\/www.selinuxplus.com\/index.php?rest_route=\/wp\/v2\/posts\/594\/revisions"}],"predecessor-version":[{"id":648,"href":"http:\/\/www.selinuxplus.com\/index.php?rest_route=\/wp\/v2\/posts\/594\/revisions\/648"}],"wp:attachment":[{"href":"http:\/\/www.selinuxplus.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=594"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.selinuxplus.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=594"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.selinuxplus.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=594"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}