diff options
-rw-r--r-- | fs/exec.c | 22 | ||||
-rw-r--r-- | include/linux/binfmts.h | 5 |
2 files changed, 27 insertions, 0 deletions
diff --git a/fs/exec.c b/fs/exec.c index d7f9e14f8977..48c525115fe4 100644 --- a/fs/exec.c +++ b/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/include/linux/binfmts.h b/include/linux/binfmts.h index 8938beabad7a..f9c9d08f4f7c 100644 --- a/include/linux/binfmts.h +++ b/include/linux/binfmts.h @@ -19,6 +19,7 @@ struct pt_regs; #ifdef __KERNEL__ #include <linux/sched.h> +#include <linux/unistd.h> #include <asm/exec.h> #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 */ |