exec: minor cleanups + minor fix
Subsystems (2)
cover exec: minor cleanups + minor fix
Andrew,
By discussion with Zach, please drop
fs-binfmts-add-a-name-field-to-the-binfmt-struct.patch fs-binfmts-better-handling-of-binfmt-loops.patch fs-binfmts-whitespace-fixes-with-scripts-cleanfile.patch
Zach is working on v2.
Meanwhile, can't we cleanup search_binary_handler() a bit? It doesn't look nice imho. And we can certainly cleanup it more (perhaps I'll try tomorrow). The error handling, request_module() logic and even "for (try=0; try<2; try++)" looks horrible imho.
Oleg.
PATCH 1/3 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.
--- fs/exec.c | 36 ++++++++++++++++++++++-------------- 1 files changed, 22 insertions(+), 14 deletions(-)
fs/exec.c +22 -14
@@ -1373,7 +1373,6 @@ int search_binary_handler(struct linux_binprm *bprm)unsigned int depth = bprm->recursion_depth;int try,retval;struct linux_binfmt *fmt; -pid_t old_pid, old_vpid;/* This allows 4 levels of binfmt rewrites before failing hard. */ if (depth >5 )
@@ -1387,12 +1386,6 @@ int search_binary_handler(struct linux_binprm *bprm)if (retval)return retval; -/* Need to fetch pid before load_binary changes it */ - old_pid = current->pid; -rcu_read_lock (); - old_vpid =task_pid_nr_ns (current,task_active_pid_ns (current->parent)); -rcu_read_unlock (); - retval = -ENOENT ;for (try=0 ; try<2 ; try++) {read_lock (&binfmt_lock);
@@ -1407,16 +1400,11 @@ int search_binary_handler(struct linux_binprm *bprm) retval =fn (bprm); bprm->recursion_depth = depth;if (retval >=0 ) { -if (depth ==0 ) { -trace_sched_process_exec (current, old_pid, bprm); -ptrace_event (PTRACE_EVENT_EXEC , old_vpid); - }put_binfmt (fmt);allow_write_access (bprm->file);if (bprm->file)fput (bprm->file); bprm->file =NULL ; - current->did_exec =1 ;proc_exec_connector (current);return retval; }
@@ -1450,9 +1438,29 @@ int search_binary_handler(struct linux_binprm *bprm) }return retval; } -EXPORT_SYMBOL (search_binary_handler); +static int exec_binprm (struct linux_binprm *bprm) +{ +pid_t old_pid, old_vpid; +int ret; + +/* Need to fetch pid before load_binary changes it */ + old_pid = current->pid; +rcu_read_lock (); + old_vpid =task_pid_nr_ns (current,task_active_pid_ns (current->parent)); +rcu_read_unlock (); + + ret =search_binary_handler (bprm); +if (ret >=0 ) { +trace_sched_process_exec (current, old_pid, bprm); +ptrace_event (PTRACE_EVENT_EXEC , old_vpid); + current->did_exec =1 ; + } + +return ret; +} +/* * sys_execve() executes a new program. */
@@ -1541,7 +1549,7 @@ static int do_execve_common(const char *filename,if (retval <0 ) goto out; - retval =search_binary_handler (bprm); + retval =exec_binprm (bprm);if (retval <0 ) goto out;
Signature · 1 line
1.5.5.1
Re: [PATCH 1/3] exec: introduce exec_binprm() for "depth == 0" code
Quoted 72 lines · Oleg Nesterov
task_pid_nr_ns()and trace/ptrace code in the middle of the recursivesearch_binary_handler()looks confusing and imho annoying. We only need this code if "depth == 0", lets add a simple helper which callssearch_binary_handler()and doestrace_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_execorPF_FORKNOEXEC.Signed-off-by Oleg Nesterov <[email protected]>--- fs/exec.c | 36 ++++++++++++++++++++++-------------- 1 files changed, 22 insertions(+), 14 deletions(-)fs/exec.c +7
-13@@ -1373,7 +1373,6 @@ int search_binary_handler(struct linux_binprm *bprm)unsigned int depth = bprm->recursion_depth;int try,retval;struct linux_binfmt *fmt; -pid_t old_pid, old_vpid;/* This allows 4 levels of binfmt rewrites before failing hard. */ if (depth >5 )@@ -1387,12 +1386,6 @@ int search_binary_handler(struct linux_binprm *bprm)if (retval)return retval; -/* Need to fetch pid before load_binary changes it */ - old_pid = current->pid; -rcu_read_lock (); - old_vpid =task_pid_nr_ns (current,task_active_pid_ns (current->parent)); -rcu_read_unlock (); - retval = -ENOENT ;for (try=0 ; try<2 ; try++) {read_lock (&binfmt_lock);@@ -1407,16 +1400,11 @@ int search_binary_handler(struct linux_binprm *bprm) retval =fn (bprm); bprm->recursion_depth = depth;if (retval >=0 ) { -if (depth ==0 ) { -trace_sched_process_exec (current, old_pid, bprm); -ptrace_event (PTRACE_EVENT_EXEC , old_vpid); - }put_binfmt (fmt);allow_write_access (bprm->file);if (bprm->file)fput (bprm->file); bprm->file =NULL ; - current->did_exec =1 ;proc_exec_connector (current);return retval; }@@ -1450,9 +1438,29 @@ int search_binary_handler(struct linux_binprm *bprm) }return retval; } -EXPORT_SYMBOL (search_binary_handler); +static int exec_binprm (struct linux_binprm *bprm) +{ +pid_t old_pid, old_vpid; +int ret; + +/* Need to fetch pid before load_binary changes it */ + old_pid = current->pid;
fs/exec.c int search_binary_handler(struct linux_binprm *bprm) · line 1459
Quoted 10 lines
fs/exec.c +10
-0+rcu_read_lock (); + old_vpid =task_pid_nr_ns (current,task_active_pid_ns (current->parent)); +rcu_read_unlock (); + + ret =search_binary_handler (bprm); +if (ret >=0 ) { +trace_sched_process_exec (current, old_pid, bprm); +ptrace_event (PTRACE_EVENT_EXEC , old_vpid); + current->did_exec =1 ; + }
Cleanup looks good. One idea here, though: this could be made more pretty by doing:
if (ret < 0)
return ret;
to avoid the indentation for the "expected" code path.
-Kees
Quoted 19 lines
fs/exec.c +5
-2+ +return ret; +} +/* * sys_execve() executes a new program. */ @@ -1541,7 +1549,7 @@ static int do_execve_common(const char *filename,if (retval <0 ) goto out; - retval =search_binary_handler (bprm); + retval =exec_binprm (bprm);if (retval <0 ) goto out; --1.5.5.1
Signature · 2 lines
Kees Cook Chrome OS Security
Re: [PATCH 1/3] exec: introduce exec_binprm() for "depth == 0" code
Quoted 23 lines · Kees Cook
Quoted 7 lines · Oleg Nesterov
fs/exec.c +7
-0+static int exec_binprm (struct linux_binprm *bprm) +{ +pid_t old_pid, old_vpid; +int ret; + +/* Need to fetch pid before load_binary changes it */ + old_pid = current->pid;fs/exec.c int search_binary_handler(struct linux_binprm *bprm) · line 1459
Quoted 10 lines
fs/exec.c +10
-0+rcu_read_lock (); + old_vpid =task_pid_nr_ns (current,task_active_pid_ns (current->parent)); +rcu_read_unlock (); + + ret =search_binary_handler (bprm); +if (ret >=0 ) { +trace_sched_process_exec (current, old_pid, bprm); +ptrace_event (PTRACE_EVENT_EXEC , old_vpid); + current->did_exec =1 ; + }Cleanup looks good. One idea here, though: this could be made more pretty by doing:
Quoted 4 lines
if (ret < 0)
return ret;to avoid the indentation for the "expected" code path.
Well, I do not reallt mind. But this "if" block is simple and small, we do we need another "return" ?
To me the code looks more readable this way, but I can redo/resend.
Oleg.
Kees Cook
Acked-byRe: [PATCH 1/3] exec: introduce exec_binprm() for "depth == 0" code
Quoted 27 lines · Oleg Nesterov
Quoted 26 lines · Kees Cook
Quoted 7 lines · Oleg Nesterov
fs/exec.c +7
-0+static int exec_binprm (struct linux_binprm *bprm) +{ +pid_t old_pid, old_vpid; +int ret; + +/* Need to fetch pid before load_binary changes it */ + old_pid = current->pid;fs/exec.c int search_binary_handler(struct linux_binprm *bprm) · line 1459
Quoted 10 lines
fs/exec.c +10
-0+rcu_read_lock (); + old_vpid =task_pid_nr_ns (current,task_active_pid_ns (current->parent)); +rcu_read_unlock (); + + ret =search_binary_handler (bprm); +if (ret >=0 ) { +trace_sched_process_exec (current, old_pid, bprm); +ptrace_event (PTRACE_EVENT_EXEC , old_vpid); + current->did_exec =1 ; + }Cleanup looks good. One idea here, though: this could be made more pretty by doing:
if (ret < 0)
return ret;
Quoted 6 lines
Quoted 1 line
to avoid the indentation for the "expected" code path.
Well, I do not reallt mind. But this "if" block is simple and small, we do we need another "return" ?
To me the code looks more readable this way, but I can redo/resend.
Cool, that's fine how it is. It was just a style suggestion. :)
Thanks!
-Kees
Signature · 2 lines
Kees Cook Chrome OS Security
PATCH 2/3 exec: kill "int depth" in search_binary_handler()
In reply to Oleg NesterovNobody except search_binary_handler() should touch ->recursion_depth, "int depth" buys nothing but complicates the code, kill it.
Probably we should also kill "fn" and the !NULL check, ->load_binary should be always defined. And it can not go away after read_unlock() or this code is buggy anyway.
--- fs/exec.c | 9 ++++----- 1 files changed, 4 insertions(+), 5 deletions(-)
fs/exec.c +4 -5
@@ -1370,12 +1370,11 @@ EXPORT_SYMBOL(remove_arg_zero);*/ int search_binary_handler (struct linux_binprm *bprm) { -unsigned int depth = bprm->recursion_depth; -int try,retval; +int try, retval;struct linux_binfmt *fmt;/* This allows 4 levels of binfmt rewrites before failing hard. */ -if (depth >5 ) +if (bprm->recursion_depth >5 )return -ELOOP ; retval =security_bprm_check (bprm);
@@ -1396,9 +1395,9 @@ int search_binary_handler(struct linux_binprm *bprm)if (!try_module_get (fmt->module))continue ;read_unlock (&binfmt_lock); - bprm->recursion_depth = depth +1 ; + bprm->recursion_depth++; retval =fn (bprm); - bprm->recursion_depth = depth; + bprm->recursion_depth--;if (retval >=0 ) {put_binfmt (fmt);allow_write_access (bprm->file);
Signature · 1 line
1.5.5.1
Re: [PATCH 2/3] exec: kill "int depth" in search_binary_handler()
Quoted 2 lines · Oleg Nesterov
Nobody except
search_binary_handler()should touch ->recursion_depth, "int depth" buys nothing but complicates the code, kill it.
I'd like to see a comment added to binfmts.h's recursion_depth field that reminds people that recursion_depth is for search_binary_handler()'s use only, and a binfmt loader shouldn't touch it. Besides that, yeah, sensible clean up.
-Kees
Signature · 2 lines
Kees Cook Chrome OS Security
PATCH v2 2/3 exec: kill "int depth" in search_binary_handler()
Quoted 9 lines · Kees Cook
Quoted 2 lines · Oleg Nesterov
Nobody except
search_binary_handler()should touch ->recursion_depth, "int depth" buys nothing but complicates the code, kill it.I'd like to see a comment added to binfmts.h's
recursion_depthfield that reminds people thatrecursion_depthis for search_binary_handler()'s use only, and a binfmt loader shouldn't touch it.
And this comment probably makes sense even without this change
Quoted 1 line
Besides that, yeah, sensible clean up.
OK, thanks, please see v2. The only change is the comment in .h
------------------------------------------------------------------------------
Subject: [PATCH 1/1] exec: kill "int depth" in search_binary_handler()
Nobody except search_binary_handler() should touch ->recursion_depth, "int depth" buys nothing but complicates the code, kill it.
Probably we should also kill "fn" and the !NULL check, ->load_binary should be always defined. And it can not go away after read_unlock() or this code is buggy anyway.
v2: add the comment about linux_binprm->recursion_depth
--- fs/exec.c | 9 ++++----- include/linux/binfmts.h | 2 +- 2 files changed, 5 insertions(+), 6 deletions(-)
fs/exec.c +4 -5
@@ -1370,12 +1370,11 @@ EXPORT_SYMBOL(remove_arg_zero);*/ int search_binary_handler (struct linux_binprm *bprm) { -unsigned int depth = bprm->recursion_depth; -int try,retval; +int try, retval;struct linux_binfmt *fmt;/* This allows 4 levels of binfmt rewrites before failing hard. */ -if (depth >5 ) +if (bprm->recursion_depth >5 )return -ELOOP ; retval =security_bprm_check (bprm);
@@ -1396,9 +1395,9 @@ int search_binary_handler(struct linux_binprm *bprm)if (!try_module_get (fmt->module))continue ;read_unlock (&binfmt_lock); - bprm->recursion_depth = depth +1 ; + bprm->recursion_depth++; retval =fn (bprm); - bprm->recursion_depth = depth; + bprm->recursion_depth--;if (retval >=0 ) {put_binfmt (fmt);allow_write_access (bprm->file);
include/linux/binfmts.h +1 -1
@@ -31,7 +31,7 @@ struct linux_binprm {#ifdef __alpha__ unsigned int taso:1;#endif -unsigned int recursion_depth; +unsigned int recursion_depth;/* only for search_binary_handler() */ struct file * file;struct cred *cred;/* new credentials */ int unsafe;/* how unsafe this exec is (mask of LSM_UNSAFE_*) */
Signature · 1 line
1.5.5.1
Re: [PATCH v2 2/3] exec: kill "int depth" in search_binary_handler()
Quoted 6 lines · Oleg Nesterov
Quoted 5 lines · Kees Cook
Quoted 2 lines · Oleg Nesterov
Nobody except
search_binary_handler()should touch ->recursion_depth, "int depth" buys nothing but complicates the code, kill it.
Quoted 6 lines
Quoted 4 lines
I'd like to see a comment added to binfmts.h's
recursion_depthfield that reminds people thatrecursion_depthis for search_binary_handler()'s use only, and a binfmt loader shouldn't touch it.And this comment probably makes sense even without this change
Yeah totally agreed -- I should have added this when I reorganized the depth handling earlier. :)
Quoted 10 lines
Quoted 1 line
Besides that, yeah, sensible clean up.
OK, thanks, please see v2. The only change is the comment in .h
------------------------------------------------------------------------------
Subject: [PATCH 1/1] exec: kill "int depth" insearch_binary_handler()Nobody except
search_binary_handler()should touch ->recursion_depth, "int depth" buys nothing but complicates the code, kill it.
Quoted 7 lines
Probably we should also kill "fn" and the !NULL check, ->load_binary should be always defined. And it can not go away after
read_unlock()or this code is buggy anyway.v2: add the comment about
linux_binprm->recursion_depthSigned-off-by Oleg Nesterov <[email protected]>
Thanks,
-Kees
Quoted 53 lines
--- fs/exec.c | 9 ++++----- include/linux/binfmts.h | 2 +- 2 files changed, 5 insertions(+), 6 deletions(-)fs/exec.c +4
-5@@ -1370,12 +1370,11 @@ EXPORT_SYMBOL(remove_arg_zero);*/ int search_binary_handler (struct linux_binprm *bprm) { -unsigned int depth = bprm->recursion_depth; -int try,retval; +int try, retval;struct linux_binfmt *fmt;/* This allows 4 levels of binfmt rewrites before failing hard. */ -if (depth >5 ) +if (bprm->recursion_depth >5 )return -ELOOP ; retval =security_bprm_check (bprm);@@ -1396,9 +1395,9 @@ int search_binary_handler(struct linux_binprm *bprm)if (!try_module_get (fmt->module))continue ;read_unlock (&binfmt_lock); - bprm->recursion_depth = depth +1 ; + bprm->recursion_depth++; retval =fn (bprm); - bprm->recursion_depth = depth; + bprm->recursion_depth--;if (retval >=0 ) {put_binfmt (fmt);allow_write_access (bprm->file);include/linux/binfmts.h +1
-2@@ -31,7 +31,7 @@ struct linux_binprm {#ifdef __alpha__ unsigned int taso:1;#endif -unsigned int recursion_depth; +unsigned int recursion_depth;/* only for search_binary_handler() */ struct file * file;struct cred *cred;/* new credentials */ int unsafe;/* how unsafe this exec is (mask of LSM_UNSAFE_*) */ --1.5.5.1
Signature · 2 lines
Kees Cook Chrome OS Security
PATCH 3/3 exec: proc_exec_connector() should be called only once
In reply to Oleg NesterovA separate one-liner with the minor fix.
PROC_EVENT_EXEC reports the "exec" event, but this message is sent at least twice if search_binary_handler() is called by ->load_binary() recursively, say, load_script().
Move it to exec_binprm(), this is "depth == 0" code too.
--- fs/exec.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
fs/exec.c +1 -1
@@ -1404,7 +1404,6 @@ int search_binary_handler(struct linux_binprm *bprm)if (bprm->file)fput (bprm->file); bprm->file =NULL ; -proc_exec_connector (current);return retval; }read_lock (&binfmt_lock);
@@ -1455,6 +1454,7 @@ static int exec_binprm(struct linux_binprm *bprm)trace_sched_process_exec (current, old_pid, bprm);ptrace_event (PTRACE_EVENT_EXEC , old_vpid); current->did_exec =1 ; +proc_exec_connector (current); }return ret;
Signature · 1 line
1.5.5.1
Re: [PATCH 3/3] exec: proc_exec_connector() should be called only once
Quoted 9 lines · Oleg Nesterov
A separate one-liner with the minor fix.
PROC_EVENT_EXECreports the "exec" event, but this message is sent at least twice ifsearch_binary_handler()is called by ->load_binary() recursively, say,load_script().Move it to
exec_binprm(), this is "depth == 0" code too.Signed-off-by Oleg Nesterov <[email protected]>
Yeah, looks right. I almost mentioned this while reading the other cleanup patch, but then you fixed it too. :)
Thanks,
-Kees
Signature · 2 lines
Kees Cook Chrome OS Security
Quoted 9 lines · Oleg Nesterov
Andrew,
By discussion with Zach, please drop
fs-binfmts-add-a-name-field-to-the-binfmt-struct.patch fs-binfmts-better-handling-of-binfmt-loops.patch fs-binfmts-whitespace-fixes-with-scripts-cleanfile.patch
Quoted 6 lines
Zach is working on v2.
Meanwhile, can't we cleanup
search_binary_handler()a bit? It doesn't look nice imho. And we can certainly cleanup it more (perhaps I'll try tomorrow). The error handling,request_module()logic and even "for (try=0; try<2; try++)" looks horrible imho.
Seriously, I think this should be cleanuped too.
Zach, I am sorry if you already rebased your changes, I'll send a couple more patches today.
Oleg.
Quoted 17 lines · Oleg Nesterov
Quoted 9 lines · Oleg Nesterov
Andrew,
By discussion with Zach, please drop
fs-binfmts-add-a-name-field-to-the-binfmt-struct.patch fs-binfmts-better-handling-of-binfmt-loops.patch fs-binfmts-whitespace-fixes-with-scripts-cleanfile.patch
Quoted 6 lines
Zach is working on v2.
Meanwhile, can't we cleanup
search_binary_handler()a bit? It doesn't look nice imho. And we can certainly cleanup it more (perhaps I'll try tomorrow). The error handling,request_module()logic and even "for (try=0; try<2; try++)" looks horrible imho.
Quoted 5 lines
Seriously, I think this should be cleanuped too.
Zach, I am sorry if you already rebased your changes, I'll send a couple more patches today.
Don't worry -- I've been holding off on sending v2 for your changes today. It's not much git wrangling to apply your additional patches anyway.
Quoted 2 lines
Oleg.
Andrew,
please ignore this and the next series, I'll resend everything with a couple of cosmetic changes.
Plus I believe audit_bprm() is not right too, this needs another patch.
Quoted 17 lines · Oleg Nesterov
Andrew,
By discussion with Zach, please drop
fs-binfmts-add-a-name-field-to-the-binfmt-struct.patch fs-binfmts-better-handling-of-binfmt-loops.patch fs-binfmts-whitespace-fixes-with-scripts-cleanfile.patch
Zach is working on v2.
Meanwhile, can't we cleanup
search_binary_handler()a bit? It doesn't look nice imho. And we can certainly cleanup it more (perhaps I'll try tomorrow). The error handling,request_module()logic and even "for (try=0; try<2; try++)" looks horrible imho.Oleg.