diff options
Diffstat (limited to 'kernel/pid_namespace.c')
-rw-r--r-- | kernel/pid_namespace.c | 41 |
1 files changed, 35 insertions, 6 deletions
diff --git a/kernel/pid_namespace.c b/kernel/pid_namespace.c index a8968396046d..57bc1fd35b3c 100644 --- a/kernel/pid_namespace.c +++ b/kernel/pid_namespace.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/acct.h> | 15 | #include <linux/acct.h> |
16 | #include <linux/slab.h> | 16 | #include <linux/slab.h> |
17 | #include <linux/proc_fs.h> | 17 | #include <linux/proc_fs.h> |
18 | #include <linux/reboot.h> | ||
18 | 19 | ||
19 | #define BITS_PER_PAGE (PAGE_SIZE*8) | 20 | #define BITS_PER_PAGE (PAGE_SIZE*8) |
20 | 21 | ||
@@ -168,13 +169,9 @@ void zap_pid_ns_processes(struct pid_namespace *pid_ns) | |||
168 | while (nr > 0) { | 169 | while (nr > 0) { |
169 | rcu_read_lock(); | 170 | rcu_read_lock(); |
170 | 171 | ||
171 | /* | ||
172 | * Any nested-container's init processes won't ignore the | ||
173 | * SEND_SIG_NOINFO signal, see send_signal()->si_fromuser(). | ||
174 | */ | ||
175 | task = pid_task(find_vpid(nr), PIDTYPE_PID); | 172 | task = pid_task(find_vpid(nr), PIDTYPE_PID); |
176 | if (task) | 173 | if (task && !__fatal_signal_pending(task)) |
177 | send_sig_info(SIGKILL, SEND_SIG_NOINFO, task); | 174 | send_sig_info(SIGKILL, SEND_SIG_FORCED, task); |
178 | 175 | ||
179 | rcu_read_unlock(); | 176 | rcu_read_unlock(); |
180 | 177 | ||
@@ -187,6 +184,9 @@ void zap_pid_ns_processes(struct pid_namespace *pid_ns) | |||
187 | rc = sys_wait4(-1, NULL, __WALL, NULL); | 184 | rc = sys_wait4(-1, NULL, __WALL, NULL); |
188 | } while (rc != -ECHILD); | 185 | } while (rc != -ECHILD); |
189 | 186 | ||
187 | if (pid_ns->reboot) | ||
188 | current->signal->group_exit_code = pid_ns->reboot; | ||
189 | |||
190 | acct_exit_ns(pid_ns); | 190 | acct_exit_ns(pid_ns); |
191 | return; | 191 | return; |
192 | } | 192 | } |
@@ -221,6 +221,35 @@ static struct ctl_table pid_ns_ctl_table[] = { | |||
221 | 221 | ||
222 | static struct ctl_path kern_path[] = { { .procname = "kernel", }, { } }; | 222 | static struct ctl_path kern_path[] = { { .procname = "kernel", }, { } }; |
223 | 223 | ||
224 | int reboot_pid_ns(struct pid_namespace *pid_ns, int cmd) | ||
225 | { | ||
226 | if (pid_ns == &init_pid_ns) | ||
227 | return 0; | ||
228 | |||
229 | switch (cmd) { | ||
230 | case LINUX_REBOOT_CMD_RESTART2: | ||
231 | case LINUX_REBOOT_CMD_RESTART: | ||
232 | pid_ns->reboot = SIGHUP; | ||
233 | break; | ||
234 | |||
235 | case LINUX_REBOOT_CMD_POWER_OFF: | ||
236 | case LINUX_REBOOT_CMD_HALT: | ||
237 | pid_ns->reboot = SIGINT; | ||
238 | break; | ||
239 | default: | ||
240 | return -EINVAL; | ||
241 | } | ||
242 | |||
243 | read_lock(&tasklist_lock); | ||
244 | force_sig(SIGKILL, pid_ns->child_reaper); | ||
245 | read_unlock(&tasklist_lock); | ||
246 | |||
247 | do_exit(0); | ||
248 | |||
249 | /* Not reached */ | ||
250 | return 0; | ||
251 | } | ||
252 | |||
224 | static __init int pid_namespaces_init(void) | 253 | static __init int pid_namespaces_init(void) |
225 | { | 254 | { |
226 | pid_ns_cachep = KMEM_CACHE(pid_namespace, SLAB_PANIC); | 255 | pid_ns_cachep = KMEM_CACHE(pid_namespace, SLAB_PANIC); |