From aa4bc7e743c74afaeac4dd7d84afe734065bd366 Mon Sep 17 00:00:00 2001
From: Wen Yang <wenyang@linux.alibaba.com>
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"