diff --git a/src/lxc/cgroups/cgfsng.c b/src/lxc/cgroups/cgfsng.c index 862714d87a..cade4d3c7f 100644 --- a/src/lxc/cgroups/cgfsng.c +++ b/src/lxc/cgroups/cgfsng.c @@ -2749,9 +2749,6 @@ static int device_cgroup_rule_parse_devpath(struct device_item *device, if (device_cgroup_parse_access(device, mode) < 0) return -1; - if (n_parts == 1) - return ret_set_errno(-1, EINVAL); - ret = stat(path, &sb); if (ret < 0) return ret_set_errno(-1, errno); diff --git a/src/lxc/cmd/lxc_init.c b/src/lxc/cmd/lxc_init.c index a03631f1a4..3ae1bf6fae 100644 --- a/src/lxc/cmd/lxc_init.c +++ b/src/lxc/cmd/lxc_init.c @@ -479,7 +479,7 @@ int main(int argc, char *argv[]) break; } default: - ret = kill(pid, was_interrupted); + kill(pid, was_interrupted); break; } ret = EXIT_SUCCESS; diff --git a/src/lxc/conf.c b/src/lxc/conf.c index 84d16d7749..434104c927 100644 --- a/src/lxc/conf.c +++ b/src/lxc/conf.c @@ -1201,7 +1201,9 @@ static int lxc_fill_autodev(const struct lxc_rootfs *rootfs) } /* Fallback to bind-mounting the device from the host. */ - snprintf(hostpath, sizeof(hostpath), "/dev/%s", device->name); + ret = snprintf(hostpath, sizeof(hostpath), "/dev/%s", device->name); + if (ret < 0 || (size_t)ret >= sizeof(hostpath)) + return ret_errno(EIO); ret = safe_mount_beneath_at(dev_dir_fd, hostpath, device->name, NULL, MS_BIND, NULL); if (ret < 0) { diff --git a/src/lxc/conf.h b/src/lxc/conf.h index 907cbdfa52..116479df94 100644 --- a/src/lxc/conf.h +++ b/src/lxc/conf.h @@ -19,6 +19,7 @@ #include "config.h" #include "list.h" #include "lxcseccomp.h" +#include "memory_utils.h" #include "ringbuf.h" #include "start.h" #include "terminal.h" @@ -69,6 +70,16 @@ struct lxc_cgroup { }; }; +static void free_lxc_cgroup(struct lxc_cgroup *ptr) +{ + if (ptr) { + free(ptr->subsystem); + free(ptr->value); + free_disarm(ptr); + } +} +define_cleanup_function(struct lxc_cgroup *, free_lxc_cgroup); + #if !HAVE_SYS_RESOURCE_H #define RLIM_INFINITY ((unsigned long)-1) struct rlimit { @@ -87,6 +98,15 @@ struct lxc_limit { struct rlimit limit; }; +static void free_lxc_limit(struct lxc_limit *ptr) +{ + if (ptr) { + free(ptr->resource); + free_disarm(ptr); + } +} +define_cleanup_function(struct lxc_limit *, free_lxc_limit); + enum idtype { ID_TYPE_UID, ID_TYPE_GID @@ -102,6 +122,16 @@ struct lxc_sysctl { char *value; }; +static void free_lxc_sysctl(struct lxc_sysctl *ptr) +{ + if (ptr) { + free(ptr->key); + free(ptr->value); + free_disarm(ptr); + } +} +define_cleanup_function(struct lxc_sysctl *, free_lxc_sysctl); + /* * Defines a structure to configure proc filesystem at runtime. * @filename : the proc filesystem will be configured without the "lxc.proc" prefix @@ -112,6 +142,16 @@ struct lxc_proc { char *value; }; +static void free_lxc_proc(struct lxc_proc *ptr) +{ + if (ptr) { + free(ptr->filename); + free(ptr->value); + free_disarm(ptr); + } +} +define_cleanup_function(struct lxc_proc *, free_lxc_proc); + /* * id_map is an id map entry. Form in confile is: * lxc.idmap = u 0 9800 100 diff --git a/src/lxc/confile.c b/src/lxc/confile.c index e7ab359291..a5cb64e506 100644 --- a/src/lxc/confile.c +++ b/src/lxc/confile.c @@ -449,7 +449,7 @@ static int set_config_net_l2proxy(const char *key, const char *value, ret = lxc_safe_uint(value, &val); if (ret < 0) - return ret_errno(-ret); + return ret_errno(ret); switch (val) { case 0: @@ -460,7 +460,7 @@ static int set_config_net_l2proxy(const char *key, const char *value, return 0; } - return ret_set_errno(-1, EINVAL); + return ret_errno(EINVAL); } static int set_config_net_name(const char *key, const char *value, @@ -1242,8 +1242,9 @@ static int set_config_hooks_version(const char *key, const char *value, static int set_config_personality(const char *key, const char *value, struct lxc_conf *lxc_conf, void *data) { - signed long personality = lxc_config_parse_arch(value); + signed long personality; + personality = lxc_config_parse_arch(value); if (personality >= 0) lxc_conf->personality = personality; else @@ -1265,7 +1266,7 @@ static int set_config_pty_max(const char *key, const char *value, ret = lxc_safe_uint(value, &max); if (ret < 0) - return -1; + return ret_errno(EINVAL); lxc_conf->pty_max = max; @@ -1280,6 +1281,7 @@ static int set_config_pty_max(const char *key, const char *value, static int set_config_start(const char *key, const char *value, struct lxc_conf *lxc_conf, void *data) { + int ret; bool is_empty; is_empty = lxc_config_value_empty(value); @@ -1290,11 +1292,12 @@ static int set_config_start(const char *key, const char *value, return 0; } - if (lxc_safe_uint(value, &lxc_conf->start_auto) < 0) - return -1; + ret = lxc_safe_uint(value, &lxc_conf->start_auto); + if (ret) + return ret; if (lxc_conf->start_auto > 1) - return -1; + return ret_errno(EINVAL); return 0; } else if (*(key + 10) == 'd') { /* lxc.start.delay */ @@ -1313,7 +1316,7 @@ static int set_config_start(const char *key, const char *value, return lxc_safe_int(value, &lxc_conf->start_order); } - return -1; + return ret_errno(EINVAL); } static int set_config_monitor(const char *key, const char *value, @@ -1327,7 +1330,7 @@ static int set_config_monitor(const char *key, const char *value, if (strcmp(key + 12, "unshare") == 0) return lxc_safe_uint(value, &lxc_conf->monitor_unshare); - return -1; + return ret_errno(EINVAL); } static int set_config_monitor_signal_pdeath(const char *key, const char *value, @@ -1343,65 +1346,59 @@ static int set_config_monitor_signal_pdeath(const char *key, const char *value, sig_n = sig_parse(value); if (sig_n < 0) - return -1; + return ret_errno(EINVAL); lxc_conf->monitor_signal_pdeath = sig_n; return 0; } - return -EINVAL; + return ret_errno(EINVAL); } static int set_config_group(const char *key, const char *value, struct lxc_conf *lxc_conf, void *data) { - char *groups, *token; - struct lxc_list *grouplist; - int ret = 0; + __do_free char *groups = NULL; + char *token; if (lxc_config_value_empty(value)) return lxc_clear_groups(lxc_conf); groups = strdup(value); if (!groups) - return -1; + return ret_errno(ENOMEM); /* In case several groups are specified in a single line split these * groups in a single element for the list. */ lxc_iterate_parts(token, groups, " \t") { + __do_free struct lxc_list *grouplist = NULL; + grouplist = malloc(sizeof(*grouplist)); - if (!grouplist) { - ret = -1; - break; - } + if (!grouplist) + return ret_errno(ENOMEM); grouplist->elem = strdup(token); - if (!grouplist->elem) { - free(grouplist); - ret = -1; - break; - } + if (!grouplist->elem) + return ret_errno(ENOMEM); - lxc_list_add_tail(&lxc_conf->groups, grouplist); + lxc_list_add_tail(&lxc_conf->groups, move_ptr(grouplist)); } - free(groups); - - return ret; + return 0; } static int set_config_environment(const char *key, const char *value, struct lxc_conf *lxc_conf, void *data) { - struct lxc_list *list_item = NULL; + __do_free struct lxc_list *list_item = NULL; if (lxc_config_value_empty(value)) return lxc_clear_environment(lxc_conf); list_item = malloc(sizeof(*list_item)); if (!list_item) - goto on_error; + return ret_errno(ENOMEM); if (!strchr(value, '=')) { const char *env_val; @@ -1410,7 +1407,7 @@ static int set_config_environment(const char *key, const char *value, env_val = getenv(env_key); if (!env_val) - goto on_error; + return ret_errno(ENOENT); env_var[0] = env_key; env_var[1] = env_val; @@ -1420,16 +1417,11 @@ static int set_config_environment(const char *key, const char *value, } if (!list_item->elem) - goto on_error; + return ret_errno(ENOMEM); - lxc_list_add_tail(&lxc_conf->environment, list_item); + lxc_list_add_tail(&lxc_conf->environment, move_ptr(list_item)); return 0; - -on_error: - free(list_item); - - return -1; } static int set_config_tty_max(const char *key, const char *value, @@ -1445,7 +1437,7 @@ static int set_config_tty_max(const char *key, const char *value, ret = lxc_safe_uint(value, &nbtty); if (ret < 0) - return -1; + return ret; lxc_conf->ttys.max = nbtty; @@ -1470,16 +1462,19 @@ static int set_config_apparmor_allow_incomplete(const char *key, struct lxc_conf *lxc_conf, void *data) { + int ret; + if (lxc_config_value_empty(value)) { lxc_conf->lsm_aa_allow_incomplete = 0; return 0; } - if (lxc_safe_uint(value, &lxc_conf->lsm_aa_allow_incomplete) < 0) - return -1; + ret = lxc_safe_uint(value, &lxc_conf->lsm_aa_allow_incomplete); + if (ret) + return ret; if (lxc_conf->lsm_aa_allow_incomplete > 1) - return -1; + return ret_errno(EINVAL); return 0; } @@ -1489,14 +1484,17 @@ static int set_config_apparmor_allow_nesting(const char *key, struct lxc_conf *lxc_conf, void *data) { + int ret; + if (lxc_config_value_empty(value)) return clr_config_apparmor_allow_nesting(key, lxc_conf, NULL); - if (lxc_safe_uint(value, &lxc_conf->lsm_aa_allow_nesting) < 0) - return -1; + ret = lxc_safe_uint(value, &lxc_conf->lsm_aa_allow_nesting); + if (ret) + return ret; if (lxc_conf->lsm_aa_allow_nesting > 1) - return -1; + return ret_errno(EINVAL); return 0; } @@ -1506,26 +1504,22 @@ static int set_config_apparmor_raw(const char *key, struct lxc_conf *lxc_conf, void *data) { - char *elem; - struct lxc_list *list; + __do_free char *elem = NULL; + __do_free struct lxc_list *list = NULL; if (lxc_config_value_empty(value)) return lxc_clear_apparmor_raw(lxc_conf); list = malloc(sizeof(*list)); - if (!list) { - errno = ENOMEM; - return -1; - } + if (!list) + return ret_errno(ENOMEM); elem = strdup(value); - if (!elem) { - free(list); - return -1; - } - list->elem = elem; + if (!elem) + return ret_errno(ENOMEM); - lxc_list_add_tail(&lxc_conf->lsm_aa_raw, list); + list->elem = move_ptr(elem); + lxc_list_add_tail(&lxc_conf->lsm_aa_raw, move_ptr(list)); return 0; } @@ -1554,12 +1548,12 @@ static int set_config_log_file(const char *key, const char *value, int ret; if (lxc_config_value_empty(value)) { - free(c->logfile); - c->logfile = NULL; + free_disarm(c->logfile); return 0; } - /* Store these values in the lxc_conf, and then try to set for actual + /* + * Store these values in the lxc_conf, and then try to set for actual * current logging. */ ret = set_config_path_item(&c->logfile, value); @@ -1580,13 +1574,17 @@ static int set_config_log_level(const char *key, const char *value, } if (value[0] >= '0' && value[0] <= '9') { - if (lxc_safe_int(value, &newlevel) < 0) - return -1; + int ret; + + ret = lxc_safe_int(value, &newlevel); + if (ret) + return ret_errno(EINVAL); } else { newlevel = lxc_log_priority_to_int(value); } - /* Store these values in the lxc_conf, and then try to set for actual + /* + * Store these values in the lxc_conf, and then try to set for actual * current logging. */ lxc_conf->loglevel = newlevel; @@ -1597,16 +1595,19 @@ static int set_config_log_level(const char *key, const char *value, static int set_config_autodev(const char *key, const char *value, struct lxc_conf *lxc_conf, void *data) { + int ret; + if (lxc_config_value_empty(value)) { lxc_conf->autodev = 0; return 0; } - if (lxc_safe_uint(value, &lxc_conf->autodev) < 0) - return -1; + ret = lxc_safe_uint(value, &lxc_conf->autodev); + if (ret) + return ret_errno(EINVAL); if (lxc_conf->autodev > 1) - return -1; + return ret_errno(EINVAL); return 0; } @@ -1637,7 +1638,7 @@ static int set_config_signal_halt(const char *key, const char *value, sig_n = sig_parse(value); if (sig_n < 0) - return -1; + return ret_errno(EINVAL); lxc_conf->haltsignal = sig_n; @@ -1656,7 +1657,7 @@ static int set_config_signal_reboot(const char *key, const char *value, sig_n = sig_parse(value); if (sig_n < 0) - return -1; + return ret_errno(EINVAL); lxc_conf->rebootsignal = sig_n; @@ -1675,7 +1676,7 @@ static int set_config_signal_stop(const char *key, const char *value, sig_n = sig_parse(value); if (sig_n < 0) - return -1; + return ret_errno(EINVAL); lxc_conf->stopsignal = sig_n; @@ -1685,10 +1686,10 @@ static int set_config_signal_stop(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) { + __do_free struct lxc_list *cglist = NULL; + call_cleaner(free_lxc_cgroup) struct lxc_cgroup *cgelem = NULL; const char *subkey, *token; size_t token_len; - struct lxc_list *cglist = NULL; - struct lxc_cgroup *cgelem = NULL; if (lxc_config_value_empty(value)) return lxc_clear_cgroups(lxc_conf, key, version); @@ -1700,53 +1701,44 @@ static int __set_config_cgroup_controller(const char *key, const char *value, token = "lxc.cgroup."; token_len = 11; } else { - return -EINVAL; + return ret_errno(EINVAL); } if (strncmp(key, token, token_len) != 0) - return -EINVAL; + return ret_errno(EINVAL); subkey = key + token_len; if (*subkey == '\0') - return -EINVAL; + return ret_errno(EINVAL); cglist = malloc(sizeof(*cglist)); if (!cglist) - goto out; + return ret_errno(ENOMEM); cgelem = malloc(sizeof(*cgelem)); if (!cgelem) - goto out; + return ret_errno(ENOMEM); memset(cgelem, 0, sizeof(*cgelem)); cgelem->subsystem = strdup(subkey); if (!cgelem->subsystem) - goto out; + return ret_errno(ENOMEM); cgelem->value = strdup(value); if (!cgelem->value) - goto out; + return ret_errno(ENOMEM); cgelem->version = version; - lxc_list_add_elem(cglist, cgelem); + lxc_list_add_elem(cglist, move_ptr(cgelem)); if (version == CGROUP2_SUPER_MAGIC) lxc_list_add_tail(&lxc_conf->cgroup2, cglist); else lxc_list_add_tail(&lxc_conf->cgroup, cglist); + move_ptr(cglist); return 0; - -out: - free(cglist); - if (cgelem) { - free(cgelem->subsystem); - free(cgelem->value); - free(cgelem); - } - - return -1; } static int set_config_cgroup_controller(const char *key, const char *value, @@ -1830,8 +1822,8 @@ static int set_config_cgroup_relative(const char *key, const char *value, return clr_config_cgroup_relative(key, lxc_conf, NULL); ret = lxc_safe_uint(value, &converted); - if (ret < 0) - return -ret; + if (ret) + return ret; if (converted == 1) { lxc_conf->cgroup_meta.relative = true; @@ -1843,7 +1835,7 @@ static int set_config_cgroup_relative(const char *key, const char *value, return 0; } - return -EINVAL; + return ret_errno(EINVAL); } static bool parse_limit_value(const char **value, rlim_t *res) @@ -1869,23 +1861,23 @@ static bool parse_limit_value(const char **value, rlim_t *res) static int set_config_prlimit(const char *key, const char *value, struct lxc_conf *lxc_conf, void *data) { + __do_free struct lxc_list *limlist = NULL; + call_cleaner(free_lxc_limit) struct lxc_limit *limelem = NULL; struct lxc_list *iter; struct rlimit limit; rlim_t limit_value; - struct lxc_list *limlist = NULL; - struct lxc_limit *limelem = NULL; if (lxc_config_value_empty(value)) return lxc_clear_limits(lxc_conf, key); if (strncmp(key, "lxc.prlimit.", STRLITERALLEN("lxc.prlimit.")) != 0) - return -1; + return ret_errno(EINVAL); key += STRLITERALLEN("lxc.prlimit."); /* soft limit comes first in the value */ if (!parse_limit_value(&value, &limit_value)) - return -1; + return ret_errno(EINVAL); limit.rlim_cur = limit_value; @@ -1896,7 +1888,7 @@ static int set_config_prlimit(const char *key, const char *value, if (*value == ':') ++value; else if (*value) /* any other character is an error here */ - return -1; + return ret_errno(EINVAL); while (isspace(*value)) ++value; @@ -1904,7 +1896,7 @@ static int set_config_prlimit(const char *key, const char *value, /* optional hard limit */ if (*value) { if (!parse_limit_value(&value, &limit_value)) - return -1; + return ret_errno(EINVAL); limit.rlim_max = limit_value; @@ -1913,7 +1905,7 @@ static int set_config_prlimit(const char *key, const char *value, ++value; if (*value) - return -1; + return ret_errno(EINVAL); } else { /* a single value sets both hard and soft limit */ limit.rlim_max = limit.rlim_cur; @@ -1931,41 +1923,30 @@ static int set_config_prlimit(const char *key, const char *value, /* allocate list element */ limlist = malloc(sizeof(*limlist)); if (!limlist) - goto on_error; + return ret_errno(ENOMEM); limelem = malloc(sizeof(*limelem)); if (!limelem) - goto on_error; + return ret_errno(ENOMEM); memset(limelem, 0, sizeof(*limelem)); limelem->resource = strdup(key); if (!limelem->resource) - goto on_error; + return ret_errno(ENOMEM); limelem->limit = limit; - lxc_list_add_elem(limlist, limelem);; - lxc_list_add_tail(&lxc_conf->limits, limlist); + lxc_list_add_elem(limlist, move_ptr(limelem));; + lxc_list_add_tail(&lxc_conf->limits, move_ptr(limlist)); return 0; - -on_error: - free(limlist); - - if (limelem) { - free(limelem->resource); - free(limelem); - } - - return -1; } static int set_config_sysctl(const char *key, const char *value, 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; struct lxc_list *iter; - char *replace_value = NULL; - struct lxc_list *sysctl_list = NULL; - struct lxc_sysctl *sysctl_elem = NULL; if (lxc_config_value_empty(value)) return clr_config_sysctl(key, lxc_conf, NULL); @@ -1977,6 +1958,8 @@ static int set_config_sysctl(const char *key, const char *value, /* find existing list element */ lxc_list_for_each(iter, &lxc_conf->sysctls) { + __do_free char *replace_value = NULL; + sysctl_elem = iter->elem; if (strcmp(key, sysctl_elem->key) != 0) @@ -1984,10 +1967,10 @@ static int set_config_sysctl(const char *key, const char *value, replace_value = strdup(value); if (!replace_value) - return -1; + return ret_errno(EINVAL); free(sysctl_elem->value); - sysctl_elem->value = replace_value; + sysctl_elem->value = move_ptr(replace_value); return 0; } @@ -1995,44 +1978,33 @@ static int set_config_sysctl(const char *key, const char *value, /* allocate list element */ sysctl_list = malloc(sizeof(*sysctl_list)); if (!sysctl_list) - goto on_error; + return ret_errno(ENOMEM); sysctl_elem = malloc(sizeof(*sysctl_elem)); if (!sysctl_elem) - goto on_error; + return ret_errno(ENOMEM); memset(sysctl_elem, 0, sizeof(*sysctl_elem)); sysctl_elem->key = strdup(key); if (!sysctl_elem->key) - goto on_error; + return ret_errno(ENOMEM); sysctl_elem->value = strdup(value); if (!sysctl_elem->value) - goto on_error; + return ret_errno(ENOMEM); - lxc_list_add_elem(sysctl_list, sysctl_elem); - lxc_list_add_tail(&lxc_conf->sysctls, sysctl_list); + lxc_list_add_elem(sysctl_list, move_ptr(sysctl_elem)); + lxc_list_add_tail(&lxc_conf->sysctls, move_ptr(sysctl_list)); return 0; - -on_error: - free(sysctl_list); - - if (sysctl_elem) { - free(sysctl_elem->key); - free(sysctl_elem->value); - free(sysctl_elem); - } - - return -1; } static int set_config_proc(const char *key, const char *value, struct lxc_conf *lxc_conf, void *data) { + __do_free struct lxc_list *proclist = NULL; + call_cleaner(free_lxc_proc) struct lxc_proc *procelem = NULL; const char *subkey; - struct lxc_list *proclist = NULL; - struct lxc_proc *procelem = NULL; if (lxc_config_value_empty(value)) return clr_config_proc(key, lxc_conf, NULL); @@ -2042,67 +2014,55 @@ static int set_config_proc(const char *key, const char *value, subkey = key + STRLITERALLEN("lxc.proc."); if (*subkey == '\0') - return -EINVAL; + return ret_errno(EINVAL); proclist = malloc(sizeof(*proclist)); if (!proclist) - goto on_error; + return ret_errno(ENOMEM); procelem = malloc(sizeof(*procelem)); if (!procelem) - goto on_error; + return ret_errno(ENOMEM); memset(procelem, 0, sizeof(*procelem)); procelem->filename = strdup(subkey); - procelem->value = strdup(value); - - if (!procelem->filename || !procelem->value) - goto on_error; + if (!procelem->filename) + return ret_errno(ENOMEM); - proclist->elem = procelem; + procelem->value = strdup(value); + if (!procelem->value) + return ret_errno(ENOMEM); - lxc_list_add_tail(&lxc_conf->procs, proclist); + proclist->elem = move_ptr(procelem); + lxc_list_add_tail(&lxc_conf->procs, move_ptr(proclist)); return 0; - -on_error: - free(proclist); - - if (procelem) { - free(procelem->filename); - free(procelem->value); - free(procelem); - } - - return -1; } static int set_config_idmaps(const char *key, const char *value, struct lxc_conf *lxc_conf, void *data) { + __do_free struct lxc_list *idmaplist = NULL; + __do_free struct id_map *idmap = NULL; unsigned long hostid, nsid, range; char type; int ret; - struct lxc_list *idmaplist = NULL; - struct id_map *idmap = NULL; if (lxc_config_value_empty(value)) return lxc_clear_idmaps(lxc_conf); idmaplist = malloc(sizeof(*idmaplist)); if (!idmaplist) - goto on_error; + return ret_errno(ENOMEM); idmap = malloc(sizeof(*idmap)); if (!idmap) - goto on_error; + return ret_errno(ENOMEM); memset(idmap, 0, sizeof(*idmap)); ret = parse_idmaps(value, &type, &nsid, &hostid, &range); - if (ret < 0) { - ERROR("Failed to parse id mappings"); - goto on_error; - } + if (ret < 0) + return log_error_errno(-EINVAL, EINVAL, "Failed to parse id mappings"); INFO("Read uid map: type %c nsid %lu hostid %lu range %lu", type, nsid, hostid, range); if (type == 'u') @@ -2110,7 +2070,7 @@ static int set_config_idmaps(const char *key, const char *value, else if (type == 'g') idmap->idtype = ID_TYPE_GID; else - goto on_error; + return ret_errno(EINVAL); idmap->hostid = hostid; idmap->nsid = nsid; @@ -2126,15 +2086,10 @@ static int set_config_idmaps(const char *key, const char *value, if (idmap->nsid == 0) lxc_conf->root_nsgid_map = idmap; - idmap = NULL; + move_ptr(idmap); + move_ptr(idmaplist); return 0; - -on_error: - free(idmaplist); - free(idmap); - - return -1; } static int set_config_mount_fstab(const char *key, const char *value, @@ -2142,7 +2097,7 @@ static int set_config_mount_fstab(const char *key, const char *value, { if (lxc_config_value_empty(value)) { clr_config_mount_fstab(key, lxc_conf, NULL); - return -1; + return ret_errno(EINVAL); } return set_config_path_item(&lxc_conf->fstab, value); @@ -2151,43 +2106,44 @@ static int set_config_mount_fstab(const char *key, const char *value, static int set_config_mount_auto(const char *key, const char *value, struct lxc_conf *lxc_conf, void *data) { - char *autos, *token; + __do_free char *autos = NULL; + char *token; int i; - int ret = -1; static struct { const char *token; int mask; int flag; } allowed_auto_mounts[] = { - { "proc", LXC_AUTO_PROC_MASK, LXC_AUTO_PROC_MIXED }, - { "proc:mixed", LXC_AUTO_PROC_MASK, LXC_AUTO_PROC_MIXED }, - { "proc:rw", LXC_AUTO_PROC_MASK, LXC_AUTO_PROC_RW }, - { "sys", LXC_AUTO_SYS_MASK, LXC_AUTO_SYS_MIXED }, - { "sys:ro", LXC_AUTO_SYS_MASK, LXC_AUTO_SYS_RO }, - { "sys:mixed", LXC_AUTO_SYS_MASK, LXC_AUTO_SYS_MIXED }, - { "sys:rw", LXC_AUTO_SYS_MASK, LXC_AUTO_SYS_RW }, - { "cgroup", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_NOSPEC }, - { "cgroup:mixed", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_MIXED }, - { "cgroup:ro", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_RO }, - { "cgroup:rw", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_RW }, - { "cgroup:force", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_NOSPEC | LXC_AUTO_CGROUP_FORCE }, - { "cgroup:mixed:force", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_MIXED | LXC_AUTO_CGROUP_FORCE }, - { "cgroup:ro:force", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_RO | LXC_AUTO_CGROUP_FORCE }, - { "cgroup:rw:force", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_RW | LXC_AUTO_CGROUP_FORCE }, - { "cgroup-full", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_FULL_NOSPEC }, - { "cgroup-full:mixed", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_FULL_MIXED }, - { "cgroup-full:ro", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_FULL_RO }, - { "cgroup-full:rw", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_FULL_RW }, - { "cgroup-full:force", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_FULL_NOSPEC | LXC_AUTO_CGROUP_FORCE }, - { "cgroup-full:mixed:force", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_FULL_MIXED | LXC_AUTO_CGROUP_FORCE }, - { "cgroup-full:ro:force", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_FULL_RO | LXC_AUTO_CGROUP_FORCE }, - { "cgroup-full:rw:force", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_FULL_RW | LXC_AUTO_CGROUP_FORCE }, - { "shmounts:", LXC_AUTO_SHMOUNTS_MASK, LXC_AUTO_SHMOUNTS }, - /* For adding anything that is just a single on/off, but has no - * options: keep mask and flag identical and just define the enum - * value as an unused bit so far - */ - { NULL, 0, 0 } + { "proc", LXC_AUTO_PROC_MASK, LXC_AUTO_PROC_MIXED }, + { "proc:mixed", LXC_AUTO_PROC_MASK, LXC_AUTO_PROC_MIXED }, + { "proc:rw", LXC_AUTO_PROC_MASK, LXC_AUTO_PROC_RW }, + { "sys", LXC_AUTO_SYS_MASK, LXC_AUTO_SYS_MIXED }, + { "sys:ro", LXC_AUTO_SYS_MASK, LXC_AUTO_SYS_RO }, + { "sys:mixed", LXC_AUTO_SYS_MASK, LXC_AUTO_SYS_MIXED }, + { "sys:rw", LXC_AUTO_SYS_MASK, LXC_AUTO_SYS_RW }, + { "cgroup", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_NOSPEC }, + { "cgroup:mixed", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_MIXED }, + { "cgroup:ro", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_RO }, + { "cgroup:rw", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_RW }, + { "cgroup:force", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_NOSPEC | LXC_AUTO_CGROUP_FORCE }, + { "cgroup:mixed:force", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_MIXED | LXC_AUTO_CGROUP_FORCE }, + { "cgroup:ro:force", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_RO | LXC_AUTO_CGROUP_FORCE }, + { "cgroup:rw:force", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_RW | LXC_AUTO_CGROUP_FORCE }, + { "cgroup-full", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_FULL_NOSPEC }, + { "cgroup-full:mixed", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_FULL_MIXED }, + { "cgroup-full:ro", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_FULL_RO }, + { "cgroup-full:rw", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_FULL_RW }, + { "cgroup-full:force", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_FULL_NOSPEC | LXC_AUTO_CGROUP_FORCE }, + { "cgroup-full:mixed:force", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_FULL_MIXED | LXC_AUTO_CGROUP_FORCE }, + { "cgroup-full:ro:force", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_FULL_RO | LXC_AUTO_CGROUP_FORCE }, + { "cgroup-full:rw:force", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_FULL_RW | LXC_AUTO_CGROUP_FORCE }, + { "shmounts:", LXC_AUTO_SHMOUNTS_MASK, LXC_AUTO_SHMOUNTS }, + /* + * For adding anything that is just a single on/off, but has no + * options: keep mask and flag identical and just define the + * enum value as an unused bit so far + */ + { NULL, 0, 0 } }; if (lxc_config_value_empty(value)) { @@ -2197,7 +2153,7 @@ static int set_config_mount_auto(const char *key, const char *value, autos = strdup(value); if (!autos) - return -1; + return ret_errno(ENOMEM); lxc_iterate_parts(token, autos, " \t") { bool is_shmounts = false; @@ -2213,73 +2169,61 @@ static int set_config_mount_auto(const char *key, const char *value, } } - if (!allowed_auto_mounts[i].token) { - ERROR("Invalid filesystem to automount \"%s\"", token); - goto on_error; - } + if (!allowed_auto_mounts[i].token) + return log_error_errno(-EINVAL, EINVAL, "Invalid filesystem to automount \"%s\"", token); lxc_conf->auto_mounts &= ~allowed_auto_mounts[i].mask; lxc_conf->auto_mounts |= allowed_auto_mounts[i].flag; if (is_shmounts) { - char *container_path; - char *host_path; + __do_free char *container_path = NULL, *host_path = NULL; + char *val; - host_path = token + STRLITERALLEN("shmounts:"); - if (*host_path == '\0') { - SYSERROR("Failed to copy shmounts host path"); - goto on_error; - } + val = token + STRLITERALLEN("shmounts:"); + if (*val == '\0') + return log_error_errno(-EINVAL, EINVAL, "Failed to copy shmounts host path"); + + host_path = strdup(val); + if (!host_path) + return log_error_errno(-EINVAL, EINVAL, "Failed to copy shmounts host path"); - container_path = strchr(host_path, ':'); - if (!container_path || *(container_path + 1) == '\0') - container_path = "/dev/.lxc-mounts"; + val = strchr(host_path, ':'); + if (!val || *(val + 1) == '\0') + val = "/dev/.lxc-mounts"; else - *container_path++ = '\0'; + *val++ = '\0'; - lxc_conf->shmount.path_host = strdup(host_path); - if (!lxc_conf->shmount.path_host) { - SYSERROR("Failed to copy shmounts host path"); - goto on_error; - } + container_path = strdup(val); + if(!container_path) + return log_error_errno(-EINVAL, EINVAL, "Failed to copy shmounts container path"); - lxc_conf->shmount.path_cont = strdup(container_path); - if(!lxc_conf->shmount.path_cont) { - SYSERROR("Failed to copy shmounts container path"); - goto on_error; - } + lxc_conf->shmount.path_host = move_ptr(host_path); + lxc_conf->shmount.path_cont = move_ptr(container_path); } } - ret = 0; - -on_error: - free(autos); - - return ret; + return 0; } static int set_config_mount(const char *key, const char *value, struct lxc_conf *lxc_conf, void *data) { - char *mntelem; - struct lxc_list *mntlist; + __do_free char *mntelem = NULL; + __do_free struct lxc_list *mntlist = NULL; if (lxc_config_value_empty(value)) return lxc_clear_mount_entries(lxc_conf); mntlist = malloc(sizeof(*mntlist)); if (!mntlist) - return -1; + return ret_errno(ENOMEM); mntelem = strdup(value); - if (!mntelem) { - free(mntlist); - return -1; - } - mntlist->elem = mntelem; + if (!mntelem) + return ret_errno(ENOMEM); - lxc_list_add_tail(&lxc_conf->mount_list, mntlist); + mntlist->elem = move_ptr(mntelem); + lxc_list_add_tail(&lxc_conf->mount_list, move_ptr(mntlist)); return 0; } @@ -2291,16 +2235,16 @@ int add_elem_to_mount_list(const char *value, struct lxc_conf *lxc_conf) { static int set_config_cap_keep(const char *key, const char *value, struct lxc_conf *lxc_conf, void *data) { - char *keepcaps, *token; - struct lxc_list *keeplist; - int ret = -1; + __do_free char *keepcaps = NULL; + __do_free struct lxc_list *keeplist = NULL; + char *token; if (lxc_config_value_empty(value)) return lxc_clear_config_keepcaps(lxc_conf); keepcaps = strdup(value); if (!keepcaps) - return -1; + return ret_errno(ENOMEM); /* In case several capability keep is specified in a single line * split these caps in a single element for the list. @@ -2311,38 +2255,31 @@ static int set_config_cap_keep(const char *key, const char *value, keeplist = malloc(sizeof(*keeplist)); if (!keeplist) - goto on_error; + return ret_errno(ENOMEM); keeplist->elem = strdup(token); - if (!keeplist->elem) { - free(keeplist); - goto on_error; - } + if (!keeplist->elem) + return ret_errno(ENOMEM); - lxc_list_add_tail(&lxc_conf->keepcaps, keeplist); + lxc_list_add_tail(&lxc_conf->keepcaps, move_ptr(keeplist)); } - ret = 0; - -on_error: - free(keepcaps); - - return ret; + return 0; } static int set_config_cap_drop(const char *key, const char *value, struct lxc_conf *lxc_conf, void *data) { - char *dropcaps, *token; - struct lxc_list *droplist; - int ret = -1; + __do_free char *dropcaps = NULL; + __do_free struct lxc_list *droplist = NULL; + char *token; if (lxc_config_value_empty(value)) return lxc_clear_config_caps(lxc_conf); dropcaps = strdup(value); if (!dropcaps) - return -1; + return ret_errno(ENOMEM); /* In case several capability drop is specified in a single line * split these caps in a single element for the list. @@ -2350,23 +2287,16 @@ static int set_config_cap_drop(const char *key, const char *value, lxc_iterate_parts(token, dropcaps, " \t") { droplist = malloc(sizeof(*droplist)); if (!droplist) - goto on_error; + return ret_errno(ENOMEM); droplist->elem = strdup(token); - if (!droplist->elem) { - free(droplist); - goto on_error; - } + if (!droplist->elem) + return ret_errno(ENOMEM); - lxc_list_add_tail(&lxc_conf->caps, droplist); + lxc_list_add_tail(&lxc_conf->caps, move_ptr(droplist)); } - ret = 0; - -on_error: - free(dropcaps); - - return ret; + return 0; } static int set_config_console_path(const char *key, const char *value, @@ -2378,19 +2308,19 @@ static int set_config_console_path(const char *key, const char *value, static int set_config_console_rotate(const char *key, const char *value, struct lxc_conf *lxc_conf, void *data) { + int ret; + if (lxc_config_value_empty(value)) { lxc_conf->console.log_rotate = 0; return 0; } - if (lxc_safe_uint(value, &lxc_conf->console.log_rotate) < 0) - return -1; + ret = lxc_safe_uint(value, &lxc_conf->console.log_rotate); + if (ret) + return ret_errno(EINVAL); - if (lxc_conf->console.log_rotate > 1) { - ERROR("The \"lxc.console.rotate\" config key can only be set " - "to 0 or 1"); - return -1; - } + if (lxc_conf->console.log_rotate > 1) + return log_error_errno(-EINVAL, EINVAL, "The \"lxc.console.rotate\" config key can only be set to 0 or 1"); return 0; } @@ -2420,29 +2350,26 @@ static int set_config_console_buffer_size(const char *key, const char *value, } ret = parse_byte_size_string(value, &size); - if (ret < 0) - return -1; + if (ret) + return ret; if (size < 0) - return -EINVAL; + return ret_errno(EINVAL); /* must be at least a page size */ pgsz = lxc_getpagesize(); if ((uint64_t)size < pgsz) { - NOTICE("Requested ringbuffer size for the console is %" PRId64 - " but must be at least %" PRId64 - " bytes. Setting ringbuffer size to %" PRId64 " bytes", + NOTICE("Requested ringbuffer size for the console is %" PRId64 " but must be at least %" PRId64 " bytes. Setting ringbuffer size to %" PRId64 " bytes", size, pgsz, pgsz); size = pgsz; } buffer_size = lxc_find_next_power2((uint64_t)size); if (buffer_size == 0) - return -EINVAL; + return ret_errno(EINVAL); if (buffer_size != size) - NOTICE("Passed size was not a power of 2. Rounding log size to " - "next power of two: %" PRIu64 " bytes", buffer_size); + NOTICE("Passed size was not a power of 2. Rounding log size to next power of two: %" PRIu64 " bytes", buffer_size); lxc_conf->console.buffer_size = buffer_size; @@ -2468,29 +2395,26 @@ static int set_config_console_size(const char *key, const char *value, } ret = parse_byte_size_string(value, &size); - if (ret < 0) - return -1; + if (ret) + return ret_errno(EINVAL); if (size < 0) - return -EINVAL; + return ret_errno(EINVAL); /* must be at least a page size */ pgsz = lxc_getpagesize(); if ((uint64_t)size < pgsz) { - NOTICE("Requested ringbuffer size for the console is %" PRId64 - " but must be at least %" PRId64 - " bytes. Setting ringbuffer size to %" PRId64 " bytes", + NOTICE("Requested ringbuffer size for the console is %" PRId64 " but must be at least %" PRId64 " bytes. Setting ringbuffer size to %" PRId64 " bytes", size, pgsz, pgsz); size = pgsz; } log_size = lxc_find_next_power2((uint64_t)size); if (log_size == 0) - return -EINVAL; + return ret_errno(EINVAL); if (log_size != size) - NOTICE("Passed size was not a power of 2. Rounding log size to " - "next power of two: %" PRIu64 " bytes", log_size); + NOTICE("Passed size was not a power of 2. Rounding log size to next power of two: %" PRIu64 " bytes", log_size); lxc_conf->console.log_size = log_size; @@ -2540,10 +2464,11 @@ int append_unexp_config_line(const char *line, struct lxc_conf *conf) linelen = strlen(line); while (conf->unexpanded_alloced <= len + linelen + 2) { - char *tmp = realloc(conf->unexpanded_config, - conf->unexpanded_alloced + 1024); + char *tmp; + + tmp = realloc(conf->unexpanded_config, conf->unexpanded_alloced + 1024); if (!tmp) - return -1; + return ret_errno(EINVAL); if (!conf->unexpanded_config) *tmp = '\0'; @@ -2565,16 +2490,15 @@ static int do_includedir(const char *dirp, struct lxc_conf *lxc_conf) { __do_closedir DIR *dir = NULL; struct dirent *direntp; - char path[PATH_MAX]; - int len; - int ret = -1; + int len, ret; dir = opendir(dirp); if (!dir) - return -1; + return -errno; while ((direntp = readdir(dir))) { const char *fnam; + char path[PATH_MAX]; fnam = direntp->d_name; if (!strcmp(fnam, ".")) @@ -2589,11 +2513,11 @@ static int do_includedir(const char *dirp, struct lxc_conf *lxc_conf) len = snprintf(path, PATH_MAX, "%s/%s", dirp, fnam); if (len < 0 || len >= PATH_MAX) - return -1; + return ret_errno(EIO); ret = lxc_config_read(path, lxc_conf, true); if (ret < 0) - return -1; + return ret; } return 0; @@ -2616,8 +2540,9 @@ static int set_config_includefiles(const char *key, const char *value, static int set_config_rootfs_path(const char *key, const char *value, struct lxc_conf *lxc_conf, void *data) { + __do_free char *dup = NULL; int ret; - char *dup, *tmp; + char *tmp; const char *container_path; if (lxc_config_value_empty(value)) { @@ -2628,7 +2553,7 @@ static int set_config_rootfs_path(const char *key, const char *value, dup = strdup(value); if (!dup) - return -1; + return ret_errno(ENOMEM); /* Split : into and * . Set "rootfs.bdev_type" to and @@ -2639,10 +2564,8 @@ static int set_config_rootfs_path(const char *key, const char *value, *tmp = '\0'; ret = set_config_path_item(&lxc_conf->rootfs.bdev_type, dup); - if (ret < 0) { - free(dup); - return -1; - } + if (ret < 0) + return ret_errno(ENOMEM); tmp++; container_path = tmp; @@ -2650,10 +2573,7 @@ static int set_config_rootfs_path(const char *key, const char *value, container_path = value; } - ret = set_config_path_item(&lxc_conf->rootfs.path, container_path); - free(dup); - - return ret; + return set_config_path_item(&lxc_conf->rootfs.path, container_path); } static int set_config_rootfs_managed(const char *key, const char *value, @@ -2671,30 +2591,26 @@ static int set_config_rootfs_mount(const char *key, const char *value, static int set_config_rootfs_options(const char *key, const char *value, struct lxc_conf *lxc_conf, void *data) { + __do_free char *mdata = NULL, *opts = NULL; unsigned long mflags = 0, pflags = 0; - char *mdata = NULL, *opts = NULL; - int ret; struct lxc_rootfs *rootfs = &lxc_conf->rootfs; + int ret; ret = parse_mntopts(value, &mflags, &mdata); if (ret < 0) - return -EINVAL; + return ret_errno(EINVAL); ret = parse_propagationopts(value, &pflags); - if (ret < 0) { - free(mdata); - return -EINVAL; - } + if (ret < 0) + return ret_errno(EINVAL); ret = set_config_string_item(&opts, value); - if (ret < 0) { - free(mdata); - return -ENOMEM; - } + if (ret < 0) + return ret_errno(ENOMEM); rootfs->mountflags = mflags | pflags; - rootfs->options = opts; - rootfs->data = mdata; + rootfs->options = move_ptr(opts); + rootfs->data = move_ptr(mdata); return 0; } @@ -2702,7 +2618,7 @@ static int set_config_rootfs_options(const char *key, const char *value, static int set_config_uts_name(const char *key, const char *value, struct lxc_conf *lxc_conf, void *data) { - struct utsname *utsname; + __do_free struct utsname *utsname = NULL; if (lxc_config_value_empty(value)) { clr_config_uts_name(key, lxc_conf, NULL); @@ -2711,16 +2627,14 @@ static int set_config_uts_name(const char *key, const char *value, utsname = malloc(sizeof(*utsname)); if (!utsname) - return -1; + return ret_errno(ENOMEM); - if (strlen(value) >= sizeof(utsname->nodename)) { - free(utsname); - return -1; - } + if (strlen(value) >= sizeof(utsname->nodename)) + return ret_errno(EINVAL); (void)strlcpy(utsname->nodename, value, sizeof(utsname->nodename)); free(lxc_conf->utsname); - lxc_conf->utsname = utsname; + lxc_conf->utsname = move_ptr(utsname); return 0; } @@ -2728,34 +2642,28 @@ static int set_config_uts_name(const char *key, const char *value, static int set_config_namespace_clone(const char *key, const char *value, struct lxc_conf *lxc_conf, void *data) { - char *ns, *token; + __do_free char *ns = NULL; + char *token; int cloneflag = 0; if (lxc_config_value_empty(value)) return clr_config_namespace_clone(key, lxc_conf, data); - if (lxc_conf->ns_keep != 0) { - errno = EINVAL; - SYSERROR("Cannot set both \"lxc.namespace.clone\" and " - "\"lxc.namespace.keep\""); - return -EINVAL; - } + if (lxc_conf->ns_keep != 0) + return log_error_errno(-EINVAL, EINVAL, "Cannot set both \"lxc.namespace.clone\" and \"lxc.namespace.keep\""); ns = strdup(value); if (!ns) - return -1; + return ret_errno(ENOMEM); lxc_iterate_parts(token, ns, " \t") { token += lxc_char_left_gc(token, strlen(token)); token[lxc_char_right_gc(token, strlen(token))] = '\0'; cloneflag = lxc_namespace_2_cloneflag(token); - if (cloneflag < 0) { - free(ns); - return -EINVAL; - } + if (cloneflag < 0) + return ret_errno(EINVAL); lxc_conf->ns_clone |= cloneflag; } - free(ns); return 0; } @@ -2763,34 +2671,28 @@ static int set_config_namespace_clone(const char *key, const char *value, static int set_config_namespace_keep(const char *key, const char *value, struct lxc_conf *lxc_conf, void *data) { - char *ns, *token; + __do_free char *ns = NULL; + char *token; int cloneflag = 0; if (lxc_config_value_empty(value)) return clr_config_namespace_keep(key, lxc_conf, data); - if (lxc_conf->ns_clone != 0) { - errno = EINVAL; - SYSERROR("Cannot set both \"lxc.namespace.clone\" and " - "\"lxc.namespace.keep\""); - return -EINVAL; - } + if (lxc_conf->ns_clone != 0) + return log_error_errno(-EINVAL, EINVAL, "Cannot set both \"lxc.namespace.clone\" and \"lxc.namespace.keep\""); ns = strdup(value); if (!ns) - return -1; + return ret_errno(ENOMEM); lxc_iterate_parts(token, ns, " \t") { token += lxc_char_left_gc(token, strlen(token)); token[lxc_char_right_gc(token, strlen(token))] = '\0'; cloneflag = lxc_namespace_2_cloneflag(token); - if (cloneflag < 0) { - free(ns); - return -EINVAL; - } + if (cloneflag < 0) + return ret_errno(EINVAL); lxc_conf->ns_keep |= cloneflag; } - free(ns); return 0; } @@ -2813,18 +2715,18 @@ static int set_config_time_offset_boot(const char *key, const char *value, unit = lxc_trim_whitespace_in_place(buf); if (strcmp(unit, "h") == 0) { if (!multiply_overflow(offset, 3600, &lxc_conf->timens.s_boot)) - return -EOVERFLOW; + return ret_errno(EOVERFLOW); } else if (strcmp(unit, "m") == 0) { if (!multiply_overflow(offset, 60, &lxc_conf->timens.s_boot)) - return -EOVERFLOW; + return ret_errno(EOVERFLOW); } else if (strcmp(unit, "s") == 0) { lxc_conf->timens.s_boot = offset; } else if (strcmp(unit, "ms") == 0) { if (!multiply_overflow(offset, 1000000, &lxc_conf->timens.ns_boot)) - return -EOVERFLOW; + return ret_errno(EOVERFLOW); } else if (strcmp(unit, "us") == 0) { if (!multiply_overflow(offset, 1000, &lxc_conf->timens.ns_boot)) - return -EOVERFLOW; + return ret_errno(EOVERFLOW); } else if (strcmp(unit, "ns") == 0) { lxc_conf->timens.ns_boot = offset; } else { @@ -2852,18 +2754,18 @@ static int set_config_time_offset_monotonic(const char *key, const char *value, unit = lxc_trim_whitespace_in_place(buf); if (strcmp(unit, "h") == 0) { if (!multiply_overflow(offset, 3600, &lxc_conf->timens.s_monotonic)) - return -EOVERFLOW; + return ret_errno(EOVERFLOW); } else if (strcmp(unit, "m") == 0) { if (!multiply_overflow(offset, 60, &lxc_conf->timens.s_monotonic)) - return -EOVERFLOW; + return ret_errno(EOVERFLOW); } else if (strcmp(unit, "s") == 0) { lxc_conf->timens.s_monotonic = offset; } else if (strcmp(unit, "ms") == 0) { if (!multiply_overflow(offset, 1000000, &lxc_conf->timens.ns_monotonic)) - return -EOVERFLOW; + return ret_errno(EOVERFLOW); } else if (strcmp(unit, "us") == 0) { if (!multiply_overflow(offset, 1000, &lxc_conf->timens.ns_monotonic)) - return -EOVERFLOW; + return ret_errno(EOVERFLOW); } else if (strcmp(unit, "ns") == 0) { lxc_conf->timens.ns_monotonic = offset; } else { @@ -2897,10 +2799,11 @@ struct parse_line_conf { static int parse_line(char *buffer, void *data) { - char *dot, *key, *line, *linep, *value; + __do_free char *linep = NULL; + char *dot, *key, *line, *value; bool empty_line; struct lxc_config_t *config; - int ret = 0; + int ret; char *dup = buffer; struct parse_line_conf *plc = data; @@ -2915,34 +2818,30 @@ static int parse_line(char *buffer, void *data) */ linep = line = strdup(dup); if (!line) - return -1; + return ret_errno(ENOMEM); if (!plc->from_include) { ret = append_unexp_config_line(line, plc->conf); if (ret < 0) - goto on_error; + return ret; } if (empty_line) - goto on_error; + return 0; line += lxc_char_left_gc(line, strlen(line)); /* ignore comments */ if (line[0] == '#') - goto on_error; + return 0; /* martian option - don't add it to the config itself */ if (strncmp(line, "lxc.", 4)) - goto on_error; - - ret = -1; + return 0; dot = strchr(line, '='); - if (!dot) { - ERROR("Invalid configuration line: %s", line); - goto on_error; - } + if (!dot) + return log_error_errno(-EINVAL, EINVAL, "Invalid configuration line: %s", line); *dot = '\0'; value = dot + 1; @@ -2964,25 +2863,18 @@ static int parse_line(char *buffer, void *data) } config = lxc_get_config(key); - if (!config) { - ERROR("Unknown configuration key \"%s\"", key); - goto on_error; - } - - ret = config->set(key, value, plc->conf, NULL); + if (!config) + return log_error_errno(-EINVAL, EINVAL, "Unknown configuration key \"%s\"", key); -on_error: - free(linep); - - return ret; + return config->set(key, value, plc->conf, NULL); } static struct new_config_item *parse_new_conf_line(char *buffer) { - char *dot, *key, *line, *linep, *value; - int ret = 0; + __do_free char *k = NULL, *linep = NULL, *v = NULL; + __do_free struct new_config_item *new = NULL; char *dup = buffer; - struct new_config_item *new = NULL; + char *dot, *key, *line, *value; linep = line = strdup(dup); if (!line) @@ -2992,14 +2884,11 @@ static struct new_config_item *parse_new_conf_line(char *buffer) /* martian option - don't add it to the config itself */ if (strncmp(line, "lxc.", 4)) - goto on_error; + return 0; - ret = -1; dot = strchr(line, '='); - if (!dot) { - ERROR("Invalid configuration item: %s", line); - goto on_error; - } + if (!dot) + return log_error_errno(NULL, EINVAL, "Invalid configuration line: %s", line); *dot = '\0'; value = dot + 1; @@ -3020,29 +2909,21 @@ static struct new_config_item *parse_new_conf_line(char *buffer) } } - ret = -1; new = malloc(sizeof(struct new_config_item)); if (!new) - goto on_error; - - new->key = strdup(key); - new->val = strdup(value); - if (!new->val || !new->key) - goto on_error; - - ret = 0; + return NULL; -on_error: - free(linep); + k = strdup(key); + if (!k) + return NULL; - if (ret < 0 && new) { - free(new->key); - free(new->val); - free(new); - new = NULL; - } + v = strdup(value); + if (!v) + return NULL; - return new; + new->key = move_ptr(k); + new->val = move_ptr(v); + return move_ptr(new); } int lxc_config_read(const char *file, struct lxc_conf *conf, bool from_include) @@ -3061,19 +2942,17 @@ int lxc_config_read(const char *file, struct lxc_conf *conf, bool from_include) int lxc_config_define_add(struct lxc_list *defines, char *arg) { - struct lxc_list *dent; + __do_free struct lxc_list *dent = NULL; dent = malloc(sizeof(struct lxc_list)); if (!dent) - return -1; + return ret_errno(ENOMEM); dent->elem = parse_new_conf_line(arg); - if (!dent->elem) { - free(dent); - return -1; - } + if (!dent->elem) + return ret_errno(ENOMEM); - lxc_list_add_tail(defines, dent); + lxc_list_add_tail(defines, move_ptr(dent)); return 0; } @@ -3111,41 +2990,40 @@ void lxc_config_define_free(struct lxc_list *defines) signed long lxc_config_parse_arch(const char *arch) { #if HAVE_SYS_PERSONALITY_H - size_t i; struct per_name { char *name; unsigned long per; } pername[] = { - { "arm", PER_LINUX32 }, - { "armel", PER_LINUX32 }, - { "armhf", PER_LINUX32 }, - { "armv7l", PER_LINUX32 }, - { "athlon", PER_LINUX32 }, - { "i386", PER_LINUX32 }, - { "i486", PER_LINUX32 }, - { "i586", PER_LINUX32 }, - { "i686", PER_LINUX32 }, - { "linux32", PER_LINUX32 }, - { "mips", PER_LINUX32 }, - { "mipsel", PER_LINUX32 }, - { "ppc", PER_LINUX32 }, - { "powerpc", PER_LINUX32 }, - { "x86", PER_LINUX32 }, - { "amd64", PER_LINUX }, - { "arm64", PER_LINUX }, - { "linux64", PER_LINUX }, - { "mips64", PER_LINUX }, - { "mips64el", PER_LINUX }, - { "ppc64", PER_LINUX }, - { "ppc64el", PER_LINUX }, - { "ppc64le", PER_LINUX }, - { "powerpc64", PER_LINUX }, - { "s390x", PER_LINUX }, - { "x86_64", PER_LINUX }, + { "arm", PER_LINUX32 }, + { "armel", PER_LINUX32 }, + { "armhf", PER_LINUX32 }, + { "armv7l", PER_LINUX32 }, + { "athlon", PER_LINUX32 }, + { "i386", PER_LINUX32 }, + { "i486", PER_LINUX32 }, + { "i586", PER_LINUX32 }, + { "i686", PER_LINUX32 }, + { "linux32", PER_LINUX32 }, + { "mips", PER_LINUX32 }, + { "mipsel", PER_LINUX32 }, + { "ppc", PER_LINUX32 }, + { "powerpc", PER_LINUX32 }, + { "x86", PER_LINUX32 }, + { "amd64", PER_LINUX }, + { "arm64", PER_LINUX }, + { "linux64", PER_LINUX }, + { "mips64", PER_LINUX }, + { "mips64el", PER_LINUX }, + { "ppc64", PER_LINUX }, + { "ppc64el", PER_LINUX }, + { "ppc64le", PER_LINUX }, + { "powerpc64", PER_LINUX }, + { "s390x", PER_LINUX }, + { "x86_64", PER_LINUX }, }; size_t len = sizeof(pername) / sizeof(pername[0]); - for (i = 0; i < len; i++) + for (int i = 0; i < len; i++) if (!strcmp(pername[i].name, arch)) return pername[i].per; #endif @@ -3185,7 +3063,7 @@ int lxc_fill_elevated_privileges(char *flaglist, int *flags) aflag = all_privs[i].flag; if (aflag < 0) - return -1; + return ret_errno(EINVAL); *flags |= aflag; } @@ -3203,10 +3081,8 @@ int write_config(int fd, const struct lxc_conf *conf) return 0; ret = lxc_write_nointr(fd, conf->unexpanded_config, len); - if (ret < 0) { - SYSERROR("Failed to write configuration file"); - return -1; - } + if (ret < 0) + return log_error_errno(-errno, errno, "Failed to write configuration file"); return 0; } @@ -3281,13 +3157,12 @@ bool clone_update_unexp_ovl_paths(struct lxc_conf *conf, const char *oldpath, const char *newpath, const char *oldname, const char *newname, const char *ovldir) { - __do_free char *newdir = NULL, - *olddir = NULL; + __do_free char *newdir = NULL, *olddir = NULL; + char *lstart = conf->unexpanded_config; + const char *key = "lxc.mount.entry"; int ret; char *lend, *p, *q; size_t newdirlen, olddirlen; - char *lstart = conf->unexpanded_config; - const char *key = "lxc.mount.entry"; olddirlen = strlen(ovldir) + strlen(oldpath) + strlen(oldname) + 2; olddir = must_realloc(NULL, olddirlen + 1); @@ -3391,13 +3266,12 @@ bool clone_update_unexp_hooks(struct lxc_conf *conf, const char *oldpath, const char *newpath, const char *oldname, const char *newname) { - __do_free char *newdir = NULL, - *olddir = NULL; + __do_free char *newdir = NULL, *olddir = NULL; + char *lstart = conf->unexpanded_config; + const char *key = "lxc.hook"; int ret; char *lend, *p; - char *lstart = conf->unexpanded_config; size_t newdirlen, olddirlen; - const char *key = "lxc.hook"; olddirlen = strlen(oldpath) + strlen(oldname) + 1; olddir = must_realloc(NULL, olddirlen + 1); @@ -3566,16 +3440,19 @@ bool network_new_hwaddrs(struct lxc_conf *conf) static int set_config_ephemeral(const char *key, const char *value, struct lxc_conf *lxc_conf, void *data) { + int ret; + if (lxc_config_value_empty(value)) { lxc_conf->ephemeral = 0; return 0; } - if (lxc_safe_uint(value, &lxc_conf->ephemeral) < 0) - return -1; + ret = lxc_safe_uint(value, &lxc_conf->ephemeral); + if (ret < 0) + return ret; if (lxc_conf->ephemeral > 1) - return -1; + return ret_errno(EINVAL); return 0; } @@ -3585,17 +3462,15 @@ static int set_config_log_syslog(const char *key, const char *value, { int facility; - if (lxc_conf->syslog) { - free(lxc_conf->syslog); - lxc_conf->syslog = NULL; - } + if (lxc_conf->syslog) + free_disarm(lxc_conf->syslog); if (lxc_config_value_empty(value)) return 0; facility = lxc_syslog_priority_to_int(value); if (facility == -EINVAL) - return -1; + return ret_errno(EINVAL); lxc_log_syslog(facility); @@ -3605,6 +3480,7 @@ static int set_config_log_syslog(const char *key, const char *value, static int set_config_no_new_privs(const char *key, const char *value, struct lxc_conf *lxc_conf, void *data) { + int ret; unsigned int v; if (lxc_config_value_empty(value)) { @@ -3612,11 +3488,12 @@ static int set_config_no_new_privs(const char *key, const char *value, return 0; } - if (lxc_safe_uint(value, &v) < 0) - return -1; + ret = lxc_safe_uint(value, &v); + if (ret < 0) + return ret; if (v > 1) - return -1; + return ret_errno(EINVAL); lxc_conf->no_new_privs = v ? true : false; @@ -3764,7 +3641,7 @@ static int __get_config_cgroup_controller(const char *key, char *retv, namespaced_token = "lxc.cgroup."; namespaced_token_len = STRLITERALLEN("lxc.cgroup."); } else { - return -1; + return ret_errno(EINVAL); } if (strcmp(key, global_token) == 0) @@ -3772,7 +3649,7 @@ static int __get_config_cgroup_controller(const char *key, char *retv, else if (strncmp(key, namespaced_token, namespaced_token_len) == 0) key += namespaced_token_len; else - return -1; + return ret_errno(EINVAL); lxc_list_for_each(it, &c->cgroup) { struct lxc_cgroup *cg = it->elem; @@ -3938,7 +3815,7 @@ static int get_config_idmaps(const char *key, char *retv, int inlen, (map->idtype == ID_TYPE_UID) ? 'u' : 'g', map->nsid, map->hostid, map->range); if (ret < 0 || ret >= __LXC_IDMAP_STR_BUF) - return -1; + return ret_errno(EIO); strprint(retv, inlen, "%s%s", buf, (listlen-- > 1) ? "\n" : ""); } @@ -4102,14 +3979,14 @@ static int get_config_hooks(const char *key, char *retv, int inlen, subkey = strchr(key, '.'); if (!subkey) - return -1; + return ret_errno(EINVAL); subkey = strchr(subkey + 1, '.'); if (!subkey) - return -1; + return ret_errno(EINVAL); subkey++; if (*subkey == '\0') - return -1; + return ret_errno(EINVAL); for (i = 0; i < NUM_LXC_HOOKS; i++) { if (strcmp(lxchook_names[i], subkey) == 0) { @@ -4119,7 +3996,7 @@ static int get_config_hooks(const char *key, char *retv, int inlen, } if (found == -1) - return -1; + return ret_errno(EINVAL); if (!retv) inlen = 0; @@ -4234,8 +4111,7 @@ static int get_config_seccomp_allow_nesting(const char *key, char *retv, #ifdef HAVE_SECCOMP return lxc_get_conf_int(c, retv, inlen, c->seccomp.allow_nesting); #else - errno = ENOSYS; - return -1; + return ret_errno(ENOSYS); #endif } @@ -4245,7 +4121,7 @@ static int get_config_seccomp_notify_cookie(const char *key, char *retv, int inl #ifdef HAVE_SECCOMP_NOTIFY return lxc_get_conf_str(retv, inlen, c->seccomp.notifier.cookie); #else - return ret_set_errno(-1, ENOSYS); + return ret_errno(ENOSYS); #endif } @@ -4258,7 +4134,7 @@ static int get_config_seccomp_notify_proxy(const char *key, char *retv, int inle ? &c->seccomp.notifier.proxy_addr.sun_path[0] : &c->seccomp.notifier.proxy_addr.sun_path[1]); #else - return ret_set_errno(-1, ENOSYS); + return ret_errno(ENOSYS); #endif } @@ -4429,7 +4305,7 @@ static int get_config_prlimit(const char *key, char *retv, int inlen, else if (strncmp(key, "lxc.prlimit.", 12) == 0) key += 12; else - return -1; + return ret_errno(EINVAL); lxc_list_for_each(it, &c->limits) { /* 2 colon separated 64 bit integers or the word 'unlimited' */ @@ -4487,7 +4363,7 @@ static int get_config_sysctl(const char *key, char *retv, int inlen, else if (strncmp(key, "lxc.sysctl.", STRLITERALLEN("lxc.sysctl.")) == 0) key += STRLITERALLEN("lxc.sysctl."); else - return -1; + return ret_errno(EINVAL); lxc_list_for_each(it, &c->sysctls) { struct lxc_sysctl *elem = it->elem; @@ -4520,7 +4396,7 @@ static int get_config_proc(const char *key, char *retv, int inlen, else if (strncmp(key, "lxc.proc.", STRLITERALLEN("lxc.proc.")) == 0) key += STRLITERALLEN("lxc.proc."); else - return -1; + return ret_errno(EINVAL); lxc_list_for_each(it, &c->procs) { struct lxc_proc *proc = it->elem; @@ -4661,16 +4537,14 @@ static inline int clr_config_tty_max(const char *key, struct lxc_conf *c, static inline int clr_config_tty_dir(const char *key, struct lxc_conf *c, void *data) { - free(c->ttys.dir); - c->ttys.dir = NULL; + free_disarm(c->ttys.dir); return 0; } static inline int clr_config_apparmor_profile(const char *key, struct lxc_conf *c, void *data) { - free(c->lsm_aa_profile); - c->lsm_aa_profile = NULL; + free_disarm(c->lsm_aa_profile); return 0; } @@ -4700,16 +4574,14 @@ static inline int clr_config_apparmor_raw(const char *key, static inline int clr_config_selinux_context(const char *key, struct lxc_conf *c, void *data) { - free(c->lsm_se_context); - c->lsm_se_context = NULL; + free_disarm(c->lsm_se_context); return 0; } static inline int clr_config_selinux_context_keyring(const char *key, struct lxc_conf *c, void *data) { - free(c->lsm_se_keyring_context); - c->lsm_se_keyring_context = NULL; + free_disarm(c->lsm_se_keyring_context); return 0; } @@ -4735,10 +4607,8 @@ static inline int clr_config_cgroup2_controller(const char *key, static int clr_config_cgroup_dir(const char *key, struct lxc_conf *lxc_conf, void *data) { - if (lxc_conf->cgroup_meta.dir) { - free(lxc_conf->cgroup_meta.dir); - lxc_conf->cgroup_meta.dir = NULL; - } + if (lxc_conf->cgroup_meta.dir) + free_disarm(lxc_conf->cgroup_meta.dir); return 0; } @@ -4799,8 +4669,7 @@ static inline int clr_config_log_level(const char *key, struct lxc_conf *c, static inline int clr_config_log_file(const char *key, struct lxc_conf *c, void *data) { - free(c->logfile); - c->logfile = NULL; + free_disarm(c->logfile); return 0; } @@ -4819,16 +4688,14 @@ static inline int clr_config_mount_auto(const char *key, struct lxc_conf *c, static inline int clr_config_mount_fstab(const char *key, struct lxc_conf *c, void *data) { - free(c->fstab); - c->fstab = NULL; + free_disarm(c->fstab); return 0; } static inline int clr_config_rootfs_path(const char *key, struct lxc_conf *c, void *data) { - free(c->rootfs.path); - c->rootfs.path = NULL; + free_disarm(c->rootfs.path); return 0; } @@ -4842,19 +4709,15 @@ static inline int clr_config_rootfs_managed(const char *key, struct lxc_conf *c, static inline int clr_config_rootfs_mount(const char *key, struct lxc_conf *c, void *data) { - free(c->rootfs.mount); - c->rootfs.mount = NULL; + free_disarm(c->rootfs.mount); return 0; } static inline int clr_config_rootfs_options(const char *key, struct lxc_conf *c, void *data) { - free(c->rootfs.options); - c->rootfs.options = NULL; - - free(c->rootfs.data); - c->rootfs.data = NULL; + free_disarm(c->rootfs.options); + free_disarm(c->rootfs.data); return 0; } @@ -4862,8 +4725,7 @@ static inline int clr_config_rootfs_options(const char *key, struct lxc_conf *c, static inline int clr_config_uts_name(const char *key, struct lxc_conf *c, void *data) { - free(c->utsname); - c->utsname = NULL; + free_disarm(c->utsname); return 0; } @@ -4904,16 +4766,14 @@ static inline int clr_config_cap_keep(const char *key, struct lxc_conf *c, static inline int clr_config_console_path(const char *key, struct lxc_conf *c, void *data) { - free(c->console.path); - c->console.path = NULL; + free_disarm(c->console.path); return 0; } static inline int clr_config_console_logfile(const char *key, struct lxc_conf *c, void *data) { - free(c->console.log_path); - c->console.log_path = NULL; + free_disarm(c->console.log_path); return 0; } @@ -4945,8 +4805,7 @@ static inline int clr_config_seccomp_allow_nesting(const char *key, c->seccomp.allow_nesting = 0; return 0; #else - errno = ENOSYS; - return -1; + return ret_errno(ENOSYS); #endif } @@ -4954,11 +4813,10 @@ static inline int clr_config_seccomp_notify_cookie(const char *key, struct lxc_conf *c, void *data) { #ifdef HAVE_SECCOMP_NOTIFY - free(c->seccomp.notifier.cookie); - c->seccomp.notifier.cookie = NULL; + free_disarm(c->seccomp.notifier.cookie); return 0; #else - return ret_set_errno(-1, ENOSYS); + return ret_errno(ENOSYS); #endif } @@ -4970,15 +4828,14 @@ static inline int clr_config_seccomp_notify_proxy(const char *key, sizeof(c->seccomp.notifier.proxy_addr)); return 0; #else - return ret_set_errno(-1, ENOSYS); + return ret_errno(ENOSYS); #endif } static inline int clr_config_seccomp_profile(const char *key, struct lxc_conf *c, void *data) { - free(c->seccomp.seccomp); - c->seccomp.seccomp = NULL; + free_disarm(c->seccomp.seccomp); return 0; } @@ -5033,8 +4890,7 @@ static inline int clr_config_start(const char *key, struct lxc_conf *c, static inline int clr_config_log_syslog(const char *key, struct lxc_conf *c, void *data) { - free(c->syslog); - c->syslog = NULL; + free_disarm(c->syslog); return 0; } @@ -5067,24 +4923,21 @@ static inline int clr_config_environment(const char *key, struct lxc_conf *c, static inline int clr_config_execute_cmd(const char *key, struct lxc_conf *c, void *data) { - free(c->execute_cmd); - c->execute_cmd = NULL; + free_disarm(c->execute_cmd); return 0; } static inline int clr_config_init_cmd(const char *key, struct lxc_conf *c, void *data) { - free(c->init_cmd); - c->init_cmd = NULL; + free_disarm(c->init_cmd); return 0; } static inline int clr_config_init_cwd(const char *key, struct lxc_conf *c, void *data) { - free(c->init_cwd); - c->init_cwd = NULL; + free_disarm(c->init_cwd); return 0; } @@ -5189,7 +5042,7 @@ static int clr_config_namespace_share(const char *key, static int get_config_includefiles(const char *key, char *retv, int inlen, struct lxc_conf *c, void *data) { - return -ENOSYS; + return ret_errno(ENOSYS); } static struct lxc_config_t *get_network_config_ops(const char *key, @@ -5197,29 +5050,24 @@ static struct lxc_config_t *get_network_config_ops(const char *key, ssize_t *idx, char **deindexed_key) { + __do_free char *copy = NULL; + struct lxc_config_t *config = NULL; int ret; unsigned int tmpidx; size_t numstrlen; - char *copy, *idx_start, *idx_end; - struct lxc_config_t *config = NULL; + char *idx_start, *idx_end; /* check that this is a sensible network key */ - if (strncmp("lxc.net.", key, 8)) { - ERROR("Invalid network configuration key \"%s\"", key); - return NULL; - } + if (strncmp("lxc.net.", key, 8)) + return log_error_errno(NULL, EINVAL, "Invalid network configuration key \"%s\"", key); copy = strdup(key); - if (!copy) { - ERROR("Failed to duplicate string \"%s\"", key); - return NULL; - } + if (!copy) + return log_error_errno(NULL, ENOMEM, "Failed to duplicate string \"%s\"", key); /* lxc.net. */ - if (!isdigit(*(key + 8))) { - ERROR("Failed to detect digit in string \"%s\"", key + 8); - goto on_error; - } + if (!isdigit(*(key + 8))) + return log_error_errno(NULL, EINVAL, "Failed to detect digit in string \"%s\"", key + 8); /* beginning of index string */ idx_start = (copy + 7); @@ -5233,22 +5081,16 @@ static struct lxc_config_t *get_network_config_ops(const char *key, /* parse current index */ ret = lxc_safe_uint((idx_start + 1), &tmpidx); if (ret < 0) { - errno = -ret; - SYSERROR("Failed to parse unsigned integer from string \"%s\"", - idx_start + 1); *idx = ret; - goto on_error; + return log_error_errno(NULL, -ret, "Failed to parse unsigned integer from string \"%s\"", idx_start + 1); } /* This, of course is utterly nonsensical on so many levels, but * better safe than sorry. * (Checking for INT_MAX here is intentional.) */ - if (tmpidx == INT_MAX) { - SYSERROR("Number of configured networks would overflow the " - "counter"); - goto on_error; - } + if (tmpidx == INT_MAX) + return log_error_errno(NULL, ERANGE, "Number of configured networks would overflow the counter"); *idx = tmpidx; numstrlen = strlen((idx_start + 1)); @@ -5259,29 +5101,21 @@ static struct lxc_config_t *get_network_config_ops(const char *key, /* lxc.net.. */ if (idx_end) { *idx_end = '.'; - if (strlen(idx_end + 1) == 0) { - ERROR("No subkey in network configuration key \"%s\"", key); - goto on_error; - } + if (strlen(idx_end + 1) == 0) + return log_error_errno(NULL, EINVAL, "No subkey in network configuration key \"%s\"", key); memmove(copy + 8, idx_end + 1, strlen(idx_end + 1)); copy[strlen(key) - (numstrlen + 1)] = '\0'; config = lxc_get_config(copy); - if (!config) { - ERROR("Unknown network configuration key \"%s\"", key); - goto on_error; - } + if (!config) + return log_error_errno(NULL, ENOENT, "Unknown network configuration key \"%s\"", key); } if (deindexed_key) - *deindexed_key = copy; + *deindexed_key = move_ptr(copy); return config; - -on_error: - free(copy); - return NULL; } /* Config entry is something like "lxc.net.0.ipv4" the key 'lxc.net.' was @@ -5291,49 +5125,43 @@ static struct lxc_config_t *get_network_config_ops(const char *key, static int set_config_net_nic(const char *key, const char *value, struct lxc_conf *lxc_conf, void *data) { - int ret; + __do_free char *deindexed_key = NULL; + ssize_t idx = -1; const char *idxstring; struct lxc_config_t *config; struct lxc_netdev *netdev; - ssize_t idx = -1; - char *deindexed_key = NULL; idxstring = key + 8; if (!isdigit(*idxstring)) - return -1; + return ret_errno(EINVAL); if (lxc_config_value_empty(value)) return clr_config_net_nic(key, lxc_conf, data); config = get_network_config_ops(key, lxc_conf, &idx, &deindexed_key); if (!config || idx < 0) - return -1; + return -errno; netdev = lxc_get_netdev_by_idx(lxc_conf, (unsigned int)idx, true); - if (!netdev) { - free(deindexed_key); - return -1; - } - - ret = config->set(deindexed_key, value, lxc_conf, netdev); - free(deindexed_key); + if (!netdev) + return ret_errno(EINVAL); - return ret; + return config->set(deindexed_key, value, lxc_conf, netdev); } static int clr_config_net_nic(const char *key, struct lxc_conf *lxc_conf, void *data) { + __do_free char *deindexed_key = NULL; + ssize_t idx = -1; int ret; const char *idxstring; struct lxc_config_t *config; struct lxc_netdev *netdev; - ssize_t idx = -1; - char *deindexed_key = NULL; idxstring = key + 8; if (!isdigit(*idxstring)) - return -1; + return ret_errno(EINVAL); /* The left conjunct is pretty self-explanatory. The right conjunct * checks whether the two pointers are equal. If they are we know that @@ -5343,8 +5171,9 @@ static int clr_config_net_nic(const char *key, struct lxc_conf *lxc_conf, if (isdigit(*idxstring) && (strrchr(key, '.') == (idxstring - 1))) { unsigned int rmnetdevidx; - if (lxc_safe_uint(idxstring, &rmnetdevidx) < 0) - return -1; + ret = lxc_safe_uint(idxstring, &rmnetdevidx); + if (ret < 0) + return ret; /* Remove network from network list. */ lxc_remove_nic_by_idx(lxc_conf, rmnetdevidx); @@ -5353,18 +5182,13 @@ static int clr_config_net_nic(const char *key, struct lxc_conf *lxc_conf, config = get_network_config_ops(key, lxc_conf, &idx, &deindexed_key); if (!config || idx < 0) - return -1; + return -errno; netdev = lxc_get_netdev_by_idx(lxc_conf, (unsigned int)idx, false); - if (!netdev) { - free(deindexed_key); - return -1; - } - - ret = config->clr(deindexed_key, lxc_conf, netdev); - free(deindexed_key); + if (!netdev) + return ret_errno(EINVAL); - return ret; + return config->clr(deindexed_key, lxc_conf, netdev); } static int clr_config_net_type(const char *key, struct lxc_conf *lxc_conf, @@ -5373,7 +5197,7 @@ static int clr_config_net_type(const char *key, struct lxc_conf *lxc_conf, struct lxc_netdev *netdev = data; if (!netdev) - return -1; + return ret_errno(EINVAL); netdev->type = -1; @@ -5386,7 +5210,7 @@ static int clr_config_net_name(const char *key, struct lxc_conf *lxc_conf, struct lxc_netdev *netdev = data; if (!netdev) - return -1; + return ret_errno(EINVAL); netdev->name[0] = '\0'; @@ -5399,7 +5223,7 @@ static int clr_config_net_flags(const char *key, struct lxc_conf *lxc_conf, struct lxc_netdev *netdev = data; if (!netdev) - return -1; + return ret_errno(EINVAL); netdev->flags = 0; @@ -5412,7 +5236,7 @@ static int clr_config_net_link(const char *key, struct lxc_conf *lxc_conf, struct lxc_netdev *netdev = data; if (!netdev) - return -1; + return ret_errno(EINVAL); netdev->link[0] = '\0'; @@ -5425,7 +5249,7 @@ static int clr_config_net_l2proxy(const char *key, struct lxc_conf *lxc_conf, struct lxc_netdev *netdev = data; if (!netdev) - return ret_set_errno(-1, EINVAL); + return ret_errno(EINVAL); netdev->l2proxy = false; @@ -5438,7 +5262,7 @@ static int clr_config_net_macvlan_mode(const char *key, struct lxc_netdev *netdev = data; if (!netdev) - return -1; + return ret_errno(EINVAL); if (netdev->type != LXC_NET_MACVLAN) return 0; @@ -5454,7 +5278,7 @@ static int clr_config_net_ipvlan_mode(const char *key, struct lxc_netdev *netdev = data; if (!netdev) - return ret_set_errno(-1, EINVAL); + return ret_errno(EINVAL); if (netdev->type != LXC_NET_IPVLAN) return 0; @@ -5470,7 +5294,7 @@ static int clr_config_net_ipvlan_isolation(const char *key, struct lxc_netdev *netdev = data; if (!netdev) - return ret_set_errno(-1, EINVAL); + return ret_errno(EINVAL); if (netdev->type != LXC_NET_IPVLAN) return 0; @@ -5486,7 +5310,7 @@ static int clr_config_net_veth_mode(const char *key, struct lxc_netdev *netdev = data; if (!netdev) - return ret_set_errno(-1, EINVAL); + return ret_errno(EINVAL); if (netdev->type != LXC_NET_VETH) return 0; @@ -5502,7 +5326,7 @@ static int clr_config_net_veth_pair(const char *key, struct lxc_conf *lxc_conf, struct lxc_netdev *netdev = data; if (!netdev) - return -1; + return ret_errno(EINVAL); netdev->priv.veth_attr.pair[0] = '\0'; @@ -5547,10 +5371,9 @@ static int clr_config_net_script_up(const char *key, struct lxc_conf *lxc_conf, struct lxc_netdev *netdev = data; if (!netdev) - return -1; + return ret_errno(EINVAL); - free(netdev->upscript); - netdev->upscript = NULL; + free_disarm(netdev->upscript); return 0; } @@ -5561,10 +5384,9 @@ static int clr_config_net_script_down(const char *key, struct lxc_netdev *netdev = data; if (!netdev) - return -1; + return ret_errno(EINVAL); - free(netdev->downscript); - netdev->downscript = NULL; + free_disarm(netdev->downscript); return 0; } @@ -5575,10 +5397,9 @@ static int clr_config_net_hwaddr(const char *key, struct lxc_conf *lxc_conf, struct lxc_netdev *netdev = data; if (!netdev) - return -1; + return ret_errno(EINVAL); - free(netdev->hwaddr); - netdev->hwaddr = NULL; + free_disarm(netdev->hwaddr); return 0; } @@ -5589,10 +5410,9 @@ static int clr_config_net_mtu(const char *key, struct lxc_conf *lxc_conf, struct lxc_netdev *netdev = data; if (!netdev) - return -1; + return ret_errno(EINVAL); - free(netdev->mtu); - netdev->mtu = NULL; + free_disarm(netdev->mtu); return 0; } @@ -5603,7 +5423,7 @@ static int clr_config_net_vlan_id(const char *key, struct lxc_conf *lxc_conf, struct lxc_netdev *netdev = data; if (!netdev) - return -1; + return ret_errno(EINVAL); netdev->priv.vlan_attr.vid = 0; @@ -5616,10 +5436,9 @@ static int clr_config_net_ipv4_gateway(const char *key, struct lxc_netdev *netdev = data; if (!netdev) - return -1; + return ret_errno(EINVAL); - free(netdev->ipv4_gateway); - netdev->ipv4_gateway = NULL; + free_disarm(netdev->ipv4_gateway); return 0; } @@ -5631,7 +5450,7 @@ static int clr_config_net_ipv4_address(const char *key, struct lxc_list *cur, *next; if (!netdev) - return -1; + return ret_errno(EINVAL); lxc_list_for_each_safe(cur, &netdev->ipv4, next) { lxc_list_del(cur); @@ -5643,13 +5462,13 @@ static int clr_config_net_ipv4_address(const char *key, } static int clr_config_net_veth_ipv4_route(const char *key, - struct lxc_conf *lxc_conf, void *data) + struct lxc_conf *lxc_conf, void *data) { struct lxc_netdev *netdev = data; struct lxc_list *cur, *next; if (!netdev) - return -1; + return ret_errno(EINVAL); lxc_list_for_each_safe(cur, &netdev->priv.veth_attr.ipv4_routes, next) { lxc_list_del(cur); @@ -5666,10 +5485,9 @@ static int clr_config_net_ipv6_gateway(const char *key, struct lxc_netdev *netdev = data; if (!netdev) - return -1; + return ret_errno(EINVAL); - free(netdev->ipv6_gateway); - netdev->ipv6_gateway = NULL; + free_disarm(netdev->ipv6_gateway); return 0; } @@ -5681,7 +5499,7 @@ static int clr_config_net_ipv6_address(const char *key, struct lxc_list *cur, *next; if (!netdev) - return -1; + return ret_errno(EINVAL); lxc_list_for_each_safe(cur, &netdev->ipv6, next) { lxc_list_del(cur); @@ -5693,13 +5511,13 @@ static int clr_config_net_ipv6_address(const char *key, } static int clr_config_net_veth_ipv6_route(const char *key, - struct lxc_conf *lxc_conf, void *data) + struct lxc_conf *lxc_conf, void *data) { struct lxc_netdev *netdev = data; struct lxc_list *cur, *next; if (!netdev) - return -1; + return ret_errno(EINVAL); lxc_list_for_each_safe(cur, &netdev->priv.veth_attr.ipv6_routes, next) { lxc_list_del(cur); @@ -5713,31 +5531,25 @@ static int clr_config_net_veth_ipv6_route(const char *key, static int get_config_net_nic(const char *key, char *retv, int inlen, struct lxc_conf *c, void *data) { - int ret; + __do_free char *deindexed_key = NULL; + ssize_t idx = -1; const char *idxstring; struct lxc_config_t *config; struct lxc_netdev *netdev; - ssize_t idx = -1; - char *deindexed_key = NULL; idxstring = key + 8; if (!isdigit(*idxstring)) - return -1; + return ret_errno(EINVAL); config = get_network_config_ops(key, c, &idx, &deindexed_key); if (!config || idx < 0) - return -1; + return -errno; netdev = lxc_get_netdev_by_idx(c, (unsigned int)idx, false); - if (!netdev) { - free(deindexed_key); - return -1; - } - - ret = config->get(deindexed_key, retv, inlen, c, netdev); - free(deindexed_key); + if (!netdev) + return ret_errno(EINVAL); - return ret; + return config->get(deindexed_key, retv, inlen, c, netdev); } static int get_config_net_type(const char *key, char *retv, int inlen, @@ -5753,7 +5565,7 @@ static int get_config_net_type(const char *key, char *retv, int inlen, memset(retv, 0, inlen); if (!netdev) - return -1; + return ret_errno(EINVAL); strprint(retv, inlen, "%s", lxc_net_type_to_str(netdev->type)); @@ -5773,7 +5585,7 @@ static int get_config_net_flags(const char *key, char *retv, int inlen, memset(retv, 0, inlen); if (!netdev) - return -1; + return ret_errno(EINVAL); if (netdev->flags & IFF_UP) strprint(retv, inlen, "up"); @@ -5794,7 +5606,7 @@ static int get_config_net_link(const char *key, char *retv, int inlen, memset(retv, 0, inlen); if (!netdev) - return -1; + return ret_errno(EINVAL); if (netdev->link[0] != '\0') strprint(retv, inlen, "%s", netdev->link); @@ -5803,7 +5615,7 @@ static int get_config_net_link(const char *key, char *retv, int inlen, } static int get_config_net_l2proxy(const char *key, char *retv, int inlen, - struct lxc_conf *c, void *data) + struct lxc_conf *c, void *data) { struct lxc_netdev *netdev = data; return lxc_get_conf_bool(c, retv, inlen, netdev->l2proxy); @@ -5822,7 +5634,7 @@ static int get_config_net_name(const char *key, char *retv, int inlen, memset(retv, 0, inlen); if (!netdev) - return -1; + return ret_errno(EINVAL); if (netdev->name[0] != '\0') strprint(retv, inlen, "%s", netdev->name); @@ -5844,7 +5656,7 @@ static int get_config_net_macvlan_mode(const char *key, char *retv, int inlen, memset(retv, 0, inlen); if (!netdev) - return -1; + return ret_errno(EINVAL); if (netdev->type != LXC_NET_MACVLAN) return 0; @@ -5875,10 +5687,10 @@ static int get_config_net_macvlan_mode(const char *key, char *retv, int inlen, static int get_config_net_ipvlan_mode(const char *key, char *retv, int inlen, struct lxc_conf *c, void *data) { - int len; int fulllen = 0; - const char *mode; struct lxc_netdev *netdev = data; + int len; + const char *mode; if (!retv) inlen = 0; @@ -5886,7 +5698,7 @@ static int get_config_net_ipvlan_mode(const char *key, char *retv, int inlen, memset(retv, 0, inlen); if (!netdev) - return ret_set_errno(-1, EINVAL); + return ret_errno(EINVAL); if (netdev->type != LXC_NET_IPVLAN) return 0; @@ -5914,10 +5726,10 @@ static int get_config_net_ipvlan_mode(const char *key, char *retv, int inlen, static int get_config_net_ipvlan_isolation(const char *key, char *retv, int inlen, struct lxc_conf *c, void *data) { - int len; int fulllen = 0; - const char *mode; struct lxc_netdev *netdev = data; + int len; + const char *mode; if (!retv) inlen = 0; @@ -5925,7 +5737,7 @@ static int get_config_net_ipvlan_isolation(const char *key, char *retv, int inle memset(retv, 0, inlen); if (!netdev) - return ret_set_errno(-1, EINVAL); + return ret_errno(EINVAL); if (netdev->type != LXC_NET_IPVLAN) return 0; @@ -5953,10 +5765,10 @@ static int get_config_net_ipvlan_isolation(const char *key, char *retv, int inle static int get_config_net_veth_mode(const char *key, char *retv, int inlen, struct lxc_conf *c, void *data) { - int len; int fulllen = 0; - const char *mode; struct lxc_netdev *netdev = data; + int len; + const char *mode; if (!retv) inlen = 0; @@ -5964,7 +5776,7 @@ static int get_config_net_veth_mode(const char *key, char *retv, int inlen, memset(retv, 0, inlen); if (!netdev) - return ret_set_errno(-1, EINVAL); + return ret_errno(EINVAL); if (netdev->type != LXC_NET_VETH) return 0; @@ -5999,7 +5811,7 @@ static int get_config_net_veth_pair(const char *key, char *retv, int inlen, memset(retv, 0, inlen); if (!netdev) - return -1; + return ret_errno(EINVAL); if (netdev->type != LXC_NET_VETH) return 0; @@ -6013,7 +5825,7 @@ static int get_config_net_veth_pair(const char *key, char *retv, int inlen, } static int get_config_net_veth_vlan_id(const char *key, char *retv, int inlen, - struct lxc_conf *c, void *data) + struct lxc_conf *c, void *data) { int len; int fulllen = 0; @@ -6079,7 +5891,7 @@ static int get_config_net_script_up(const char *key, char *retv, int inlen, memset(retv, 0, inlen); if (!netdev) - return -1; + return ret_errno(EINVAL); if (netdev->upscript) strprint(retv, inlen, "%s", netdev->upscript); @@ -6100,7 +5912,7 @@ static int get_config_net_script_down(const char *key, char *retv, int inlen, memset(retv, 0, inlen); if (!netdev) - return -1; + return ret_errno(EINVAL); if (netdev->downscript) strprint(retv, inlen, "%s", netdev->downscript); @@ -6121,7 +5933,7 @@ static int get_config_net_hwaddr(const char *key, char *retv, int inlen, memset(retv, 0, inlen); if (!netdev) - return -1; + return ret_errno(EINVAL); if (netdev->hwaddr) strprint(retv, inlen, "%s", netdev->hwaddr); @@ -6142,7 +5954,7 @@ static int get_config_net_mtu(const char *key, char *retv, int inlen, memset(retv, 0, inlen); if (!netdev) - return -1; + return ret_errno(EINVAL); if (netdev->mtu) strprint(retv, inlen, "%s", netdev->mtu); @@ -6163,7 +5975,7 @@ static int get_config_net_vlan_id(const char *key, char *retv, int inlen, memset(retv, 0, inlen); if (!netdev) - return -1; + return ret_errno(EINVAL); if (netdev->type != LXC_NET_VLAN) return 0; @@ -6187,14 +5999,15 @@ static int get_config_net_ipv4_gateway(const char *key, char *retv, int inlen, memset(retv, 0, inlen); if (!netdev) - return -1; + return ret_errno(EINVAL); if (netdev->ipv4_gateway_auto) { strprint(retv, inlen, "auto"); } else if (netdev->ipv4_gateway_dev) { strprint(retv, inlen, "dev"); } else if (netdev->ipv4_gateway) { - inet_ntop(AF_INET, netdev->ipv4_gateway, buf, sizeof(buf)); + if (!inet_ntop(AF_INET, netdev->ipv4_gateway, buf, sizeof(buf))) + return -errno; strprint(retv, inlen, "%s", buf); } @@ -6217,13 +6030,14 @@ static int get_config_net_ipv4_address(const char *key, char *retv, int inlen, memset(retv, 0, inlen); if (!netdev) - return -1; + return ret_errno(EINVAL); listlen = lxc_list_len(&netdev->ipv4); lxc_list_for_each(it, &netdev->ipv4) { struct lxc_inetdev *i = it->elem; - inet_ntop(AF_INET, &i->addr, buf, sizeof(buf)); + if (!inet_ntop(AF_INET, &i->addr, buf, sizeof(buf))) + return -errno; strprint(retv, inlen, "%s/%u%s", buf, i->prefix, (listlen-- > 1) ? "\n" : ""); } @@ -6247,7 +6061,7 @@ static int get_config_net_veth_ipv4_route(const char *key, char *retv, int inlen memset(retv, 0, inlen); if (!netdev) - return ret_set_errno(-1, EINVAL); + return ret_errno(EINVAL); if (netdev->type != LXC_NET_VETH) return 0; @@ -6256,7 +6070,8 @@ static int get_config_net_veth_ipv4_route(const char *key, char *retv, int inlen lxc_list_for_each(it, &netdev->priv.veth_attr.ipv4_routes) { struct lxc_inetdev *i = it->elem; - inet_ntop(AF_INET, &i->addr, buf, sizeof(buf)); + if (!inet_ntop(AF_INET, &i->addr, buf, sizeof(buf))) + return -errno; strprint(retv, inlen, "%s/%u%s", buf, i->prefix, (listlen-- > 1) ? "\n" : ""); } @@ -6278,14 +6093,15 @@ static int get_config_net_ipv6_gateway(const char *key, char *retv, int inlen, memset(retv, 0, inlen); if (!netdev) - return -1; + return ret_errno(EINVAL); if (netdev->ipv6_gateway_auto) { strprint(retv, inlen, "auto"); } else if (netdev->ipv6_gateway_dev) { strprint(retv, inlen, "dev"); } else if (netdev->ipv6_gateway) { - inet_ntop(AF_INET6, netdev->ipv6_gateway, buf, sizeof(buf)); + if (!inet_ntop(AF_INET6, netdev->ipv6_gateway, buf, sizeof(buf))) + return -errno; strprint(retv, inlen, "%s", buf); } @@ -6308,13 +6124,14 @@ static int get_config_net_ipv6_address(const char *key, char *retv, int inlen, memset(retv, 0, inlen); if (!netdev) - return -1; + return ret_errno(EINVAL); listlen = lxc_list_len(&netdev->ipv6); lxc_list_for_each(it, &netdev->ipv6) { struct lxc_inet6dev *i = it->elem; - inet_ntop(AF_INET6, &i->addr, buf, sizeof(buf)); + if (!inet_ntop(AF_INET6, &i->addr, buf, sizeof(buf))) + return -errno; strprint(retv, inlen, "%s/%u%s", buf, i->prefix, (listlen-- > 1) ? "\n" : ""); } @@ -6323,7 +6140,7 @@ static int get_config_net_ipv6_address(const char *key, char *retv, int inlen, } static int get_config_net_veth_ipv6_route(const char *key, char *retv, int inlen, - struct lxc_conf *c, void *data) + struct lxc_conf *c, void *data) { int len; size_t listlen; @@ -6338,7 +6155,7 @@ static int get_config_net_veth_ipv6_route(const char *key, char *retv, int inlen memset(retv, 0, inlen); if (!netdev) - return ret_set_errno(-1, EINVAL); + return ret_errno(EINVAL); if (netdev->type != LXC_NET_VETH) return 0; @@ -6347,7 +6164,8 @@ static int get_config_net_veth_ipv6_route(const char *key, char *retv, int inlen lxc_list_for_each(it, &netdev->priv.veth_attr.ipv6_routes) { struct lxc_inet6dev *i = it->elem; - inet_ntop(AF_INET6, &i->addr, buf, sizeof(buf)); + if (!inet_ntop(AF_INET6, &i->addr, buf, sizeof(buf))) + return -errno; strprint(retv, inlen, "%s/%u%s", buf, i->prefix, (listlen-- > 1) ? "\n" : ""); } @@ -6442,7 +6260,7 @@ int lxc_list_subkeys(struct lxc_conf *conf, const char *key, char *retv, } else if (!strcmp(key, "lxc.keyring")) { strprint(retv, inlen, "session\n"); } else { - fulllen = -1; + fulllen = ret_errno(EINVAL); } return fulllen; @@ -6462,11 +6280,11 @@ int lxc_list_net(struct lxc_conf *c, const char *key, char *retv, int inlen) (void)get_network_config_ops(key, c, &idx, NULL); if (idx < 0) - return -1; + return ret_errno(EINVAL); netdev = lxc_get_netdev_by_idx(c, (unsigned int)idx, false); if (!netdev) - return -1; + return ret_errno(EINVAL); if (!retv) inlen = 0; diff --git a/src/lxc/confile_utils.c b/src/lxc/confile_utils.c index 06e9f6b193..7e2c7a57a9 100644 --- a/src/lxc/confile_utils.c +++ b/src/lxc/confile_utils.c @@ -15,9 +15,11 @@ #include "confile_utils.h" #include "error.h" #include "list.h" +#include "lxc.h" #include "log.h" #include "lxccontainer.h" #include "macro.h" +#include "memory_utils.h" #include "network.h" #include "parse.h" #include "utils.h" @@ -31,16 +33,16 @@ lxc_log_define(confile_utils, lxc); int parse_idmaps(const char *idmap, char *type, unsigned long *nsid, unsigned long *hostid, unsigned long *range) { + __do_free char *dup = NULL; int ret = -1; unsigned long tmp_hostid, tmp_nsid, tmp_range; char tmp_type; char *window, *slide; - char *dup = NULL; /* Duplicate string. */ dup = strdup(idmap); if (!dup) - goto on_error; + return ret_errno(ENOMEM); /* A prototypical idmap entry would be: "u 1000 1000000 65536" */ @@ -49,13 +51,11 @@ int parse_idmaps(const char *idmap, char *type, unsigned long *nsid, /* skip whitespace */ slide += strspn(slide, " \t\r"); if (slide != window && *slide == '\0') - goto on_error; + return ret_errno(EINVAL); /* Validate type. */ - if (*slide != 'u' && *slide != 'g') { - ERROR("Invalid id mapping type: %c", *slide); - goto on_error; - } + if (*slide != 'u' && *slide != 'g') + return log_error_errno(-EINVAL, EINVAL, "Invalid id mapping type: %c", *slide); /* Assign type. */ tmp_type = *slide; @@ -68,7 +68,7 @@ int parse_idmaps(const char *idmap, char *type, unsigned long *nsid, slide += strspn(slide, " \t\r"); /* There must be whitespace. */ if (slide == window) - goto on_error; + return ret_errno(EINVAL); /* Mark beginning of nsid. */ window = slide; @@ -76,15 +76,14 @@ int parse_idmaps(const char *idmap, char *type, unsigned long *nsid, slide += strcspn(slide, " \t\r"); /* There must be non-whitespace. */ if (slide == window || *slide == '\0') - goto on_error; + return ret_errno(EINVAL); /* Mark end of nsid. */ *slide = '\0'; /* Parse nsid. */ - if (lxc_safe_ulong(window, &tmp_nsid) < 0) { - ERROR("Failed to parse nsid: %s", window); - goto on_error; - } + ret = lxc_safe_ulong(window, &tmp_nsid); + if (ret < 0) + return log_error_errno(ret, errno, "Failed to parse nsid: %s", window); /* Move beyond \0. */ slide++; @@ -94,7 +93,7 @@ int parse_idmaps(const char *idmap, char *type, unsigned long *nsid, * So only ensure that we're not at the end of the string. */ if (*slide == '\0') - goto on_error; + return ret_errno(EINVAL); /* Mark beginning of hostid. */ window = slide; @@ -102,15 +101,14 @@ int parse_idmaps(const char *idmap, char *type, unsigned long *nsid, slide += strcspn(slide, " \t\r"); /* There must be non-whitespace. */ if (slide == window || *slide == '\0') - goto on_error; + return ret_errno(EINVAL); /* Mark end of nsid. */ *slide = '\0'; /* Parse hostid. */ - if (lxc_safe_ulong(window, &tmp_hostid) < 0) { - ERROR("Failed to parse hostid: %s", window); - goto on_error; - } + ret = lxc_safe_ulong(window, &tmp_hostid); + if (ret < 0) + return log_error_errno(ret, errno, "Failed to parse hostid: %s", window); /* Move beyond \0. */ slide++; @@ -120,7 +118,7 @@ int parse_idmaps(const char *idmap, char *type, unsigned long *nsid, * So only ensure that we're not at the end of the string. */ if (*slide == '\0') - goto on_error; + return ret_errno(EINVAL); /* Mark beginning of range. */ window = slide; @@ -128,35 +126,29 @@ int parse_idmaps(const char *idmap, char *type, unsigned long *nsid, slide += strcspn(slide, " \t\r"); /* There must be non-whitespace. */ if (slide == window) - goto on_error; + return ret_errno(EINVAL); /* The range is the last valid entry we expect. So make sure that there * is no trailing garbage and if there is, error out. */ if (*(slide + strspn(slide, " \t\r\n")) != '\0') - goto on_error; + return ret_errno(EINVAL); /* Mark end of range. */ *slide = '\0'; /* Parse range. */ - if (lxc_safe_ulong(window, &tmp_range) < 0) { - ERROR("Failed to parse id mapping range: %s", window); - goto on_error; - } + ret = lxc_safe_ulong(window, &tmp_range); + if (ret < 0) + return log_error_errno(ret, errno, "Failed to parse id mapping range: %s", window); - *type = tmp_type; - *nsid = tmp_nsid; + *type = tmp_type; + *nsid = tmp_nsid; *hostid = tmp_hostid; - *range = tmp_range; + *range = tmp_range; /* Yay, we survived. */ - ret = 0; - -on_error: - free(dup); - - return ret; + return 0; } bool lxc_config_value_empty(const char *value) @@ -169,13 +161,13 @@ bool lxc_config_value_empty(const char *value) struct lxc_netdev *lxc_network_add(struct lxc_list *networks, int idx, bool tail) { - struct lxc_list *newlist; - struct lxc_netdev *netdev = NULL; + __do_free struct lxc_list *newlist = NULL; + __do_free struct lxc_netdev *netdev = NULL; /* network does not exist */ netdev = malloc(sizeof(*netdev)); if (!netdev) - return NULL; + return ret_set_errno(NULL, ENOMEM); memset(netdev, 0, sizeof(*netdev)); lxc_list_init(&netdev->ipv4); @@ -186,10 +178,8 @@ struct lxc_netdev *lxc_network_add(struct lxc_list *networks, int idx, bool tail /* prepare new list */ newlist = malloc(sizeof(*newlist)); - if (!newlist) { - free(netdev); - return NULL; - } + if (!newlist) + return ret_set_errno(NULL, ENOMEM); lxc_list_init(newlist); newlist->elem = netdev; @@ -198,8 +188,9 @@ struct lxc_netdev *lxc_network_add(struct lxc_list *networks, int idx, bool tail lxc_list_add_tail(networks, newlist); else lxc_list_add(networks, newlist); + move_ptr(newlist); - return netdev; + return move_ptr(netdev); } /* Takes care of finding the correct netdev struct in the networks list or @@ -224,7 +215,7 @@ struct lxc_netdev *lxc_get_netdev_by_idx(struct lxc_conf *conf, } if (!allocate) - return NULL; + return ret_set_errno(NULL, EINVAL); return lxc_network_add(insert, idx, true); } @@ -418,6 +409,9 @@ static void lxc_free_netdev(struct lxc_netdev *netdev) { struct lxc_list *cur, *next; + if (!netdev) + return; + free(netdev->upscript); free(netdev->downscript); free(netdev->hwaddr); @@ -459,11 +453,12 @@ static void lxc_free_netdev(struct lxc_netdev *netdev) free(netdev); } +define_cleanup_function(struct lxc_netdev *, lxc_free_netdev); + bool lxc_remove_nic_by_idx(struct lxc_conf *conf, unsigned int idx) { + call_cleaner(lxc_free_netdev) struct lxc_netdev *netdev = NULL; struct lxc_list *cur, *next; - struct lxc_netdev *netdev; - bool found = false; lxc_list_for_each_safe(cur, &conf->network, next) { netdev = cur->elem; @@ -471,25 +466,19 @@ bool lxc_remove_nic_by_idx(struct lxc_conf *conf, unsigned int idx) continue; lxc_list_del(cur); - found = true; - break; + free(cur); + return true; } - if (!found) - return false; - - lxc_free_netdev(netdev); - free(cur); - - return true; + return false; } void lxc_free_networks(struct lxc_list *networks) { struct lxc_list *cur, *next; - struct lxc_netdev *netdev; - lxc_list_for_each_safe(cur, networks, next) { + lxc_list_for_each_safe (cur, networks, next) { + struct lxc_netdev *netdev = cur->elem; netdev = cur->elem; lxc_free_netdev(netdev); free(cur); @@ -499,13 +488,12 @@ void lxc_free_networks(struct lxc_list *networks) lxc_list_init(networks); } - static struct lxc_veth_mode { char *name; int mode; } veth_mode[] = { - { "bridge", VETH_MODE_BRIDGE }, - { "router", VETH_MODE_ROUTER }, + { "bridge", VETH_MODE_BRIDGE }, + { "router", VETH_MODE_ROUTER }, }; int lxc_veth_mode_to_flag(int *mode, const char *value) @@ -518,7 +506,7 @@ int lxc_veth_mode_to_flag(int *mode, const char *value) return 0; } - return ret_set_errno(-1, EINVAL); + return ret_errno(EINVAL); } char *lxc_veth_flag_to_mode(int mode) @@ -530,24 +518,22 @@ char *lxc_veth_flag_to_mode(int mode) return veth_mode[i].name; } - return NULL; + return ret_set_errno(NULL, EINVAL); } static struct lxc_macvlan_mode { char *name; int mode; } macvlan_mode[] = { - { "private", MACVLAN_MODE_PRIVATE }, - { "vepa", MACVLAN_MODE_VEPA }, - { "bridge", MACVLAN_MODE_BRIDGE }, - { "passthru", MACVLAN_MODE_PASSTHRU }, + { "private", MACVLAN_MODE_PRIVATE }, + { "vepa", MACVLAN_MODE_VEPA }, + { "bridge", MACVLAN_MODE_BRIDGE }, + { "passthru", MACVLAN_MODE_PASSTHRU }, }; int lxc_macvlan_mode_to_flag(int *mode, const char *value) { - size_t i; - - for (i = 0; i < sizeof(macvlan_mode) / sizeof(macvlan_mode[0]); i++) { + for (size_t i = 0; i < sizeof(macvlan_mode) / sizeof(macvlan_mode[0]); i++) { if (strcmp(macvlan_mode[i].name, value)) continue; @@ -555,30 +541,28 @@ int lxc_macvlan_mode_to_flag(int *mode, const char *value) return 0; } - return -1; + return ret_errno(EINVAL); } char *lxc_macvlan_flag_to_mode(int mode) { - size_t i; - - for (i = 0; i < sizeof(macvlan_mode) / sizeof(macvlan_mode[0]); i++) { + for (size_t i = 0; i < sizeof(macvlan_mode) / sizeof(macvlan_mode[0]); i++) { if (macvlan_mode[i].mode != mode) continue; return macvlan_mode[i].name; } - return NULL; + return ret_set_errno(NULL, EINVAL); } static struct lxc_ipvlan_mode { char *name; int mode; } ipvlan_mode[] = { - { "l3", IPVLAN_MODE_L3 }, - { "l3s", IPVLAN_MODE_L3S }, - { "l2", IPVLAN_MODE_L2 }, + { "l3", IPVLAN_MODE_L3 }, + { "l3s", IPVLAN_MODE_L3S }, + { "l2", IPVLAN_MODE_L2 }, }; int lxc_ipvlan_mode_to_flag(int *mode, const char *value) @@ -591,7 +575,7 @@ int lxc_ipvlan_mode_to_flag(int *mode, const char *value) return 0; } - return -1; + return ret_errno(EINVAL); } char *lxc_ipvlan_flag_to_mode(int mode) @@ -603,16 +587,16 @@ char *lxc_ipvlan_flag_to_mode(int mode) return ipvlan_mode[i].name; } - return NULL; + return ret_set_errno(NULL, EINVAL); } static struct lxc_ipvlan_isolation { char *name; int flag; } ipvlan_isolation[] = { - { "bridge", IPVLAN_ISOLATION_BRIDGE }, - { "private", IPVLAN_ISOLATION_PRIVATE }, - { "vepa", IPVLAN_ISOLATION_VEPA }, + { "bridge", IPVLAN_ISOLATION_BRIDGE }, + { "private", IPVLAN_ISOLATION_PRIVATE }, + { "vepa", IPVLAN_ISOLATION_VEPA }, }; int lxc_ipvlan_isolation_to_flag(int *flag, const char *value) @@ -625,7 +609,7 @@ int lxc_ipvlan_isolation_to_flag(int *flag, const char *value) return 0; } - return -1; + return ret_errno(EINVAL); } char *lxc_ipvlan_flag_to_isolation(int flag) @@ -637,7 +621,7 @@ char *lxc_ipvlan_flag_to_isolation(int flag) return ipvlan_isolation[i].name; } - return NULL; + return ret_set_errno(NULL, EINVAL); } int set_config_string_item(char **conf_item, const char *value) @@ -645,28 +629,22 @@ int set_config_string_item(char **conf_item, const char *value) char *new_value; if (lxc_config_value_empty(value)) { - free(*conf_item); - *conf_item = NULL; + free_disarm(*conf_item); return 0; } new_value = strdup(value); - if (!new_value) { - SYSERROR("Failed to duplicate string \"%s\"", value); - return -1; - } + if (!new_value) + return log_error_errno(-ENOMEM, ENOMEM, "Failed to duplicate string \"%s\"", value); - free(*conf_item); - *conf_item = new_value; + free_move_ptr(*conf_item, new_value); return 0; } int set_config_string_item_max(char **conf_item, const char *value, size_t max) { - if (strlen(value) >= max) { - ERROR("%s is too long (>= %lu)", value, (unsigned long)max); - return -1; - } + if (strlen(value) >= max) + return log_error_errno(-ENAMETOOLONG, ENAMETOOLONG, "%s is too long (>= %lu)", value, (unsigned long)max); return set_config_string_item(conf_item, value); } @@ -678,6 +656,7 @@ int set_config_path_item(char **conf_item, const char *value) int set_config_bool_item(bool *conf_item, const char *value, bool empty_conf_action) { + int ret; unsigned int val = 0; if (lxc_config_value_empty(value)) { @@ -685,8 +664,9 @@ int set_config_bool_item(bool *conf_item, const char *value, bool empty_conf_act return 0; } - if (lxc_safe_uint(value, &val) < 0) - return -EINVAL; + ret = lxc_safe_uint(value, &val); + if (ret < 0) + return ret; switch (val) { case 0: @@ -697,7 +677,7 @@ int set_config_bool_item(bool *conf_item, const char *value, bool empty_conf_act return 0; } - return -EINVAL; + return ret_errno(EINVAL); } int config_ip_prefix(struct in_addr *addr) @@ -719,12 +699,11 @@ int network_ifname(char *valuep, const char *value, size_t size) size_t retlen; if (!valuep || !value) - return -1; + return ret_errno(EINVAL); retlen = strlcpy(valuep, value, size); if (retlen >= size) - ERROR("Network device name \"%s\" is too long (>= %zu)", value, - size); + ERROR("Network device name \"%s\" is too long (>= %zu)", value, size); return 0; } @@ -800,8 +779,7 @@ bool new_hwaddr(char *hwaddr) rand() % 255, rand() % 255); #endif if (ret < 0 || ret >= 18) { - SYSERROR("Failed to call snprintf()"); - return false; + return log_error_errno(false, EIO, "Failed to call snprintf()"); } return true; @@ -890,37 +868,24 @@ static int lxc_container_name_to_pid(const char *lxcname_or_pid, pid = strtol(lxcname_or_pid, &err, 10); if (*err != '\0' || pid < 1) { - struct lxc_container *c; + __put_lxc_container struct lxc_container *c = NULL; c = lxc_container_new(lxcname_or_pid, lxcpath); - if (!c) { - ERROR("\"%s\" is not a valid pid nor a container name", - lxcname_or_pid); - return -1; - } + if (!c) + return log_error_errno(-EINVAL, EINVAL, "\"%s\" is not a valid pid nor a container name", lxcname_or_pid); - if (!c->may_control(c)) { - ERROR("Insufficient privileges to control container " - "\"%s\"", c->name); - lxc_container_put(c); - return -1; - } + if (!c->may_control(c)) + return log_error_errno(-EPERM, EPERM, "Insufficient privileges to control container \"%s\"", c->name); pid = c->init_pid(c); - if (pid < 1) { - ERROR("Container \"%s\" is not running", c->name); - lxc_container_put(c); - return -1; - } + if (pid < 1) + return log_error_errno(-EINVAL, EINVAL, "Container \"%s\" is not running", c->name); - lxc_container_put(c); } ret = kill(pid, 0); - if (ret < 0) { - SYSERROR("Failed to send signal to pid %d", (int)pid); - return -1; - } + if (ret < 0) + return log_error_errno(-errno, errno, "Failed to send signal to pid %d", (int)pid); return pid; } @@ -928,8 +893,9 @@ static int lxc_container_name_to_pid(const char *lxcname_or_pid, int lxc_inherit_namespace(const char *nsfd_path, const char *lxcpath, const char *namespace) { + __do_free char *dup = NULL; int fd, pid; - char *dup, *lastslash; + char *lastslash; if (nsfd_path[0] == '/') { return open(nsfd_path, O_RDONLY | O_CLOEXEC); @@ -939,21 +905,20 @@ int lxc_inherit_namespace(const char *nsfd_path, const char *lxcpath, if (lastslash) { dup = strdup(nsfd_path); if (!dup) - return -1; + return ret_errno(ENOMEM); dup[lastslash - nsfd_path] = '\0'; - pid = lxc_container_name_to_pid(lastslash + 1, dup); - free(dup); - } else { - pid = lxc_container_name_to_pid(nsfd_path, lxcpath); + lxcpath = lastslash + 1; + nsfd_path = lastslash + 1; } + pid = lxc_container_name_to_pid(nsfd_path, lxcpath); if (pid < 0) - return -1; + return pid; fd = lxc_preserve_ns(pid, namespace); if (fd < 0) - return -1; + return -errno; return fd; } @@ -1044,10 +1009,12 @@ static const struct signame signames[] = { static int sig_num(const char *sig) { + int ret; unsigned int signum; - if (lxc_safe_uint(sig, &signum) < 0) - return -1; + ret = lxc_safe_uint(sig, &signum); + if (ret < 0) + return ret; return signum; } @@ -1061,12 +1028,12 @@ static int rt_sig_num(const char *signame) signame += 4; if (!isdigit(*signame)) - return -1; + return ret_errno(EINVAL); sig_n = sig_num(signame); sig_n = rtmax ? SIGRTMAX - sig_n : SIGRTMIN + sig_n; if (sig_n > SIGRTMAX || sig_n < SIGRTMIN) - return -1; + return ret_errno(EINVAL); return sig_n; } @@ -1087,5 +1054,5 @@ int sig_parse(const char *signame) return signames[n].num; } - return -1; + return ret_errno(EINVAL); } diff --git a/src/lxc/confile_utils.h b/src/lxc/confile_utils.h index 3da1f462a3..670f3894b8 100644 --- a/src/lxc/confile_utils.h +++ b/src/lxc/confile_utils.h @@ -9,24 +9,22 @@ #include "conf.h" #include "confile_utils.h" -#define strprint(str, inlen, ...) \ - do { \ - if (str) \ - len = snprintf(str, inlen, ##__VA_ARGS__); \ - else \ - len = snprintf((char *){""}, 0, ##__VA_ARGS__); \ - if (len < 0) { \ - SYSERROR("failed to create string"); \ - return -1; \ - }; \ - fulllen += len; \ - if (inlen > 0) { \ - if (str) \ - str += len; \ - inlen -= len; \ - if (inlen < 0) \ - inlen = 0; \ - } \ +#define strprint(str, inlen, ...) \ + do { \ + if (str) \ + len = snprintf(str, inlen, ##__VA_ARGS__); \ + else \ + len = snprintf((char *){""}, 0, ##__VA_ARGS__); \ + if (len < 0) \ + return log_error_errno(-EIO, EIO, "failed to create string"); \ + fulllen += len; \ + if (inlen > 0) { \ + if (str) \ + str += len; \ + inlen -= len; \ + if (inlen < 0) \ + inlen = 0; \ + } \ } while (0); __hidden extern int parse_idmaps(const char *idmap, char *type, unsigned long *nsid, diff --git a/src/lxc/criu.c b/src/lxc/criu.c index c0caffa1b0..31961d0f07 100644 --- a/src/lxc/criu.c +++ b/src/lxc/criu.c @@ -79,36 +79,26 @@ struct criu_opts { static int load_tty_major_minor(char *directory, char *output, int len) { - FILE *f; char path[PATH_MAX]; - int ret; + ssize_t ret; ret = snprintf(path, sizeof(path), "%s/tty.info", directory); - if (ret < 0 || ret >= sizeof(path)) { - ERROR("snprintf'd too many characters: %d", ret); - return -1; - } + if (ret < 0 || (size_t)ret >= sizeof(path)) + return ret_errno(EIO); - f = fopen(path, "re"); - if (!f) { - /* This means we're coming from a liblxc which didn't export + ret = lxc_read_from_file(path, output, len); + if (ret < 0) { + /* + * This means we're coming from a liblxc which didn't export * the tty info. In this case they had to have lxc.console.path * = * none, so there's no problem restoring. */ if (errno == ENOENT) return 0; - SYSERROR("couldn't open %s", path); - return -1; + return log_error_errno(-errno, errno, "Failed to open \"%s\"", path); } - if (!fgets(output, len, f)) { - fclose(f); - SYSERROR("couldn't read %s", path); - return -1; - } - - fclose(f); return 0; } diff --git a/src/lxc/lxc.h b/src/lxc/lxc.h index 9e31366eb5..f688b25c26 100644 --- a/src/lxc/lxc.h +++ b/src/lxc/lxc.h @@ -13,6 +13,7 @@ extern "C" { #include #include "compiler.h" +#include "memory_utils.h" #include "state.h" struct lxc_msg; @@ -94,6 +95,13 @@ extern int lxc_container_get(struct lxc_container *c); * If it is the last reference, free the lxccontainer and return 1. */ extern int lxc_container_put(struct lxc_container *c); +static inline void put_lxc_container(struct lxc_container *c) +{ + if (c) + lxc_container_put(c); +} +define_cleanup_function(struct lxc_container *, put_lxc_container); +#define __put_lxc_container call_cleaner(put_lxc_container) /* * Get a list of valid wait states. diff --git a/src/lxc/lxclock.c b/src/lxc/lxclock.c index 318e5bf5a3..361cde92b4 100644 --- a/src/lxc/lxclock.c +++ b/src/lxc/lxclock.c @@ -17,6 +17,7 @@ #include "config.h" #include "log.h" #include "lxclock.h" +#include "memory_utils.h" #include "utils.h" #ifdef MUTEX_DEBUGGING @@ -35,7 +36,6 @@ static inline void dump_stacktrace(void) void *array[MAX_STACKDEPTH]; size_t size; char **strings; - size_t i; size = backtrace(array, MAX_STACKDEPTH); strings = backtrace_symbols(array, size); @@ -43,7 +43,7 @@ static inline void dump_stacktrace(void) /* Using fprintf here as our logging module is not thread safe. */ fprintf(stderr, "\tObtained %zu stack frames\n", size); - for (i = 0; i < size; i++) + for (int i = 0; i < size; i++) fprintf(stderr, "\t\t%s\n", strings[i]); free(strings); @@ -80,9 +80,9 @@ static void unlock_mutex(pthread_mutex_t *l) static char *lxclock_name(const char *p, const char *n) { + __do_free char *dest = NULL, *rundir = NULL; int ret; size_t len; - char *dest, *rundir; /* lockfile will be: * "/run" + "/lxc/lock/$lxcpath/$lxcname + '\0' if root @@ -100,134 +100,96 @@ static char *lxclock_name(const char *p, const char *n) len += strlen(rundir); dest = malloc(len); - if (!dest) { - free(rundir); + if (!dest) return NULL; - } ret = snprintf(dest, len, "%s/lxc/lock/%s", rundir, p); - if (ret < 0 || (size_t)ret >= len) { - free(dest); - free(rundir); - return NULL; - } + if (ret < 0 || (size_t)ret >= len) + return ret_set_errno(NULL, EIO); ret = mkdir_p(dest, 0755); - if (ret < 0) { - free(dest); - free(rundir); + if (ret < 0) return NULL; - } ret = snprintf(dest, len, "%s/lxc/lock/%s/.%s", rundir, p, n); - free(rundir); - if (ret < 0 || (size_t)ret >= len) { - free(dest); - return NULL; - } + if (ret < 0 || (size_t)ret >= len) + return ret_set_errno(NULL, EIO); - return dest; + return move_ptr(dest); } static sem_t *lxc_new_unnamed_sem(void) { + __do_free sem_t *s = NULL; int ret; - sem_t *s; s = malloc(sizeof(*s)); if (!s) - return NULL; + return ret_set_errno(NULL, ENOMEM); ret = sem_init(s, 0, 1); - if (ret < 0) { - free(s); + if (ret < 0) return NULL; - } - return s; + return move_ptr(s); } struct lxc_lock *lxc_newlock(const char *lxcpath, const char *name) { - struct lxc_lock *l; + __do_free struct lxc_lock *l = NULL; - l = malloc(sizeof(*l)); + l = zalloc(sizeof(*l)); if (!l) - goto on_error; - - if (!name) { + return ret_set_errno(NULL, ENOMEM); + + if (name) { + l->type = LXC_LOCK_FLOCK; + l->u.f.fname = lxclock_name(lxcpath, name); + if (!l->u.f.fname) + return ret_set_errno(NULL, ENOMEM); + l->u.f.fd = -EBADF; + } else { l->type = LXC_LOCK_ANON_SEM; l->u.sem = lxc_new_unnamed_sem(); - if (!l->u.sem) { - free(l); - l = NULL; - } - - goto on_error; + if (!l->u.sem) + return ret_set_errno(NULL, ENOMEM); } - l->type = LXC_LOCK_FLOCK; - l->u.f.fname = lxclock_name(lxcpath, name); - if (!l->u.f.fname) { - if (!name) - free(l->u.sem); - free(l); - l = NULL; - goto on_error; - } - - l->u.f.fd = -1; - -on_error: - return l; + return move_ptr(l); } int lxclock(struct lxc_lock *l, int timeout) { + int ret = -1; struct flock lk; - int ret = -1, saved_errno = errno; - switch(l->type) { + switch (l->type) { case LXC_LOCK_ANON_SEM: if (!timeout) { ret = sem_wait(l->u.sem); - if (ret < 0) - saved_errno = errno; } else { struct timespec ts; ret = clock_gettime(CLOCK_REALTIME, &ts); - if (ret < 0) { - ret = -2; - goto on_error; - } + if (ret < 0) + return -2; ts.tv_sec += timeout; ret = sem_timedwait(l->u.sem, &ts); - if (ret < 0) - saved_errno = errno; } break; case LXC_LOCK_FLOCK: - ret = -2; - if (timeout) { - ERROR("Timeouts are not supported with file locks"); - goto on_error; - } + if (timeout) + return log_error(-2, "Timeouts are not supported with file locks"); - if (!l->u.f.fname) { - ERROR("No filename set for file lock"); - goto on_error; - } + if (!l->u.f.fname) + return log_error(-2, "No filename set for file lock"); - if (l->u.f.fd == -1) { + if (l->u.f.fd < 0) { l->u.f.fd = open(l->u.f.fname, O_CREAT | O_RDWR | O_NOFOLLOW | O_CLOEXEC | O_NOCTTY, S_IWUSR | S_IRUSR); - if (l->u.f.fd == -1) { - SYSERROR("Failed to open \"%s\"", l->u.f.fname); - saved_errno = errno; - goto on_error; - } + if (l->u.f.fd < 0) + return log_error_errno(-2, errno, "Failed to open \"%s\"", l->u.f.fname); } memset(&lk, 0, sizeof(struct flock)); @@ -236,59 +198,47 @@ int lxclock(struct lxc_lock *l, int timeout) lk.l_whence = SEEK_SET; ret = fcntl(l->u.f.fd, F_OFD_SETLKW, &lk); - if (ret < 0) { - if (errno == EINVAL) - ret = flock(l->u.f.fd, LOCK_EX); - saved_errno = errno; - } - + if (ret < 0 && errno == EINVAL) + ret = flock(l->u.f.fd, LOCK_EX); break; + default: + return ret_set_errno(-1, EINVAL); } -on_error: - errno = saved_errno; return ret; } int lxcunlock(struct lxc_lock *l) { struct flock lk; - int ret = 0, saved_errno = errno; + int ret = 0; switch (l->type) { case LXC_LOCK_ANON_SEM: - if (!l->u.sem) { - ret = -2; - } else { - ret = sem_post(l->u.sem); - saved_errno = errno; - } + if (!l->u.sem) + return -2; + ret = sem_post(l->u.sem); break; case LXC_LOCK_FLOCK: - if (l->u.f.fd != -1) { - memset(&lk, 0, sizeof(struct flock)); + if (l->u.f.fd < 0) + return -2; - lk.l_type = F_UNLCK; - lk.l_whence = SEEK_SET; + memset(&lk, 0, sizeof(struct flock)); - ret = fcntl(l->u.f.fd, F_OFD_SETLK, &lk); - if (ret < 0) { - if (errno == EINVAL) - ret = flock(l->u.f.fd, LOCK_EX | LOCK_NB); - saved_errno = errno; - } + lk.l_type = F_UNLCK; + lk.l_whence = SEEK_SET; - close(l->u.f.fd); - l->u.f.fd = -1; - } else { - ret = -2; - } + ret = fcntl(l->u.f.fd, F_OFD_SETLK, &lk); + if (ret < 0 && errno == EINVAL) + ret = flock(l->u.f.fd, LOCK_EX | LOCK_NB); + close_prot_errno_disarm(l->u.f.fd); break; + default: + return ret_set_errno(-1, EINVAL); } - errno = saved_errno; return ret; } @@ -304,24 +254,16 @@ void lxc_putlock(struct lxc_lock *l) if (!l) return; - switch(l->type) { + switch (l->type) { case LXC_LOCK_ANON_SEM: if (l->u.sem) { sem_destroy(l->u.sem); - free(l->u.sem); - l->u.sem = NULL; + free_disarm(l->u.sem); } - break; case LXC_LOCK_FLOCK: - if (l->u.f.fd != -1) { - close(l->u.f.fd); - l->u.f.fd = -1; - } - - free(l->u.f.fname); - l->u.f.fname = NULL; - + close_prot_errno_disarm(l->u.f.fd); + free_disarm(l->u.f.fname); break; } diff --git a/src/lxc/network.c b/src/lxc/network.c index fdb9aa09cc..7542521ffc 100644 --- a/src/lxc/network.c +++ b/src/lxc/network.c @@ -3012,7 +3012,7 @@ static int lxc_delete_network_unpriv_exec(const char *lxcpath, const char *lxcna int bytes, ret; pid_t child; int pipefd[2]; - char buffer[PATH_MAX] = {0}; + char buffer[PATH_MAX] = {}; if (netdev->type != LXC_NET_VETH) return log_error_errno(-1, EINVAL, "Network type %d not support for unprivileged use", netdev->type); diff --git a/src/lxc/storage/btrfs.c b/src/lxc/storage/btrfs.c index 92a4a6def2..0a28dc9c98 100644 --- a/src/lxc/storage/btrfs.c +++ b/src/lxc/storage/btrfs.c @@ -824,6 +824,7 @@ static int btrfs_lxc_rm_rf(const char *path) ERROR("Out of memory"); free_btrfs_tree(tree); close(fd); + return -ENOMEM; } memcpy(name, tmp, name_len); diff --git a/src/lxc/storage/lvm.c b/src/lxc/storage/lvm.c index 7b224ec259..9c79565e25 100644 --- a/src/lxc/storage/lvm.c +++ b/src/lxc/storage/lvm.c @@ -97,41 +97,32 @@ static int lvm_snapshot_exec_wrapper(void *data) */ static int do_lvm_create(const char *path, uint64_t size, const char *thinpool) { + __do_free char *pathdup = NULL; int len, ret; - char *pathdup, *vg, *lv; + char *vg, *lv; char cmd_output[PATH_MAX]; char sz[24]; __do_free char *tp = NULL; struct lvcreate_args cmd_args = {0}; ret = snprintf(sz, 24, "%" PRIu64 "b", size); - if (ret < 0 || ret >= 24) { - ERROR("Failed to create string: %d", ret); - return -1; - } + if (ret < 0 || ret >= 24) + return log_error(-EIO, "Failed to create string: %d", ret); pathdup = strdup(path); - if (!pathdup) { - ERROR("Failed to duplicate string \"%s\"", path); - return -1; - } + if (!pathdup) + return log_error(-ENOMEM, "Failed to duplicate string \"%s\"", path); lv = strrchr(pathdup, '/'); - if (!lv) { - ERROR("Failed to detect \"/\" in string \"%s\"", pathdup); - free(pathdup); - return -1; - } + if (!lv) + return log_error(-EINVAL, "Failed to detect \"/\" in string \"%s\"", pathdup); *lv = '\0'; lv++; TRACE("Parsed logical volume \"%s\"", lv); vg = strrchr(pathdup, '/'); - if (!vg) { - ERROR("Failed to detect \"/\" in string \"%s\"", pathdup); - free(pathdup); - return -1; - } + if (!vg) + return log_error(-EINVAL, "Failed to detect \"/\" in string \"%s\"", pathdup); vg++; TRACE("Parsed volume group \"%s\"", vg); @@ -140,18 +131,13 @@ static int do_lvm_create(const char *path, uint64_t size, const char *thinpool) tp = must_realloc(NULL, len); ret = snprintf(tp, len, "%s/%s", pathdup, thinpool); - if (ret < 0 || ret >= len) { - ERROR("Failed to create string: %d", ret); - free(pathdup); - return -1; - } + if (ret < 0 || ret >= len) + return log_error(-EIO, "Failed to create string: %d", ret); ret = lvm_is_thin_pool(tp); TRACE("got %d for thin pool at path: %s", ret, tp); if (ret < 0) { - ERROR("Failed to detect whether \"%s\" is a thinpool", tp); - free(pathdup); - return -1; + return log_error(-EINVAL, "Failed to detect whether \"%s\" is a thinpool", tp); } else if (!ret) { TRACE("Detected that \"%s\" is not a thinpool", tp); tp = NULL; @@ -165,30 +151,23 @@ static int do_lvm_create(const char *path, uint64_t size, const char *thinpool) cmd_args.lv = lv; cmd_args.size = sz; cmd_args.sigwipe = true; - TRACE("Creating new lvm storage volume \"%s\" on volume group \"%s\" " - "of size \"%s\"", lv, vg, sz); - ret = run_command_status(cmd_output, sizeof(cmd_output), - lvm_create_exec_wrapper, (void *)&cmd_args); + TRACE("Creating new lvm storage volume \"%s\" on volume group \"%s\" of size \"%s\"", lv, vg, sz); + ret = run_command_status(cmd_output, sizeof(cmd_output), lvm_create_exec_wrapper, + (void *)&cmd_args); /* If lvcreate is old and doesn't support signature wiping, try again without it. * Test for exit code EINVALID_CMD_LINE(3) of lvcreate command. */ if (WIFEXITED(ret) && WEXITSTATUS(ret) == 3) { cmd_args.sigwipe = false; - ret = run_command(cmd_output, sizeof(cmd_output), - lvm_create_exec_wrapper, (void *)&cmd_args); + ret = run_command(cmd_output, sizeof(cmd_output), lvm_create_exec_wrapper, + (void *)&cmd_args); } - if (ret != 0) { - ERROR("Failed to create logical volume \"%s\": %s", lv, - cmd_output); - free(pathdup); - return -1; - } - TRACE("Created new lvm storage volume \"%s\" on volume group \"%s\" " - "of size \"%s\"", lv, vg, sz); + if (ret != 0) + return log_error(-1, "Failed to create logical volume \"%s\": %s", lv, cmd_output); + TRACE("Created new lvm storage volume \"%s\" on volume group \"%s\" of size \"%s\"", lv, vg, sz); - free(pathdup); return ret; } diff --git a/src/lxc/string_utils.c b/src/lxc/string_utils.c index 3d0d31a6c6..9918299fb8 100644 --- a/src/lxc/string_utils.c +++ b/src/lxc/string_utils.c @@ -907,21 +907,21 @@ int parse_byte_size_string(const char *s, int64_t *converted) char suffix[3] = {0}; if (!s || !strcmp(s, "")) - return -EINVAL; + return ret_errno(EINVAL); end = stpncpy(dup, s, sizeof(dup) - 1); if (*end != '\0') - return -EINVAL; + return ret_errno(EINVAL); if (isdigit(*(end - 1))) suffix_len = 0; else if (isalpha(*(end - 1))) suffix_len = 1; else - return -EINVAL; + return ret_errno(EINVAL); if (suffix_len > 0 && (end - 2) == dup && !isdigit(*(end - 2))) - return -EINVAL; + return ret_errno(EINVAL); if (suffix_len > 0 && isalpha(*(end - 2))) suffix_len++; @@ -934,8 +934,8 @@ int parse_byte_size_string(const char *s, int64_t *converted) dup[lxc_char_right_gc(dup, strlen(dup))] = '\0'; ret = lxc_safe_long_long(dup, &conv); - if (ret < 0) - return -ret; + if (ret) + return ret; if (suffix_len != 2) { *converted = conv; @@ -949,11 +949,11 @@ int parse_byte_size_string(const char *s, int64_t *converted) else if (strcasecmp(suffix, "GB") == 0) mltpl = 1024 * 1024 * 1024; else - return -EINVAL; + return ret_errno(EINVAL); overflow = conv * mltpl; if (conv != 0 && (overflow / conv) != mltpl) - return -ERANGE; + return ret_errno(ERANGE); *converted = overflow; return 0; diff --git a/src/lxc/utils.c b/src/lxc/utils.c index 27b0fb7359..243dfd33d3 100644 --- a/src/lxc/utils.c +++ b/src/lxc/utils.c @@ -240,7 +240,9 @@ int mkdir_p(const char *dir, mode_t mode) char *get_rundir() { - char *rundir; + __do_free char *rundir = NULL; + char *static_rundir; + int ret; size_t len; const char *homedir; struct stat sb; @@ -251,9 +253,9 @@ char *get_rundir() if (geteuid() == sb.st_uid || getegid() == sb.st_gid) return strdup(RUNTIME_PATH); - rundir = getenv("XDG_RUNTIME_DIR"); - if (rundir) - return strdup(rundir); + static_rundir = getenv("XDG_RUNTIME_DIR"); + if (static_rundir) + return strdup(static_rundir); INFO("XDG_RUNTIME_DIR isn't set in the environment"); homedir = getenv("HOME"); @@ -265,8 +267,11 @@ char *get_rundir() if (!rundir) return NULL; - snprintf(rundir, len, "%s/.cache/lxc/run/", homedir); - return rundir; + ret = snprintf(rundir, len, "%s/.cache/lxc/run/", homedir); + if (ret < 0 || (size_t)ret >= len) + return ret_set_errno(NULL, EIO); + + return move_ptr(rundir); } int wait_for_pid(pid_t pid) @@ -1089,7 +1094,9 @@ int __safe_mount_beneath_at(int beneath_fd, const char *src, const char *dst, co source_fd = openat2(beneath_fd, src, &how, sizeof(how)); if (source_fd < 0) return -errno; - snprintf(src_buf, sizeof(src_buf), "/proc/self/fd/%d", source_fd); + ret = snprintf(src_buf, sizeof(src_buf), "/proc/self/fd/%d", source_fd); + if (ret < 0 || ret >= sizeof(src_buf)) + return -EIO; } else { src_buf[0] = '\0'; } @@ -1372,10 +1379,8 @@ int lxc_preserve_ns(const int pid, const char *ns) ret = snprintf(path, __NS_PATH_LEN, "/proc/%d/ns%s%s", pid, !ns || strcmp(ns, "") == 0 ? "" : "/", !ns || strcmp(ns, "") == 0 ? "" : ns); - if (ret < 0 || (size_t)ret >= __NS_PATH_LEN) { - errno = EFBIG; - return -1; - } + if (ret < 0 || (size_t)ret >= __NS_PATH_LEN) + return ret_errno(EIO); return open(path, O_RDONLY | O_CLOEXEC); }