aboutsummaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-02-05 15:54:53 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2014-02-05 15:54:53 -0500
commitc4ad8f98bef77c7356aa6a9ad9188a6acc6b849d (patch)
tree16117463e3106b2be026afbe843019cf5d3c3270 /include
parent878a876b2e10888afe53766dcca33f723ae20edc (diff)
execve: use 'struct filename *' for executable name passing
This changes 'do_execve()' to get the executable name as a 'struct filename', and to free it when it is done. This is what the normal users want, and it simplifies and streamlines their error handling. The controlled lifetime of the executable name also fixes a use-after-free problem with the trace_sched_process_exec tracepoint: the lifetime of the passed-in string for kernel users was not at all obvious, and the user-mode helper code used UMH_WAIT_EXEC to serialize the pathname allocation lifetime with the execve() having finished, which in turn meant that the trace point that happened after mm_release() of the old process VM ended up using already free'd memory. To solve the kernel string lifetime issue, this simply introduces "getname_kernel()" that works like the normal user-space getname() function, except with the source coming from kernel memory. As Oleg points out, this also means that we could drop the tcomm[] array from 'struct linux_binprm', since the pathname lifetime now covers setup_new_exec(). That would be a separate cleanup. Reported-by: Igor Zhbanov <i.zhbanov@samsung.com> Tested-by: Steven Rostedt <rostedt@goodmis.org> Cc: Oleg Nesterov <oleg@redhat.com> Cc: Al Viro <viro@zeniv.linux.org.uk> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'include')
-rw-r--r--include/linux/binfmts.h1
-rw-r--r--include/linux/fs.h1
-rw-r--r--include/linux/sched.h3
3 files changed, 3 insertions, 2 deletions
diff --git a/include/linux/binfmts.h b/include/linux/binfmts.h
index fd8bf3219ef7..b4a745d7d9a9 100644
--- a/include/linux/binfmts.h
+++ b/include/linux/binfmts.h
@@ -115,7 +115,6 @@ extern int copy_strings_kernel(int argc, const char *const *argv,
115extern int prepare_bprm_creds(struct linux_binprm *bprm); 115extern int prepare_bprm_creds(struct linux_binprm *bprm);
116extern void install_exec_creds(struct linux_binprm *bprm); 116extern void install_exec_creds(struct linux_binprm *bprm);
117extern void set_binfmt(struct linux_binfmt *new); 117extern void set_binfmt(struct linux_binfmt *new);
118extern void free_bprm(struct linux_binprm *);
119extern ssize_t read_code(struct file *, unsigned long, loff_t, size_t); 118extern ssize_t read_code(struct file *, unsigned long, loff_t, size_t);
120 119
121#endif /* _LINUX_BINFMTS_H */ 120#endif /* _LINUX_BINFMTS_H */
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 09f553c59813..d79678c188ad 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -2079,6 +2079,7 @@ extern struct file * dentry_open(const struct path *, int, const struct cred *);
2079extern int filp_close(struct file *, fl_owner_t id); 2079extern int filp_close(struct file *, fl_owner_t id);
2080 2080
2081extern struct filename *getname(const char __user *); 2081extern struct filename *getname(const char __user *);
2082extern struct filename *getname_kernel(const char *);
2082 2083
2083enum { 2084enum {
2084 FILE_CREATED = 1, 2085 FILE_CREATED = 1,
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 68a0e84463a0..a781dec1cd0b 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -128,6 +128,7 @@ struct bio_list;
128struct fs_struct; 128struct fs_struct;
129struct perf_event_context; 129struct perf_event_context;
130struct blk_plug; 130struct blk_plug;
131struct filename;
131 132
132/* 133/*
133 * List of flags we want to share for kernel threads, 134 * List of flags we want to share for kernel threads,
@@ -2311,7 +2312,7 @@ extern void do_group_exit(int);
2311extern int allow_signal(int); 2312extern int allow_signal(int);
2312extern int disallow_signal(int); 2313extern int disallow_signal(int);
2313 2314
2314extern int do_execve(const char *, 2315extern int do_execve(struct filename *,
2315 const char __user * const __user *, 2316 const char __user * const __user *,
2316 const char __user * const __user *); 2317 const char __user * const __user *);
2317extern long do_fork(unsigned long, unsigned long, unsigned long, int __user *, int __user *); 2318extern long do_fork(unsigned long, unsigned long, unsigned long, int __user *, int __user *);