Unverified Commit 8aa60255 by Stéphane Graber Committed by GitHub

Merge pull request #3762 from brauner/2021-03-31/fixes

fixes: Makefile, lxc-user-nic, simplify get_network_config_ops()
parents b405dec6 7707b0e0
......@@ -233,10 +233,10 @@ struct alloted_s {
struct alloted_s *next;
};
static struct alloted_s *append_alloted(struct alloted_s **head, char *name,
int n)
static struct alloted_s *append_alloted(struct alloted_s **head, char *name, int n)
{
struct alloted_s *cur, *al;
__do_free struct alloted_s *al = NULL;
struct alloted_s *cur;
if (!head || !name) {
/* Sanity check. Parameters should not be null. */
......@@ -244,32 +244,29 @@ static struct alloted_s *append_alloted(struct alloted_s **head, char *name,
return NULL;
}
al = malloc(sizeof(struct alloted_s));
al = zalloc(sizeof(struct alloted_s));
if (!al) {
CMD_SYSERROR("Failed to allocate memory\n");
return NULL;
}
al->name = strdup(name);
if (!al->name) {
free(al);
if (!al->name)
return NULL;
}
al->allowed = n;
al->next = NULL;
if (!*head) {
if (*head) {
cur = *head;
while (cur->next)
cur = cur->next;
cur->next = al;
} else {
*head = al;
return al;
}
cur = *head;
while (cur->next)
cur = cur->next;
cur->next = al;
return al;
return move_ptr(al);
}
static void free_alloted(struct alloted_s **head)
......@@ -321,10 +318,10 @@ static int get_alloted(char *me, char *intype, char *link,
if (ret != 4)
continue;
if (strlen(name) == 0)
if (is_empty_string(name))
continue;
if (strcmp(name, me)) {
if (!strequal(name, me)) {
if (name[0] != '@')
continue;
......@@ -332,17 +329,17 @@ static int get_alloted(char *me, char *intype, char *link,
continue;
}
if (strcmp(type, intype))
if (!strequal(type, intype))
continue;
if (strcmp(link, br))
if (!strequal(link, br))
continue;
/* Found the user or group with the appropriate settings,
* therefore finish the search. What to do if there are more
* than one applicable lines? not specified in the docs. Since
* getline is implemented with realloc, we don't need to free
* line until exiting func.
/*
* Found the user or group with the appropriate settings,
* therefore finish the search. What to do if there are is more
* than one applicable line? Currently this is not specified in
* the docs.
*
* If append_alloted returns NULL, e.g. due to a malloc error,
* we set count to 0 and break the loop, allowing cleanup and
......
......@@ -95,6 +95,7 @@ lxc_config_define(init_cwd);
lxc_config_define(init_gid);
lxc_config_define(init_uid);
lxc_config_define(init_groups);
lxc_config_define(jump_table_net);
lxc_config_define(keyring_session);
lxc_config_define(log_file);
lxc_config_define(log_level);
......@@ -123,7 +124,6 @@ lxc_config_define(net_ipvlan_mode);
lxc_config_define(net_ipvlan_isolation);
lxc_config_define(net_mtu);
lxc_config_define(net_name);
lxc_config_define(net_nic);
lxc_config_define(net_script_down);
lxc_config_define(net_script_up);
lxc_config_define(net_type);
......@@ -227,9 +227,9 @@ static struct lxc_config_t config_jump_table[] = {
{ "lxc.namespace.clone", true, set_config_namespace_clone, get_config_namespace_clone, clr_config_namespace_clone, },
{ "lxc.namespace.keep", true, set_config_namespace_keep, get_config_namespace_keep, clr_config_namespace_keep, },
{ "lxc.namespace.share", true, set_config_namespace_share, get_config_namespace_share, clr_config_namespace_share, },
{ "lxc.time.offset.boot", true, set_config_time_offset_boot, get_config_time_offset_boot, clr_config_time_offset_boot, },
{ "lxc.time.offset.boot", true, set_config_time_offset_boot, get_config_time_offset_boot, clr_config_time_offset_boot, },
{ "lxc.time.offset.monotonic", true, set_config_time_offset_monotonic, get_config_time_offset_monotonic, clr_config_time_offset_monotonic, },
{ "lxc.net.", false, set_config_net_nic, get_config_net_nic, clr_config_net_nic, },
{ "lxc.net.", false, set_config_jump_table_net, get_config_jump_table_net, clr_config_jump_table_net, },
{ "lxc.net", true, set_config_net, get_config_net, clr_config_net, },
{ "lxc.no_new_privs", true, set_config_no_new_privs, get_config_no_new_privs, clr_config_no_new_privs, },
{ "lxc.prlimit", false, set_config_prlimit, get_config_prlimit, clr_config_prlimit, },
......@@ -257,7 +257,11 @@ static struct lxc_config_t config_jump_table[] = {
{ "lxc.proc", false, set_config_proc, get_config_proc, clr_config_proc, },
};
static struct lxc_config_t config_jump_table_net[] = {
struct lxc_config_net_t {
LXC_CONFIG_MEMBERS;
};
static struct lxc_config_net_t config_jump_table_net[] = {
/* If a longer key is added please update. */
#define NETWORK_SUBKEY_SIZE_MAX (STRLITERALLEN("veth.vlan.tagged.id") * 2)
{ "flags", true, set_config_net_flags, get_config_net_flags, clr_config_net_flags, },
......@@ -318,12 +322,20 @@ struct lxc_config_t *lxc_get_config(const char *key)
return NULL;
}
static struct lxc_config_t *lxc_get_config_net(const char *key)
static inline bool match_config_net_item(const struct lxc_config_net_t *entry,
const char *key)
{
if (entry->strict)
return strequal(entry->name, key);
return strnequal(entry->name, key, strlen(entry->name));
}
static struct lxc_config_net_t *lxc_get_config_net(const char *key)
{
for (size_t i = 0; i < ARRAY_SIZE(config_jump_table_net); i++) {
struct lxc_config_t *cur = &config_jump_table_net[i];
struct lxc_config_net_t *cur = &config_jump_table_net[i];
if (!match_config_item(cur, key))
if (!match_config_net_item(cur, key))
continue;
return cur;
......@@ -5204,97 +5216,94 @@ static int get_config_includefiles(const char *key, char *retv, int inlen,
return ret_errno(ENOSYS);
}
static struct lxc_config_t *get_network_config_ops(const char *key,
struct lxc_conf *lxc_conf,
ssize_t *idx,
const char **const subkey)
struct config_net_info {
char buf[NETWORK_SUBKEY_SIZE_MAX];
const char *subkey;
const struct lxc_config_net_t *ops;
struct lxc_netdev *netdev;
};
static int get_network_config_ops(const char *key, struct lxc_conf *lxc_conf,
struct config_net_info *info, bool allocate)
{
struct lxc_config_t *config = NULL;
int ret;
int64_t tmpidx;
const char *idx_start, *subkey_start;
char buf[NETWORK_SUBKEY_SIZE_MAX];
if (!idx)
return ret_set_errno(NULL, EINVAL);
unsigned int idx;
const char *idx_start;
if (is_empty_string(key))
return ret_set_errno(NULL, EINVAL);
return ret_errno(EINVAL);
/* check that this is a sensible network key */
if (!strnequal("lxc.net.", key, STRLITERALLEN("lxc.net.")))
return log_error_errno(NULL, EINVAL, "Invalid network configuration key \"%s\"", key);
return syserror_set(-EINVAL, "Invalid network configuration key \"%s\"", key);
/* lxc.net.<n> */
/* beginning of index string */
idx_start = key + STRLITERALLEN("lxc.net.");
if (!isdigit(*idx_start))
return log_error_errno(NULL, EINVAL, "Failed to detect digit in string \"%s\"", key + 8);
return syserror_set(-EINVAL, "Failed to detect digit in string \"%s\"", key + 8);
ret = lxc_safe_int64_residual(idx_start, &tmpidx, 10, buf, sizeof(buf));
ret = lxc_safe_int64_residual(idx_start, &tmpidx, 10, info->buf, sizeof(info->buf));
if (ret)
return log_error_errno(NULL, -ret, "Failed to parse network index");
return syserror("Failed to parse network index");
if (tmpidx < 0 || tmpidx >= INT_MAX)
return log_error_errno(NULL, ERANGE, "Number of configured networks would overflow the counter");
*idx = (ssize_t)tmpidx;
return syserror_set(-ERANGE, "Number of configured networks would overflow the counter");
idx = (unsigned int)tmpidx;
if (!subkey)
return NULL;
info->netdev = lxc_get_netdev_by_idx(lxc_conf, idx, allocate);
if (!info->netdev)
return ret_errno(EINVAL);
/* Make sure subkey points to the empty string. */
info->subkey = info->buf;
if (is_empty_string(info->subkey))
return ret_errno(ENOENT);
subkey_start = &buf[1];
if (is_empty_string(subkey_start))
return log_error_errno(NULL, EINVAL, "No network subkey specified");
if (info->subkey[0] != '.')
return syserror_set(-EINVAL, "Invalid subkey");
info->subkey++;
/* lxc.net.<idx>.<subkey> */
*subkey = subkey_start;
config = lxc_get_config_net(*subkey);
if (!config)
return log_error_errno(NULL, ENOENT, "Unknown network configuration key \"%s\"", key);
info->ops = lxc_get_config_net(info->subkey);
if (!info->ops)
return syserror_set(-ENOENT, "Unknown network configuration key \"%s\"", key);
return config;
return 0;
}
/* Config entry is something like "lxc.net.0.ipv4" the key 'lxc.net.' was
* found. So we make sure next comes an integer, find the right callback (by
* rewriting the key), and call it.
*/
static int set_config_net_nic(const char *key, const char *value,
struct lxc_conf *lxc_conf, void *data)
static int set_config_jump_table_net(const char *key, const char *value,
struct lxc_conf *lxc_conf, void *data)
{
const char *subkey = NULL;
ssize_t idx = -1;
struct config_net_info info = {};
int ret;
const char *idxstring;
struct lxc_config_t *config;
struct lxc_netdev *netdev;
idxstring = key + STRLITERALLEN("lxc.net.");
if (!isdigit(*idxstring))
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, &subkey);
if (!config || idx < 0)
return -errno;
return clr_config_jump_table_net(key, lxc_conf, data);
netdev = lxc_get_netdev_by_idx(lxc_conf, (unsigned int)idx, true);
if (!netdev)
return ret_errno(EINVAL);
ret = get_network_config_ops(key, lxc_conf, &info, true);
if (ret)
return ret;
return config->set(subkey, value, lxc_conf, netdev);
return info.ops->set(info.subkey, value, lxc_conf, info.netdev);
}
static int clr_config_net_nic(const char *key, struct lxc_conf *lxc_conf,
void *data)
static int clr_config_jump_table_net(const char *key, struct lxc_conf *lxc_conf,
void *data)
{
const char *subkey = NULL;
ssize_t idx = -1;
struct config_net_info info = {};
int ret;
const char *idxstring;
struct lxc_config_t *config;
struct lxc_netdev *netdev;
idxstring = key + 8;
if (!isdigit(*idxstring))
......@@ -5317,15 +5326,11 @@ static int clr_config_net_nic(const char *key, struct lxc_conf *lxc_conf,
return 0;
}
config = get_network_config_ops(key, lxc_conf, &idx, &subkey);
if (!config || idx < 0)
return -errno;
netdev = lxc_get_netdev_by_idx(lxc_conf, (unsigned int)idx, false);
if (!netdev)
return ret_errno(EINVAL);
ret = get_network_config_ops(key, lxc_conf, &info, false);
if (ret)
return ret;
return config->clr(subkey, lxc_conf, netdev);
return info.ops->clr(info.subkey, lxc_conf, info.netdev);
}
static int clr_config_net_type(const char *key, struct lxc_conf *lxc_conf,
......@@ -5683,28 +5688,22 @@ static int clr_config_net_veth_ipv6_route(const char *key,
return 0;
}
static int get_config_net_nic(const char *key, char *retv, int inlen,
struct lxc_conf *c, void *data)
static int get_config_jump_table_net(const char *key, char *retv, int inlen,
struct lxc_conf *c, void *data)
{
const char *subkey = NULL;
ssize_t idx = -1;
struct config_net_info info = {};
int ret;
const char *idxstring;
struct lxc_config_t *config;
struct lxc_netdev *netdev;
idxstring = key + STRLITERALLEN("lxc.net.");
if (!isdigit(*idxstring))
return ret_errno(EINVAL);
config = get_network_config_ops(key, c, &idx, &subkey);
if (!config || idx < 0)
return -errno;
netdev = lxc_get_netdev_by_idx(c, (unsigned int)idx, false);
if (!netdev)
return ret_errno(EINVAL);
ret = get_network_config_ops(key, c, &info, false);
if (ret)
return ret;
return config->get(subkey, retv, inlen, c, netdev);
return info.ops->get(info.subkey, retv, inlen, c, info.netdev);
}
static int get_config_net_type(const char *key, char *retv, int inlen,
......@@ -6427,23 +6426,22 @@ int lxc_list_subkeys(struct lxc_conf *conf, const char *key, char *retv,
int lxc_list_net(struct lxc_conf *c, const char *key, char *retv, int inlen)
{
int len;
const char *idxstring;
struct config_net_info info = {};
struct lxc_netdev *netdev;
int len, ret;
const char *idxstring;
int fulllen = 0;
ssize_t idx = -1;
idxstring = key + STRLITERALLEN("lxc.net.");
if (!isdigit(*idxstring))
return ret_errno(EINVAL);
(void)get_network_config_ops(key, c, &idx, NULL);
if (idx < 0)
return ret_errno(EINVAL);
netdev = lxc_get_netdev_by_idx(c, (unsigned int)idx, false);
if (!netdev)
return ret_errno(EINVAL);
ret = get_network_config_ops(key, c, &info, false);
if (ret) {
if (ret != -ENOENT)
return ret_errno(EINVAL);
}
netdev = info.netdev;
if (!retv)
inlen = 0;
......
......@@ -32,12 +32,15 @@ typedef int (*config_get_cb)(const char *key, char *value, int inlen,
typedef int (*config_clr_cb)(const char *key, struct lxc_conf *conf,
void *data);
#define LXC_CONFIG_MEMBERS \
char *name; \
bool strict; \
config_set_cb set; \
config_get_cb get; \
config_clr_cb clr
struct lxc_config_t {
char *name;
bool strict;
config_set_cb set;
config_get_cb get;
config_clr_cb clr;
LXC_CONFIG_MEMBERS;
};
struct new_config_item {
......
......@@ -192,41 +192,6 @@ char *lxc_string_join(const char *sep, const char **parts, bool use_as_prefix)
return result;
}
char **lxc_normalize_path(const char *path)
{
char **components;
size_t components_len = 0;
size_t pos = 0;
components = lxc_string_split(path, '/');
if (!components)
return NULL;
/* resolve '.' and '..' */
for (pos = 0; pos < components_len;) {
if (strequal(components[pos], ".") ||
(strequal(components[pos], "..") && pos == 0)) {
/* eat this element */
free(components[pos]);
memmove(&components[pos], &components[pos + 1],
sizeof(char *) * (components_len - pos));
components_len--;
} else if (strequal(components[pos], "..")) {
/* eat this and the previous element */
free(components[pos - 1]);
free(components[pos]);
memmove(&components[pos - 1], &components[pos + 1],
sizeof(char *) * (components_len - pos));
components_len -= 2;
pos--;
} else {
pos++;
}
}
return components;
}
/* taken from systemd */
char *path_simplify(const char *path)
{
......@@ -672,8 +637,9 @@ int lxc_safe_uint64(const char *numstr, uint64_t *converted, int base)
return 0;
}
int lxc_safe_int64_residual(const char *numstr, int64_t *converted, int base, char *residual,
size_t residual_len)
int lxc_safe_int64_residual(const char *restrict numstr,
int64_t *restrict converted, int base,
char *restrict residual, size_t residual_len)
{
char *remaining = NULL;
int64_t u;
......@@ -692,7 +658,7 @@ int lxc_safe_int64_residual(const char *numstr, int64_t *converted, int base, ch
errno = 0;
u = strtoll(numstr, &remaining, base);
if (errno == ERANGE && u == INT64_MAX)
return -ERANGE;
return ret_errno(ERANGE);
if (remaining == numstr)
return -EINVAL;
......@@ -705,11 +671,11 @@ int lxc_safe_int64_residual(const char *numstr, int64_t *converted, int base, ch
len = strlen(remaining);
if (len >= residual_len)
return -EINVAL;
return ret_errno(EINVAL);
memcpy(residual, remaining, len);
} else if (*remaining != '\0') {
return -EINVAL;
return ret_errno(EINVAL);
}
out:
......
......@@ -30,21 +30,7 @@ __hidden extern char *lxc_string_replace(const char *needle, const char *replace
const char *haystack);
__hidden extern bool lxc_string_in_array(const char *needle, const char **haystack);
__hidden extern char *lxc_string_join(const char *sep, const char **parts, bool use_as_prefix);
/*
* Normalize and split path: Leading and trailing / are removed, multiple
* / are compactified, .. and . are resolved (.. on the top level is considered
* identical to .).
* Examples:
* / -> { NULL }
* foo/../bar -> { bar, NULL }
* ../../ -> { NULL }
* ./bar/baz/.. -> { bar, NULL }
* foo//bar -> { foo, bar, NULL }
*/
__hidden extern char **lxc_normalize_path(const char *path);
/* remove multiple slashes from the path, e.g. ///foo//bar -> /foo/bar */
__hidden extern char *lxc_deslashify(const char *path);
__hidden extern char *lxc_append_paths(const char *first, const char *second);
/*
......@@ -78,8 +64,10 @@ __hidden extern int lxc_safe_long(const char *numstr, long int *converted);
__hidden extern int lxc_safe_long_long(const char *numstr, long long int *converted);
__hidden extern int lxc_safe_ulong(const char *numstr, unsigned long *converted);
__hidden extern int lxc_safe_uint64(const char *numstr, uint64_t *converted, int base);
__hidden extern int lxc_safe_int64_residual(const char *numstr, int64_t *converted, int base,
char *residual, size_t residual_len);
__hidden extern int lxc_safe_int64_residual(const char *restrict numstr,
int64_t *restrict converted,
int base, char *restrict residual,
size_t residual_len);
/* Handles B, kb, MB, GB. Detects overflows and reports -ERANGE. */
__hidden extern int parse_byte_size_string(const char *s, long long int *converted);
......
......@@ -289,6 +289,41 @@ static int mk_rand_ovl_dirs(struct mnts *mnts, unsigned int num, struct lxc_argu
return 0;
}
static char **lxc_normalize_path(const char *path)
{
char **components;
size_t components_len = 0;
size_t pos = 0;
components = lxc_string_split(path, '/');
if (!components)
return NULL;
/* resolve '.' and '..' */
for (pos = 0; pos < components_len;) {
if (strequal(components[pos], ".") ||
(strequal(components[pos], "..") && pos == 0)) {
/* eat this element */
free(components[pos]);
memmove(&components[pos], &components[pos + 1],
sizeof(char *) * (components_len - pos));
components_len--;
} else if (strequal(components[pos], "..")) {
/* eat this and the previous element */
free(components[pos - 1]);
free(components[pos]);
memmove(&components[pos - 1], &components[pos + 1],
sizeof(char *) * (components_len - pos));
components_len -= 2;
pos--;
} else {
pos++;
}
}
return components;
}
static char *construct_path(char *path, bool as_prefix)
{
char **components = NULL;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment