[systemd-devel] [PATCH] Add detect_userns to detect uid/gid shifts (V2)
Stéphane Graber
stgraber at ubuntu.com
Fri Jan 9 07:14:39 PST 2015
On Fri, Jan 09, 2015 at 11:08:26AM +0100, David Herrmann wrote:
> 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.
Into the parent namespace.
An example is:
- host (0 0 4294967295) (init_user_ns all uids mapped)
- container (0 1000000 1000000) (a million uids mapped from 0 to 1000000 in the namespace, corresponding to 1000000 to 1999999 on the host)
- sub-container (0 100000 65536) (65536 uids mapped from 0 to 65536 in the namespace, corresponding to 100000 to 165534 in container and 1100000 to 1165534 on the host)
You can't create a new userns mapping uids which aren't in your own
userns so the child userns map will at most be the same as its parent.
So it's therefore impossible to have a sub-userns with a map of "0 0
4294967295" if its parent userns has something more restrictive. If it
doesn't, then we're back in that last corner case where you can indeed
create userns with a map identical to the init_user_ns map in which case
uid 0 in container == uid 0 on the host.
>
> 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
--
Stéphane Graber
Ubuntu developer
http://www.ubuntu.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: Digital signature
URL: <http://lists.freedesktop.org/archives/systemd-devel/attachments/20150109/3b256dd0/attachment-0001.sig>
More information about the systemd-devel
mailing list