aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2012-10-10 21:28:25 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2012-10-12 13:35:07 -0400
commita74fb73c12398b250fdc5e333a11e15a9e3a84fc (patch)
tree2bec2f6e20320f5a4bc01d1e19d7190842ef1c37
parentfb45550d76bb584857cf0ea3be79fa78207a3cff (diff)
infrastructure for saner ret_from_kernel_thread semantics
* allow kernel_execve() leave the actual return to userland to caller (selected by CONFIG_GENERIC_KERNEL_EXECVE). Callers updated accordingly. * architecture that does select GENERIC_KERNEL_EXECVE in its Kconfig should have its ret_from_kernel_thread() do this: call schedule_tail call the callback left for it by copy_thread(); if it ever returns, that's because it has just done successful kernel_execve() jump to return from syscall IOW, its only difference from ret_from_fork() is that it does call the callback. * such an architecture should also get rid of ret_from_kernel_execve() and __ARCH_WANT_KERNEL_EXECVE This is the last part of infrastructure patches in that area - from that point on work on different architectures can live independently. Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r--arch/Kconfig3
-rw-r--r--include/linux/syscalls.h8
-rw-r--r--init/main.c20
-rw-r--r--kernel/kmod.c3
-rw-r--r--kernel/kthread.c1
5 files changed, 27 insertions, 8 deletions
diff --git a/arch/Kconfig b/arch/Kconfig
index d397e11d167d..d27efb9bfafd 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -261,6 +261,9 @@ config ARCH_WANT_OLD_COMPAT_IPC
261config GENERIC_KERNEL_THREAD 261config GENERIC_KERNEL_THREAD
262 bool 262 bool
263 263
264config GENERIC_KERNEL_EXECVE
265 bool
266
264config HAVE_ARCH_SECCOMP_FILTER 267config HAVE_ARCH_SECCOMP_FILTER
265 bool 268 bool
266 help 269 help
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
index 19439c75c5b2..727f0cd73921 100644
--- a/include/linux/syscalls.h
+++ b/include/linux/syscalls.h
@@ -827,7 +827,15 @@ asmlinkage long sys_fanotify_mark(int fanotify_fd, unsigned int flags,
827 const char __user *pathname); 827 const char __user *pathname);
828asmlinkage long sys_syncfs(int fd); 828asmlinkage long sys_syncfs(int fd);
829 829
830#ifndef CONFIG_GENERIC_KERNEL_EXECVE
830int kernel_execve(const char *filename, const char *const argv[], const char *const envp[]); 831int kernel_execve(const char *filename, const char *const argv[], const char *const envp[]);
832#else
833#define kernel_execve(filename, argv, envp) \
834 do_execve(filename, \
835 (const char __user *const __user *)argv, \
836 (const char __user *const __user *)envp, \
837 current_pt_regs())
838#endif
831 839
832 840
833asmlinkage long sys_perf_event_open( 841asmlinkage long sys_perf_event_open(
diff --git a/init/main.c b/init/main.c
index a490ffecb7b9..02df2ddc5f83 100644
--- a/init/main.c
+++ b/init/main.c
@@ -69,6 +69,7 @@
69#include <linux/slab.h> 69#include <linux/slab.h>
70#include <linux/perf_event.h> 70#include <linux/perf_event.h>
71#include <linux/file.h> 71#include <linux/file.h>
72#include <linux/ptrace.h>
72 73
73#include <asm/io.h> 74#include <asm/io.h>
74#include <asm/bugs.h> 75#include <asm/bugs.h>
@@ -788,10 +789,10 @@ static void __init do_pre_smp_initcalls(void)
788 do_one_initcall(*fn); 789 do_one_initcall(*fn);
789} 790}
790 791
791static void run_init_process(const char *init_filename) 792static int run_init_process(const char *init_filename)
792{ 793{
793 argv_init[0] = init_filename; 794 argv_init[0] = init_filename;
794 kernel_execve(init_filename, argv_init, envp_init); 795 return kernel_execve(init_filename, argv_init, envp_init);
795} 796}
796 797
797static void __init kernel_init_freeable(void); 798static void __init kernel_init_freeable(void);
@@ -810,7 +811,8 @@ static int __ref kernel_init(void *unused)
810 flush_delayed_fput(); 811 flush_delayed_fput();
811 812
812 if (ramdisk_execute_command) { 813 if (ramdisk_execute_command) {
813 run_init_process(ramdisk_execute_command); 814 if (!run_init_process(ramdisk_execute_command))
815 return 0;
814 printk(KERN_WARNING "Failed to execute %s\n", 816 printk(KERN_WARNING "Failed to execute %s\n",
815 ramdisk_execute_command); 817 ramdisk_execute_command);
816 } 818 }
@@ -822,14 +824,16 @@ static int __ref kernel_init(void *unused)
822 * trying to recover a really broken machine. 824 * trying to recover a really broken machine.
823 */ 825 */
824 if (execute_command) { 826 if (execute_command) {
825 run_init_process(execute_command); 827 if (!run_init_process(execute_command))
828 return 0;
826 printk(KERN_WARNING "Failed to execute %s. Attempting " 829 printk(KERN_WARNING "Failed to execute %s. Attempting "
827 "defaults...\n", execute_command); 830 "defaults...\n", execute_command);
828 } 831 }
829 run_init_process("/sbin/init"); 832 if (!run_init_process("/sbin/init") ||
830 run_init_process("/etc/init"); 833 !run_init_process("/etc/init") ||
831 run_init_process("/bin/init"); 834 !run_init_process("/bin/init") ||
832 run_init_process("/bin/sh"); 835 !run_init_process("/bin/sh"))
836 return 0;
833 837
834 panic("No init found. Try passing init= option to kernel. " 838 panic("No init found. Try passing init= option to kernel. "
835 "See Linux Documentation/init.txt for guidance."); 839 "See Linux Documentation/init.txt for guidance.");
diff --git a/kernel/kmod.c b/kernel/kmod.c
index b6e5ca9c758a..1c317e386831 100644
--- a/kernel/kmod.c
+++ b/kernel/kmod.c
@@ -37,6 +37,7 @@
37#include <linux/notifier.h> 37#include <linux/notifier.h>
38#include <linux/suspend.h> 38#include <linux/suspend.h>
39#include <linux/rwsem.h> 39#include <linux/rwsem.h>
40#include <linux/ptrace.h>
40#include <asm/uaccess.h> 41#include <asm/uaccess.h>
41 42
42#include <trace/events/module.h> 43#include <trace/events/module.h>
@@ -221,6 +222,8 @@ static int ____call_usermodehelper(void *data)
221 retval = kernel_execve(sub_info->path, 222 retval = kernel_execve(sub_info->path,
222 (const char *const *)sub_info->argv, 223 (const char *const *)sub_info->argv,
223 (const char *const *)sub_info->envp); 224 (const char *const *)sub_info->envp);
225 if (!retval)
226 return 0;
224 227
225 /* Exec failed? */ 228 /* Exec failed? */
226fail: 229fail:
diff --git a/kernel/kthread.c b/kernel/kthread.c
index b579af57ea10..7ba65c1aa6b3 100644
--- a/kernel/kthread.c
+++ b/kernel/kthread.c
@@ -16,6 +16,7 @@
16#include <linux/mutex.h> 16#include <linux/mutex.h>
17#include <linux/slab.h> 17#include <linux/slab.h>
18#include <linux/freezer.h> 18#include <linux/freezer.h>
19#include <linux/ptrace.h>
19#include <trace/events/sched.h> 20#include <trace/events/sched.h>
20 21
21static DEFINE_SPINLOCK(kthread_create_lock); 22static DEFINE_SPINLOCK(kthread_create_lock);