summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRuediger Oertel <ro@suse.de>2014-06-13 16:41:06 +0200
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>2014-06-21 11:02:24 -0400
commit3eb31d88fd664d55251102d8504d05426a97d0b3 (patch)
tree71149a8661b56e7c236a3ad1a07fa913691c6b5a
parent686e842aecfc9f89547f9d9021afb9e1a21067ec (diff)
Reset signal-mask on re-exec to init=..
Process 1 (aka init) needs to be started with an empty signal mask. That includes the process 1 that's started after the initrd is finished. When the initrd is using systemd (as it does with dracut based initrds) then it is systemd that calls the real init. Normally this is systemd again, except when the user uses for instance "init=/bin/bash" on the kernel command line. (cherry picked from commit 5a85ca1cb622fda4a39c8a6f00dccea7f8a1e82a)
-rw-r--r--src/core/main.c8
1 files changed, 8 insertions, 0 deletions
diff --git a/src/core/main.c b/src/core/main.c
index 8417e7a2e..62f8140e8 100644
--- a/src/core/main.c
+++ b/src/core/main.c
@@ -1780,6 +1780,7 @@ finish:
if (reexecute) {
const char **args;
unsigned i, args_size;
+ sigset_t ss, o_ss;
/* Close and disarm the watchdog, so that the new
* instance can reinitialize it, but doesn't get
@@ -1863,6 +1864,11 @@ finish:
args[i++] = NULL;
assert(i <= args_size);
+ /* reenable any blocked signals, especially important
+ * if we switch from initial ramdisk to init=... */
+ sigemptyset(&ss);
+ sigprocmask(SIG_SETMASK, &ss, &o_ss);
+
if (switch_root_init) {
args[0] = switch_root_init;
execv(args[0], (char* const*) args);
@@ -1881,6 +1887,8 @@ finish:
log_error("Failed to execute /bin/sh, giving up: %m");
} else
log_warning("Failed to execute /sbin/init, giving up: %m");
+
+ sigprocmask(SIG_SETMASK, &o_ss, NULL);
}
if (arg_serialization) {