]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
util: Fine tune running_in_chroot() a bit
authorLennart Poettering <lennart@poettering.net>
Thu, 24 Nov 2016 16:42:19 +0000 (17:42 +0100)
committerMartin Pitt <martin.pitt@ubuntu.com>
Wed, 14 Dec 2016 09:13:52 +0000 (10:13 +0100)
Let's be a bit more careful when detecting chroot() environments, so that we
can discern them from namespaced environments.

Previously this would simply check if the root directory of PID 1 matches our
own root directory. With this commit, we also check whether the namespaces of
PID 1 and ourselves are the same. If not we assume we are running inside of a
namespaced environment instead of a chroot() environment.

This has the benefit that systemctl (which uses running_in_chroot()) will work
as usual when invoked in a namespaced service.

src/basic/virt.c

index d8d57381ad36fea357dc1d718dfac26b738e21ad..9b7eb7131946db741172ac62e7225d28b14454a5 100644 (file)
 
 #include "alloc-util.h"
 #include "dirent-util.h"
+#include "env-util.h"
 #include "fd-util.h"
 #include "fileio.h"
+#include "fs-util.h"
 #include "macro.h"
 #include "process-util.h"
 #include "stat-util.h"
 #include "string-table.h"
 #include "string-util.h"
 #include "virt.h"
-#include "env-util.h"
 
 static int detect_vm_cpuid(void) {
 
@@ -556,16 +557,30 @@ int running_in_userns(void) {
 }
 
 int running_in_chroot(void) {
-        int ret;
+        _cleanup_free_ char *self_mnt = NULL, *pid1_mnt = NULL;
+        int r;
+
+        /* Try to detect whether we are running in a chroot() environment. Specifically, check whether we have a
+         * different root directory than PID 1, even though we live in the same mount namespace as it. */
 
         if (getenv_bool("SYSTEMD_IGNORE_CHROOT") > 0)
                 return 0;
 
-        ret = files_same("/proc/1/root", "/");
-        if (ret < 0)
-                return ret;
+        r = files_same("/proc/1/root", "/");
+        if (r < 0)
+                return r;
+        if (r > 0)
+                return 0;
+
+        r = readlink_malloc("/proc/self/ns/mnt", &self_mnt);
+        if (r < 0)
+                return r;
+
+        r = readlink_malloc("/proc/1/ns/mnt", &pid1_mnt);
+        if (r < 0)
+                return r;
 
-        return ret == 0;
+        return streq(self_mnt, pid1_mnt); /* Only if we live in the same namespace! */
 }
 
 static const char *const virtualization_table[_VIRTUALIZATION_MAX] = {