generic sys_execve()
authorAl Viro <viro@zeniv.linux.org.uk>
Sun, 30 Sep 2012 17:38:55 +0000 (13:38 -0400)
committerAl Viro <viro@zeniv.linux.org.uk>
Mon, 1 Oct 2012 02:20:51 +0000 (22:20 -0400)
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>
fs/exec.c
include/linux/compat.h

index 48c5251..50a1270 100644 (file)
--- 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[],
index 09b28b7..c4be3f5 100644 (file)
@@ -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,