Merge pull request #3952 from brauner/2021-08-25.list.2

conf: port more types to new list type
This commit is contained in:
Stéphane Graber 2021-08-26 10:53:06 -04:00 committed by GitHub
commit 19202d882b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 609 additions and 818 deletions

View File

@ -782,7 +782,6 @@ static int lxc_attach_set_environment(struct attach_context *ctx,
char **extra_env, char **extra_keep) char **extra_env, char **extra_keep)
{ {
int ret; int ret;
struct lxc_list *iterator;
if (policy == LXC_ATTACH_CLEAR_ENV) { if (policy == LXC_ATTACH_CLEAR_ENV) {
int path_kept = 0; int path_kept = 0;
@ -863,17 +862,9 @@ static int lxc_attach_set_environment(struct attach_context *ctx,
/* Set container environment variables.*/ /* Set container environment variables.*/
if (ctx->container->lxc_conf) { if (ctx->container->lxc_conf) {
lxc_list_for_each(iterator, &ctx->container->lxc_conf->environment) { ret = lxc_set_environment(ctx->container->lxc_conf);
char *env_tmp;
env_tmp = strdup((char *)iterator->elem);
if (!env_tmp)
return -1;
ret = putenv(env_tmp);
if (ret < 0) if (ret < 0)
return log_error_errno(-1, errno, "Failed to set environment variable: %s", (char *)iterator->elem); return -1;
}
} }
/* Set extra environment variables. */ /* Set extra environment variables. */
@ -1659,23 +1650,15 @@ int lxc_attach(struct lxc_container *container, lxc_attach_exec_t exec_function,
goto on_error; goto on_error;
/* Setup /proc limits */ /* Setup /proc limits */
if (!lxc_list_empty(&conf->procs)) { ret = setup_proc_filesystem(conf, pid);
ret = setup_proc_filesystem(&conf->procs, pid);
if (ret < 0) if (ret < 0)
goto on_error; goto on_error;
TRACE("Setup /proc/%d settings", pid);
}
/* Setup resource limits */ /* Setup resource limits */
if (!lxc_list_empty(&conf->limits)) { ret = setup_resource_limits(conf, pid);
ret = setup_resource_limits(&conf->limits, pid);
if (ret < 0) if (ret < 0)
goto on_error; goto on_error;
TRACE("Setup resource limits");
}
if (options->attach_flags & LXC_ATTACH_TERMINAL) { if (options->attach_flags & LXC_ATTACH_TERMINAL) {
ret = lxc_attach_terminal_mainloop_init(&terminal, &descr); ret = lxc_attach_terminal_mainloop_init(&terminal, &descr);
if (ret < 0) if (ret < 0)

View File

@ -575,7 +575,7 @@ __cgfsng_ops static void cgfsng_payload_destroy(struct cgroup_ops *ops,
if (ret < 0) if (ret < 0)
WARN("Failed to detach bpf program from cgroup"); WARN("Failed to detach bpf program from cgroup");
if (!lxc_list_empty(&handler->conf->id_map)) { if (!list_empty(&handler->conf->id_map)) {
struct generic_userns_exec_data wrap = { struct generic_userns_exec_data wrap = {
.conf = handler->conf, .conf = handler->conf,
.path_prune = ops->container_limit_cgroup, .path_prune = ops->container_limit_cgroup,
@ -1363,7 +1363,7 @@ __cgfsng_ops static bool cgfsng_chown(struct cgroup_ops *ops,
if (!conf) if (!conf)
return ret_set_errno(false, EINVAL); return ret_set_errno(false, EINVAL);
if (lxc_list_empty(&conf->id_map)) if (list_empty(&conf->id_map))
return true; return true;
wrap.origuid = geteuid(); wrap.origuid = geteuid();
@ -2289,7 +2289,7 @@ static int __cg_unified_attach(const struct hierarchy *h,
if (unified_fd < 0) if (unified_fd < 0)
return ret_errno(EBADF); return ret_errno(EBADF);
if (!lxc_list_empty(&conf->id_map)) { if (!list_empty(&conf->id_map)) {
struct userns_exec_unified_attach_data args = { struct userns_exec_unified_attach_data args = {
.conf = conf, .conf = conf,
.unified_fd = unified_fd, .unified_fd = unified_fd,
@ -2707,11 +2707,8 @@ __cgfsng_ops static bool cgfsng_setup_limits_legacy(struct cgroup_ops *ops,
struct lxc_conf *conf, struct lxc_conf *conf,
bool do_devices) bool do_devices)
{ {
__do_free struct lxc_list *sorted_cgroup_settings = NULL; struct list_head *cgroup_settings;
struct lxc_list *cgroup_settings = &conf->cgroup; struct lxc_cgroup *cgroup;
struct lxc_list *iterator, *next;
struct lxc_cgroup *cg;
bool ret = false;
if (!ops) if (!ops)
return ret_set_errno(false, ENOENT); return ret_set_errno(false, ENOENT);
@ -2720,7 +2717,7 @@ __cgfsng_ops static bool cgfsng_setup_limits_legacy(struct cgroup_ops *ops,
return ret_set_errno(false, EINVAL); return ret_set_errno(false, EINVAL);
cgroup_settings = &conf->cgroup; cgroup_settings = &conf->cgroup;
if (lxc_list_empty(cgroup_settings)) if (list_empty(cgroup_settings))
return true; return true;
if (!ops->hierarchies) if (!ops->hierarchies)
@ -2729,35 +2726,23 @@ __cgfsng_ops static bool cgfsng_setup_limits_legacy(struct cgroup_ops *ops,
if (pure_unified_layout(ops)) if (pure_unified_layout(ops))
return log_warn_errno(true, EINVAL, "Ignoring legacy cgroup limits on pure cgroup2 system"); return log_warn_errno(true, EINVAL, "Ignoring legacy cgroup limits on pure cgroup2 system");
sorted_cgroup_settings = sort_cgroup_settings(cgroup_settings); sort_cgroup_settings(conf);
if (!sorted_cgroup_settings) list_for_each_entry(cgroup, cgroup_settings, head) {
return false; if (do_devices == strnequal("devices", cgroup->subsystem, 7)) {
if (cg_legacy_set_data(ops, cgroup->subsystem, cgroup->value, strnequal("cpuset", cgroup->subsystem, 6))) {
lxc_list_for_each(iterator, sorted_cgroup_settings) {
cg = iterator->elem;
if (do_devices == strnequal("devices", cg->subsystem, 7)) {
if (cg_legacy_set_data(ops, cg->subsystem, cg->value, strnequal("cpuset", cg->subsystem, 6))) {
if (do_devices && (errno == EACCES || errno == EPERM)) { if (do_devices && (errno == EACCES || errno == EPERM)) {
SYSWARN("Failed to set \"%s\" to \"%s\"", cg->subsystem, cg->value); SYSWARN("Failed to set \"%s\" to \"%s\"", cgroup->subsystem, cgroup->value);
continue; continue;
} }
SYSERROR("Failed to set \"%s\" to \"%s\"", cg->subsystem, cg->value); SYSERROR("Failed to set \"%s\" to \"%s\"", cgroup->subsystem, cgroup->value);
goto out; return false;
} }
DEBUG("Set controller \"%s\" set to \"%s\"", cg->subsystem, cg->value); DEBUG("Set controller \"%s\" set to \"%s\"", cgroup->subsystem, cgroup->value);
} }
} }
ret = true;
INFO("Limits for the legacy cgroup hierarchies have been setup"); INFO("Limits for the legacy cgroup hierarchies have been setup");
out: return true;
lxc_list_for_each_safe(iterator, sorted_cgroup_settings, next) {
lxc_list_del(iterator);
free(iterator);
}
return ret;
} }
/* /*
@ -2793,9 +2778,10 @@ static int bpf_device_cgroup_prepare(struct cgroup_ops *ops,
__cgfsng_ops static bool cgfsng_setup_limits(struct cgroup_ops *ops, __cgfsng_ops static bool cgfsng_setup_limits(struct cgroup_ops *ops,
struct lxc_handler *handler) struct lxc_handler *handler)
{ {
struct lxc_list *cgroup_settings, *iterator; struct list_head *cgroup_settings;
struct hierarchy *h; struct hierarchy *h;
struct lxc_conf *conf; struct lxc_conf *conf;
struct lxc_cgroup *cgroup;
if (!ops) if (!ops)
return ret_set_errno(false, ENOENT); return ret_set_errno(false, ENOENT);
@ -2811,7 +2797,7 @@ __cgfsng_ops static bool cgfsng_setup_limits(struct cgroup_ops *ops,
conf = handler->conf; conf = handler->conf;
cgroup_settings = &conf->cgroup2; cgroup_settings = &conf->cgroup2;
if (lxc_list_empty(cgroup_settings)) if (list_empty(cgroup_settings))
return true; return true;
if (!pure_unified_layout(ops)) if (!pure_unified_layout(ops))
@ -2821,18 +2807,17 @@ __cgfsng_ops static bool cgfsng_setup_limits(struct cgroup_ops *ops,
return false; return false;
h = ops->unified; h = ops->unified;
lxc_list_for_each (iterator, cgroup_settings) { list_for_each_entry(cgroup, cgroup_settings, head) {
struct lxc_cgroup *cg = iterator->elem;
int ret; int ret;
if (strnequal("devices", cg->subsystem, 7)) if (strnequal("devices", cgroup->subsystem, 7))
ret = bpf_device_cgroup_prepare(ops, conf, cg->subsystem, cg->value); ret = bpf_device_cgroup_prepare(ops, conf, cgroup->subsystem, cgroup->value);
else else
ret = lxc_write_openat(h->path_lim, cg->subsystem, cg->value, strlen(cg->value)); ret = lxc_write_openat(h->path_lim, cgroup->subsystem, cgroup->value, strlen(cgroup->value));
if (ret < 0) if (ret < 0)
return log_error_errno(false, errno, "Failed to set \"%s\" to \"%s\"", cg->subsystem, cg->value); return log_error_errno(false, errno, "Failed to set \"%s\" to \"%s\"", cgroup->subsystem, cgroup->value);
TRACE("Set \"%s\" to \"%s\"", cg->subsystem, cg->value); TRACE("Set \"%s\" to \"%s\"", cgroup->subsystem, cgroup->value);
} }
return log_info(true, "Limits for the unified cgroup hierarchy have been setup"); return log_info(true, "Limits for the unified cgroup hierarchy have been setup");
@ -3359,7 +3344,7 @@ static int initialize_cgroups(struct cgroup_ops *ops, struct lxc_conf *conf)
*/ */
ops->dfd_mnt = dfd; ops->dfd_mnt = dfd;
ret = __initialize_cgroups(ops, conf->cgroup_meta.relative, !lxc_list_empty(&conf->id_map)); ret = __initialize_cgroups(ops, conf->cgroup_meta.relative, !list_empty(&conf->id_map));
if (ret < 0) if (ret < 0)
return syserror_ret(ret, "Failed to initialize cgroups"); return syserror_ret(ret, "Failed to initialize cgroups");
@ -3436,7 +3421,7 @@ static int __unified_attach_fd(const struct lxc_conf *conf, int fd_unified, pid_
{ {
int ret; int ret;
if (!lxc_list_empty(&conf->id_map)) { if (!list_empty(&conf->id_map)) {
struct userns_exec_unified_attach_data args = { struct userns_exec_unified_attach_data args = {
.conf = conf, .conf = conf,
.unified_fd = fd_unified, .unified_fd = fd_unified,

View File

@ -26,7 +26,6 @@
struct lxc_handler; struct lxc_handler;
struct lxc_conf; struct lxc_conf;
struct lxc_list;
typedef enum { typedef enum {
CGROUP_LAYOUT_UNKNOWN = -1, CGROUP_LAYOUT_UNKNOWN = -1,

View File

@ -114,11 +114,10 @@ static int do_child(void *vargv)
return -1; return -1;
} }
static struct lxc_list active_map; static LIST_HEAD(active_map);
static int add_map_entry(long host_id, long ns_id, long range, int which) static int add_map_entry(long host_id, long ns_id, long range, int which)
{ {
struct lxc_list *tmp = NULL;
struct id_map *newmap; struct id_map *newmap;
newmap = malloc(sizeof(*newmap)); newmap = malloc(sizeof(*newmap));
@ -129,14 +128,8 @@ static int add_map_entry(long host_id, long ns_id, long range, int which)
newmap->nsid = ns_id; newmap->nsid = ns_id;
newmap->range = range; newmap->range = range;
newmap->idtype = which; newmap->idtype = which;
tmp = malloc(sizeof(*tmp));
if (!tmp) {
free(newmap);
return -1;
}
tmp->elem = newmap; list_add_tail(&newmap->head, &active_map);
lxc_list_add_tail(&active_map, tmp);
return 0; return 0;
} }
@ -280,11 +273,9 @@ static bool do_map_self(void)
{ {
struct id_map *map; struct id_map *map;
long nsuid = 0, nsgid = 0; long nsuid = 0, nsgid = 0;
struct lxc_list *tmp = NULL;
int ret; int ret;
lxc_list_for_each(tmp, &active_map) { list_for_each_entry(map, &active_map, head) {
map = tmp->elem;
if (map->idtype == ID_TYPE_UID) { if (map->idtype == ID_TYPE_UID) {
if (is_in_ns_range(nsuid, map)) if (is_in_ns_range(nsuid, map))
nsuid += map->range; nsuid += map->range;
@ -336,8 +327,6 @@ int main(int argc, char *argv[])
} }
} }
lxc_list_init(&active_map);
while ((c = getopt(argc, argv, "m:hs")) != EOF) { while ((c = getopt(argc, argv, "m:hs")) != EOF) {
switch (c) { switch (c) {
case 'm': case 'm':
@ -359,7 +348,7 @@ int main(int argc, char *argv[])
} }
}; };
if (lxc_list_empty(&active_map)) { if (list_empty(&active_map)) {
ret = find_default_map(); ret = find_default_map();
if (ret < 0) { if (ret < 0) {
fprintf(stderr, "Failed to find subuid or subgid allocation\n"); fprintf(stderr, "Failed to find subuid or subgid allocation\n");

File diff suppressed because it is too large Load Diff

View File

@ -78,6 +78,8 @@ struct lxc_cgroup {
bool relative; bool relative;
}; };
}; };
struct list_head head;
}; };
static void free_lxc_cgroup(struct lxc_cgroup *ptr) static void free_lxc_cgroup(struct lxc_cgroup *ptr)
@ -95,6 +97,7 @@ define_cleanup_function(struct lxc_cgroup *, free_lxc_cgroup);
struct rlimit { struct rlimit {
unsigned long rlim_cur; unsigned long rlim_cur;
unsigned long rlim_max; unsigned long rlim_max;
struct list_head head;
}; };
#endif #endif
@ -106,6 +109,7 @@ struct rlimit {
struct lxc_limit { struct lxc_limit {
char *resource; char *resource;
struct rlimit limit; struct rlimit limit;
struct list_head head;
}; };
static void free_lxc_limit(struct lxc_limit *ptr) static void free_lxc_limit(struct lxc_limit *ptr)
@ -130,6 +134,7 @@ enum idtype {
struct lxc_sysctl { struct lxc_sysctl {
char *key; char *key;
char *value; char *value;
struct list_head head;
}; };
static void free_lxc_sysctl(struct lxc_sysctl *ptr) static void free_lxc_sysctl(struct lxc_sysctl *ptr)
@ -150,6 +155,7 @@ define_cleanup_function(struct lxc_sysctl *, free_lxc_sysctl);
struct lxc_proc { struct lxc_proc {
char *filename; char *filename;
char *value; char *value;
struct list_head head;
}; };
static void free_lxc_proc(struct lxc_proc *ptr) static void free_lxc_proc(struct lxc_proc *ptr)
@ -175,6 +181,7 @@ define_cleanup_function(struct lxc_proc *, free_lxc_proc);
struct id_map { struct id_map {
enum idtype idtype; enum idtype idtype;
unsigned long hostid, nsid, range; unsigned long hostid, nsid, range;
struct list_head head;
}; };
/* Defines the number of tty configured and contains the /* Defines the number of tty configured and contains the
@ -204,13 +211,15 @@ struct lxc_mount_options {
unsigned int create_file : 1; unsigned int create_file : 1;
unsigned int optional : 1; unsigned int optional : 1;
unsigned int relative : 1; unsigned int relative : 1;
unsigned int recursive : 1; unsigned int bind_recursively : 1;
unsigned int propagate_recursively : 1;
unsigned int bind : 1; unsigned int bind : 1;
char userns_path[PATH_MAX]; char userns_path[PATH_MAX];
unsigned long mnt_flags; unsigned long mnt_flags;
unsigned long prop_flags; unsigned long prop_flags;
char *data; char *data;
struct lxc_mount_attr attr; struct lxc_mount_attr attr;
char *raw_options;
}; };
/* Defines a structure to store the rootfs location, the /* Defines a structure to store the rootfs location, the
@ -219,7 +228,6 @@ struct lxc_mount_options {
* @mount : where it is mounted * @mount : where it is mounted
* @buf : static buffer to construct paths * @buf : static buffer to construct paths
* @bev_type : optional backing store type * @bev_type : optional backing store type
* @options : mount options
* @managed : whether it is managed by LXC * @managed : whether it is managed by LXC
* @dfd_mnt : fd for @mount * @dfd_mnt : fd for @mount
* @dfd_dev : fd for /dev of the container * @dfd_dev : fd for /dev of the container
@ -238,8 +246,6 @@ struct lxc_rootfs {
char buf[PATH_MAX]; char buf[PATH_MAX];
char *bdev_type; char *bdev_type;
char *options;
unsigned long mountflags;
bool managed; bool managed;
struct lxc_mount_options mnt_opts; struct lxc_mount_options mnt_opts;
struct lxc_storage *storage; struct lxc_storage *storage;
@ -331,6 +337,23 @@ struct timens_offsets {
int64_t ns_monotonic; int64_t ns_monotonic;
}; };
struct environment_entry {
char *key;
char *val;
struct list_head head;
};
struct cap_entry {
char *cap_name;
int cap;
struct list_head head;
};
struct caps {
int keep;
struct list_head list;
};
struct lxc_conf { struct lxc_conf {
/* Pointer to the name of the container. Do not free! */ /* Pointer to the name of the container. Do not free! */
const char *name; const char *name;
@ -340,13 +363,13 @@ struct lxc_conf {
struct utsname *utsname; struct utsname *utsname;
struct { struct {
struct lxc_list cgroup; struct list_head cgroup;
struct lxc_list cgroup2; struct list_head cgroup2;
struct bpf_devices bpf_devices; struct bpf_devices bpf_devices;
}; };
struct { struct {
struct lxc_list id_map; struct list_head id_map;
/* /*
* Pointer to the idmap entry for the container's root uid in * Pointer to the idmap entry for the container's root uid in
@ -369,8 +392,7 @@ struct lxc_conf {
struct lxc_list mount_list; struct lxc_list mount_list;
}; };
struct lxc_list caps; struct caps caps;
struct lxc_list keepcaps;
/* /dev/tty<idx> devices */ /* /dev/tty<idx> devices */
struct lxc_tty_info ttys; struct lxc_tty_info ttys;
@ -430,14 +452,9 @@ struct lxc_conf {
unsigned int monitor_unshare; unsigned int monitor_unshare;
unsigned int monitor_signal_pdeath; unsigned int monitor_signal_pdeath;
/* list of included files */
struct lxc_list includes;
/* config entries which are not "lxc.*" are aliens */
struct lxc_list aliens;
/* list of environment variables we'll add to the container when /* list of environment variables we'll add to the container when
* started */ * started */
struct lxc_list environment; struct list_head environment;
/* text representation of the config file */ /* text representation of the config file */
char *unexpanded_config; char *unexpanded_config;
@ -468,7 +485,7 @@ struct lxc_conf {
bool no_new_privs; bool no_new_privs;
/* RLIMIT_* limits */ /* RLIMIT_* limits */
struct lxc_list limits; struct list_head limits;
/* Contains generic info about the cgroup configuration for this /* Contains generic info about the cgroup configuration for this
* container. Note that struct lxc_cgroup contains a union. It is only * container. Note that struct lxc_cgroup contains a union. It is only
@ -490,10 +507,10 @@ struct lxc_conf {
struct list_head state_clients; struct list_head state_clients;
/* sysctls */ /* sysctls */
struct lxc_list sysctls; struct list_head sysctls;
/* procs */ /* procs */
struct lxc_list procs; struct list_head procs;
struct shmount { struct shmount {
/* Absolute path to the shared mount point on the host */ /* Absolute path to the shared mount point on the host */
@ -519,11 +536,10 @@ __hidden extern void lxc_storage_put(struct lxc_conf *conf);
__hidden extern int lxc_rootfs_init(struct lxc_conf *conf, bool userns); __hidden extern int lxc_rootfs_init(struct lxc_conf *conf, bool userns);
__hidden extern int lxc_rootfs_prepare_parent(struct lxc_handler *handler); __hidden extern int lxc_rootfs_prepare_parent(struct lxc_handler *handler);
__hidden extern int lxc_idmapped_mounts_parent(struct lxc_handler *handler); __hidden extern int lxc_idmapped_mounts_parent(struct lxc_handler *handler);
__hidden extern int lxc_map_ids(struct lxc_list *idmap, pid_t pid); __hidden extern int lxc_map_ids(struct list_head *idmap, pid_t pid);
__hidden extern int lxc_create_tty(const char *name, struct lxc_conf *conf); __hidden extern int lxc_create_tty(const char *name, struct lxc_conf *conf);
__hidden extern void lxc_delete_tty(struct lxc_tty_info *ttys); __hidden extern void lxc_delete_tty(struct lxc_tty_info *ttys);
__hidden extern int lxc_clear_config_caps(struct lxc_conf *c); __hidden extern int lxc_clear_config_caps(struct lxc_conf *c);
__hidden extern int lxc_clear_config_keepcaps(struct lxc_conf *c);
__hidden extern int lxc_clear_cgroups(struct lxc_conf *c, const char *key, int version); __hidden extern int lxc_clear_cgroups(struct lxc_conf *c, const char *key, int version);
__hidden extern int lxc_clear_mount_entries(struct lxc_conf *c); __hidden extern int lxc_clear_mount_entries(struct lxc_conf *c);
__hidden extern int lxc_clear_automounts(struct lxc_conf *c); __hidden extern int lxc_clear_automounts(struct lxc_conf *c);
@ -534,12 +550,11 @@ __hidden extern int lxc_clear_environment(struct lxc_conf *c);
__hidden extern int lxc_clear_limits(struct lxc_conf *c, const char *key); __hidden extern int lxc_clear_limits(struct lxc_conf *c, const char *key);
__hidden extern int lxc_delete_autodev(struct lxc_handler *handler); __hidden extern int lxc_delete_autodev(struct lxc_handler *handler);
__hidden extern int lxc_clear_autodev_tmpfs_size(struct lxc_conf *c); __hidden extern int lxc_clear_autodev_tmpfs_size(struct lxc_conf *c);
__hidden extern void lxc_clear_includes(struct lxc_conf *conf);
__hidden extern int lxc_setup_rootfs_prepare_root(struct lxc_conf *conf, const char *name, __hidden extern int lxc_setup_rootfs_prepare_root(struct lxc_conf *conf, const char *name,
const char *lxcpath); const char *lxcpath);
__hidden extern int lxc_setup(struct lxc_handler *handler); __hidden extern int lxc_setup(struct lxc_handler *handler);
__hidden extern int lxc_setup_parent(struct lxc_handler *handler); __hidden extern int lxc_setup_parent(struct lxc_handler *handler);
__hidden extern int setup_resource_limits(struct lxc_list *limits, pid_t pid); __hidden extern int setup_resource_limits(struct lxc_conf *conf, pid_t pid);
__hidden extern int find_unmapped_nsid(const struct lxc_conf *conf, enum idtype idtype); __hidden extern int find_unmapped_nsid(const struct lxc_conf *conf, enum idtype idtype);
__hidden extern int mapped_hostid(unsigned id, const struct lxc_conf *conf, enum idtype idtype); __hidden extern int mapped_hostid(unsigned id, const struct lxc_conf *conf, enum idtype idtype);
__hidden extern int userns_exec_1(const struct lxc_conf *conf, int (*fn)(void *), void *data, __hidden extern int userns_exec_1(const struct lxc_conf *conf, int (*fn)(void *), void *data,
@ -553,26 +568,23 @@ __hidden extern int parse_mount_attrs(struct lxc_mount_options *opts, const char
__hidden extern void tmp_proc_unmount(struct lxc_conf *lxc_conf); __hidden extern void tmp_proc_unmount(struct lxc_conf *lxc_conf);
__hidden extern void suggest_default_idmap(void); __hidden extern void suggest_default_idmap(void);
__hidden extern FILE *make_anonymous_mount_file(struct lxc_list *mount, bool include_nesting_helpers); __hidden extern FILE *make_anonymous_mount_file(struct lxc_list *mount, bool include_nesting_helpers);
__hidden extern struct lxc_list *sort_cgroup_settings(struct lxc_list *cgroup_settings); __hidden extern void sort_cgroup_settings(struct lxc_conf *conf);
__hidden extern int run_script(const char *name, const char *section, const char *script, ...); __hidden extern int run_script(const char *name, const char *section, const char *script, ...);
__hidden extern int run_script_argv(const char *name, unsigned int hook_version, const char *section, __hidden extern int run_script_argv(const char *name, unsigned int hook_version, const char *section,
const char *script, const char *hookname, char **argsin); const char *script, const char *hookname, char **argsin);
__hidden extern int in_caplist(int cap, struct lxc_list *caps);
__hidden extern bool has_cap(int cap, struct lxc_conf *conf);
static inline bool lxc_wants_cap(int cap, struct lxc_conf *conf) static inline bool lxc_wants_cap(int cap, struct lxc_conf *conf)
{ {
if (lxc_caps_last_cap() < cap) if (lxc_caps_last_cap() < cap)
return false; return false;
if (!lxc_list_empty(&conf->keepcaps)) return has_cap(cap, conf);
return in_caplist(cap, &conf->keepcaps);
return !in_caplist(cap, &conf->caps);
} }
__hidden extern int setup_sysctl_parameters(struct lxc_list *sysctls); __hidden extern int setup_sysctl_parameters(struct lxc_conf *conf);
__hidden extern int lxc_clear_sysctls(struct lxc_conf *c, const char *key); __hidden extern int lxc_clear_sysctls(struct lxc_conf *c, const char *key);
__hidden extern int setup_proc_filesystem(struct lxc_list *procs, pid_t pid); __hidden extern int setup_proc_filesystem(struct lxc_conf *conf, pid_t pid);
__hidden extern int lxc_clear_procs(struct lxc_conf *c, const char *key); __hidden extern int lxc_clear_procs(struct lxc_conf *c, const char *key);
__hidden extern int lxc_clear_apparmor_raw(struct lxc_conf *c); __hidden extern int lxc_clear_apparmor_raw(struct lxc_conf *c);
__hidden extern int lxc_clear_namespace(struct lxc_conf *c); __hidden extern int lxc_clear_namespace(struct lxc_conf *c);
@ -607,6 +619,7 @@ static inline void put_lxc_mount_options(struct lxc_mount_options *mnt_opts)
mnt_opts->prop_flags = 0; mnt_opts->prop_flags = 0;
free_disarm(mnt_opts->data); free_disarm(mnt_opts->data);
free_disarm(mnt_opts->raw_options);
} }
static inline void put_lxc_rootfs(struct lxc_rootfs *rootfs, bool unpin) static inline void put_lxc_rootfs(struct lxc_rootfs *rootfs, bool unpin)
@ -642,4 +655,7 @@ static inline int lxc_personality(personality_t persona)
return personality(persona); return personality(persona);
} }
__hidden extern int lxc_set_environment(const struct lxc_conf *conf);
__hidden extern int parse_cap(const char *cap);
#endif /* __LXC_CONF_H */ #endif /* __LXC_CONF_H */

View File

@ -1539,35 +1539,40 @@ static int set_config_group(const char *key, const char *value,
static int set_config_environment(const char *key, const char *value, static int set_config_environment(const char *key, const char *value,
struct lxc_conf *lxc_conf, void *data) struct lxc_conf *lxc_conf, void *data)
{ {
__do_free struct lxc_list *list_item = NULL; __do_free char *dup = NULL, *val = NULL;
__do_free struct environment_entry *new_env = NULL;
char *env_val;
if (lxc_config_value_empty(value)) if (lxc_config_value_empty(value))
return lxc_clear_environment(lxc_conf); return lxc_clear_environment(lxc_conf);
list_item = lxc_list_new(); new_env = zalloc(sizeof(struct environment_entry));
if (!list_item) if (!new_env)
return ret_errno(ENOMEM); return ret_errno(ENOMEM);
if (!strchr(value, '=')) { dup = strdup(value);
const char *env_val; if (!dup)
const char *env_key = value; return ret_errno(ENOMEM);
const char *env_var[3] = {0};
env_val = getenv(env_key); env_val = strchr(dup, '=');
if (!env_val) {
env_val = getenv(dup);
} else {
*env_val = '\0';
env_val++;
}
if (!env_val) if (!env_val)
return ret_errno(ENOENT); return ret_errno(ENOENT);
env_var[0] = env_key; val = strdup(env_val);
env_var[1] = env_val; if (!val)
list_item->elem = lxc_string_join("=", env_var, false);
} else {
list_item->elem = strdup(value);
}
if (!list_item->elem)
return ret_errno(ENOMEM); return ret_errno(ENOMEM);
lxc_list_add_tail(&lxc_conf->environment, move_ptr(list_item)); new_env->key = move_ptr(dup);
new_env->val = move_ptr(val);
list_add_tail(&new_env->head, &lxc_conf->environment);
move_ptr(new_env);
return 0; return 0;
} }
@ -1858,8 +1863,7 @@ static int set_config_signal_stop(const char *key, const char *value,
static int __set_config_cgroup_controller(const char *key, const char *value, static int __set_config_cgroup_controller(const char *key, const char *value,
struct lxc_conf *lxc_conf, int version) struct lxc_conf *lxc_conf, int version)
{ {
__do_free struct lxc_list *cglist = NULL; call_cleaner(free_lxc_cgroup) struct lxc_cgroup *new_cgroup = NULL;
call_cleaner(free_lxc_cgroup) struct lxc_cgroup *cgelem = NULL;
const char *subkey, *token; const char *subkey, *token;
size_t token_len; size_t token_len;
@ -1883,31 +1887,25 @@ static int __set_config_cgroup_controller(const char *key, const char *value,
if (*subkey == '\0') if (*subkey == '\0')
return ret_errno(EINVAL); return ret_errno(EINVAL);
cglist = lxc_list_new(); new_cgroup = zalloc(sizeof(*new_cgroup));
if (!cglist) if (!new_cgroup)
return ret_errno(ENOMEM); return ret_errno(ENOMEM);
cgelem = zalloc(sizeof(*cgelem)); new_cgroup->subsystem = strdup(subkey);
if (!cgelem) if (!new_cgroup->subsystem)
return ret_errno(ENOMEM); return ret_errno(ENOMEM);
cgelem->subsystem = strdup(subkey); new_cgroup->value = strdup(value);
if (!cgelem->subsystem) if (!new_cgroup->value)
return ret_errno(ENOMEM); return ret_errno(ENOMEM);
cgelem->value = strdup(value); new_cgroup->version = version;
if (!cgelem->value)
return ret_errno(ENOMEM);
cgelem->version = version;
lxc_list_add_elem(cglist, move_ptr(cgelem));
if (version == CGROUP2_SUPER_MAGIC) if (version == CGROUP2_SUPER_MAGIC)
lxc_list_add_tail(&lxc_conf->cgroup2, cglist); list_add_tail(&new_cgroup->head, &lxc_conf->cgroup2);
else else
lxc_list_add_tail(&lxc_conf->cgroup, cglist); list_add_tail(&new_cgroup->head, &lxc_conf->cgroup);
move_ptr(cglist); move_ptr(new_cgroup);
return 0; return 0;
} }
@ -2056,11 +2054,10 @@ static bool parse_limit_value(const char **value, rlim_t *res)
static int set_config_prlimit(const char *key, const char *value, static int set_config_prlimit(const char *key, const char *value,
struct lxc_conf *lxc_conf, void *data) struct lxc_conf *lxc_conf, void *data)
{ {
__do_free struct lxc_list *list = NULL; call_cleaner(free_lxc_limit) struct lxc_limit *new_lim = NULL;
call_cleaner(free_lxc_limit) struct lxc_limit *elem = NULL;
struct lxc_list *iter;
struct rlimit limit; struct rlimit limit;
rlim_t limit_value; rlim_t limit_value;
struct lxc_limit *lim;
if (lxc_config_value_empty(value)) if (lxc_config_value_empty(value))
return lxc_clear_limits(lxc_conf, key); return lxc_clear_limits(lxc_conf, key);
@ -2107,32 +2104,25 @@ static int set_config_prlimit(const char *key, const char *value,
} }
/* find existing list element */ /* find existing list element */
lxc_list_for_each(iter, &lxc_conf->limits) { list_for_each_entry(lim, &lxc_conf->limits, head) {
struct lxc_limit *cur = iter->elem; if (!strequal(key, lim->resource))
if (!strequal(key, cur->resource))
continue; continue;
cur->limit = limit; lim->limit = limit;
return 0; return 0;
} }
/* allocate list element */ new_lim = zalloc(sizeof(*new_lim));
list = lxc_list_new(); if (!new_lim)
if (!list)
return ret_errno(ENOMEM); return ret_errno(ENOMEM);
elem = zalloc(sizeof(*elem)); new_lim->resource = strdup(key);
if (!elem) if (!new_lim->resource)
return ret_errno(ENOMEM); return ret_errno(ENOMEM);
elem->resource = strdup(key); new_lim->limit = limit;
if (!elem->resource) list_add_tail(&new_lim->head, &lxc_conf->limits);
return ret_errno(ENOMEM); move_ptr(new_lim);
elem->limit = limit;
lxc_list_add_elem(list, move_ptr(elem));;
lxc_list_add_tail(&lxc_conf->limits, move_ptr(list));
return 0; return 0;
} }
@ -2140,9 +2130,8 @@ static int set_config_prlimit(const char *key, const char *value,
static int set_config_sysctl(const char *key, const char *value, static int set_config_sysctl(const char *key, const char *value,
struct lxc_conf *lxc_conf, void *data) struct lxc_conf *lxc_conf, void *data)
{ {
__do_free struct lxc_list *sysctl_list = NULL;
call_cleaner(free_lxc_sysctl) struct lxc_sysctl *sysctl_elem = NULL; call_cleaner(free_lxc_sysctl) struct lxc_sysctl *sysctl_elem = NULL;
struct lxc_list *iter; struct lxc_sysctl *sysctl, *nsysctl;
if (lxc_config_value_empty(value)) if (lxc_config_value_empty(value))
return clr_config_sysctl(key, lxc_conf, NULL); return clr_config_sysctl(key, lxc_conf, NULL);
@ -2155,28 +2144,22 @@ static int set_config_sysctl(const char *key, const char *value,
return ret_errno(EINVAL); return ret_errno(EINVAL);
/* find existing list element */ /* find existing list element */
lxc_list_for_each(iter, &lxc_conf->sysctls) { list_for_each_entry_safe(sysctl, nsysctl, &lxc_conf->sysctls, head) {
__do_free char *replace_value = NULL; __do_free char *replace_value = NULL;
struct lxc_sysctl *cur = iter->elem;
if (!strequal(key, cur->key)) if (!strequal(key, sysctl->key))
continue; continue;
replace_value = strdup(value); replace_value = strdup(value);
if (!replace_value) if (!replace_value)
return ret_errno(EINVAL); return ret_errno(EINVAL);
free(cur->value); free(sysctl->value);
cur->value = move_ptr(replace_value); sysctl->value = move_ptr(replace_value);
return 0; return 0;
} }
/* allocate list element */
sysctl_list = lxc_list_new();
if (!sysctl_list)
return ret_errno(ENOMEM);
sysctl_elem = zalloc(sizeof(*sysctl_elem)); sysctl_elem = zalloc(sizeof(*sysctl_elem));
if (!sysctl_elem) if (!sysctl_elem)
return ret_errno(ENOMEM); return ret_errno(ENOMEM);
@ -2189,8 +2172,8 @@ static int set_config_sysctl(const char *key, const char *value,
if (!sysctl_elem->value) if (!sysctl_elem->value)
return ret_errno(ENOMEM); return ret_errno(ENOMEM);
lxc_list_add_elem(sysctl_list, move_ptr(sysctl_elem)); list_add_tail(&sysctl_elem->head, &lxc_conf->sysctls);
lxc_list_add_tail(&lxc_conf->sysctls, move_ptr(sysctl_list)); move_ptr(sysctl_elem);
return 0; return 0;
} }
@ -2198,8 +2181,7 @@ static int set_config_sysctl(const char *key, const char *value,
static int set_config_proc(const char *key, const char *value, static int set_config_proc(const char *key, const char *value,
struct lxc_conf *lxc_conf, void *data) struct lxc_conf *lxc_conf, void *data)
{ {
__do_free struct lxc_list *proclist = NULL; call_cleaner(free_lxc_proc) struct lxc_proc *new_proc = NULL;
call_cleaner(free_lxc_proc) struct lxc_proc *procelem = NULL;
const char *subkey; const char *subkey;
if (lxc_config_value_empty(value)) if (lxc_config_value_empty(value))
@ -2212,24 +2194,20 @@ static int set_config_proc(const char *key, const char *value,
if (*subkey == '\0') if (*subkey == '\0')
return ret_errno(EINVAL); return ret_errno(EINVAL);
proclist = lxc_list_new(); new_proc = zalloc(sizeof(*new_proc));
if (!proclist) if (!new_proc)
return ret_errno(ENOMEM); return ret_errno(ENOMEM);
procelem = zalloc(sizeof(*procelem)); new_proc->filename = strdup(subkey);
if (!procelem) if (!new_proc->filename)
return ret_errno(ENOMEM); return ret_errno(ENOMEM);
procelem->filename = strdup(subkey); new_proc->value = strdup(value);
if (!procelem->filename) if (!new_proc->value)
return ret_errno(ENOMEM); return ret_errno(ENOMEM);
procelem->value = strdup(value); list_add_tail(&new_proc->head, &lxc_conf->procs);
if (!procelem->value) move_ptr(new_proc);
return ret_errno(ENOMEM);
proclist->elem = move_ptr(procelem);
lxc_list_add_tail(&lxc_conf->procs, move_ptr(proclist));
return 0; return 0;
} }
@ -2237,7 +2215,6 @@ static int set_config_proc(const char *key, const char *value,
static int set_config_idmaps(const char *key, const char *value, static int set_config_idmaps(const char *key, const char *value,
struct lxc_conf *lxc_conf, void *data) struct lxc_conf *lxc_conf, void *data)
{ {
__do_free struct lxc_list *idmaplist = NULL;
__do_free struct id_map *idmap = NULL; __do_free struct id_map *idmap = NULL;
unsigned long hostid, nsid, range; unsigned long hostid, nsid, range;
char type; char type;
@ -2246,10 +2223,6 @@ static int set_config_idmaps(const char *key, const char *value,
if (lxc_config_value_empty(value)) if (lxc_config_value_empty(value))
return lxc_clear_idmaps(lxc_conf); return lxc_clear_idmaps(lxc_conf);
idmaplist = lxc_list_new();
if (!idmaplist)
return ret_errno(ENOMEM);
idmap = zalloc(sizeof(*idmap)); idmap = zalloc(sizeof(*idmap));
if (!idmap) if (!idmap)
return ret_errno(ENOMEM); return ret_errno(ENOMEM);
@ -2269,8 +2242,7 @@ static int set_config_idmaps(const char *key, const char *value,
idmap->hostid = hostid; idmap->hostid = hostid;
idmap->nsid = nsid; idmap->nsid = nsid;
idmap->range = range; idmap->range = range;
idmaplist->elem = idmap; list_add_tail(&idmap->head, &lxc_conf->id_map);
lxc_list_add_tail(&lxc_conf->id_map, idmaplist);
if (!lxc_conf->root_nsuid_map && idmap->idtype == ID_TYPE_UID) if (!lxc_conf->root_nsuid_map && idmap->idtype == ID_TYPE_UID)
if (idmap->nsid == 0) if (idmap->nsid == 0)
@ -2281,7 +2253,6 @@ static int set_config_idmaps(const char *key, const char *value,
lxc_conf->root_nsgid_map = idmap; lxc_conf->root_nsgid_map = idmap;
move_ptr(idmap); move_ptr(idmap);
move_ptr(idmaplist);
return 0; return 0;
} }
@ -2429,70 +2400,96 @@ int add_elem_to_mount_list(const char *value, struct lxc_conf *lxc_conf) {
return set_config_mount(NULL, value, lxc_conf, NULL); return set_config_mount(NULL, value, lxc_conf, NULL);
} }
static int add_cap_entry(struct lxc_conf *conf, char *caps, bool keep)
{
char *token;
/*
* In case several capability keep is specified in a single line split
* these caps in a single element for the list.
*/
lxc_iterate_parts(token, caps, " \t") {
__do_free struct cap_entry *new_cap = NULL;
int cap;
if (strequal(token, "none")) {
if (!keep)
return syserror_set(-EINVAL, "The \"none\" keyword is only valid when keeping caps");
lxc_clear_config_caps(conf);
continue;
}
cap = parse_cap(token);
if (cap < 0) {
if (cap != -2)
return syserror_set(-EINVAL, "Invalid capability specified");
INFO("Ignoring unknown capability \"%s\"", token);
continue;
}
new_cap = zalloc(sizeof(struct cap_entry));
if (!new_cap)
return ret_errno(ENOMEM);
new_cap->cap_name = strdup(token);
if (!new_cap->cap_name)
return ret_errno(ENOMEM);
new_cap->cap = cap;
list_add_tail(&new_cap->head, &conf->caps.list);
move_ptr(new_cap);
}
return 0;
}
static int set_config_cap_keep(const char *key, const char *value, static int set_config_cap_keep(const char *key, const char *value,
struct lxc_conf *lxc_conf, void *data) struct lxc_conf *lxc_conf, void *data)
{ {
__do_free char *keepcaps = NULL; __do_free char *caps = NULL;
__do_free struct lxc_list *keeplist = NULL; int ret;
char *token;
if (lxc_config_value_empty(value)) if (lxc_config_value_empty(value))
return lxc_clear_config_keepcaps(lxc_conf); return lxc_clear_config_caps(lxc_conf);
keepcaps = strdup(value); caps = strdup(value);
if (!keepcaps) if (!caps)
return ret_errno(ENOMEM); return ret_errno(ENOMEM);
/* In case several capability keep is specified in a single line if (!lxc_conf->caps.keep && !list_empty(&lxc_conf->caps.list))
* split these caps in a single element for the list. return syserror_set(-EINVAL, "Keeping and dropping capabilities are mutually exclusive");
*/
lxc_iterate_parts(token, keepcaps, " \t") {
if (strequal(token, "none"))
lxc_clear_config_keepcaps(lxc_conf);
keeplist = lxc_list_new(); ret = add_cap_entry(lxc_conf, caps, true);
if (!keeplist) if (ret < 0)
return ret_errno(ENOMEM); return ret;
keeplist->elem = strdup(token);
if (!keeplist->elem)
return ret_errno(ENOMEM);
lxc_list_add_tail(&lxc_conf->keepcaps, move_ptr(keeplist));
}
lxc_conf->caps.keep = true;
return 0; return 0;
} }
static int set_config_cap_drop(const char *key, const char *value, static int set_config_cap_drop(const char *key, const char *value,
struct lxc_conf *lxc_conf, void *data) struct lxc_conf *lxc_conf, void *data)
{ {
__do_free char *dropcaps = NULL; __do_free char *caps = NULL;
__do_free struct lxc_list *droplist = NULL; int ret;
char *token;
if (lxc_config_value_empty(value)) if (lxc_config_value_empty(value))
return lxc_clear_config_caps(lxc_conf); return lxc_clear_config_caps(lxc_conf);
dropcaps = strdup(value); if (lxc_conf->caps.keep)
if (!dropcaps) return syserror_set(-EINVAL, "Keeping and dropping capabilities are mutually exclusive");
caps = strdup(value);
if (!caps)
return ret_errno(ENOMEM); return ret_errno(ENOMEM);
/* In case several capability drop is specified in a single line ret = add_cap_entry(lxc_conf, caps, false);
* split these caps in a single element for the list. if (ret < 0)
*/ return ret;
lxc_iterate_parts(token, dropcaps, " \t") {
droplist = lxc_list_new();
if (!droplist)
return ret_errno(ENOMEM);
droplist->elem = strdup(token);
if (!droplist->elem)
return ret_errno(ENOMEM);
lxc_list_add_tail(&lxc_conf->caps, move_ptr(droplist));
}
lxc_conf->caps.keep = false;
return 0; return 0;
} }
@ -2818,7 +2815,7 @@ static int set_config_rootfs_options(const char *key, const char *value,
if (ret < 0) if (ret < 0)
return ret_errno(EINVAL); return ret_errno(EINVAL);
rootfs->options = move_ptr(raw_options); rootfs->mnt_opts.raw_options = move_ptr(raw_options);
return 0; return 0;
} }
@ -3862,12 +3859,13 @@ static int __get_config_cgroup_controller(const char *key, char *retv,
int inlen, struct lxc_conf *c, int inlen, struct lxc_conf *c,
int version) int version)
{ {
int fulllen = 0;
bool get_all = false;
int len; int len;
size_t namespaced_token_len; size_t namespaced_token_len;
char *global_token, *namespaced_token; char *global_token, *namespaced_token;
struct lxc_list *it; struct list_head *list;
int fulllen = 0; struct lxc_cgroup *cgroup;
bool get_all = false;
if (!retv) if (!retv)
inlen = 0; inlen = 0;
@ -3878,10 +3876,12 @@ static int __get_config_cgroup_controller(const char *key, char *retv,
global_token = "lxc.cgroup2"; global_token = "lxc.cgroup2";
namespaced_token = "lxc.cgroup2."; namespaced_token = "lxc.cgroup2.";
namespaced_token_len = STRLITERALLEN("lxc.cgroup2."); namespaced_token_len = STRLITERALLEN("lxc.cgroup2.");
list = &c->cgroup2;
} else if (version == CGROUP_SUPER_MAGIC) { } else if (version == CGROUP_SUPER_MAGIC) {
global_token = "lxc.cgroup"; global_token = "lxc.cgroup";
namespaced_token = "lxc.cgroup."; namespaced_token = "lxc.cgroup.";
namespaced_token_len = STRLITERALLEN("lxc.cgroup."); namespaced_token_len = STRLITERALLEN("lxc.cgroup.");
list = &c->cgroup;
} else { } else {
return ret_errno(EINVAL); return ret_errno(EINVAL);
} }
@ -3893,17 +3893,15 @@ static int __get_config_cgroup_controller(const char *key, char *retv,
else else
return ret_errno(EINVAL); return ret_errno(EINVAL);
lxc_list_for_each(it, &c->cgroup) { list_for_each_entry(cgroup, list, head) {
struct lxc_cgroup *cg = it->elem;
if (get_all) { if (get_all) {
if (version != cg->version) if (version != cgroup->version)
continue; continue;
strprint(retv, inlen, "%s.%s = %s\n", global_token, strprint(retv, inlen, "%s.%s = %s\n", global_token,
cg->subsystem, cg->value); cgroup->subsystem, cgroup->value);
} else if (strequal(cg->subsystem, key)) { } else if (strequal(cgroup->subsystem, key)) {
strprint(retv, inlen, "%s\n", cg->value); strprint(retv, inlen, "%s\n", cgroup->value);
} }
} }
@ -4022,7 +4020,7 @@ static inline int get_config_cgroup_relative(const char *key, char *retv,
static int get_config_idmaps(const char *key, char *retv, int inlen, static int get_config_idmaps(const char *key, char *retv, int inlen,
struct lxc_conf *c, void *data) struct lxc_conf *c, void *data)
{ {
struct lxc_list *it; struct id_map *map;
int len, listlen, ret; int len, listlen, ret;
int fulllen = 0; int fulllen = 0;
/* "u 1000 1000000 65536" /* "u 1000 1000000 65536"
@ -4053,9 +4051,8 @@ static int get_config_idmaps(const char *key, char *retv, int inlen,
else else
memset(retv, 0, inlen); memset(retv, 0, inlen);
listlen = lxc_list_len(&c->id_map); listlen = list_len(&c->id_map);
lxc_list_for_each(it, &c->id_map) { list_for_each_entry(map, &c->id_map, head) {
struct id_map *map = it->elem;
ret = strnprintf(buf, sizeof(buf), "%c %lu %lu %lu", ret = strnprintf(buf, sizeof(buf), "%c %lu %lu %lu",
(map->idtype == ID_TYPE_UID) ? 'u' : 'g', (map->idtype == ID_TYPE_UID) ? 'u' : 'g',
map->nsid, map->hostid, map->range); map->nsid, map->hostid, map->range);
@ -4203,7 +4200,7 @@ static int get_config_rootfs_mount(const char *key, char *retv, int inlen,
static int get_config_rootfs_options(const char *key, char *retv, int inlen, static int get_config_rootfs_options(const char *key, char *retv, int inlen,
struct lxc_conf *c, void *data) struct lxc_conf *c, void *data)
{ {
return lxc_get_conf_str(retv, inlen, c->rootfs.options); return lxc_get_conf_str(retv, inlen, c->rootfs.mnt_opts.raw_options);
} }
static int get_config_uts_name(const char *key, char *retv, int inlen, static int get_config_uts_name(const char *key, char *retv, int inlen,
@ -4284,15 +4281,15 @@ static int get_config_cap_drop(const char *key, char *retv, int inlen,
struct lxc_conf *c, void *data) struct lxc_conf *c, void *data)
{ {
int len, fulllen = 0; int len, fulllen = 0;
struct lxc_list *it; struct cap_entry *cap;
if (!retv) if (!retv)
inlen = 0; inlen = 0;
else else
memset(retv, 0, inlen); memset(retv, 0, inlen);
lxc_list_for_each(it, &c->caps) { list_for_each_entry(cap, &c->caps.list, head) {
strprint(retv, inlen, "%s\n", (char *)it->elem); strprint(retv, inlen, "%s\n", cap->cap_name);
} }
return fulllen; return fulllen;
@ -4302,15 +4299,15 @@ static int get_config_cap_keep(const char *key, char *retv, int inlen,
struct lxc_conf *c, void *data) struct lxc_conf *c, void *data)
{ {
int len, fulllen = 0; int len, fulllen = 0;
struct lxc_list *it; struct cap_entry *cap;
if (!retv) if (!retv)
inlen = 0; inlen = 0;
else else
memset(retv, 0, inlen); memset(retv, 0, inlen);
lxc_list_for_each(it, &c->keepcaps) { list_for_each_entry(cap, &c->caps.list, head) {
strprint(retv, inlen, "%s\n", (char *)it->elem); strprint(retv, inlen, "%s\n", cap->cap_name);
} }
return fulllen; return fulllen;
@ -4476,15 +4473,15 @@ static int get_config_environment(const char *key, char *retv, int inlen,
struct lxc_conf *c, void *data) struct lxc_conf *c, void *data)
{ {
int len, fulllen = 0; int len, fulllen = 0;
struct lxc_list *it; struct environment_entry *env;
if (!retv) if (!retv)
inlen = 0; inlen = 0;
else else
memset(retv, 0, inlen); memset(retv, 0, inlen);
lxc_list_for_each(it, &c->environment) { list_for_each_entry(env, &c->environment, head) {
strprint(retv, inlen, "%s\n", (char *)it->elem); strprint(retv, inlen, "%s=%s\n", env->key, env->val);
} }
return fulllen; return fulllen;
@ -4561,7 +4558,7 @@ static int get_config_prlimit(const char *key, char *retv, int inlen,
{ {
int fulllen = 0, len; int fulllen = 0, len;
bool get_all = false; bool get_all = false;
struct lxc_list *it; struct lxc_limit *lim;
if (!retv) if (!retv)
inlen = 0; inlen = 0;
@ -4575,11 +4572,10 @@ static int get_config_prlimit(const char *key, char *retv, int inlen,
else else
return ret_errno(EINVAL); return ret_errno(EINVAL);
lxc_list_for_each(it, &c->limits) { list_for_each_entry(lim, &c->limits, head) {
/* 2 colon separated 64 bit integers or the word 'unlimited' */ /* 2 colon separated 64 bit integers or the word 'unlimited' */
char buf[INTTYPE_TO_STRLEN(uint64_t) * 2 + 2]; char buf[INTTYPE_TO_STRLEN(uint64_t) * 2 + 2];
int partlen; int partlen;
struct lxc_limit *lim = it->elem;
if (lim->limit.rlim_cur == RLIM_INFINITY) { if (lim->limit.rlim_cur == RLIM_INFINITY) {
memcpy(buf, "unlimited", STRLITERALLEN("unlimited") + 1); memcpy(buf, "unlimited", STRLITERALLEN("unlimited") + 1);
@ -4616,10 +4612,10 @@ static int get_config_prlimit(const char *key, char *retv, int inlen,
static int get_config_sysctl(const char *key, char *retv, int inlen, static int get_config_sysctl(const char *key, char *retv, int inlen,
struct lxc_conf *c, void *data) struct lxc_conf *c, void *data)
{ {
int len;
struct lxc_list *it;
int fulllen = 0; int fulllen = 0;
bool get_all = false; bool get_all = false;
int len;
struct lxc_sysctl *sysctl;
if (!retv) if (!retv)
inlen = 0; inlen = 0;
@ -4633,13 +4629,12 @@ static int get_config_sysctl(const char *key, char *retv, int inlen,
else else
return ret_errno(EINVAL); return ret_errno(EINVAL);
lxc_list_for_each(it, &c->sysctls) { list_for_each_entry(sysctl, &c->sysctls, head) {
struct lxc_sysctl *elem = it->elem;
if (get_all) { if (get_all) {
strprint(retv, inlen, "lxc.sysctl.%s = %s\n", elem->key, strprint(retv, inlen, "lxc.sysctl.%s = %s\n", sysctl->key,
elem->value); sysctl->value);
} else if (strequal(elem->key, key)) { } else if (strequal(sysctl->key, key)) {
strprint(retv, inlen, "%s", elem->value); strprint(retv, inlen, "%s", sysctl->value);
} }
} }
@ -4649,10 +4644,10 @@ static int get_config_sysctl(const char *key, char *retv, int inlen,
static int get_config_proc(const char *key, char *retv, int inlen, static int get_config_proc(const char *key, char *retv, int inlen,
struct lxc_conf *c, void *data) struct lxc_conf *c, void *data)
{ {
struct lxc_list *it;
int len;
int fulllen = 0; int fulllen = 0;
bool get_all = false; bool get_all = false;
int len;
struct lxc_proc *proc;
if (!retv) if (!retv)
inlen = 0; inlen = 0;
@ -4666,9 +4661,7 @@ static int get_config_proc(const char *key, char *retv, int inlen,
else else
return ret_errno(EINVAL); return ret_errno(EINVAL);
lxc_list_for_each(it, &c->procs) { list_for_each_entry(proc, &c->procs, head) {
struct lxc_proc *proc = it->elem;
if (get_all) { if (get_all) {
strprint(retv, inlen, "lxc.proc.%s = %s\n", strprint(retv, inlen, "lxc.proc.%s = %s\n",
proc->filename, proc->value); proc->filename, proc->value);
@ -5014,7 +5007,6 @@ static inline int clr_config_rootfs_mount(const char *key, struct lxc_conf *c,
static inline int clr_config_rootfs_options(const char *key, struct lxc_conf *c, static inline int clr_config_rootfs_options(const char *key, struct lxc_conf *c,
void *data) void *data)
{ {
free_disarm(c->rootfs.options);
put_lxc_mount_options(&c->rootfs.mnt_opts); put_lxc_mount_options(&c->rootfs.mnt_opts);
return 0; return 0;
@ -5058,7 +5050,7 @@ static inline int clr_config_cap_drop(const char *key, struct lxc_conf *c,
static inline int clr_config_cap_keep(const char *key, struct lxc_conf *c, static inline int clr_config_cap_keep(const char *key, struct lxc_conf *c,
void *data) void *data)
{ {
return lxc_clear_config_keepcaps(c); return lxc_clear_config_caps(c);
} }
static inline int clr_config_console_path(const char *key, struct lxc_conf *c, static inline int clr_config_console_path(const char *key, struct lxc_conf *c,
@ -5296,7 +5288,6 @@ static inline int clr_config_proc(const char *key, struct lxc_conf *c,
static inline int clr_config_includefiles(const char *key, struct lxc_conf *c, static inline int clr_config_includefiles(const char *key, struct lxc_conf *c,
void *data) void *data)
{ {
lxc_clear_includes(c);
return 0; return 0;
} }

View File

@ -668,7 +668,7 @@ static void must_append_sized(char **buf, size_t *bufsz, const char *data, size_
static bool is_privileged(struct lxc_conf *conf) static bool is_privileged(struct lxc_conf *conf)
{ {
return lxc_list_empty(&conf->id_map); return list_empty(&conf->id_map);
} }
static const char* AA_ALL_DEST_PATH_LIST[] = { static const char* AA_ALL_DEST_PATH_LIST[] = {

View File

@ -1219,7 +1219,7 @@ static int do_create_container_dir(const char *path, struct lxc_conf *conf)
ret = 0; ret = 0;
} }
if (!lxc_list_empty(&conf->id_map)) { if (!list_empty(&conf->id_map)) {
ret = chown_mapped_root(path, conf); ret = chown_mapped_root(path, conf);
if (ret < 0) if (ret < 0)
ret = -1; ret = -1;
@ -1290,7 +1290,7 @@ static struct lxc_storage *do_storage_create(struct lxc_container *c,
/* If we are not root, chown the rootfs dir to root in the target user /* If we are not root, chown the rootfs dir to root in the target user
* namespace. * namespace.
*/ */
if (am_guest_unpriv() || !lxc_list_empty(&c->lxc_conf->id_map)) { if (am_guest_unpriv() || !list_empty(&c->lxc_conf->id_map)) {
ret = chown_mapped_root(bdev->dest, c->lxc_conf); ret = chown_mapped_root(bdev->dest, c->lxc_conf);
if (ret < 0) { if (ret < 0) {
ERROR("Error chowning \"%s\" to container root", bdev->dest); ERROR("Error chowning \"%s\" to container root", bdev->dest);
@ -1482,11 +1482,10 @@ static bool create_run_template(struct lxc_container *c, char *tpath,
* ... <-m mapn> -- and we append "--mapped-uid x", where x is * ... <-m mapn> -- and we append "--mapped-uid x", where x is
* the mapped uid for our geteuid() * the mapped uid for our geteuid()
*/ */
if (!lxc_list_empty(&conf->id_map)) { if (!list_empty(&conf->id_map)) {
int extraargs, hostuid_mapped, hostgid_mapped; int extraargs, hostuid_mapped, hostgid_mapped;
char **n2; char **n2;
char txtuid[20], txtgid[20]; char txtuid[20], txtgid[20];
struct lxc_list *it;
struct id_map *map; struct id_map *map;
int n2args = 1; int n2args = 1;
@ -1498,8 +1497,7 @@ static bool create_run_template(struct lxc_container *c, char *tpath,
tpath = "lxc-usernsexec"; tpath = "lxc-usernsexec";
n2[0] = "lxc-usernsexec"; n2[0] = "lxc-usernsexec";
lxc_list_for_each(it, &conf->id_map) { list_for_each_entry(map, &conf->id_map, head) {
map = it->elem;
n2args += 2; n2args += 2;
n2 = realloc(n2, n2args * sizeof(char *)); n2 = realloc(n2, n2args * sizeof(char *));
if (!n2) if (!n2)
@ -2239,7 +2237,7 @@ static inline bool enter_net_ns(struct lxc_container *c)
if (pid < 0) if (pid < 0)
return false; return false;
if ((geteuid() != 0 || (c->lxc_conf && !lxc_list_empty(&c->lxc_conf->id_map))) && if ((geteuid() != 0 || (c->lxc_conf && !list_empty(&c->lxc_conf->id_map))) &&
(access("/proc/self/ns/user", F_OK) == 0)) (access("/proc/self/ns/user", F_OK) == 0))
if (!switch_to_ns(pid, "user")) if (!switch_to_ns(pid, "user"))
return false; return false;
@ -5077,7 +5075,7 @@ static int do_lxcapi_mount(struct lxc_container *c, const char *source,
} }
/* Enter the container namespaces */ /* Enter the container namespaces */
if (!lxc_list_empty(&c->lxc_conf->id_map)) { if (!list_empty(&c->lxc_conf->id_map)) {
if (!switch_to_ns(init_pid, "user")) { if (!switch_to_ns(init_pid, "user")) {
ERROR("Failed to enter user namespace"); ERROR("Failed to enter user namespace");
_exit(EXIT_FAILURE); _exit(EXIT_FAILURE);
@ -5170,7 +5168,7 @@ static int do_lxcapi_umount(struct lxc_container *c, const char *target,
} }
/* Enter the container namespaces */ /* Enter the container namespaces */
if (!lxc_list_empty(&c->lxc_conf->id_map)) { if (!list_empty(&c->lxc_conf->id_map)) {
if (!switch_to_ns(init_pid, "user")) { if (!switch_to_ns(init_pid, "user")) {
ERROR("Failed to enter user namespace"); ERROR("Failed to enter user namespace");
_exit(EXIT_FAILURE); _exit(EXIT_FAILURE);

View File

@ -1057,7 +1057,6 @@ static int do_start(void *data)
int ret; int ret;
uid_t new_uid; uid_t new_uid;
gid_t new_gid; gid_t new_gid;
struct lxc_list *iterator;
uid_t nsuid = 0; uid_t nsuid = 0;
gid_t nsgid = 0; gid_t nsgid = 0;
@ -1110,7 +1109,7 @@ static int do_start(void *data)
/* If we are in a new user namespace, become root there to have /* If we are in a new user namespace, become root there to have
* privilege over our namespace. * privilege over our namespace.
*/ */
if (!lxc_list_empty(&handler->conf->id_map)) { if (!list_empty(&handler->conf->id_map)) {
if (!handler->conf->root_nsuid_map) if (!handler->conf->root_nsuid_map)
nsuid = handler->conf->init_uid; nsuid = handler->conf->init_uid;
@ -1257,18 +1256,14 @@ static int do_start(void *data)
} }
} }
/* Add the requested environment variables to the current environment to /*
* allow them to be used by the various hooks, such as the start hook * Add the requested environment variables to the current environment
* below. * to allow them to be used by the various hooks, such as the start
* hook below.
*/ */
lxc_list_for_each(iterator, &handler->conf->environment) { ret = lxc_set_environment(handler->conf);
ret = putenv((char *)iterator->elem); if (ret < 0)
if (ret < 0) {
SYSERROR("Failed to set environment variable: %s",
(char *)iterator->elem);
goto out_warn_father; goto out_warn_father;
}
}
if (!lxc_sync_wait_parent(handler, START_SYNC_POST_CONFIGURE)) if (!lxc_sync_wait_parent(handler, START_SYNC_POST_CONFIGURE))
goto out_warn_father; goto out_warn_father;
@ -1361,14 +1356,9 @@ static int do_start(void *data)
if (ret < 0) if (ret < 0)
SYSERROR("Failed to clear environment."); SYSERROR("Failed to clear environment.");
lxc_list_for_each(iterator, &handler->conf->environment) { ret = lxc_set_environment(handler->conf);
ret = putenv((char *)iterator->elem); if (ret < 0)
if (ret < 0) {
SYSERROR("Failed to set environment variable: %s",
(char *)iterator->elem);
goto out_warn_father; goto out_warn_father;
}
}
ret = putenv("container=lxc"); ret = putenv("container=lxc");
if (ret < 0) { if (ret < 0) {
@ -1406,7 +1396,7 @@ static int do_start(void *data)
* we switched to root in the new user namespace further above. Only * we switched to root in the new user namespace further above. Only
* drop groups if we can, so ensure that we have necessary privilege. * drop groups if we can, so ensure that we have necessary privilege.
*/ */
if (lxc_list_empty(&handler->conf->id_map)) { if (list_empty(&handler->conf->id_map)) {
#if HAVE_LIBCAP #if HAVE_LIBCAP
if (lxc_proc_cap_is_set(CAP_SETGID, CAP_EFFECTIVE)) if (lxc_proc_cap_is_set(CAP_SETGID, CAP_EFFECTIVE))
#endif #endif
@ -1473,7 +1463,7 @@ int resolve_clone_flags(struct lxc_handler *handler)
if ((conf->ns_clone & ns_info[i].clone_flag)) if ((conf->ns_clone & ns_info[i].clone_flag))
handler->ns_clone_flags |= ns_info[i].clone_flag; handler->ns_clone_flags |= ns_info[i].clone_flag;
} else { } else {
if (i == LXC_NS_USER && lxc_list_empty(&handler->conf->id_map)) if (i == LXC_NS_USER && list_empty(&handler->conf->id_map))
continue; continue;
if (i == LXC_NS_NET && lxc_requests_empty_network(handler)) if (i == LXC_NS_NET && lxc_requests_empty_network(handler))
@ -1576,7 +1566,7 @@ static int lxc_spawn(struct lxc_handler *handler)
int i, ret; int i, ret;
char pidstr[20]; char pidstr[20];
bool wants_to_map_ids; bool wants_to_map_ids;
struct lxc_list *id_map; struct list_head *id_map;
const char *name = handler->name; const char *name = handler->name;
const char *lxcpath = handler->lxcpath; const char *lxcpath = handler->lxcpath;
bool share_ns = false; bool share_ns = false;
@ -1584,7 +1574,7 @@ static int lxc_spawn(struct lxc_handler *handler)
struct cgroup_ops *cgroup_ops = handler->cgroup_ops; struct cgroup_ops *cgroup_ops = handler->cgroup_ops;
id_map = &conf->id_map; id_map = &conf->id_map;
wants_to_map_ids = !lxc_list_empty(id_map); wants_to_map_ids = !list_empty(id_map);
for (i = 0; i < LXC_NS_MAX; i++) { for (i = 0; i < LXC_NS_MAX; i++) {
if (!conf->ns_share[i]) if (!conf->ns_share[i])
@ -1816,19 +1806,17 @@ static int lxc_spawn(struct lxc_handler *handler)
} }
} }
if (!lxc_list_empty(&conf->procs)) { ret = setup_proc_filesystem(conf, handler->pid);
ret = setup_proc_filesystem(&conf->procs, handler->pid); if (ret < 0) {
if (ret < 0) ERROR("Failed to setup procfs limits");
goto out_delete_net; goto out_delete_net;
} }
if (!lxc_list_empty(&conf->limits)) { ret = setup_resource_limits(conf, handler->pid);
ret = setup_resource_limits(&conf->limits, handler->pid);
if (ret < 0) { if (ret < 0) {
ERROR("Failed to setup resource limits"); ERROR("Failed to setup resource limits");
goto out_delete_net; goto out_delete_net;
} }
}
/* Tell the child to continue its initialization. */ /* Tell the child to continue its initialization. */
if (!lxc_sync_wake_child(handler, START_SYNC_POST_CONFIGURE)) if (!lxc_sync_wake_child(handler, START_SYNC_POST_CONFIGURE))
@ -2014,14 +2002,14 @@ int __lxc_start(struct lxc_handler *handler, struct lxc_operations *ops,
* it readonly. * it readonly.
* If the container is unprivileged then skip rootfs pinning. * If the container is unprivileged then skip rootfs pinning.
*/ */
ret = lxc_rootfs_init(conf, !lxc_list_empty(&conf->id_map)); ret = lxc_rootfs_init(conf, !list_empty(&conf->id_map));
if (ret) { if (ret) {
ERROR("Failed to handle rootfs pinning for container \"%s\"", handler->name); ERROR("Failed to handle rootfs pinning for container \"%s\"", handler->name);
ret = -1; ret = -1;
goto out_abort; goto out_abort;
} }
if (geteuid() == 0 && !lxc_list_empty(&conf->id_map)) { if (geteuid() == 0 && !list_empty(&conf->id_map)) {
/* /*
* Most filesystems can't be mounted inside a userns so handle them here. * Most filesystems can't be mounted inside a userns so handle them here.
*/ */

View File

@ -57,7 +57,7 @@ int ovl_clonepaths(struct lxc_storage *orig, struct lxc_storage *new, const char
return -1; return -1;
} }
if (am_guest_unpriv() || !lxc_list_empty(&conf->id_map)) { if (am_guest_unpriv() || !list_empty(&conf->id_map)) {
ret = chown_mapped_root(new->dest, conf); ret = chown_mapped_root(new->dest, conf);
if (ret < 0) if (ret < 0)
WARN("Failed to update ownership of %s", new->dest); WARN("Failed to update ownership of %s", new->dest);
@ -88,7 +88,7 @@ int ovl_clonepaths(struct lxc_storage *orig, struct lxc_storage *new, const char
if (ret < 0 && errno != EEXIST) if (ret < 0 && errno != EEXIST)
return log_error_errno(-errno, errno, "Failed to create directory \"%s\"", work); return log_error_errno(-errno, errno, "Failed to create directory \"%s\"", work);
if (am_guest_unpriv() || !lxc_list_empty(&conf->id_map)) { if (am_guest_unpriv() || !list_empty(&conf->id_map)) {
__do_free char *lxc_overlay_delta_dir = NULL, __do_free char *lxc_overlay_delta_dir = NULL,
*lxc_overlay_private_dir = NULL; *lxc_overlay_private_dir = NULL;
@ -155,7 +155,7 @@ int ovl_clonepaths(struct lxc_storage *orig, struct lxc_storage *new, const char
if (ret < 0 && errno != EEXIST) if (ret < 0 && errno != EEXIST)
return log_error_errno(-errno, errno, "Failed to create directory \"%s\"", ndelta); return log_error_errno(-errno, errno, "Failed to create directory \"%s\"", ndelta);
if (am_guest_unpriv() || !lxc_list_empty(&conf->id_map)) { if (am_guest_unpriv() || !list_empty(&conf->id_map)) {
__do_free char *lxc_overlay_delta_dir = NULL, __do_free char *lxc_overlay_delta_dir = NULL,
*lxc_overlay_private_dir = NULL; *lxc_overlay_private_dir = NULL;
@ -276,7 +276,7 @@ int ovl_create(struct lxc_storage *bdev, const char *dest, const char *n,
if (ret < 0 && errno != EEXIST) if (ret < 0 && errno != EEXIST)
return log_error_errno(-errno, errno, "Failed to create directory \"%s\"", delta); return log_error_errno(-errno, errno, "Failed to create directory \"%s\"", delta);
if (am_guest_unpriv() || !lxc_list_empty(&conf->id_map)) { if (am_guest_unpriv() || !list_empty(&conf->id_map)) {
__do_free char *lxc_overlay_private_dir = NULL; __do_free char *lxc_overlay_private_dir = NULL;
lxc_overlay_private_dir = must_make_path(tmp, LXC_OVERLAY_PRIVATE_DIR, NULL); lxc_overlay_private_dir = must_make_path(tmp, LXC_OVERLAY_PRIVATE_DIR, NULL);

View File

@ -606,7 +606,7 @@ struct lxc_storage *storage_init(struct lxc_conf *conf)
const struct lxc_storage_type *q; const struct lxc_storage_type *q;
const char *src = conf->rootfs.path; const char *src = conf->rootfs.path;
const char *dst = conf->rootfs.mount; const char *dst = conf->rootfs.mount;
const char *mntopts = conf->rootfs.options; const char *mntopts = conf->rootfs.mnt_opts.raw_options;
BUILD_BUG_ON(LXC_STORAGE_INTERNAL_OVERLAY_RESTORE <= LXC_CLONE_MAXFLAGS); BUILD_BUG_ON(LXC_STORAGE_INTERNAL_OVERLAY_RESTORE <= LXC_CLONE_MAXFLAGS);

View File

@ -876,7 +876,7 @@ static int lxc_terminal_map_ids(struct lxc_conf *c, struct lxc_terminal *termina
{ {
int ret; int ret;
if (lxc_list_empty(&c->id_map)) if (list_empty(&c->id_map))
return 0; return 0;
if (is_empty_string(terminal->name) && terminal->pty < 0) if (is_empty_string(terminal->name) && terminal->pty < 0)

View File

@ -30,7 +30,6 @@ struct lxc_terminal_info {
}; };
struct lxc_terminal_state { struct lxc_terminal_state {
struct lxc_list node;
int stdinfd; int stdinfd;
int stdoutfd; int stdoutfd;
int ptxfd; int ptxfd;