initrd: extend SYSTEMD_IN_INITRD to accept non-ramfs rootfs

Sometimes, non-ramfs initrd root are useful. Eg, for kdump, because
initramfs is memory consuming, so mount a compressed image in earlier
initrd, chroot into it then let systemd do the rest of job is a good
solution.

But systemd doesn't recognize the initrd environment if rootfs is not a
temporary fs. This is a reasonable check, because switch-root in initrd
will wipe the whole rootfs, will be a disaster if there are any
misdetect.

So extend SYSTEMD_IN_INITRD environment variable, now it accepts boolean
value and two extra keyword, "auto" and "lenient". "auto" is same as
before, and it's the default value. "lenient" will let systemd bypass
the rootfs check.
This commit is contained in:
Kairui Song
2021-01-14 01:19:09 +08:00
parent 96cceb35e7
commit 1f22621ba3
2 changed files with 30 additions and 12 deletions
+23 -9
View File
@@ -53,11 +53,13 @@ int prot_from_flags(int flags) {
bool in_initrd(void) {
int r;
const char *e;
bool lenient = false;
if (saved_in_initrd >= 0)
return saved_in_initrd;
/* We make two checks here:
/* We have two checks here:
*
* 1. the flag file /etc/initrd-release must exist
* 2. the root file system must be a memory file system
@@ -65,17 +67,29 @@ bool in_initrd(void) {
* The second check is extra paranoia, since misdetecting an
* initrd can have bad consequences due the initrd
* emptying when transititioning to the main systemd.
*
* If env var $SYSTEMD_IN_INITRD is not set or set to "auto",
* both checks are used. If it's set to "lenient", only check
* 1 is used. If set to a booleen value, then the boolean
* value is returned.
*/
r = getenv_bool_secure("SYSTEMD_IN_INITRD");
if (r < 0 && r != -ENXIO)
log_debug_errno(r, "Failed to parse $SYSTEMD_IN_INITRD, ignoring: %m");
e = secure_getenv("SYSTEMD_IN_INITRD");
if (e) {
if (streq(e, "lenient"))
lenient = true;
else if (!streq(e, "auto")) {
r = parse_boolean(e);
if (r >= 0) {
saved_in_initrd = r > 0;
return saved_in_initrd;
}
log_debug_errno(r, "Failed to parse $SYSTEMD_IN_INITRD, ignoring: %m");
}
}
if (r >= 0)
saved_in_initrd = r > 0;
else
saved_in_initrd = access("/etc/initrd-release", F_OK) >= 0 &&
path_is_temporary_fs("/") > 0;
saved_in_initrd = (lenient || path_is_temporary_fs("/") > 0) &&
access("/etc/initrd-release", F_OK) >= 0;
return saved_in_initrd;
}