From aa4bc7e743c74afaeac4dd7d84afe734065bd366 Mon Sep 17 00:00:00 2001 From: Wen Yang Date: Thu, 18 Jun 2020 22:36:22 +0800 Subject: [PATCH] core: fix unnecessary fallback to the rescue mode caused by initrd-switch-root.service's exit status judgment error commit 1f0958f640b8 ("core: when determining whether a process exit status is clean, consider whether it is a command or a daemon") introduces a side effect that causes system falls into rescure mode due initrd-switch-root.service entered failed state, detailed information should refer to the redhat's doc, as follows: https://access.redhat.com/solutions/4973191 https://bugzilla.redhat.com/show_bug.cgi?id=1414904 As we know that in the cloud computing scenarios, some very critical services may run on the server, and the server may run continuously for several years without restarting.The initramfske may still maintain the original state many years ago without any changes. In addition, this server may have been installed a lot of user mode programs and kernel mode drivers due to various operations and maintenance over the years. If the initramfs is regenerated because of upgrading systemd, the user-mode programs or drivers previously installed may be inserted into the initramfs, introducing unknown risks, and may even cause the system to fail to start. So we hope that this patch may avoid the above issues. Resolves: #1825232 (cherry picked from commit ec8955ee3842b81d790cf5fa949844bf63a93b7c) --- src/core/service.c | 9 +++++++++ src/shared/special.h | 1 + 2 files changed, 10 insertions(+) diff --git a/src/core/service.c b/src/core/service.c index 4c73b6ef96..d2d1dcb107 100644 --- a/src/core/service.c +++ b/src/core/service.c @@ -2644,6 +2644,15 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) { else assert_not_reached("Unknown code"); + /* Here's a special hack: avoid a timing issue caused by switching + * root when the initramfs contains an old systemd binary. + * + * https://bugzilla.redhat.com/show_bug.cgi?id=1855149 + * https://bugzilla.redhat.com/show_bug.cgi?id=1825232 */ + if (f != SERVICE_SUCCESS && status == SIGTERM && + unit_has_name(UNIT(s), SPECIAL_INITRD_SWITCH_ROOT_SERVICE)) + f = SERVICE_SUCCESS; + if (s->main_pid == pid) { /* Forking services may occasionally move to a new PID. * As long as they update the PID file before exiting the old diff --git a/src/shared/special.h b/src/shared/special.h index b045047d36..cf393879bf 100644 --- a/src/shared/special.h +++ b/src/shared/special.h @@ -96,6 +96,7 @@ #define SPECIAL_QUOTACHECK_SERVICE "systemd-quotacheck.service" #define SPECIAL_QUOTAON_SERVICE "quotaon.service" #define SPECIAL_REMOUNT_FS_SERVICE "systemd-remount-fs.service" +#define SPECIAL_INITRD_SWITCH_ROOT_SERVICE "initrd-switch-root.service" /* Services systemd relies on */ #define SPECIAL_DBUS_SERVICE "dbus.service"