Browse Source

jail: implement OCI user additionalGIDs

Signed-off-by: Daniel Golle <daniel@makrotopia.org>
Daniel Golle 3 years ago
parent
commit
c049047be4
1 changed files with 47 additions and 7 deletions
  1. 47 7
      jail/jail.c

+ 47 - 7
jail/jail.c

@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2015 John Crispin <blogic@openwrt.org>
+ * Copyright (C) 2020 Daniel Golle <daniel@makrotopia.org>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU Lesser General Public License version 2.1
@@ -91,6 +92,8 @@ static struct {
 	int pw_uid;
 	int pw_gid;
 	int gr_gid;
+	gid_t *additional_gids;
+	size_t num_additional_gids;
 	int require_jail;
 	struct {
 		struct hook_execvpe **createRuntime;
@@ -860,6 +863,18 @@ static int exec_jail(void *pipes_ptr)
 	}
 	run_hooks(opts.hooks.startContainer);
 
+	if (!(opts.namespace & CLONE_NEWUSER)) {
+		get_jail_user(&pw_uid, &pw_gid, &gr_gid);
+
+		set_jail_user(opts.pw_uid?:pw_uid, opts.pw_gid?:pw_gid, opts.gr_gid?:gr_gid);
+	}
+
+	if (opts.additional_gids &&
+	    (setgroups(opts.num_additional_gids, opts.additional_gids) < 0)) {
+		ERROR("setgroups failed: %m\n");
+		exit(EXIT_FAILURE);
+	}
+
 	if (applyOCIcapabilities(opts.capset))
 		exit(EXIT_FAILURE);
 
@@ -871,12 +886,6 @@ static int exec_jail(void *pipes_ptr)
 		exit(EXIT_FAILURE);
 	}
 
-	if (!(opts.namespace & CLONE_NEWUSER)) {
-		get_jail_user(&pw_uid, &pw_gid, &gr_gid);
-
-		set_jail_user(opts.pw_uid?:pw_uid, opts.pw_gid?:pw_gid, opts.gr_gid?:gr_gid);
-	}
-
 	char **envp = build_envp(opts.seccomp, opts.envp);
 	if (!envp)
 		exit(EXIT_FAILURE);
@@ -1216,6 +1225,9 @@ static const struct blobmsg_policy oci_process_user_policy[] = {
 
 static int parseOCIprocessuser(struct blob_attr *msg) {
 	struct blob_attr *tb[__OCI_PROCESS_USER_MAX];
+	struct blob_attr *cur;
+	int rem;
+	int has_gid = 0;
 
 	blobmsg_parse(oci_process_user_policy, __OCI_PROCESS_USER_MAX, tb, blobmsg_data(msg), blobmsg_len(msg));
 
@@ -1225,9 +1237,37 @@ static int parseOCIprocessuser(struct blob_attr *msg) {
 	if (tb[OCI_PROCESS_USER_GID]) {
 		opts.pw_gid = blobmsg_get_u32(tb[OCI_PROCESS_USER_GID]);
 		opts.gr_gid = blobmsg_get_u32(tb[OCI_PROCESS_USER_GID]);
+		has_gid = 1;
+	}
+
+	if (tb[OCI_PROCESS_USER_ADDITIONALGIDS]) {
+		size_t gidcnt = 0;
+
+		blobmsg_for_each_attr(cur, tb[OCI_PROCESS_USER_ADDITIONALGIDS], rem) {
+			++gidcnt;
+			if (has_gid && (blobmsg_get_u32(cur) == opts.gr_gid))
+				continue;
+		}
+
+		if (gidcnt) {
+			opts.additional_gids = calloc(gidcnt + has_gid, sizeof(gid_t));
+			gidcnt = 0;
+
+			/* always add primary GID to set of GIDs if set */
+			if (has_gid)
+				opts.additional_gids[gidcnt++] = opts.gr_gid;
+
+			blobmsg_for_each_attr(cur, tb[OCI_PROCESS_USER_ADDITIONALGIDS], rem) {
+				if (has_gid && (blobmsg_get_u32(cur) == opts.gr_gid))
+					continue;
+				opts.additional_gids[gidcnt++] = blobmsg_get_u32(cur);
+			}
+			opts.num_additional_gids = gidcnt;
+		}
+		DEBUG("read %lu additional groups\n", gidcnt);
 	}
 
-	/* ToDo: umask, additional GIDs */
+	/* ToDo: umask */
 
 	return 0;
 }