aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJorge Lucangeli Obes <jorgelo@google.com>2016-09-23 15:21:57 -0400
committerJorge Lucangeli Obes <jorgelo@google.com>2016-09-23 15:35:23 -0400
commit200299c81d043606bf1290408251c01d46c51baf (patch)
tree248188b98b73e415fbaf8770ebb2d8fd05b32814
parent85683d1c6ff3c8f84e23399893eda9ab2a6e15b4 (diff)
downloadminijail-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.c9
-rw-r--r--libminijail.h1
-rw-r--r--minijail0.c21
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)) {