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