richardphibel / rpms / systemd

Forked from rpms/systemd 2 years ago
Clone
b677e7
From 99ca5b681fceedd010b2616b1248a483f4bfbd97 Mon Sep 17 00:00:00 2001
b677e7
From: Kairui Song <kasong@redhat.com>
b677e7
Date: Wed, 13 Jan 2021 00:04:53 +0800
b677e7
Subject: [PATCH] initrd: extend SYSTEMD_IN_INITRD to accept non-ramfs rootfs
b677e7
b677e7
Sometimes, non-ramfs initrd root are useful. Eg, for kdump, because
b677e7
initramfs is memory consuming, so mount a compressed image in earlier
b677e7
initrd, chroot into it then let systemd do the rest of job is a good
b677e7
solution.
b677e7
b677e7
But systemd doesn't recognize the initrd environment if rootfs is not a
b677e7
temporary fs. This is a reasonable check, because switch-root in initrd
b677e7
will wipe the whole rootfs, will be a disaster if there are any
b677e7
misdetect.
b677e7
b677e7
So extend SYSTEMD_IN_INITRD environment variable, now it accepts boolean
b677e7
value and two extra keyword, "auto" and "lenient". "auto" is same as
b677e7
before, and it's the default value. "lenient" will let systemd bypass
b677e7
the rootfs check.
b677e7
b677e7
(cherry picked from commit db4c45cf4f10ca094b9e9570b758abd445d65381)
b677e7
b677e7
Related: #1959339
b677e7
---
b677e7
 doc/ENVIRONMENT.md |  8 ++++++++
b677e7
 src/basic/util.c   | 28 +++++++++++++++++++++++++---
b677e7
 2 files changed, 33 insertions(+), 3 deletions(-)
b677e7
b677e7
diff --git a/doc/ENVIRONMENT.md b/doc/ENVIRONMENT.md
b677e7
index 36b649afe1..8d7ce6ae2c 100644
b677e7
--- a/doc/ENVIRONMENT.md
b677e7
+++ b/doc/ENVIRONMENT.md
b677e7
@@ -37,6 +37,14 @@ All tools:
b677e7
   useful for debugging, in order to test generators and other code against
b677e7
   specific kernel command lines.
b677e7
 
b677e7
+* `$SYSTEMD_IN_INITRD=[auto|lenient|0|1]` — if set, specifies initrd detection
b677e7
+  method. Defaults to `auto`. Behavior is defined as follows:
b677e7
+  `auto`: Checks if `/etc/initrd-release` exists, and a temporary fs is mounted
b677e7
+          on `/`. If both conditions meet, then it's in initrd.
b677e7
+  `lenient`: Similiar to `auto`, but the rootfs check is skipped.
b677e7
+  `0|1`: Simply overrides initrd detection. This is useful for debugging and
b677e7
+         testing initrd-only programs in the main system.
b677e7
+
b677e7
 * `$SYSTEMD_EMOJI=0` — if set, tools such as "systemd-analyze security" will
b677e7
   not output graphical smiley emojis, but ASCII alternatives instead. Note that
b677e7
   this only controls use of Unicode emoji glyphs, and has no effect on other
b677e7
diff --git a/src/basic/util.c b/src/basic/util.c
b677e7
index b443e639f3..59bcf7b00c 100644
b677e7
--- a/src/basic/util.c
b677e7
+++ b/src/basic/util.c
b677e7
@@ -130,11 +130,14 @@ int prot_from_flags(int flags) {
b677e7
 }
b677e7
 
b677e7
 bool in_initrd(void) {
b677e7
+        int r;
b677e7
+        const char *e;
b677e7
+        bool lenient = false;
b677e7
 
b677e7
         if (saved_in_initrd >= 0)
b677e7
                 return saved_in_initrd;
b677e7
 
b677e7
-        /* We make two checks here:
b677e7
+        /* We have two checks here:
b677e7
          *
b677e7
          * 1. the flag file /etc/initrd-release must exist
b677e7
          * 2. the root file system must be a memory file system
b677e7
@@ -142,10 +145,29 @@ bool in_initrd(void) {
b677e7
          * The second check is extra paranoia, since misdetecting an
b677e7
          * initrd can have bad consequences due the initrd
b677e7
          * emptying when transititioning to the main systemd.
b677e7
+         *
b677e7
+         * If env var $SYSTEMD_IN_INITRD is not set or set to "auto",
b677e7
+         * both checks are used. If it's set to "lenient", only check
b677e7
+         * 1 is used. If set to a booleen value, then the boolean
b677e7
+         * value is returned.
b677e7
          */
b677e7
 
b677e7
-        saved_in_initrd = access("/etc/initrd-release", F_OK) >= 0 &&
b677e7
-                          path_is_temporary_fs("/") > 0;
b677e7
+        e = secure_getenv("SYSTEMD_IN_INITRD");
b677e7
+        if (e) {
b677e7
+                if (streq(e, "lenient"))
b677e7
+                        lenient = true;
b677e7
+                else if (!streq(e, "auto")) {
b677e7
+                        r = parse_boolean(e);
b677e7
+                        if (r >= 0) {
b677e7
+                                saved_in_initrd = r > 0;
b677e7
+                                return saved_in_initrd;
b677e7
+                        }
b677e7
+                        log_debug_errno(r, "Failed to parse $SYSTEMD_IN_INITRD, ignoring: %m");
b677e7
+                }
b677e7
+        }
b677e7
+
b677e7
+        saved_in_initrd = (lenient || path_is_temporary_fs("/") > 0) &&
b677e7
+                          access("/etc/initrd-release", F_OK) >= 0;
b677e7
 
b677e7
         return saved_in_initrd;
b677e7
 }