]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
basic/virt: treat missing /proc as sign of being in a chroot
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Fri, 28 Oct 2022 13:59:49 +0000 (15:59 +0200)
committerLuca Boccassi <luca.boccassi@gmail.com>
Wed, 9 Nov 2022 09:10:59 +0000 (10:10 +0100)
The logic of running_in_chroot() has been the same since the introduction of
this function in b4f10a5e8956d26f0bc6b9aef12846b57caee08b: if /proc is not
mounted, the function returns -ENOENT and all callers treat this as false. But
that might be the most common case of chrooted calls, esp. in all the naïve
chroots that were done with the chroot binary without additional setup.

(In particular rpm executes all scriptlets in a chroot without bothering to set
up /proc or /sys, and we have codepaths in sysusers and tmpfiles to support
running in such an environment.)

This change effectively shortcircuits various calls to udevadm, downgrades
logging in tmpfiles, and disables all verbs marked with VERB_ONLINE_ONLY in
systemctl. detect-virt -r is also affected:

$ sudo chroot /var/lib/machines/rawhide
before> systemd-detect-virt -r && echo OK
Failed to check for chroot() environment: No such file or directory
after> systemd-detect-virt -r && echo OK
OK

src/basic/virt.c

index 710f0372ea6eef60187fcdb1017b0900572832ab..9a0b5a28d19ee84085945f9fdc91893c5a07c585 100644 (file)
@@ -867,10 +867,26 @@ int running_in_userns(void) {
 int running_in_chroot(void) {
         int r;
 
+        /* If we're PID1, /proc may not be mounted (and most likely we're not in a chroot). But PID1 will
+         * mount /proc, so all other programs can assume that if /proc is *not* available, we're in some
+         * chroot. */
+
         if (getenv_bool("SYSTEMD_IGNORE_CHROOT") > 0)
                 return 0;
 
+        if (getpid_cached() == 1)
+                return false;  /* We're PID 1, we can't be in a chroot. */
+
         r = files_same("/proc/1/root", "/", 0);
+        if (r == -ENOENT) {
+                r = proc_mounted();
+                if (r == 0) {
+                        log_debug("/proc is not mounted, assuming we're in a chroot.");
+                        return 1;
+                }
+                if (r > 0)  /* If we have fake /proc/, we can't do the check properly. */
+                        return -ENOSYS;
+        }
         if (r < 0)
                 return r;