/* This is a variation of get_list below it. This version allows two additional * features. If a list is passed to it, it adds to it. It allows for empty * entries (i.e. "group1,,group2") generating and empty list entry. */ static struct lxc_list *accumulate_list(char *input, char *delimiter, struct lxc_list *str_list) { char *workstr = NULL; char *workptr = NULL; char *next_ptr = NULL; struct lxc_list *worklist; struct lxc_list *workstr_list; workstr = strdup(input); if (!workstr) return NULL; workstr_list = str_list; if (!workstr_list) { workstr_list = malloc(sizeof(*workstr_list)); lxc_list_init(workstr_list); } for (workptr = workstr; workptr; workptr = next_ptr) { /* We can't use strtok_r here because it collapses multiple * delimiters into 1 making empty fields impossible... */ next_ptr = strchr(workptr, *delimiter); if (next_ptr) *next_ptr++ = '\0'; /* At this point, we'd like to check to see if this group is * already contained in the list and ignore it if it is... This * also helps us with any corner cases where a string begins or * ends with a delimiter. */ if (list_contains_entry(workptr, workstr_list)) { if (*workptr) fprintf(stderr, "Duplicate group \"%s\" in list - ignoring\n", workptr); else fprintf(stderr, "Duplicate NULL group in list - ignoring\n"); } else { worklist = malloc(sizeof(*worklist)); if (!worklist) break; worklist->elem = strdup(workptr); if (!worklist->elem) { free(worklist); break; } lxc_list_add_tail(workstr_list, worklist); } } free(workstr); return workstr_list; }
/* * This is called if the user did not pass any uid ranges in * through -m flags. It's called once to get the default uid * map, and once for the default gid map. * Go through /etc/subuids and /etc/subgids to find this user's * allowed map. We only use the first one for each of uid and * gid, because otherwise we're not sure which entries the user * wanted. */ static int read_default_map(char *fnam, int which, char *username) { FILE *fin; char *line = NULL; size_t sz = 0; struct id_map *newmap; struct lxc_list *tmp = NULL; char *p1, *p2; fin = fopen(fnam, "r"); if (!fin) return -1; while (getline(&line, &sz, fin) != -1) { if (sz <= strlen(username) || strncmp(line, username, strlen(username)) != 0 || line[strlen(username)] != ':') continue; p1 = strchr(line, ':'); if (!p1) continue; p2 = strchr(p1+1, ':'); if (!p2) continue; newmap = malloc(sizeof(*newmap)); if (!newmap) { fclose(fin); free(line); return -1; } newmap->hostid = atol(p1+1); newmap->range = atol(p2+1); newmap->nsid = 0; newmap->idtype = which; tmp = malloc(sizeof(*tmp)); if (!tmp) { fclose(fin); free(line); free(newmap); return -1; } tmp->elem = newmap; lxc_list_add_tail(&active_map, tmp); break; } free(line); fclose(fin); 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) { struct id_map *newmap; struct lxc_list *tmp = NULL; int ret; int i; char types[2] = {'u', 'g'}; char which; long host_id, ns_id, range; if (!map) return -1; ret = sscanf(map, "%c:%ld:%ld:%ld", &which, &ns_id, &host_id, &range); if (ret != 4) return -1; if (which != 'b' && which != 'u' && which != 'g') return -1; for (i = 0; i < 2; i++) { 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; else newmap->idtype = ID_TYPE_GID; tmp = malloc(sizeof(*tmp)); if (!tmp) { free(newmap); return -1; } tmp->elem = newmap; lxc_list_add_tail(&active_map, tmp); } return 0; }
static int config_network_type(const char *key, char *value, struct lxc_conf *lxc_conf) { struct lxc_list *network = &lxc_conf->network; struct lxc_netdev *netdev; struct lxc_list *list; netdev = malloc(sizeof(*netdev)); if (!netdev) { SYSERROR("failed to allocate memory"); return -1; } memset(netdev, 0, sizeof(*netdev)); lxc_list_init(&netdev->ipv4); lxc_list_init(&netdev->ipv6); list = malloc(sizeof(*list)); if (!list) { SYSERROR("failed to allocate memory"); return -1; } lxc_list_init(list); list->elem = netdev; lxc_list_add_tail(network, list); if (!strcmp(value, "veth")) netdev->type = LXC_NET_VETH; else if (!strcmp(value, "macvlan")) netdev->type = LXC_NET_MACVLAN; else if (!strcmp(value, "vlan")) netdev->type = LXC_NET_VLAN; else if (!strcmp(value, "phys")) netdev->type = LXC_NET_PHYS; else if (!strcmp(value, "empty")) netdev->type = LXC_NET_EMPTY; else { ERROR("invalid network type %s", value); return -1; } return 0; }
static struct lxc_list *get_list(char *input, char *delimiter) { char *workstr = NULL; char *workptr = NULL; char *sptr = NULL; char *token = NULL; struct lxc_list *worklist; struct lxc_list *workstr_list; workstr_list = malloc(sizeof(*workstr_list)); lxc_list_init(workstr_list); workstr = strdup(input); if (!workstr) { free(workstr_list); return NULL; } for (workptr = workstr;;workptr = NULL) { token = strtok_r(workptr, delimiter, &sptr); if (!token) { break; } worklist = malloc(sizeof(*worklist)); if (!worklist) break; worklist->elem = strdup(token); if (!worklist->elem) { free(worklist); break; } lxc_list_add_tail(workstr_list, worklist); } free(workstr); return workstr_list; }
/* * This is called if the user did not pass any uid ranges in through -m flags. * It's called once to get the default uid map, and once for the default gid * map. * Go through /etc/subuids and /etc/subgids to find this user's allowed map. We * only use the first one for each of uid and gid, because otherwise we're not * sure which entries the user wanted. */ static int read_default_map(char *fnam, int which, char *user) { size_t len; char *p1, *p2; unsigned long ul1, ul2; FILE *fin; int ret = -1; size_t sz = 0; char *line = NULL; struct lxc_list *tmp = NULL; struct id_map *newmap = NULL; fin = fopen(fnam, "r"); if (!fin) return -1; len = strlen(user); while (getline(&line, &sz, fin) != -1) { if (sz <= len || strncmp(line, user, len) != 0 || line[len] != ':') continue; p1 = strchr(line, ':'); if (!p1) continue; p2 = strchr(p1 + 1, ':'); if (!p2) continue; line[strlen(line) - 1] = '\0'; *p2 = '\0'; ret = lxc_safe_ulong(p1 + 1, &ul1); if (ret < 0) break; ret = lxc_safe_ulong(p2 + 1, &ul2); 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; break; } fclose(fin); free(line); return ret; }