Commit e2fa1520 by Serge Hallyn Committed by Daniel Lezcano

fix reboot support detection

In order for reboot(LINUX_REBOOT_CMD_CADON) to detect whether container reboot is supported, it must be done in a non-init pid namespace. Fix that. Signed-off-by: 's avatarSerge Hallyn <serge.hallyn@canonical.com> Signed-off-by: 's avatarDaniel Lezcano <dlezcano@fr.ibm.com>
parent 721d262c
......@@ -414,22 +414,57 @@ void lxc_abort(const char *name, struct lxc_handler *handler)
#include <sys/reboot.h>
#include <linux/reboot.h>
static int must_drop_cap_sys_boot(void)
/*
* reboot(LINUX_REBOOT_CMD_CAD_ON) will return -EINVAL
* in a child pid namespace if container reboot support exists.
* Otherwise, it will either succeed or return -EPERM.
*/
static int container_reboot_supported(void *arg)
{
FILE *f = fopen("/proc/sys/kernel/ctrl-alt-del", "r");
int *cmd = arg;
int ret;
int v;
if (!f)
ret = reboot(*cmd);
if (ret == -1 && errno == EINVAL)
return 1;
return 0;
}
static int must_drop_cap_sys_boot(void)
{
FILE *f = fopen("/proc/sys/kernel/ctrl-alt-del", "r");
int ret, cmd, v;
long stack_size = 4096;
void *stack = alloca(stack_size) + stack_size;
int status;
pid_t pid;
if (!f) {
DEBUG("failed to open /proc/sys/kernel/ctrl-alt-del");
return 1;
}
ret = fscanf(f, "%d", &v);
fclose(f);
if (ret != 1)
if (ret != 1) {
DEBUG("Failed to read /proc/sys/kernel/ctrl-alt-del");
return 1;
ret = reboot(v ? LINUX_REBOOT_CMD_CAD_ON : LINUX_REBOOT_CMD_CAD_OFF);
if (ret != -1)
}
cmd = v ? LINUX_REBOOT_CMD_CAD_ON : LINUX_REBOOT_CMD_CAD_OFF;
pid = clone(container_reboot_supported, stack, CLONE_NEWPID | SIGCHLD, &cmd);
if (pid < 0) {
SYSERROR("failed to clone\n");
return -1;
}
if (wait(&status) < 0) {
SYSERROR("unexpected wait error: %m\n");
return -1;
}
if (WEXITSTATUS(status) != 1)
return 1;
return 0;
}
......@@ -461,20 +496,23 @@ static int do_start(void *data)
if (lxc_sync_barrier_parent(handler, LXC_SYNC_CONFIGURE))
return -1;
/* Setup the container, ip, names, utsname, ... */
if (lxc_setup(handler->name, handler->conf)) {
ERROR("failed to setup the container");
goto out_warn_father;
}
if (must_drop_cap_sys_boot()) {
if (prctl(PR_CAPBSET_DROP, CAP_SYS_BOOT, 0, 0, 0)) {
SYSERROR("failed to remove CAP_SYS_BOOT capability");
return -1;
}
handler->conf->need_utmp_watch = 1;
} else
DEBUG("Dropped cap_sys_boot\n");
} else {
DEBUG("Not dropping cap_sys_boot or watching utmp\n");
handler->conf->need_utmp_watch = 0;
}
/* Setup the container, ip, names, utsname, ... */
if (lxc_setup(handler->name, handler->conf)) {
ERROR("failed to setup the container");
goto out_warn_father;
}
close(handler->sigfd);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment