diff --git a/[refs] b/[refs] index 0d101b19a690..653c85103b0c 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: a3460a59747cfddfa7be4758e5ef08bf5d751d59 +refs/heads/master: 282124d18626379a20b41d25e0c580f290cd09d4 diff --git a/trunk/fs/exec.c b/trunk/fs/exec.c index d7f9e14f8977..48c525115fe4 100644 --- a/trunk/fs/exec.c +++ b/trunk/fs/exec.c @@ -2318,3 +2318,25 @@ int dump_seek(struct file *file, loff_t off) return ret; } EXPORT_SYMBOL(dump_seek); + +#ifdef __ARCH_WANT_KERNEL_EXECVE +int kernel_execve(const char *filename, + const char *const argv[], + const char *const envp[]) +{ + struct pt_regs *p = current_pt_regs(); + int ret; + + ret = do_execve(filename, + (const char __user *const __user *)argv, + (const char __user *const __user *)envp, p); + if (ret < 0) + return ret; + + /* + * We were successful. We won't be returning to our caller, but + * instead to user space by manipulating the kernel stack. + */ + ret_from_kernel_execve(p); +} +#endif diff --git a/trunk/include/linux/binfmts.h b/trunk/include/linux/binfmts.h index 8938beabad7a..f9c9d08f4f7c 100644 --- a/trunk/include/linux/binfmts.h +++ b/trunk/include/linux/binfmts.h @@ -19,6 +19,7 @@ struct pt_regs; #ifdef __KERNEL__ #include +#include #include #define CORENAME_MAX_SIZE 128 @@ -137,5 +138,9 @@ extern void do_coredump(long signr, int exit_code, struct pt_regs *regs); extern void set_binfmt(struct linux_binfmt *new); extern void free_bprm(struct linux_binprm *); +#ifdef __ARCH_WANT_KERNEL_EXECVE +extern void ret_from_kernel_execve(struct pt_regs *normal) __noreturn; +#endif + #endif /* __KERNEL__ */ #endif /* _LINUX_BINFMTS_H */