diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2012-09-30 13:38:55 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2012-09-30 22:20:51 -0400 |
commit | 38b983b3461e7d3c64a981e2338bb34605c46f30 (patch) | |
tree | fb7dc311ba4d175746fb693530cf63db9ddb8616 | |
parent | 282124d18626379a20b41d25e0c580f290cd09d4 (diff) |
generic sys_execve()
Selected by __ARCH_WANT_SYS_EXECVE in unistd.h. Requires
* working current_pt_regs()
* *NOT* doing a syscall-in-kernel kind of kernel_execve()
implementation. Using generic kernel_execve() is fine.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r-- | fs/exec.c | 38 | ||||
-rw-r--r-- | include/linux/compat.h | 8 |
2 files changed, 40 insertions, 6 deletions
diff --git a/fs/exec.c b/fs/exec.c index 48c525115fe4..50a1270da95b 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -401,7 +401,7 @@ struct user_arg_ptr { union { const char __user *const __user *native; #ifdef CONFIG_COMPAT - compat_uptr_t __user *compat; + const compat_uptr_t __user *compat; #endif } ptr; }; @@ -1600,9 +1600,9 @@ int do_execve(const char *filename, } #ifdef CONFIG_COMPAT -int compat_do_execve(char *filename, - compat_uptr_t __user *__argv, - compat_uptr_t __user *__envp, +int compat_do_execve(const char *filename, + const compat_uptr_t __user *__argv, + const compat_uptr_t __user *__envp, struct pt_regs *regs) { struct user_arg_ptr argv = { @@ -2319,6 +2319,36 @@ int dump_seek(struct file *file, loff_t off) } EXPORT_SYMBOL(dump_seek); +#ifdef __ARCH_WANT_SYS_EXECVE +SYSCALL_DEFINE3(execve, + const char __user *, filename, + const char __user *const __user *, argv, + const char __user *const __user *, envp) +{ + const char *path = getname(filename); + int error = PTR_ERR(path); + if (!IS_ERR(path)) { + error = do_execve(path, argv, envp, current_pt_regs()); + putname(path); + } + return error; +} +#ifdef CONFIG_COMPAT +asmlinkage long compat_sys_execve(const char __user * filename, + const compat_uptr_t __user * argv, + const compat_uptr_t __user * envp) +{ + const char *path = getname(filename); + int error = PTR_ERR(path); + if (!IS_ERR(path)) { + error = compat_do_execve(path, argv, envp, current_pt_regs()); + putname(path); + } + return error; +} +#endif +#endif + #ifdef __ARCH_WANT_KERNEL_EXECVE int kernel_execve(const char *filename, const char *const argv[], diff --git a/include/linux/compat.h b/include/linux/compat.h index 09b28b7369d7..c4be3f55511d 100644 --- a/include/linux/compat.h +++ b/include/linux/compat.h @@ -289,8 +289,12 @@ asmlinkage ssize_t compat_sys_pwritev(unsigned long fd, const struct compat_iovec __user *vec, unsigned long vlen, u32 pos_low, u32 pos_high); -int compat_do_execve(char *filename, compat_uptr_t __user *argv, - compat_uptr_t __user *envp, struct pt_regs *regs); +int compat_do_execve(const char *filename, const compat_uptr_t __user *argv, + const compat_uptr_t __user *envp, struct pt_regs *regs); +#ifdef __ARCH_WANT_SYS_EXECVE +asmlinkage long compat_sys_execve(const char __user *filename, const compat_uptr_t __user *argv, + const compat_uptr_t __user *envp); +#endif asmlinkage long compat_sys_select(int n, compat_ulong_t __user *inp, compat_ulong_t __user *outp, compat_ulong_t __user *exp, |