From 1e3eee8cf0e654e101a4208b4cee7ecec65671a7 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Thu, 27 Jan 2022 15:03:27 +0100 Subject: manager: if we are reexecuting, do not invoke any fallbacks For https://bugzilla.redhat.com/show_bug.cgi?id=1986176: if we are trying to reexecute, and this fails for any reason, we shouldn't try to execute /sbin/init or /bin/sh. It is better to just freeze. If we freeze it is easier to diagnose what happened, but if we execute one of the fallbacks, we don't really know what will happen. In particular the new init might just return, causing the machine to shut down. Or we may successfully spawn /bin/sh, which could leave the machine open. --- src/core/main.c | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) (limited to 'src/core') diff --git a/src/core/main.c b/src/core/main.c index ea2b9b7a52..93cbf62769 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -1824,7 +1824,8 @@ static void filter_args( } } -static void do_reexecute( +static int do_reexecute( + ManagerObjective objective, int argc, char* argv[], const struct rlimit *saved_rlimit_nofile, @@ -1838,6 +1839,7 @@ static void do_reexecute( const char **args; int r; + assert(IN_SET(objective, MANAGER_REEXECUTE, MANAGER_SWITCH_ROOT)); assert(argc >= 0); assert(saved_rlimit_nofile); assert(saved_rlimit_memlock); @@ -1901,6 +1903,12 @@ static void do_reexecute( args[0] = SYSTEMD_BINARY_PATH; (void) execv(args[0], (char* const*) args); + + if (objective == MANAGER_REEXECUTE) { + *ret_error_message = "Failed to execute our own binary"; + return log_error_errno(errno, "Failed to execute our own binary %s: %m", args[0]); + } + log_debug_errno(errno, "Failed to execute our own binary %s, trying fallback: %m", args[0]); } @@ -1938,17 +1946,16 @@ static void do_reexecute( ANSI_HIGHLIGHT_RED " !! " ANSI_NORMAL, "Failed to execute /sbin/init"); + *ret_error_message = "Failed to execute fallback shell"; if (r == -ENOENT) { log_warning("No /sbin/init, trying fallback"); args[0] = "/bin/sh"; args[1] = NULL; (void) execve(args[0], (char* const*) args, saved_env); - log_error_errno(errno, "Failed to execute /bin/sh, giving up: %m"); + return log_error_errno(errno, "Failed to execute /bin/sh, giving up: %m"); } else - log_warning_errno(r, "Failed to execute /sbin/init, giving up: %m"); - - *ret_error_message = "Failed to execute fallback shell"; + return log_warning_errno(r, "Failed to execute /sbin/init, giving up: %m"); } static int invoke_main_loop( @@ -3045,13 +3052,14 @@ finish: mac_selinux_finish(); if (IN_SET(r, MANAGER_REEXECUTE, MANAGER_SWITCH_ROOT)) - do_reexecute(argc, argv, - &saved_rlimit_nofile, - &saved_rlimit_memlock, - fds, - switch_root_dir, - switch_root_init, - &error_message); /* This only returns if reexecution failed */ + r = do_reexecute(r, + argc, argv, + &saved_rlimit_nofile, + &saved_rlimit_memlock, + fds, + switch_root_dir, + switch_root_init, + &error_message); /* This only returns if reexecution failed */ arg_serialization = safe_fclose(arg_serialization); fds = fdset_free(fds); -- cgit v1.2.3