diff options
author | Jorge Lucangeli Obes <jorgelo@google.com> | 2016-09-23 15:21:57 -0400 |
---|---|---|
committer | Jorge Lucangeli Obes <jorgelo@google.com> | 2016-09-23 15:35:23 -0400 |
commit | 200299c81d043606bf1290408251c01d46c51baf (patch) | |
tree | 248188b98b73e415fbaf8770ebb2d8fd05b32814 | |
parent | 85683d1c6ff3c8f84e23399893eda9ab2a6e15b4 (diff) | |
download | minijail-200299c81d043606bf1290408251c01d46c51baf.tar.gz |
Allow entering a user namespace with a default gid mapping.
https://android-review.googlesource.com/253910 added functionality to
enter a user namespace with a default uid mapping. This CL completes
that with a default gid mapping.
This is useful when using user namespaces to gain root inside a
namespace. Note that setting the gid map as a non-root user requires
disabling the setgroups(2) system call by writing "deny" to
/proc/[pid]/setgroups.
Eventually we might expose disabling setgroups(2) as a command-line
option, but there's no need to do it now.
Bug: 30691131
Test: Using minijail0:
$ ./minijail0 -m /usr/bin/id
uid=0(root) gid=65534(nogroup) groups=0(root),65534(nogroup)
$ ./minijail0 -m -M /usr/bin/id
uid=0(root) gid=0(root) groups=0(root),65534(nogroup)
Change-Id: I8f91bc43516a47df7bbf12a121cf658e89861aa0
-rw-r--r-- | libminijail.c | 9 | ||||
-rw-r--r-- | libminijail.h | 1 | ||||
-rw-r--r-- | minijail0.c | 21 |
3 files changed, 29 insertions, 2 deletions
diff --git a/libminijail.c b/libminijail.c index 597fef2..5513b19 100644 --- a/libminijail.c +++ b/libminijail.c @@ -133,6 +133,7 @@ struct minijail { int enter_net:1; int ns_cgroups:1; int userns:1; + int disable_setgroups:1; int seccomp:1; int remount_proc_ro:1; int no_new_privs:1; @@ -463,6 +464,11 @@ void API minijail_namespace_user(struct minijail *j) j->flags.userns = 1; } +void API minijail_namespace_user_disable_setgroups(struct minijail *j) +{ + j->flags.disable_setgroups = 1; +} + int API minijail_uidmap(struct minijail *j, const char *uidmap) { j->uidmap = strdup(uidmap); @@ -1263,6 +1269,9 @@ static void write_ugid_maps_or_die(const struct minijail *j) { if (j->uidmap && write_proc_file(j->initpid, j->uidmap, "uid_map") != 0) kill_child_and_die(j, "failed to write uid_map"); + if (j->gidmap && j->flags.disable_setgroups && + write_proc_file(j->initpid, "deny", "setgroups") != 0) + kill_child_and_die(j, "failed to disable setgroups(2)"); if (j->gidmap && write_proc_file(j->initpid, j->gidmap, "gid_map") != 0) kill_child_and_die(j, "failed to write gid_map"); } diff --git a/libminijail.h b/libminijail.h index 98d5009..ae829d9 100644 --- a/libminijail.h +++ b/libminijail.h @@ -75,6 +75,7 @@ void minijail_namespace_cgroups(struct minijail *j); */ void minijail_namespace_pids(struct minijail *j); void minijail_namespace_user(struct minijail *j); +void minijail_namespace_user_disable_setgroups(struct minijail *j); int minijail_uidmap(struct minijail *j, const char *uidmap); int minijail_gidmap(struct minijail *j, const char *gidmap); void minijail_remount_proc_readonly(struct minijail *j); diff --git a/minijail0.c b/minijail0.c index dbe1797..48e1d07 100644 --- a/minijail0.c +++ b/minijail0.c @@ -195,7 +195,7 @@ static int parse_args(struct minijail *j, int argc, char *argv[], return 1; const char *optstring = - "u:g:sS:c:C:P:b:V:f:m::M:k:a:e::T:vrGhHinNplLtIUKY"; + "u:g:sS:c:C:P:b:V:f:m::M::k:a:e::T:vrGhHinNplLtIUKY"; while ((opt = getopt(argc, argv, optstring)) != -1) { switch (opt) { case 'u': @@ -341,10 +341,27 @@ static int parse_args(struct minijail *j, int argc, char *argv[], case 'M': minijail_namespace_user(j); minijail_namespace_pids(j); - if (0 != minijail_gidmap(j, optarg)) { + + if (optarg) { + map = strdup(optarg); + } else { + /* + * If no map is passed, map the current gid to + * root. + * This means that we're likely *not* running as + * root, so we also have to disable + * setgroups(2) to be able to set the gid map. + * See http://man7.org/linux/man-pages/man7/user_namespaces.7.html + */ + minijail_namespace_user_disable_setgroups(j); + + map = build_idmap(0, getgid()); + } + if (0 != minijail_gidmap(j, map)) { fprintf(stderr, "Could not set gid map.\n"); exit(1); } + free(map); break; case 'a': if (0 != minijail_use_alt_syscall(j, optarg)) { |