summaryrefslogtreecommitdiff
path: root/src/core
diff options
context:
space:
mode:
authorDaan De Meyer <daan.j.demeyer@gmail.com>2023-05-08 13:48:25 +0200
committerDaan De Meyer <daan.j.demeyer@gmail.com>2023-05-12 07:48:50 +0200
commitaaa27e2e21c04339914f26b7125789087eb51166 (patch)
treef4d5db8b319865c2765eb1ad7d7d4ad37915d143 /src/core
parent3f92250f4c10a723693b734b803c98f3b0d53f3e (diff)
downloadsystemd-aaa27e2e21c04339914f26b7125789087eb51166.tar.gz
core: Check if any init exists before switching root
If we switch root and can't execute an init program afterwards, we're completely stuck as we can't go back to the initramfs to start emergency.service as it will have been completely removed by the switch root operation. To prevent leaving users with a completely undebuggable system, let's at least check before we switch root whether at least one of the init programs we might want to execute actually exist, and fail early if none of them exists.
Diffstat (limited to 'src/core')
-rw-r--r--src/core/main.c19
1 files changed, 19 insertions, 0 deletions
diff --git a/src/core/main.c b/src/core/main.c
index e86e0d941e..5347372c81 100644
--- a/src/core/main.c
+++ b/src/core/main.c
@@ -31,6 +31,7 @@
#include "bus-util.h"
#include "capability-util.h"
#include "cgroup-util.h"
+#include "chase.h"
#include "clock-util.h"
#include "conf-parser.h"
#include "cpu-set-util.h"
@@ -1774,6 +1775,24 @@ static int do_reexecute(
assert(saved_rlimit_memlock);
assert(ret_error_message);
+ if (switch_root_init) {
+ r = chase(switch_root_init, switch_root_dir, CHASE_PREFIX_ROOT, NULL, NULL);
+ if (r < 0)
+ log_warning_errno(r, "Failed to chase configured init %s/%s: %m",
+ strempty(switch_root_dir), switch_root_init);
+ } else {
+ r = chase(SYSTEMD_BINARY_PATH, switch_root_dir, CHASE_PREFIX_ROOT, NULL, NULL);
+ if (r < 0)
+ log_debug_errno(r, "Failed to chase our own binary %s/%s: %m",
+ strempty(switch_root_dir), SYSTEMD_BINARY_PATH);
+ }
+
+ if (r < 0) {
+ r = chase("/sbin/init", switch_root_dir, CHASE_PREFIX_ROOT, NULL, NULL);
+ if (r < 0)
+ return log_error_errno(r, "Failed to chase %s/sbin/init", strempty(switch_root_dir));
+ }
+
/* Close and disarm the watchdog, so that the new instance can reinitialize it, but doesn't get
* rebooted while we do that */
watchdog_close(true);