* default to running as UID/GID 0 when using lxc-execute */
new->init_uid = 0;
new->init_gid = 0;
+ memset(&new->init_groups, 0, sizeof(lxc_groups_t));
memset(&new->cgroup_meta, 0, sizeof(struct lxc_cgroup));
memset(&new->ns_share, 0, sizeof(char *) * LXC_NS_MAX);
memset(&new->timens, 0, sizeof(struct timens_offsets));
struct lxc_conf *lxc_conf, void *data)
{
__do_free char *value_dup = NULL;
- __do_free gid_t *init_groups = NULL;
- int num_groups = 0;
- int iter = 0;
+ gid_t *init_groups = NULL;
+ size_t num_groups = 0;
+ size_t idx;
char *token;
if (lxc_config_value_empty(value))
lxc_iterate_parts(token, value_dup, ",")
num_groups++;
+ if (num_groups == INT_MAX)
+ return log_error_errno(-ERANGE, ERANGE, "Excessive number of supplementary groups specified");
+
if (num_groups == 0)
return clr_config_init_groups(key, lxc_conf, NULL);
- init_groups = zalloc(sizeof(gid_t) * num_groups);
+ idx = lxc_conf->init_groups.size;
+ init_groups = realloc(lxc_conf->init_groups.list, sizeof(gid_t) * (idx + num_groups));
if (!init_groups)
return ret_errno(ENOMEM);
+ /*
+ * Once the realloc() succeeded we need to hand control of the memory
+ * back to the config otherwise we risk a double-free when
+ * lxc_conf_free() is called.
+ */
+ lxc_conf->init_groups.list = init_groups;
+
/* Restore duplicated value so we can call lxc_iterate_parts() again. */
strcpy(value_dup, value);
if (ret)
return ret;
- init_groups[iter++] = group;
+ init_groups[idx++] = group;
}
- lxc_conf->init_groups.size = num_groups;
- lxc_conf->init_groups.list = move_ptr(init_groups);
+ lxc_conf->init_groups.size += num_groups;
return 0;
}
static inline int clr_config_init_groups(const char *key, struct lxc_conf *c,
void *data)
{
- free_disarm(c->init_groups.list);
c->init_groups.size = 0;
+ free_disarm(c->init_groups.list);
return 0;
}