From: Serge Hallyn Date: Fri, 1 Nov 2019 05:34:02 +0000 (-0500) Subject: lxc-usernsexec: support easily mapping own uid X-Git-Tag: lxc-4.0.0~99^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=81d15993cc84164d997e17739e9be7b24d32c4d4;p=thirdparty%2Flxc.git lxc-usernsexec: support easily mapping own uid Signed-off-by: Serge Hallyn --- diff --git a/src/lxc/cmd/lxc_usernsexec.c b/src/lxc/cmd/lxc_usernsexec.c index 608001e8c..396a208be 100644 --- a/src/lxc/cmd/lxc_usernsexec.c +++ b/src/lxc/cmd/lxc_usernsexec.c @@ -57,12 +57,13 @@ extern int lxc_log_fd; static void usage(const char *name) { - printf("usage: %s [-h] [-m ] -- [command [arg ..]]\n", name); + printf("usage: %s [-h] [-m ] [-s] -- [command [arg ..]]\n", name); printf("\n"); printf(" -h this message\n"); printf("\n"); printf(" -m uid maps to use\n"); printf("\n"); + printf(" -s: map self\n"); printf(" uid-maps: [u|g|b]:ns_id:host_id:range\n"); printf(" [u|g|b]: map user id, group id, or both\n"); printf(" ns_id: the base id in the new namespace\n"); @@ -136,18 +137,40 @@ static int do_child(void *vargv) static struct lxc_list active_map; +static int add_map_entry(long host_id, long ns_id, long range, int which) +{ + struct lxc_list *tmp = NULL; + struct id_map *newmap; + + newmap = malloc(sizeof(*newmap)); + if (!newmap) + return -1; + + newmap->hostid = host_id; + newmap->nsid = ns_id; + newmap->range = range; + newmap->idtype = which; + tmp = malloc(sizeof(*tmp)); + if (!tmp) { + free(newmap); + return -1; + } + + tmp->elem = newmap; + lxc_list_add_tail(&active_map, tmp); + return 0; +} + /* * Given a string like "b:0:100000:10", map both uids and gids 0-10 to 100000 * to 100010 */ static int parse_map(char *map) { - int i, ret; + int i, ret, idtype; long host_id, ns_id, range; char which; - struct id_map *newmap; char types[2] = {'u', 'g'}; - struct lxc_list *tmp = NULL; if (!map) return -1; @@ -163,27 +186,14 @@ static int parse_map(char *map) if (which != types[i] && which != 'b') continue; - newmap = malloc(sizeof(*newmap)); - if (!newmap) - return -1; - - newmap->hostid = host_id; - newmap->nsid = ns_id; - newmap->range = range; - if (types[i] == 'u') - newmap->idtype = ID_TYPE_UID; + idtype = ID_TYPE_UID; else - newmap->idtype = ID_TYPE_GID; - - tmp = malloc(sizeof(*tmp)); - if (!tmp) { - free(newmap); - return -1; - } + idtype = ID_TYPE_GID; - tmp->elem = newmap; - lxc_list_add_tail(&active_map, tmp); + ret = add_map_entry(host_id, ns_id, range, idtype); + if (ret < 0) + return ret; } return 0; @@ -206,8 +216,6 @@ static int read_default_map(char *fnam, int which, char *user) unsigned long ul1, ul2; int ret = -1; size_t sz = 0; - struct lxc_list *tmp = NULL; - struct id_map *newmap = NULL; fin = fopen(fnam, "r"); if (!fin) @@ -237,26 +245,7 @@ static int read_default_map(char *fnam, int which, char *user) if (ret < 0) break; - ret = -1; - newmap = malloc(sizeof(*newmap)); - if (!newmap) - break; - - newmap->nsid = 0; - newmap->idtype = which; - newmap->hostid = ul1; - newmap->range = ul2; - - tmp = malloc(sizeof(*tmp)); - if (!tmp) { - free(newmap); - break; - } - - tmp->elem = newmap; - lxc_list_add_tail(&active_map, tmp); - - ret = 0; + ret = add_map_entry(ul1, 0, ul2, which); break; } @@ -299,6 +288,42 @@ static int find_default_map(void) return 0; } +static bool is_in_ns_range(long id, struct id_map *map) +{ + if (id < map->nsid) + return false; + if (id >= map->nsid + map->range) + return false; + return true; +} + +static bool do_map_self(void) +{ + struct id_map *map; + long nsuid = 0, nsgid = 0; + struct lxc_list *tmp = NULL; + int ret; + + lxc_list_for_each(tmp, &active_map) { + map = tmp->elem; + if (map->idtype == ID_TYPE_UID) { + if (is_in_ns_range(nsuid, map)) + nsuid += map->range; + } else { + if (is_in_ns_range(nsgid, map)) + nsgid += map->range; + } + } + + ret = add_map_entry(getgid(), nsgid, 1, ID_TYPE_GID); + if (ret < 0) + return false; + ret = add_map_entry(getuid(), nsuid, 1, ID_TYPE_UID); + if (ret < 0) + return false; + return true; +} + int main(int argc, char *argv[]) { int c, pid, ret, status; @@ -308,6 +333,7 @@ int main(int argc, char *argv[]) unsigned long flags = CLONE_NEWUSER | CLONE_NEWNS; char ttyname0[256] = {0}, ttyname1[256] = {0}, ttyname2[256] = {0}; char *default_args[] = {"/bin/sh", NULL}; + bool map_self = false; lxc_log_fd = STDERR_FILENO; @@ -333,7 +359,7 @@ int main(int argc, char *argv[]) lxc_list_init(&active_map); - while ((c = getopt(argc, argv, "m:h")) != EOF) { + while ((c = getopt(argc, argv, "m:hs")) != EOF) { switch (c) { case 'm': ret = parse_map(optarg); @@ -345,6 +371,9 @@ int main(int argc, char *argv[]) case 'h': usage(argv[0]); _exit(EXIT_SUCCESS); + case 's': + map_self = true; + break; default: usage(argv[0]); _exit(EXIT_FAILURE); @@ -359,6 +388,15 @@ int main(int argc, char *argv[]) } } + // Do we want to support map-self with no other allocations? + // If so we should move this above the previous block. + if (map_self) { + if (!do_map_self()) { + fprintf(stderr, "Failed mapping own uid\n"); + _exit(EXIT_FAILURE); + } + } + argv = &argv[optind]; argc = argc - optind; if (argc < 1)