detect-virt: check the inode number of the pid namespace
authorLuca Boccassi <luca.boccassi@gmail.com>
Thu, 21 Nov 2024 00:47:39 +0000 (00:47 +0000)
committerLennart Poettering <lennart@poettering.net>
Fri, 22 Nov 2024 23:14:20 +0000 (00:14 +0100)
The indoe number of root pid namespace is hardcoded in the kernel to
0xEFFFFFFC since 3.8, so check the inode number of our pid namespace
if all else fails. If it's not 0xEFFFFFFC then we are in a pid
namespace, hence a container environment.

Fixes https://github.com/systemd/systemd/issues/35249

[Reworked by Lennart, to make use of namespace_is_init()]

src/basic/virt.c
test/units/TEST-74-AUX-UTILS.detect-virt.sh

index fd0c353791643a805691ae3e3be16175774f69c4..7792d64f16b1d344a42c7e30fdbb5f48d6e618e0 100644 (file)
@@ -645,6 +645,16 @@ static int running_in_cgroupns(void) {
         }
 }
 
+static int running_in_pidns(void) {
+        int r;
+
+        r = namespace_is_init(NAMESPACE_PID);
+        if (r < 0)
+                return log_debug_errno(r, "Failed to test if in root PID namespace, ignoring: %m");
+
+        return !r;
+}
+
 static Virtualization detect_container_files(void) {
         static const struct {
                 const char *file_path;
@@ -790,12 +800,21 @@ check_files:
 
         r = running_in_cgroupns();
         if (r > 0) {
+                log_debug("Running in a cgroup namespace, assuming unknown container manager.");
                 v = VIRTUALIZATION_CONTAINER_OTHER;
                 goto finish;
         }
         if (r < 0)
                 log_debug_errno(r, "Failed to detect cgroup namespace: %m");
 
+        /* Finally, the root pid namespace has an hardcoded inode number of 0xEFFFFFFC since kernel 3.8, so
+         * if all else fails we can check the inode number of our pid namespace and compare it. */
+        if (running_in_pidns() > 0) {
+                log_debug("Running in a pid namespace, assuming unknown container manager.");
+                v = VIRTUALIZATION_CONTAINER_OTHER;
+                goto finish;
+        }
+
         /* If none of that worked, give up, assume no container manager. */
         v = VIRTUALIZATION_NONE;
         goto finish;
index fe1db4d2aa20ae0b680a005afd1704e767a68f03..a1539d9b44f65be19a655050a4900c1a6049f8f7 100755 (executable)
@@ -5,3 +5,7 @@ set -o pipefail
 
 SYSTEMD_IN_CHROOT=1 systemd-detect-virt --chroot
 (! SYSTEMD_IN_CHROOT=0 systemd-detect-virt --chroot)
+
+if ! systemd-detect-virt -c; then
+    unshare --mount-proc --fork --user --pid systemd-detect-virt --container
+fi