Add $SYSTEMD_IN_CHROOT to override chroot detection
authorDaan De Meyer <daan.j.demeyer@gmail.com>
Wed, 14 Aug 2024 10:43:05 +0000 (12:43 +0200)
committerDaan De Meyer <daan.j.demeyer@gmail.com>
Mon, 19 Aug 2024 05:49:55 +0000 (07:49 +0200)
When running unprivileged, checking /proc/1/root doesn't work because
it requires privileges. Instead, let's add an environment variable so
the process that chroot's can tell (systemd) subprocesses whether
they're running in a chroot or not.

(cherry picked from commit 2701c2f67de592fe2565b084cfaec1667767dbaf)

docs/ENVIRONMENT.md
src/basic/virt.c
test/test-systemctl-enable.sh
test/units/TEST-74-AUX-UTILS.detect-virt.sh [new file with mode: 0755]

index c8b75ac2655f40d7ec50213b507330362f900f3c..6081351580730b8a385d485a1dbcc1ca67fcbb9c 100644 (file)
@@ -23,17 +23,17 @@ All tools:
 * `$SYSTEMD_OFFLINE=[0|1]` — if set to `1`, then `systemctl` will refrain from
   talking to PID 1; this has the same effect as the historical detection of
   `chroot()`. Setting this variable to `0` instead has a similar effect as
-  `$SYSTEMD_IGNORE_CHROOT=1`; i.e. tools will try to communicate with PID 1
+  `$SYSTEMD_IN_CHROOT=0`; i.e. tools will try to communicate with PID 1
   even if a `chroot()` environment is detected. You almost certainly want to
   set this to `1` if you maintain a package build system or similar and are
   trying to use a modern container system and not plain `chroot()`.
 
-* `$SYSTEMD_IGNORE_CHROOT=1` — if set, don't check whether being invoked in a
-  `chroot()` environment. This is particularly relevant for systemctl, as it
-  will not alter its behaviour for `chroot()` environments if set. Normally it
-  refrains from talking to PID 1 in such a case; turning most operations such
-  as `start` into no-ops.  If that's what's explicitly desired, you might
-  consider setting `$SYSTEMD_OFFLINE=1`.
+* `$SYSTEMD_IN_CHROOT=0|1` — takes a boolean. If set, overrides chroot detection.
+  This is particularly relevant for systemctl, as it will not alter its behaviour
+  for `chroot()` environments if `SYSTEMD_IN_CHROOT=0`. Normally it refrains from
+  talking to PID 1 in such a case; turning most operations such as `start` into
+  no-ops. If that's what's explicitly desired, you might consider setting
+  `$SYSTEMD_OFFLINE=1`.
 
 * `$SYSTEMD_FIRST_BOOT=0|1` — if set, assume "first boot" condition to be false
   or true, instead of checking the flag file created by PID 1.
index 09703506f93367125bcd8a0c98952f7d0033056a..2cb3a0839337a598dfaa6f76cd3fd45ba4462f96 100644 (file)
@@ -896,6 +896,13 @@ int running_in_chroot(void) {
          * mount /proc, so all other programs can assume that if /proc is *not* available, we're in some
          * chroot. */
 
+        r = getenv_bool("SYSTEMD_IN_CHROOT");
+        if (r >= 0)
+                return r > 0;
+        if (r != -ENXIO)
+                log_debug_errno(r, "Failed to parse $SYSTEMD_IN_CHROOT, ignoring: %m");
+
+        /* Deprecated but kept for backwards compatibility. */
         if (getenv_bool("SYSTEMD_IGNORE_CHROOT") > 0)
                 return 0;
 
index 5615c900f4861ffa2fe410407a64a2f85573578f..3fc59f6f9ee86cc274b370b48dc385d2762d1c81 100644 (file)
@@ -3,7 +3,7 @@
 set -ex
 
 # Silence warning from running_in_chroot_or_offline()
-export SYSTEMD_IGNORE_CHROOT=1
+export SYSTEMD_IN_CHROOT=0
 
 systemctl=${1:-systemctl}
 systemd_id128=${2:-systemd-id128}
diff --git a/test/units/TEST-74-AUX-UTILS.detect-virt.sh b/test/units/TEST-74-AUX-UTILS.detect-virt.sh
new file mode 100755 (executable)
index 0000000..fe1db4d
--- /dev/null
@@ -0,0 +1,7 @@
+#!/usr/bin/env bash
+# SPDX-License-Identifier: LGPL-2.1-or-later
+set -eux
+set -o pipefail
+
+SYSTEMD_IN_CHROOT=1 systemd-detect-virt --chroot
+(! SYSTEMD_IN_CHROOT=0 systemd-detect-virt --chroot)