From: Mike Yuan Date: Thu, 18 Sep 2025 23:16:19 +0000 (+0200) Subject: virt: revert to detect chroot by comparing with / rather than /proc/PID/root X-Git-Tag: v259-rc1~499 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=01184496a2b518f33c56b5803549f27fa8f226fe;p=thirdparty%2Fsystemd.git virt: revert to detect chroot by comparing with / rather than /proc/PID/root This partially reverts d6267b9b18a30c81dd3335230ef71af04e1ea330 So, arch-chroot currently uses a rather cursed setup: it sets up a PID namespace, but mounts /proc/ from the outside into the chroot tree, and then call chroot(2), essentially making it somewhere between chroot(8) and a full-blown container. Hence, the PID dirs in /proc/ reveal the outer world. The offending commit switched chroot detection to compare /proc/1/root and /proc/OUR_PID/root, exhibiting the faulty behavior where the mentioned environment now gets deemed to be non-chroot. Now, this is very much an issue in arch-chroot. However, if /proc/ is to be properly associated with the pidns, then we'd treat it as a container and no longer a chroot. Also, the previous logic feels more readable and more honestly reported errors in proc_mounted(). Hence I opted for reverting the change here. Still note that the culprit (once again :/) lies in the arch-chroot's pidns impl, not systemd. Fixes https://gitlab.archlinux.org/archlinux/packaging/packages/systemd/-/issues/54 --- diff --git a/src/basic/virt.c b/src/basic/virt.c index 1a0156159d0..ad4b9aa3eaf 100644 --- a/src/basic/virt.c +++ b/src/basic/virt.c @@ -16,8 +16,8 @@ #include "log.h" #include "namespace-util.h" #include "parse-util.h" -#include "pidref.h" #include "process-util.h" +#include "stat-util.h" #include "string-table.h" #include "string-util.h" #include "strv.h" @@ -816,16 +816,19 @@ int running_in_chroot(void) { if (getenv_bool("SYSTEMD_IGNORE_CHROOT") > 0) return 0; - r = pidref_from_same_root_fs(&PIDREF_MAKE_FROM_PID(1), NULL); - if (r == -ENOSYS) { - if (getpid_cached() == 1) - return false; /* We will mount /proc, assuming we're not in a chroot. */ + r = inode_same("/proc/1/root", "/", /* flags = */ 0); + if (r == -ENOENT) { + r = proc_mounted(); + if (r == 0) { + if (getpid_cached() == 1) + return false; /* We will mount /proc, assuming we're not in a chroot. */ - log_debug("/proc/ is not mounted, assuming we're in a chroot."); - return true; + log_debug("/proc/ is not mounted, assuming we're in a chroot."); + return true; + } + if (r > 0) /* If we have fake /proc/, we can't do the check properly. */ + return -ENOSYS; } - if (r == -ESRCH) /* We must have a fake /proc/, we can't do the check properly. */ - return -ENOSYS; if (r < 0) return r;