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 _______________________________________________ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel