diff options
author | Oleg Nesterov <oleg@redhat.com> | 2013-09-11 17:24:38 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-09-11 18:59:03 -0400 |
commit | 5d1baf3b63bfc8c709dc44df85ff1475c7ef489d (patch) | |
tree | c22cad96687d70a544674f7eb823026aecf4ceeb /fs | |
parent | 96d0df79f2644fc823f26c06491e182d87a90c2a (diff) |
exec: introduce exec_binprm() for "depth == 0" code
task_pid_nr_ns() and trace/ptrace code in the middle of the recursive
search_binary_handler() looks confusing and imho annoying. We only need
this code if "depth == 0", lets add a simple helper which calls
search_binary_handler() and does trace_sched_process_exec() +
ptrace_event().
The patch also moves the setting of task->did_exec, we need to do this
only once.
Note: we can kill either task->did_exec or PF_FORKNOEXEC.
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Acked-by: Kees Cook <keescook@chromium.org>
Cc: Al Viro <viro@ZenIV.linux.org.uk>
Cc: Evgeniy Polyakov <zbr@ioremap.net>
Cc: Zach Levis <zml@linux.vnet.ibm.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/exec.c | 36 |
1 files changed, 22 insertions, 14 deletions
@@ -1373,7 +1373,6 @@ int search_binary_handler(struct linux_binprm *bprm) | |||
1373 | unsigned int depth = bprm->recursion_depth; | 1373 | unsigned int depth = bprm->recursion_depth; |
1374 | int try,retval; | 1374 | int try,retval; |
1375 | struct linux_binfmt *fmt; | 1375 | struct linux_binfmt *fmt; |
1376 | pid_t old_pid, old_vpid; | ||
1377 | 1376 | ||
1378 | /* This allows 4 levels of binfmt rewrites before failing hard. */ | 1377 | /* This allows 4 levels of binfmt rewrites before failing hard. */ |
1379 | if (depth > 5) | 1378 | if (depth > 5) |
@@ -1387,12 +1386,6 @@ int search_binary_handler(struct linux_binprm *bprm) | |||
1387 | if (retval) | 1386 | if (retval) |
1388 | return retval; | 1387 | return retval; |
1389 | 1388 | ||
1390 | /* Need to fetch pid before load_binary changes it */ | ||
1391 | old_pid = current->pid; | ||
1392 | rcu_read_lock(); | ||
1393 | old_vpid = task_pid_nr_ns(current, task_active_pid_ns(current->parent)); | ||
1394 | rcu_read_unlock(); | ||
1395 | |||
1396 | retval = -ENOENT; | 1389 | retval = -ENOENT; |
1397 | for (try=0; try<2; try++) { | 1390 | for (try=0; try<2; try++) { |
1398 | read_lock(&binfmt_lock); | 1391 | read_lock(&binfmt_lock); |
@@ -1407,16 +1400,11 @@ int search_binary_handler(struct linux_binprm *bprm) | |||
1407 | retval = fn(bprm); | 1400 | retval = fn(bprm); |
1408 | bprm->recursion_depth = depth; | 1401 | bprm->recursion_depth = depth; |
1409 | if (retval >= 0) { | 1402 | if (retval >= 0) { |
1410 | if (depth == 0) { | ||
1411 | trace_sched_process_exec(current, old_pid, bprm); | ||
1412 | ptrace_event(PTRACE_EVENT_EXEC, old_vpid); | ||
1413 | } | ||
1414 | put_binfmt(fmt); | 1403 | put_binfmt(fmt); |
1415 | allow_write_access(bprm->file); | 1404 | allow_write_access(bprm->file); |
1416 | if (bprm->file) | 1405 | if (bprm->file) |
1417 | fput(bprm->file); | 1406 | fput(bprm->file); |
1418 | bprm->file = NULL; | 1407 | bprm->file = NULL; |
1419 | current->did_exec = 1; | ||
1420 | proc_exec_connector(current); | 1408 | proc_exec_connector(current); |
1421 | return retval; | 1409 | return retval; |
1422 | } | 1410 | } |
@@ -1450,9 +1438,29 @@ int search_binary_handler(struct linux_binprm *bprm) | |||
1450 | } | 1438 | } |
1451 | return retval; | 1439 | return retval; |
1452 | } | 1440 | } |
1453 | |||
1454 | EXPORT_SYMBOL(search_binary_handler); | 1441 | EXPORT_SYMBOL(search_binary_handler); |
1455 | 1442 | ||
1443 | static int exec_binprm(struct linux_binprm *bprm) | ||
1444 | { | ||
1445 | pid_t old_pid, old_vpid; | ||
1446 | int ret; | ||
1447 | |||
1448 | /* Need to fetch pid before load_binary changes it */ | ||
1449 | old_pid = current->pid; | ||
1450 | rcu_read_lock(); | ||
1451 | old_vpid = task_pid_nr_ns(current, task_active_pid_ns(current->parent)); | ||
1452 | rcu_read_unlock(); | ||
1453 | |||
1454 | ret = search_binary_handler(bprm); | ||
1455 | if (ret >= 0) { | ||
1456 | trace_sched_process_exec(current, old_pid, bprm); | ||
1457 | ptrace_event(PTRACE_EVENT_EXEC, old_vpid); | ||
1458 | current->did_exec = 1; | ||
1459 | } | ||
1460 | |||
1461 | return ret; | ||
1462 | } | ||
1463 | |||
1456 | /* | 1464 | /* |
1457 | * sys_execve() executes a new program. | 1465 | * sys_execve() executes a new program. |
1458 | */ | 1466 | */ |
@@ -1541,7 +1549,7 @@ static int do_execve_common(const char *filename, | |||
1541 | if (retval < 0) | 1549 | if (retval < 0) |
1542 | goto out; | 1550 | goto out; |
1543 | 1551 | ||
1544 | retval = search_binary_handler(bprm); | 1552 | retval = exec_binprm(bprm); |
1545 | if (retval < 0) | 1553 | if (retval < 0) |
1546 | goto out; | 1554 | goto out; |
1547 | 1555 | ||