diff options
-rw-r--r-- | fs/exec.c | 5 | ||||
-rw-r--r-- | include/linux/pid.h | 5 | ||||
-rw-r--r-- | include/linux/pid_namespace.h | 6 | ||||
-rw-r--r-- | include/linux/sched.h | 1 | ||||
-rw-r--r-- | init/main.c | 5 | ||||
-rw-r--r-- | kernel/exit.c | 23 | ||||
-rw-r--r-- | kernel/pid.c | 3 | ||||
-rw-r--r-- | kernel/signal.c | 11 |
8 files changed, 40 insertions, 19 deletions
@@ -38,6 +38,7 @@ | |||
38 | #include <linux/binfmts.h> | 38 | #include <linux/binfmts.h> |
39 | #include <linux/swap.h> | 39 | #include <linux/swap.h> |
40 | #include <linux/utsname.h> | 40 | #include <linux/utsname.h> |
41 | #include <linux/pid_namespace.h> | ||
41 | #include <linux/module.h> | 42 | #include <linux/module.h> |
42 | #include <linux/namei.h> | 43 | #include <linux/namei.h> |
43 | #include <linux/proc_fs.h> | 44 | #include <linux/proc_fs.h> |
@@ -620,8 +621,8 @@ static int de_thread(struct task_struct *tsk) | |||
620 | * Reparenting needs write_lock on tasklist_lock, | 621 | * Reparenting needs write_lock on tasklist_lock, |
621 | * so it is safe to do it under read_lock. | 622 | * so it is safe to do it under read_lock. |
622 | */ | 623 | */ |
623 | if (unlikely(tsk->group_leader == child_reaper)) | 624 | if (unlikely(tsk->group_leader == child_reaper(tsk))) |
624 | child_reaper = tsk; | 625 | tsk->nsproxy->pid_ns->child_reaper = tsk; |
625 | 626 | ||
626 | zap_other_threads(tsk); | 627 | zap_other_threads(tsk); |
627 | read_unlock(&tasklist_lock); | 628 | read_unlock(&tasklist_lock); |
diff --git a/include/linux/pid.h b/include/linux/pid.h index 2c0007d17218..4dec047b1837 100644 --- a/include/linux/pid.h +++ b/include/linux/pid.h | |||
@@ -35,8 +35,9 @@ enum pid_type | |||
35 | * | 35 | * |
36 | * Holding a reference to struct pid solves both of these problems. | 36 | * Holding a reference to struct pid solves both of these problems. |
37 | * It is small so holding a reference does not consume a lot of | 37 | * It is small so holding a reference does not consume a lot of |
38 | * resources, and since a new struct pid is allocated when the numeric | 38 | * resources, and since a new struct pid is allocated when the numeric pid |
39 | * pid value is reused we don't mistakenly refer to new processes. | 39 | * value is reused (when pids wrap around) we don't mistakenly refer to new |
40 | * processes. | ||
40 | */ | 41 | */ |
41 | 42 | ||
42 | struct pid | 43 | struct pid |
diff --git a/include/linux/pid_namespace.h b/include/linux/pid_namespace.h index 76e7c6b2cf33..d2a9d419f01f 100644 --- a/include/linux/pid_namespace.h +++ b/include/linux/pid_namespace.h | |||
@@ -19,6 +19,7 @@ struct pid_namespace { | |||
19 | struct kref kref; | 19 | struct kref kref; |
20 | struct pidmap pidmap[PIDMAP_ENTRIES]; | 20 | struct pidmap pidmap[PIDMAP_ENTRIES]; |
21 | int last_pid; | 21 | int last_pid; |
22 | struct task_struct *child_reaper; | ||
22 | }; | 23 | }; |
23 | 24 | ||
24 | extern struct pid_namespace init_pid_ns; | 25 | extern struct pid_namespace init_pid_ns; |
@@ -36,4 +37,9 @@ static inline void put_pid_ns(struct pid_namespace *ns) | |||
36 | kref_put(&ns->kref, free_pid_ns); | 37 | kref_put(&ns->kref, free_pid_ns); |
37 | } | 38 | } |
38 | 39 | ||
40 | static inline struct task_struct *child_reaper(struct task_struct *tsk) | ||
41 | { | ||
42 | return tsk->nsproxy->pid_ns->child_reaper; | ||
43 | } | ||
44 | |||
39 | #endif /* _LINUX_PID_NS_H */ | 45 | #endif /* _LINUX_PID_NS_H */ |
diff --git a/include/linux/sched.h b/include/linux/sched.h index 6fec1d419714..f0317edea141 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h | |||
@@ -1400,7 +1400,6 @@ extern NORET_TYPE void do_group_exit(int); | |||
1400 | extern void daemonize(const char *, ...); | 1400 | extern void daemonize(const char *, ...); |
1401 | extern int allow_signal(int); | 1401 | extern int allow_signal(int); |
1402 | extern int disallow_signal(int); | 1402 | extern int disallow_signal(int); |
1403 | extern struct task_struct *child_reaper; | ||
1404 | 1403 | ||
1405 | extern int do_execve(char *, char __user * __user *, char __user * __user *, struct pt_regs *); | 1404 | extern int do_execve(char *, char __user * __user *, char __user * __user *, struct pt_regs *); |
1406 | extern long do_fork(unsigned long, unsigned long, struct pt_regs *, unsigned long, int __user *, int __user *); | 1405 | extern long do_fork(unsigned long, unsigned long, struct pt_regs *, unsigned long, int __user *, int __user *); |
diff --git a/init/main.c b/init/main.c index 4cdcd06e6d78..036f97c0c34c 100644 --- a/init/main.c +++ b/init/main.c | |||
@@ -51,6 +51,7 @@ | |||
51 | #include <linux/debug_locks.h> | 51 | #include <linux/debug_locks.h> |
52 | #include <linux/lockdep.h> | 52 | #include <linux/lockdep.h> |
53 | #include <linux/utsrelease.h> | 53 | #include <linux/utsrelease.h> |
54 | #include <linux/pid_namespace.h> | ||
54 | #include <linux/compile.h> | 55 | #include <linux/compile.h> |
55 | 56 | ||
56 | #include <asm/io.h> | 57 | #include <asm/io.h> |
@@ -626,8 +627,6 @@ static int __init initcall_debug_setup(char *str) | |||
626 | } | 627 | } |
627 | __setup("initcall_debug", initcall_debug_setup); | 628 | __setup("initcall_debug", initcall_debug_setup); |
628 | 629 | ||
629 | struct task_struct *child_reaper = &init_task; | ||
630 | |||
631 | extern initcall_t __initcall_start[], __initcall_end[]; | 630 | extern initcall_t __initcall_start[], __initcall_end[]; |
632 | 631 | ||
633 | static void __init do_initcalls(void) | 632 | static void __init do_initcalls(void) |
@@ -727,7 +726,7 @@ static int init(void * unused) | |||
727 | * assumptions about where in the task array this | 726 | * assumptions about where in the task array this |
728 | * can be found. | 727 | * can be found. |
729 | */ | 728 | */ |
730 | child_reaper = current; | 729 | init_pid_ns.child_reaper = current; |
731 | 730 | ||
732 | cad_pid = task_pid(current); | 731 | cad_pid = task_pid(current); |
733 | 732 | ||
diff --git a/kernel/exit.c b/kernel/exit.c index 28d9feedfd27..fd0e067952ab 100644 --- a/kernel/exit.c +++ b/kernel/exit.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <linux/file.h> | 22 | #include <linux/file.h> |
23 | #include <linux/binfmts.h> | 23 | #include <linux/binfmts.h> |
24 | #include <linux/nsproxy.h> | 24 | #include <linux/nsproxy.h> |
25 | #include <linux/pid_namespace.h> | ||
25 | #include <linux/ptrace.h> | 26 | #include <linux/ptrace.h> |
26 | #include <linux/profile.h> | 27 | #include <linux/profile.h> |
27 | #include <linux/mount.h> | 28 | #include <linux/mount.h> |
@@ -48,7 +49,6 @@ | |||
48 | #include <asm/mmu_context.h> | 49 | #include <asm/mmu_context.h> |
49 | 50 | ||
50 | extern void sem_exit (void); | 51 | extern void sem_exit (void); |
51 | extern struct task_struct *child_reaper; | ||
52 | 52 | ||
53 | static void exit_mm(struct task_struct * tsk); | 53 | static void exit_mm(struct task_struct * tsk); |
54 | 54 | ||
@@ -260,7 +260,8 @@ static int has_stopped_jobs(int pgrp) | |||
260 | } | 260 | } |
261 | 261 | ||
262 | /** | 262 | /** |
263 | * reparent_to_init - Reparent the calling kernel thread to the init task. | 263 | * reparent_to_init - Reparent the calling kernel thread to the init task |
264 | * of the pid space that the thread belongs to. | ||
264 | * | 265 | * |
265 | * If a kernel thread is launched as a result of a system call, or if | 266 | * If a kernel thread is launched as a result of a system call, or if |
266 | * it ever exits, it should generally reparent itself to init so that | 267 | * it ever exits, it should generally reparent itself to init so that |
@@ -278,8 +279,8 @@ static void reparent_to_init(void) | |||
278 | ptrace_unlink(current); | 279 | ptrace_unlink(current); |
279 | /* Reparent to init */ | 280 | /* Reparent to init */ |
280 | remove_parent(current); | 281 | remove_parent(current); |
281 | current->parent = child_reaper; | 282 | current->parent = child_reaper(current); |
282 | current->real_parent = child_reaper; | 283 | current->real_parent = child_reaper(current); |
283 | add_parent(current); | 284 | add_parent(current); |
284 | 285 | ||
285 | /* Set the exit signal to SIGCHLD so we signal init on exit */ | 286 | /* Set the exit signal to SIGCHLD so we signal init on exit */ |
@@ -662,7 +663,8 @@ reparent_thread(struct task_struct *p, struct task_struct *father, int traced) | |||
662 | * When we die, we re-parent all our children. | 663 | * When we die, we re-parent all our children. |
663 | * Try to give them to another thread in our thread | 664 | * Try to give them to another thread in our thread |
664 | * group, and if no such member exists, give it to | 665 | * group, and if no such member exists, give it to |
665 | * the global child reaper process (ie "init") | 666 | * the child reaper process (ie "init") in our pid |
667 | * space. | ||
666 | */ | 668 | */ |
667 | static void | 669 | static void |
668 | forget_original_parent(struct task_struct *father, struct list_head *to_release) | 670 | forget_original_parent(struct task_struct *father, struct list_head *to_release) |
@@ -673,7 +675,7 @@ forget_original_parent(struct task_struct *father, struct list_head *to_release) | |||
673 | do { | 675 | do { |
674 | reaper = next_thread(reaper); | 676 | reaper = next_thread(reaper); |
675 | if (reaper == father) { | 677 | if (reaper == father) { |
676 | reaper = child_reaper; | 678 | reaper = child_reaper(father); |
677 | break; | 679 | break; |
678 | } | 680 | } |
679 | } while (reaper->exit_state); | 681 | } while (reaper->exit_state); |
@@ -859,8 +861,13 @@ fastcall NORET_TYPE void do_exit(long code) | |||
859 | panic("Aiee, killing interrupt handler!"); | 861 | panic("Aiee, killing interrupt handler!"); |
860 | if (unlikely(!tsk->pid)) | 862 | if (unlikely(!tsk->pid)) |
861 | panic("Attempted to kill the idle task!"); | 863 | panic("Attempted to kill the idle task!"); |
862 | if (unlikely(tsk == child_reaper)) | 864 | if (unlikely(tsk == child_reaper(tsk))) { |
863 | panic("Attempted to kill init!"); | 865 | if (tsk->nsproxy->pid_ns != &init_pid_ns) |
866 | tsk->nsproxy->pid_ns->child_reaper = init_pid_ns.child_reaper; | ||
867 | else | ||
868 | panic("Attempted to kill init!"); | ||
869 | } | ||
870 | |||
864 | 871 | ||
865 | if (unlikely(current->ptrace & PT_TRACE_EXIT)) { | 872 | if (unlikely(current->ptrace & PT_TRACE_EXIT)) { |
866 | current->ptrace_message = code; | 873 | current->ptrace_message = code; |
diff --git a/kernel/pid.c b/kernel/pid.c index 1d9cc268b499..2efe9d8d367b 100644 --- a/kernel/pid.c +++ b/kernel/pid.c | |||
@@ -65,7 +65,8 @@ struct pid_namespace init_pid_ns = { | |||
65 | .pidmap = { | 65 | .pidmap = { |
66 | [ 0 ... PIDMAP_ENTRIES-1] = { ATOMIC_INIT(BITS_PER_PAGE), NULL } | 66 | [ 0 ... PIDMAP_ENTRIES-1] = { ATOMIC_INIT(BITS_PER_PAGE), NULL } |
67 | }, | 67 | }, |
68 | .last_pid = 0 | 68 | .last_pid = 0, |
69 | .child_reaper = &init_task | ||
69 | }; | 70 | }; |
70 | 71 | ||
71 | /* | 72 | /* |
diff --git a/kernel/signal.c b/kernel/signal.c index 9eac4db60eda..1921ffdc5e77 100644 --- a/kernel/signal.c +++ b/kernel/signal.c | |||
@@ -24,6 +24,9 @@ | |||
24 | #include <linux/signal.h> | 24 | #include <linux/signal.h> |
25 | #include <linux/capability.h> | 25 | #include <linux/capability.h> |
26 | #include <linux/freezer.h> | 26 | #include <linux/freezer.h> |
27 | #include <linux/pid_namespace.h> | ||
28 | #include <linux/nsproxy.h> | ||
29 | |||
27 | #include <asm/param.h> | 30 | #include <asm/param.h> |
28 | #include <asm/uaccess.h> | 31 | #include <asm/uaccess.h> |
29 | #include <asm/unistd.h> | 32 | #include <asm/unistd.h> |
@@ -1877,8 +1880,12 @@ relock: | |||
1877 | if (sig_kernel_ignore(signr)) /* Default is nothing. */ | 1880 | if (sig_kernel_ignore(signr)) /* Default is nothing. */ |
1878 | continue; | 1881 | continue; |
1879 | 1882 | ||
1880 | /* Init gets no signals it doesn't want. */ | 1883 | /* |
1881 | if (current == child_reaper) | 1884 | * Init of a pid space gets no signals it doesn't want from |
1885 | * within that pid space. It can of course get signals from | ||
1886 | * its parent pid space. | ||
1887 | */ | ||
1888 | if (current == child_reaper(current)) | ||
1882 | continue; | 1889 | continue; |
1883 | 1890 | ||
1884 | if (sig_kernel_stop(signr)) { | 1891 | if (sig_kernel_stop(signr)) { |