diff options
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/pid_namespace.c | 33 | ||||
| -rw-r--r-- | kernel/sys.c | 9 |
2 files changed, 42 insertions, 0 deletions
diff --git a/kernel/pid_namespace.c b/kernel/pid_namespace.c index 17b232869a04..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 | ||
| @@ -183,6 +184,9 @@ void zap_pid_ns_processes(struct pid_namespace *pid_ns) | |||
| 183 | rc = sys_wait4(-1, NULL, __WALL, NULL); | 184 | rc = sys_wait4(-1, NULL, __WALL, NULL); |
| 184 | } while (rc != -ECHILD); | 185 | } while (rc != -ECHILD); |
| 185 | 186 | ||
| 187 | if (pid_ns->reboot) | ||
| 188 | current->signal->group_exit_code = pid_ns->reboot; | ||
| 189 | |||
| 186 | acct_exit_ns(pid_ns); | 190 | acct_exit_ns(pid_ns); |
| 187 | return; | 191 | return; |
| 188 | } | 192 | } |
| @@ -217,6 +221,35 @@ static struct ctl_table pid_ns_ctl_table[] = { | |||
| 217 | 221 | ||
| 218 | static struct ctl_path kern_path[] = { { .procname = "kernel", }, { } }; | 222 | static struct ctl_path kern_path[] = { { .procname = "kernel", }, { } }; |
| 219 | 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 | |||
| 220 | static __init int pid_namespaces_init(void) | 253 | static __init int pid_namespaces_init(void) |
| 221 | { | 254 | { |
| 222 | pid_ns_cachep = KMEM_CACHE(pid_namespace, SLAB_PANIC); | 255 | pid_ns_cachep = KMEM_CACHE(pid_namespace, SLAB_PANIC); |
diff --git a/kernel/sys.c b/kernel/sys.c index 9eb7fcab8df6..e7006eb6c1e4 100644 --- a/kernel/sys.c +++ b/kernel/sys.c | |||
| @@ -444,6 +444,15 @@ SYSCALL_DEFINE4(reboot, int, magic1, int, magic2, unsigned int, cmd, | |||
| 444 | magic2 != LINUX_REBOOT_MAGIC2C)) | 444 | magic2 != LINUX_REBOOT_MAGIC2C)) |
| 445 | return -EINVAL; | 445 | return -EINVAL; |
| 446 | 446 | ||
| 447 | /* | ||
| 448 | * If pid namespaces are enabled and the current task is in a child | ||
| 449 | * pid_namespace, the command is handled by reboot_pid_ns() which will | ||
| 450 | * call do_exit(). | ||
| 451 | */ | ||
| 452 | ret = reboot_pid_ns(task_active_pid_ns(current), cmd); | ||
| 453 | if (ret) | ||
| 454 | return ret; | ||
| 455 | |||
| 447 | /* Instead of trying to make the power_off code look like | 456 | /* Instead of trying to make the power_off code look like |
| 448 | * halt when pm_power_off is not set do it the easy way. | 457 | * halt when pm_power_off is not set do it the easy way. |
| 449 | */ | 458 | */ |
