shutdown: in containers, invoke reboot(2), too. Then fallback to exit() if CAP_SYS_BOOT is missing
The kernel's PID namespaces support reboot(2) just fine, so let's make use of it if possible.
This commit is contained in:
parent
57371e5829
commit
cb7ec5645e
|
@ -263,14 +263,8 @@ int main(int argc, char *argv[]) {
|
||||||
arguments[2] = NULL;
|
arguments[2] = NULL;
|
||||||
execute_directory(SYSTEM_SHUTDOWN_PATH, NULL, arguments);
|
execute_directory(SYSTEM_SHUTDOWN_PATH, NULL, arguments);
|
||||||
|
|
||||||
/* If we are in a container, just exit, this will kill our
|
if (!in_container &&
|
||||||
* container for good. */
|
access("/run/initramfs/shutdown", X_OK) == 0) {
|
||||||
if (in_container) {
|
|
||||||
log_error("Exiting container.");
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (access("/run/initramfs/shutdown", X_OK) == 0) {
|
|
||||||
|
|
||||||
if (prepare_new_root() >= 0 &&
|
if (prepare_new_root() >= 0 &&
|
||||||
pivot_to_new_root() >= 0) {
|
pivot_to_new_root() >= 0) {
|
||||||
|
@ -280,25 +274,37 @@ int main(int argc, char *argv[]) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cmd == LINUX_REBOOT_CMD_KEXEC) {
|
if (cmd == LINUX_REBOOT_CMD_KEXEC) {
|
||||||
/* We cheat and exec kexec to avoid doing all its work */
|
|
||||||
pid_t pid = fork();
|
|
||||||
|
|
||||||
if (pid < 0)
|
if (!in_container) {
|
||||||
log_error("Could not fork: %m. Falling back to normal reboot.");
|
/* We cheat and exec kexec to avoid doing all its work */
|
||||||
else if (pid > 0) {
|
pid_t pid = fork();
|
||||||
wait_for_terminate_and_warn("kexec", pid);
|
|
||||||
log_warning("kexec failed. Falling back to normal reboot.");
|
if (pid < 0)
|
||||||
} else {
|
log_error("Could not fork: %m. Falling back to normal reboot.");
|
||||||
/* Child */
|
else if (pid > 0) {
|
||||||
const char *args[3] = { "/sbin/kexec", "-e", NULL };
|
wait_for_terminate_and_warn("kexec", pid);
|
||||||
execv(args[0], (char * const *) args);
|
log_warning("kexec failed. Falling back to normal reboot.");
|
||||||
return EXIT_FAILURE;
|
} else {
|
||||||
|
/* Child */
|
||||||
|
const char *args[3] = { "/sbin/kexec", "-e", NULL };
|
||||||
|
execv(args[0], (char * const *) args);
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd = RB_AUTOBOOT;
|
cmd = RB_AUTOBOOT;
|
||||||
}
|
}
|
||||||
|
|
||||||
reboot(cmd);
|
reboot(cmd);
|
||||||
|
|
||||||
|
if (errno == EPERM && in_container) {
|
||||||
|
/* If we are in a container, and we lacked
|
||||||
|
* CAP_SYS_BOOT just exit, this will kill our
|
||||||
|
* container for good. */
|
||||||
|
log_error("Exiting container.");
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
log_error("Failed to invoke reboot(): %m");
|
log_error("Failed to invoke reboot(): %m");
|
||||||
r = -errno;
|
r = -errno;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue