Merge pull request #27684 from mrc0mmand/more-nspawn-tests

test: further extend systemd-nspawn coverage
This commit is contained in:
Yu Watanabe
2023-05-19 03:00:54 +09:00
committed by GitHub
9 changed files with 462 additions and 117 deletions
+2 -2
View File
@@ -638,7 +638,7 @@ int mount_all(const char *dest,
r = chase(mount_table[k].where, dest, CHASE_NONEXISTENT|CHASE_PREFIX_ROOT, &where, NULL);
if (r < 0)
return log_error_errno(r, "Failed to resolve %s/%s: %m", dest, mount_table[k].where);
return log_error_errno(r, "Failed to resolve %s%s: %m", strempty(dest), mount_table[k].where);
/* Skip this entry if it is not a remount. */
if (mount_table[k].what) {
@@ -697,7 +697,7 @@ int mount_all(const char *dest,
* for those. */
r = chase(mount_table[k].what, dest, CHASE_PREFIX_ROOT, &prefixed, NULL);
if (r < 0)
return log_error_errno(r, "Failed to resolve %s/%s: %m", dest, mount_table[k].what);
return log_error_errno(r, "Failed to resolve %s%s: %m", strempty(dest), mount_table[k].what);
}
r = mount_verbose_full(
+36 -26
View File
@@ -752,38 +752,48 @@ int remove_veth_links(const char *primary, char **pairs) {
}
static int network_iface_pair_parse(const char* iftype, char ***l, const char *p, const char* ifprefix) {
_cleanup_free_ char *a = NULL, *b = NULL;
int r;
r = extract_first_word(&p, &a, ":", EXTRACT_DONT_COALESCE_SEPARATORS);
if (r < 0)
return log_error_errno(r, "Failed to extract first word in %s parameter: %m", iftype);
if (r == 0)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"Short read while reading %s parameter: %m", iftype);
if (!ifname_valid(a))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"%s, interface name not valid: %s", iftype, a);
for (;;) {
_cleanup_free_ char *word = NULL, *a = NULL, *b = NULL;
const char *interface;
if (isempty(p)) {
if (ifprefix)
b = strjoin(ifprefix, a);
else
b = strdup(a);
} else
b = strdup(p);
if (!b)
return log_oom();
r = extract_first_word(&p, &word, NULL, 0);
if (r < 0)
return log_error_errno(r, "Failed to parse interface name: %m");
if (r == 0)
break;
if (!ifname_valid(b))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"%s, interface name not valid: %s", iftype, b);
interface = word;
r = extract_first_word(&interface, &a, ":", EXTRACT_DONT_COALESCE_SEPARATORS);
if (r < 0)
return log_error_errno(r, "Failed to extract first word in %s parameter: %m", iftype);
if (r == 0)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"Short read while reading %s parameter: %m", iftype);
if (!ifname_valid(a))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"%s, interface name not valid: %s", iftype, a);
r = strv_push_pair(l, a, b);
if (r < 0)
return log_oom();
if (isempty(interface)) {
if (ifprefix)
b = strjoin(ifprefix, a);
else
b = strdup(a);
} else
b = strdup(interface);
if (!b)
return log_oom();
if (!ifname_valid(b))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"%s, interface name not valid: %s", iftype, b);
r = strv_consume_pair(l, TAKE_PTR(a), TAKE_PTR(b));
if (r < 0)
return log_oom();
}
a = b = NULL;
return 0;
}
+55 -63
View File
@@ -90,7 +90,7 @@ static int oci_unsupported(const char *name, JsonVariant *v, JsonDispatchFlags f
}
static int oci_terminal(const char *name, JsonVariant *v, JsonDispatchFlags flags, void *userdata) {
Settings *s = userdata;
Settings *s = ASSERT_PTR(userdata);
/* If not specified, or set to true, we'll default to either an interactive or a read-only
* console. If specified as false, we'll forcibly move to "pipe" mode though. */
@@ -115,6 +115,7 @@ static int oci_console_dimension(const char *name, JsonVariant *variant, JsonDis
}
static int oci_console_size(const char *name, JsonVariant *v, JsonDispatchFlags flags, void *userdata) {
Settings *s = ASSERT_PTR(userdata);
static const JsonDispatch table[] = {
{ "height", JSON_VARIANT_UNSIGNED, oci_console_dimension, offsetof(Settings, console_height), JSON_MANDATORY },
@@ -122,7 +123,7 @@ static int oci_console_size(const char *name, JsonVariant *v, JsonDispatchFlags
{}
};
return json_dispatch(v, table, oci_unexpected, flags, userdata);
return json_dispatch(v, table, oci_unexpected, flags, s);
}
static int oci_absolute_path(const char *name, JsonVariant *v, JsonDispatchFlags flags, void *userdata) {
@@ -186,9 +187,8 @@ static int oci_args(const char *name, JsonVariant *v, JsonDispatchFlags flags, v
static int oci_rlimit_type(const char *name, JsonVariant *v, JsonDispatchFlags flags, void *userdata) {
const char *z;
int t, *type = userdata;
assert_se(type);
int *type = ASSERT_PTR(userdata);
int t;
z = startswith(json_variant_string(v), "RLIMIT_");
if (!z)
@@ -206,7 +206,8 @@ static int oci_rlimit_type(const char *name, JsonVariant *v, JsonDispatchFlags f
}
static int oci_rlimit_value(const char *name, JsonVariant *v, JsonDispatchFlags flags, void *userdata) {
rlim_t z, *value = ASSERT_PTR(userdata);
rlim_t *value = ASSERT_PTR(userdata);
rlim_t z;
if (json_variant_is_negative(v))
z = RLIM_INFINITY;
@@ -227,7 +228,6 @@ static int oci_rlimit_value(const char *name, JsonVariant *v, JsonDispatchFlags
}
static int oci_rlimits(const char *name, JsonVariant *v, JsonDispatchFlags flags, void *userdata) {
Settings *s = ASSERT_PTR(userdata);
JsonVariant *e;
int r;
@@ -276,7 +276,8 @@ static int oci_rlimits(const char *name, JsonVariant *v, JsonDispatchFlags flags
}
static int oci_capability_array(const char *name, JsonVariant *v, JsonDispatchFlags flags, void *userdata) {
uint64_t *mask = userdata, m = 0;
uint64_t *mask = ASSERT_PTR(userdata);
uint64_t m = 0;
JsonVariant *e;
JSON_VARIANT_ARRAY_FOREACH(e, v) {
@@ -347,10 +348,10 @@ static int oci_oom_score_adj(const char *name, JsonVariant *v, JsonDispatchFlags
}
static int oci_uid_gid(const char *name, JsonVariant *v, JsonDispatchFlags flags, void *userdata) {
uid_t *uid = userdata, u;
uid_t *uid = ASSERT_PTR(userdata);
uid_t u;
uint64_t k;
assert(uid);
assert_cc(sizeof(uid_t) == sizeof(gid_t));
k = json_variant_unsigned(v);
@@ -395,6 +396,7 @@ static int oci_supplementary_gids(const char *name, JsonVariant *v, JsonDispatch
}
static int oci_user(const char *name, JsonVariant *v, JsonDispatchFlags flags, void *userdata) {
static const JsonDispatch table[] = {
{ "uid", JSON_VARIANT_UNSIGNED, oci_uid_gid, offsetof(Settings, uid), JSON_MANDATORY },
{ "gid", JSON_VARIANT_UNSIGNED, oci_uid_gid, offsetof(Settings, gid), JSON_MANDATORY },
@@ -427,7 +429,7 @@ static int oci_process(const char *name, JsonVariant *v, JsonDispatchFlags flags
}
static int oci_root(const char *name, JsonVariant *v, JsonDispatchFlags flags, void *userdata) {
Settings *s = userdata;
Settings *s = ASSERT_PTR(userdata);
int r;
static const JsonDispatch table[] = {
@@ -511,13 +513,15 @@ typedef struct oci_mount_data {
char **options;
} oci_mount_data;
static void cleanup_oci_mount_data(oci_mount_data *data) {
static void oci_mount_data_done(oci_mount_data *data) {
free(data->destination);
free(data->source);
strv_free(data->options);
free(data->type);
strv_free(data->options);
}
DEFINE_TRIVIAL_DESTRUCTOR(oci_mount_data_donep, oci_mount_data, oci_mount_data_done);
static int oci_mounts(const char *name, JsonVariant *v, JsonDispatchFlags flags, void *userdata) {
Settings *s = ASSERT_PTR(userdata);
JsonVariant *e;
@@ -533,8 +537,8 @@ static int oci_mounts(const char *name, JsonVariant *v, JsonDispatchFlags flags,
};
_cleanup_free_ char *joined_options = NULL;
_cleanup_(oci_mount_data_donep) oci_mount_data data = {};
CustomMount *m;
_cleanup_(cleanup_oci_mount_data) oci_mount_data data = {};
r = json_dispatch(e, table, oci_unexpected, flags, &data);
if (r < 0)
@@ -610,20 +614,27 @@ static int oci_namespace_type(const char *name, JsonVariant *v, JsonDispatchFlag
return 0;
}
struct namespace_data {
unsigned long type;
char *path;
};
static void namespace_data_done(struct namespace_data *p) {
assert(p);
free(p->path);
}
DEFINE_TRIVIAL_DESTRUCTOR(namespace_data_donep, struct namespace_data, namespace_data_done);
static int oci_namespaces(const char *name, JsonVariant *v, JsonDispatchFlags flags, void *userdata) {
Settings *s = userdata;
Settings *s = ASSERT_PTR(userdata);
unsigned long n = 0;
JsonVariant *e;
int r;
assert_se(s);
JSON_VARIANT_ARRAY_FOREACH(e, v) {
struct namespace_data {
unsigned long type;
char *path;
} data = {};
_cleanup_(namespace_data_donep) struct namespace_data data = {};
static const JsonDispatch table[] = {
{ "type", JSON_VARIANT_STRING, oci_namespace_type, offsetof(struct namespace_data, type), JSON_MANDATORY },
@@ -632,26 +643,19 @@ static int oci_namespaces(const char *name, JsonVariant *v, JsonDispatchFlags fl
};
r = json_dispatch(e, table, oci_unexpected, flags, &data);
if (r < 0) {
free(data.path);
if (r < 0)
return r;
}
if (data.path) {
if (data.type != CLONE_NEWNET) {
free(data.path);
if (data.type != CLONE_NEWNET)
return json_log(e, flags, SYNTHETIC_ERRNO(EOPNOTSUPP),
"Specifying namespace path for non-network namespace is not supported.");
}
if (s->network_namespace_path) {
free(data.path);
if (s->network_namespace_path)
return json_log(e, flags, SYNTHETIC_ERRNO(EINVAL),
"Network namespace path specified more than once, refusing.");
}
free(s->network_namespace_path);
s->network_namespace_path = data.path;
free_and_replace(s->network_namespace_path, data.path);
}
if (FLAGS_SET(n, data.type))
@@ -675,10 +679,10 @@ static int oci_namespaces(const char *name, JsonVariant *v, JsonDispatchFlags fl
}
static int oci_uid_gid_range(const char *name, JsonVariant *v, JsonDispatchFlags flags, void *userdata) {
uid_t *uid = userdata, u;
uid_t *uid = ASSERT_PTR(userdata);
uid_t u;
uint64_t k;
assert(uid);
assert_cc(sizeof(uid_t) == sizeof(gid_t));
/* This is very much like oci_uid_gid(), except the checks are a bit different, as this is a UID range rather
@@ -777,11 +781,9 @@ static int oci_device_type(const char *name, JsonVariant *v, JsonDispatchFlags f
}
static int oci_device_major(const char *name, JsonVariant *v, JsonDispatchFlags flags, void *userdata) {
unsigned *u = userdata;
unsigned *u = ASSERT_PTR(userdata);
uint64_t k;
assert_se(u);
k = json_variant_unsigned(v);
if (!DEVICE_MAJOR_VALID(k))
return json_log(v, flags, SYNTHETIC_ERRNO(ERANGE),
@@ -792,11 +794,9 @@ static int oci_device_major(const char *name, JsonVariant *v, JsonDispatchFlags
}
static int oci_device_minor(const char *name, JsonVariant *v, JsonDispatchFlags flags, void *userdata) {
unsigned *u = userdata;
unsigned *u = ASSERT_PTR(userdata);
uint64_t k;
assert_se(u);
k = json_variant_unsigned(v);
if (!DEVICE_MINOR_VALID(k))
return json_log(v, flags, SYNTHETIC_ERRNO(ERANGE),
@@ -807,11 +807,10 @@ static int oci_device_minor(const char *name, JsonVariant *v, JsonDispatchFlags
}
static int oci_device_file_mode(const char *name, JsonVariant *v, JsonDispatchFlags flags, void *userdata) {
mode_t *mode = userdata, m;
mode_t *mode = ASSERT_PTR(userdata);
mode_t m;
uint64_t k;
assert(mode);
k = json_variant_unsigned(v);
m = (mode_t) k;
@@ -931,7 +930,7 @@ static int oci_cgroups_path(const char *name, JsonVariant *v, JsonDispatchFlags
}
static int oci_cgroup_device_type(const char *name, JsonVariant *v, JsonDispatchFlags flags, void *userdata) {
mode_t *mode = userdata;
mode_t *mode = ASSERT_PTR(userdata);
const char *n;
assert_se(n = json_variant_string(v));
@@ -958,7 +957,7 @@ struct device_data {
};
static int oci_cgroup_device_access(const char *name, JsonVariant *v, JsonDispatchFlags flags, void *userdata) {
struct device_data *d = userdata;
struct device_data *d = ASSERT_PTR(userdata);
bool r = false, w = false, m = false;
const char *s;
size_t i;
@@ -984,7 +983,6 @@ static int oci_cgroup_device_access(const char *name, JsonVariant *v, JsonDispat
}
static int oci_cgroup_devices(const char *name, JsonVariant *v, JsonDispatchFlags flags, void *userdata) {
_cleanup_free_ struct device_data *list = NULL;
Settings *s = ASSERT_PTR(userdata);
size_t n_list = 0, i;
@@ -1187,7 +1185,7 @@ static int oci_cgroup_memory(const char *name, JsonVariant *v, JsonDispatchFlags
{}
};
Settings *s = userdata;
Settings *s = ASSERT_PTR(userdata);
int r;
r = json_dispatch(v, table, oci_unexpected, flags, &data);
@@ -1303,7 +1301,7 @@ static int oci_cgroup_cpu(const char *name, JsonVariant *v, JsonDispatchFlags fl
.period = UINT64_MAX,
};
Settings *s = userdata;
Settings *s = ASSERT_PTR(userdata);
int r;
r = json_dispatch(v, table, oci_unexpected, flags, &data);
@@ -1741,13 +1739,15 @@ struct syscall_rule {
size_t n_arguments;
};
static void syscall_rule_free(struct syscall_rule *rule) {
static void syscall_rule_done(struct syscall_rule *rule) {
assert(rule);
strv_free(rule->names);
free(rule->arguments);
};
DEFINE_TRIVIAL_DESTRUCTOR(syscall_rule_donep, struct syscall_rule, syscall_rule_done);
static int oci_seccomp_action(const char *name, JsonVariant *v, JsonDispatchFlags flags, void *userdata) {
uint32_t *action = ASSERT_PTR(userdata);
int r;
@@ -1831,18 +1831,17 @@ static int oci_seccomp_syscalls(const char *name, JsonVariant *v, JsonDispatchFl
{ "args", JSON_VARIANT_ARRAY, oci_seccomp_args, 0, 0 },
{}
};
struct syscall_rule rule = {
_cleanup_(syscall_rule_donep) struct syscall_rule rule = {
.action = UINT32_MAX,
};
r = json_dispatch(e, table, oci_unexpected, flags, &rule);
if (r < 0)
goto fail_rule;
return r;
if (strv_isempty(rule.names)) {
json_log(e, flags, 0, "System call name list is empty.");
r = -EINVAL;
goto fail_rule;
return -EINVAL;
}
STRV_FOREACH(i, rule.names) {
@@ -1856,15 +1855,8 @@ static int oci_seccomp_syscalls(const char *name, JsonVariant *v, JsonDispatchFl
r = seccomp_rule_add_array(sc, rule.action, nr, rule.n_arguments, rule.arguments);
if (r < 0)
goto fail_rule;
return r;
}
syscall_rule_free(&rule);
continue;
fail_rule:
syscall_rule_free(&rule);
return r;
}
return 0;
@@ -2031,7 +2023,7 @@ static int oci_linux(const char *name, JsonVariant *v, JsonDispatchFlags flags,
}
static int oci_hook_timeout(const char *name, JsonVariant *v, JsonDispatchFlags flags, void *userdata) {
usec_t *u = userdata;
usec_t *u = ASSERT_PTR(userdata);
uint64_t k;
k = json_variant_unsigned(v);