[systemd-devel] [PATCH] Add detect_userns to detect uid/gid shifts (V2)

St├ęphane Graber stgraber at ubuntu.com
Thu Jan 8 15:07:03 PST 2015


This adds a new detect_userns function in virt.c which will check
whether systemd is running in the host user namespace (single map of all
available uids and gids) or is using a uid/gid map.

The check makes sure that uid_map and gid_map are both exactly equal to
the default host map (assuming 32bit uid_t) for a process running in the
host namespace.
---
 src/shared/virt.c | 43 +++++++++++++++++++++++++++++++++++++++++++
 src/shared/virt.h |  1 +
 2 files changed, 44 insertions(+)

diff --git a/src/shared/virt.c b/src/shared/virt.c
index f10baab..7fa8d0b 100644
--- a/src/shared/virt.c
+++ b/src/shared/virt.c
@@ -22,6 +22,7 @@
 #include <string.h>
 #include <errno.h>
 #include <unistd.h>
+#include <limits.h>
 
 #include "util.h"
 #include "virt.h"
@@ -363,3 +364,45 @@ int detect_virtualization(const char **id) {
 
         return VIRTUALIZATION_NONE;
 }
+
+/* Detect whether we run in a uid/gid shifted namespace */
+int detect_userns(void) {
+        int r;
+
+        _cleanup_free_ char* uid_map = NULL;
+        _cleanup_free_ char* gid_map = NULL;
+
+        uid_t id_host = 0;
+        uid_t id_container = 0;
+        uid_t id_count = 0;
+
+        /* Check if we are uid-shifted */
+        r = read_one_line_file("/proc/self/uid_map", &uid_map);
+        if (r == 0 &&
+            sscanf(uid_map, "%u %u %u", &id_host, &id_container, &id_count) &&
+            (id_host != 0 || id_container != 0 || id_count != UINT_MAX))
+                return 1;
+
+        /* Check if we are gid-shifted */
+        r = read_one_line_file("/proc/self/gid_map", &gid_map);
+        if (r == 0 &&
+            sscanf(gid_map, "%u %u %u", &id_host, &id_container, &id_count) &&
+            (id_host != 0 || id_container != 0 || id_count != UINT_MAX))
+                return 1;
+
+        /* In the following cases, let's assume we are in the host namespace:
+           - Neither uid_map nor gid_map exist in /proc/self.
+             (this indicates lack of userns support in the kernel)
+
+           - Both the uid and gid map equals to the complete set of available
+             uids or gids. This can only be true on the host namespace or if a
+             container was setup to have the same map as the host.
+
+             That last possibility isn't detectable short of guessing
+             based on syscall results but there's also no real use case
+             for such a setup (why create a new uid/gid mapping namespace
+             if you then re-use the host map as-is?).
+         */
+
+        return 0;
+}
diff --git a/src/shared/virt.h b/src/shared/virt.h
index 7194ab2..e19c7e8 100644
--- a/src/shared/virt.h
+++ b/src/shared/virt.h
@@ -33,3 +33,4 @@ enum {
 };
 
 int detect_virtualization(const char **id);
+int detect_userns(void);
-- 
1.9.1



More information about the systemd-devel mailing list