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

David Herrmann dh.herrmann at gmail.com
Fri Jan 9 02:08:26 PST 2015


Hi

On Fri, Jan 9, 2015 at 12:07 AM, Stéphane Graber <stgraber at ubuntu.com> wrote:
> 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;
> +

Do these files describe the mapping into the init_user_ns or into the
parent namespace? Because in the second case, if you create a
user-namespace with a non-identity mapping and inside of it a user-ns
with an identity-mapping, your detect_userns() will return 0, even
though you run in a user-namespace.

Thanks
David

> +        /* 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 at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/systemd-devel


More information about the systemd-devel mailing list