summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFrantisek Sumsal <frantisek@sumsal.cz>2023-05-16 17:26:25 +0200
committerGitHub <noreply@github.com>2023-05-16 17:26:25 +0200
commita5a4d5a18e6270b3623dc5c48f1c61344f1d0555 (patch)
tree136327df8a5acd02c2692c6ef9c34b9a75c8dade
parent329f4b06f5124a8db042e8bd42fbc3265744aaa6 (diff)
parentcd70372b934bded2249f26c72d4b6ab9bdf50a13 (diff)
downloadsystemd-a5a4d5a18e6270b3623dc5c48f1c61344f1d0555.tar.gz
Merge pull request #27651 from mrc0mmand/more-nspawn-tests
nspawn: OCI related fixes & tests
-rw-r--r--src/nspawn/nspawn-oci.c33
-rw-r--r--src/nspawn/nspawn-settings.c26
-rw-r--r--src/nspawn/nspawn.c1
-rw-r--r--test/fuzz/fuzz-nspawn-oci/basic.json247
-rwxr-xr-xtest/units/testsuite-13.nspawn-oci.sh383
-rwxr-xr-xtest/units/testsuite-13.nspawn.sh21
6 files changed, 641 insertions, 70 deletions
diff --git a/src/nspawn/nspawn-oci.c b/src/nspawn/nspawn-oci.c
index 3c6bfd3eaf..5e21538597 100644
--- a/src/nspawn/nspawn-oci.c
+++ b/src/nspawn/nspawn-oci.c
@@ -605,7 +605,7 @@ static int oci_namespace_type(const char *name, JsonVariant *v, JsonDispatchFlag
*nsflags = CLONE_NEWCGROUP;
else
return json_log(v, flags, SYNTHETIC_ERRNO(EINVAL),
- "Unknown cgroup type, refusing: %s", n);
+ "Unknown namespace type, refusing: %s", n);
return 0;
}
@@ -663,7 +663,7 @@ static int oci_namespaces(const char *name, JsonVariant *v, JsonDispatchFlags fl
if (!FLAGS_SET(n, CLONE_NEWNS))
return json_log(v, flags, SYNTHETIC_ERRNO(EOPNOTSUPP),
- "Containers without file system namespace aren't supported.");
+ "Containers without a mount namespace aren't supported.");
s->private_network = FLAGS_SET(n, CLONE_NEWNET);
s->userns_mode = FLAGS_SET(n, CLONE_NEWUSER) ? USER_NAMESPACE_FIXED : USER_NAMESPACE_NO;
@@ -819,7 +819,7 @@ static int oci_device_file_mode(const char *name, JsonVariant *v, JsonDispatchFl
return json_log(v, flags, SYNTHETIC_ERRNO(ERANGE),
"fileMode out of range, refusing.");
- *mode = m;
+ *mode = (*mode & ~07777) | m;
return 0;
}
@@ -874,7 +874,7 @@ static int oci_devices(const char *name, JsonVariant *v, JsonDispatchFlags flags
/* Suppress a couple of implicit device nodes */
r = devname_from_devnum(node->mode, makedev(node->major, node->minor), &path);
if (r < 0)
- json_log(e, flags|JSON_DEBUG, 0, "Failed to resolve device node %u:%u, ignoring: %m", node->major, node->minor);
+ json_log(e, flags|JSON_DEBUG, r, "Failed to resolve device node %u:%u, ignoring: %m", node->major, node->minor);
else {
if (PATH_IN_SET(path,
"/dev/null",
@@ -1177,13 +1177,13 @@ static int oci_cgroup_memory(const char *name, JsonVariant *v, JsonDispatchFlags
};
static const JsonDispatch table[] = {
- { "limit", JSON_VARIANT_NUMBER, oci_cgroup_memory_limit, offsetof(struct memory_data, limit), 0 },
- { "reservation", JSON_VARIANT_NUMBER, oci_cgroup_memory_limit, offsetof(struct memory_data, reservation), 0 },
- { "swap", JSON_VARIANT_NUMBER, oci_cgroup_memory_limit, offsetof(struct memory_data, swap), 0 },
- { "kernel", JSON_VARIANT_NUMBER, oci_unsupported, 0, JSON_PERMISSIVE },
- { "kernelTCP", JSON_VARIANT_NUMBER, oci_unsupported, 0, JSON_PERMISSIVE },
- { "swapiness", JSON_VARIANT_NUMBER, oci_unsupported, 0, JSON_PERMISSIVE },
- { "disableOOMKiller", JSON_VARIANT_NUMBER, oci_unsupported, 0, JSON_PERMISSIVE },
+ { "limit", JSON_VARIANT_NUMBER, oci_cgroup_memory_limit, offsetof(struct memory_data, limit), 0 },
+ { "reservation", JSON_VARIANT_NUMBER, oci_cgroup_memory_limit, offsetof(struct memory_data, reservation), 0 },
+ { "swap", JSON_VARIANT_NUMBER, oci_cgroup_memory_limit, offsetof(struct memory_data, swap), 0 },
+ { "kernel", JSON_VARIANT_NUMBER, oci_unsupported, 0, JSON_PERMISSIVE },
+ { "kernelTCP", JSON_VARIANT_NUMBER, oci_unsupported, 0, JSON_PERMISSIVE },
+ { "swapiness", JSON_VARIANT_NUMBER, oci_unsupported, 0, JSON_PERMISSIVE },
+ { "disableOOMKiller", JSON_VARIANT_BOOLEAN, oci_unsupported, 0, JSON_PERMISSIVE },
{}
};
@@ -1589,7 +1589,7 @@ static int oci_sysctl(const char *name, JsonVariant *v, JsonDispatchFlags flags,
assert_se(m = json_variant_string(w));
- if (sysctl_key_valid(k))
+ if (!sysctl_key_valid(k))
return json_log(v, flags, SYNTHETIC_ERRNO(EINVAL),
"sysctl key invalid, refusing: %s", k);
@@ -1829,6 +1829,7 @@ static int oci_seccomp_syscalls(const char *name, JsonVariant *v, JsonDispatchFl
{ "names", JSON_VARIANT_ARRAY, json_dispatch_strv, offsetof(struct syscall_rule, names), JSON_MANDATORY },
{ "action", JSON_VARIANT_STRING, oci_seccomp_action, offsetof(struct syscall_rule, action), JSON_MANDATORY },
{ "args", JSON_VARIANT_ARRAY, oci_seccomp_args, 0, 0 },
+ {}
};
struct syscall_rule rule = {
.action = UINT32_MAX,
@@ -2083,7 +2084,7 @@ static int oci_hooks_array(const char *name, JsonVariant *v, JsonDispatchFlags f
.timeout = USEC_INFINITY,
};
- r = json_dispatch(e, table, oci_unexpected, flags, userdata);
+ r = json_dispatch(e, table, oci_unexpected, flags, new_item);
if (r < 0) {
free(new_item->path);
strv_free(new_item->args);
@@ -2100,9 +2101,9 @@ static int oci_hooks_array(const char *name, JsonVariant *v, JsonDispatchFlags f
static int oci_hooks(const char *name, JsonVariant *v, JsonDispatchFlags flags, void *userdata) {
static const JsonDispatch table[] = {
- { "prestart", JSON_VARIANT_OBJECT, oci_hooks_array, 0, 0 },
- { "poststart", JSON_VARIANT_OBJECT, oci_hooks_array, 0, 0 },
- { "poststop", JSON_VARIANT_OBJECT, oci_hooks_array, 0, 0 },
+ { "prestart", JSON_VARIANT_ARRAY, oci_hooks_array, 0, 0 },
+ { "poststart", JSON_VARIANT_ARRAY, oci_hooks_array, 0, 0 },
+ { "poststop", JSON_VARIANT_ARRAY, oci_hooks_array, 0, 0 },
{}
};
diff --git a/src/nspawn/nspawn-settings.c b/src/nspawn/nspawn-settings.c
index 7500eabd18..161b1c1c70 100644
--- a/src/nspawn/nspawn-settings.c
+++ b/src/nspawn/nspawn-settings.c
@@ -97,27 +97,25 @@ int settings_load(FILE *f, const char *path, Settings **ret) {
return 0;
}
-static void free_oci_hooks(OciHook *h, size_t n) {
- size_t i;
+static void free_oci_hooks(OciHook *hooks, size_t n) {
+ assert(hooks || n == 0);
- assert(h || n == 0);
-
- for (i = 0; i < n; i++) {
- free(h[i].path);
- strv_free(h[i].args);
- strv_free(h[i].env);
+ FOREACH_ARRAY(hook, hooks, n) {
+ free(hook->path);
+ strv_free(hook->args);
+ strv_free(hook->env);
}
- free(h);
+ free(hooks);
}
-void device_node_array_free(DeviceNode *node, size_t n) {
- size_t i;
+void device_node_array_free(DeviceNode *nodes, size_t n) {
+ assert(nodes || n == 0);
- for (i = 0; i < n; i++)
- free(node[i].path);
+ FOREACH_ARRAY(node, nodes, n)
+ free(node->path);
- free(node);
+ free(nodes);
}
Settings* settings_free(Settings *s) {
diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c
index 49802d6fdf..5d49e05064 100644
--- a/src/nspawn/nspawn.c
+++ b/src/nspawn/nspawn.c
@@ -4651,6 +4651,7 @@ static int merge_settings(Settings *settings, const char *path) {
device_node_array_free(arg_extra_nodes, arg_n_extra_nodes);
arg_extra_nodes = TAKE_PTR(settings->extra_nodes);
arg_n_extra_nodes = settings->n_extra_nodes;
+ settings->n_extra_nodes = 0;
return 0;
}
diff --git a/test/fuzz/fuzz-nspawn-oci/basic.json b/test/fuzz/fuzz-nspawn-oci/basic.json
index f42739e03a..24bacf39c1 100644
--- a/test/fuzz/fuzz-nspawn-oci/basic.json
+++ b/test/fuzz/fuzz-nspawn-oci/basic.json
@@ -1,6 +1,8 @@
{
"ociVersion": "1.0.0",
+ "hostname" : "foo",
+
"root": {
"path": "rootfs",
"readonly": true
@@ -33,11 +35,42 @@
"cwd": "/tmp/src",
- "rlimits": [
+ "noNewPrivileges" : true,
+ "oomScoreAdj" : 20,
+ "capabilities" : {
+ "bounding" : [
+ "CAP_AUDIT_WRITE",
+ "CAP_KILL",
+ "CAP_NET_BIND_SERVICE"
+ ],
+ "permitted" : [
+ "CAP_AUDIT_WRITE",
+ "CAP_KILL",
+ "CAP_NET_BIND_SERVICE"
+ ],
+ "inheritable" : [
+ "CAP_AUDIT_WRITE",
+ "CAP_KILL",
+ "CAP_NET_BIND_SERVICE"
+ ],
+ "effective" : [
+ "CAP_AUDIT_WRITE",
+ "CAP_KILL"
+ ],
+ "ambient" : [
+ "CAP_NET_BIND_SERVICE"
+ ]
+ },
+ "rlimits" : [
{
- "type": "RLIMIT_NOFILE",
- "hard": 1020,
- "soft": 1020
+ "type" : "RLIMIT_NOFILE",
+ "soft" : 1024,
+ "hard" : 1024
+ },
+ {
+ "type" : "RLIMIT_RTPRIO",
+ "soft" : 5,
+ "hard" : 10
}
]
},
@@ -110,32 +143,206 @@
}
],
- "hooks": {},
-
- "linux": {
- "resources": {
- "devices": [
+ "linux" : {
+ "namespaces" : [
+ {
+ "type" : "mount"
+ },
+ {
+ "type" : "network",
+ "path" : "$NETNS"
+ },
+ {
+ "type" : "pid"
+ },
+ {
+ "type" : "uts"
+ }
+ ],
+ "uidMappings" : [
+ {
+ "containerID" : 0,
+ "hostID" : 1000,
+ "size" : 100
+ }
+ ],
+ "gidMappings" : [
+ {
+ "containerID" : 0,
+ "hostID" : 1000,
+ "size" : 100
+ }
+ ],
+ "devices" : [
+ {
+ "type" : "c",
+ "path" : "/dev/zero",
+ "major" : 1,
+ "minor" : 5,
+ "fileMode" : 444
+ },
+ {
+ "type" : "b",
+ "path" : "$DEV",
+ "major" : 4,
+ "minor" : 2,
+ "fileMode" : 666,
+ "uid" : 0,
+ "gid" : 0
+ }
+ ],
+ "resources" : {
+ "devices" : [
+ {
+ "allow" : false,
+ "access" : "m"
+ },
+ {
+ "allow" : true,
+ "type" : "b",
+ "major" : 4,
+ "minor" : 2,
+ "access" : "rwm"
+ }
+ ],
+ "memory" : {
+ "limit" : 134217728,
+ "reservation" : 33554432,
+ "swap" : 268435456
+ },
+ "cpu" : {
+ "shares" : 1024,
+ "quota" : 1000000,
+ "period" : 500000,
+ "cpus" : "0-7"
+ },
+ "blockIO" : {
+ "weight" : 10,
+ "weightDevice" : [
+ {
+ "major" : 4,
+ "minor" : 2,
+ "weight" : 500
+ }
+ ],
+ "throttleReadBpsDevice" : [
+ {
+ "major" : 4,
+ "minor" : 2,
+ "rate" : 500
+ }
+ ],
+ "throttleWriteBpsDevice" : [
+ {
+ "major" : 4,
+ "minor" : 2,
+ "rate" : 500
+ }
+ ],
+ "throttleReadIOPSDevice" : [
+ {
+ "major" : 4,
+ "minor" : 2,
+ "rate" : 500
+ }
+ ],
+ "throttleWriteIOPSDevice" : [
+ {
+ "major" : 4,
+ "minor" : 2,
+ "rate" : 500
+ }
+ ]
+ },
+ "pids" : {
+ "limit" : 1024
+ }
+ },
+ "sysctl" : {
+ "kernel.domainname" : "foo.bar",
+ "vm.swappiness" : "60"
+ },
+ "seccomp" : {
+ "defaultAction" : "SCMP_ACT_ALLOW",
+ "architectures" : [
+ "SCMP_ARCH_ARM",
+ "SCMP_ARCH_X86_64"
+ ],
+ "syscalls" : [
{
- "allow": false,
- "access": "rwm"
+ "names" : [
+ "lchown",
+ "chmod"
+ ],
+ "action" : "SCMP_ACT_ERRNO",
+ "args" : [
+ {
+ "index" : 0,
+ "value" : 1,
+ "op" : "SCMP_CMP_NE"
+ },
+ {
+ "index" : 1,
+ "value" : 2,
+ "valueTwo" : 3,
+ "op" : "SCMP_CMP_MASKED_EQ"
+ }
+ ]
}
]
},
- "namespaces": [
+ "rootfsPropagation" : "shared",
+ "maskedPaths" : [
+ "/proc/kcore",
+ "/root/nonexistent"
+ ],
+ "readonlyPaths" : [
+ "/proc/sys",
+ "/opt/readonly"
+ ]
+ },
+ "hooks" : {
+ "prestart" : [
{
- "type": "pid"
+ "path" : "/bin/sh",
+ "args" : [
+ "-xec",
+ "echo $PRESTART_FOO >/prestart"
+ ],
+ "env" : [
+ "PRESTART_FOO=prestart_bar",
+ "ALSO_FOO=also_bar"
+ ],
+ "timeout" : 666
},
{
- "type": "ipc"
- },
+ "path" : "/bin/touch",
+ "args" : [
+ "/tmp/also-prestart"
+ ]
+ }
+ ],
+ "poststart" : [
{
- "type": "mount"
+ "path" : "/bin/sh",
+ "args" : [
+ "touch",
+ "/poststart"
+ ]
+ }
+ ],
+ "poststop" : [
+ {
+ "path" : "/bin/sh",
+ "args" : [
+ "touch",
+ "/poststop"
+ ]
}
]
},
-
- "annotations": {
- "com.example.key1": "value1",
- "com.example.key2": "value2"
+ "annotations" : {
+ "hello.world" : "1",
+ "foo" : "bar"
}
}
diff --git a/test/units/testsuite-13.nspawn-oci.sh b/test/units/testsuite-13.nspawn-oci.sh
new file mode 100755
index 0000000000..cbfdb18290
--- /dev/null
+++ b/test/units/testsuite-13.nspawn-oci.sh
@@ -0,0 +1,383 @@
+#!/usr/bin/env bash
+# SPDX-License-Identifier: LGPL-2.1-or-later
+# shellcheck disable=SC2016
+set -eux
+set -o pipefail
+
+export SYSTEMD_LOG_LEVEL=debug
+export SYSTEMD_LOG_TARGET=journal
+CREATE_BB_CONTAINER="/usr/lib/systemd/tests/testdata/create-busybox-container"
+
+# shellcheck disable=SC2317
+at_exit() {
+ set +e
+
+ mountpoint -q /var/lib/machines && umount /var/lib/machines
+ [[ -n "${DEV:-}" ]] && rm -f "$DEV"
+ [[ -n "${NETNS:-}" ]] && umount "$NETNS" && rm -f "$NETNS"
+ [[ -n "${TMPDIR:-}" ]] && rm -fr "$TMPDIR"
+}
+
+trap at_exit EXIT
+
+# Mount tmpfs over /var/lib/machines to not pollute the image
+mkdir -p /var/lib/machines
+mount -t tmpfs tmpfs /var/lib/machines
+
+# Setup a couple of dirs/devices for the OCI containers
+DEV="$(mktemp -u /dev/oci-dev-XXX)"
+mknod -m 666 "$DEV" b 42 42
+NETNS="$(mktemp /var/tmp/netns.XXX)"
+mount --bind /proc/self/ns/net "$NETNS"
+TMPDIR="$(mktemp -d)"
+touch "$TMPDIR/hello"
+OCI="$(mktemp -d /var/lib/machines/testsuite-13.oci-bundle.XXX)"
+"$CREATE_BB_CONTAINER" "$OCI/rootfs"
+mkdir -p "$OCI/rootfs/opt/var"
+mkdir -p "$OCI/rootfs/opt/readonly"
+
+# Let's start with a simple config
+cat >"$OCI/config.json" <<EOF
+{
+ "ociVersion" : "1.0.0",
+ "root" : {
+ "path" : "rootfs"
+ },
+ "mounts" : [
+ {
+ "destination" : "/root",
+ "type" : "tmpfs",
+ "source" : "tmpfs"
+ }
+ ]
+}
+EOF
+systemd-nspawn --oci-bundle="$OCI" sh -xec 'mountpoint /root'
+
+# And now for something a bit more involved
+# Notes:
+# - the hooks are parsed & processed, but never executed
+# - set sysctl's are parsed but never used?
+# - same goes for arg_sysctl in nspawn.c
+cat >"$OCI/config.json" <<EOF
+{
+ "ociVersion" : "1.0.0",
+ "hostname" : "my-oci-container",
+ "root" : {
+ "path" : "rootfs",
+ "readonly" : false
+ },
+ "mounts" : [
+ {
+ "destination" : "/root",
+ "type" : "tmpfs",
+ "source" : "tmpfs"
+ },
+ {
+ "destination" : "/var",
+ "type" : "none",
+ "source" : "$TMPDIR",
+ "options" : ["rbind", "rw"]
+ }
+ ],
+ "process" : {
+ "terminal" : false,
+ "consoleSize" : {
+ "height" : 25,
+ "width" : 80
+ },
+ "user" : {
+ "uid" : 0,
+ "gid" : 0,
+ "additionalGids" : [5, 6]
+ },
+ "env" : [
+ "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
+ "FOO=bar"
+ ],
+ "cwd" : "/root",
+ "args" : [
+ "sh",
+ "-xe",
+ "/entrypoint.sh"
+ ],
+ "noNewPrivileges" : true,
+ "oomScoreAdj" : 20,
+ "capabilities" : {
+ "bounding" : [
+ "CAP_AUDIT_WRITE",
+ "CAP_KILL",
+ "CAP_NET_BIND_SERVICE"
+ ],
+ "permitted" : [
+ "CAP_AUDIT_WRITE",
+ "CAP_KILL",
+ "CAP_NET_BIND_SERVICE"
+ ],
+ "inheritable" : [
+ "CAP_AUDIT_WRITE",
+ "CAP_KILL",
+ "CAP_NET_BIND_SERVICE"
+ ],
+ "effective" : [
+ "CAP_AUDIT_WRITE",
+ "CAP_KILL"
+ ],
+ "ambient" : [
+ "CAP_NET_BIND_SERVICE"
+ ]
+ },
+ "rlimits" : [
+ {
+ "type" : "RLIMIT_NOFILE",
+ "soft" : 1024,
+ "hard" : 1024
+ },
+ {
+ "type" : "RLIMIT_RTPRIO",
+ "soft" : 5,
+ "hard" : 10
+ }
+ ]
+ },
+ "linux" : {
+ "namespaces" : [
+ {
+ "type" : "mount"
+ },
+ {
+ "type" : "network",
+ "path" : "$NETNS"
+ },
+ {
+ "type" : "pid"
+ },
+ {
+ "type" : "uts"
+ }
+ ],
+ "uidMappings" : [
+ {
+ "containerID" : 0,
+ "hostID" : 1000,
+ "size" : 100
+ }
+ ],
+ "gidMappings" : [
+ {
+ "containerID" : 0,
+ "hostID" : 1000,
+ "size" : 100
+ }
+ ],
+ "devices" : [
+ {
+ "type" : "c",
+ "path" : "/dev/zero",
+ "major" : 1,
+ "minor" : 5,
+ "fileMode" : 444
+ },
+ {
+ "type" : "b",
+ "path" : "$DEV",
+ "major" : 4,
+ "minor" : 2,
+ "fileMode" : 666,
+ "uid" : 0,
+ "gid" : 0
+ }
+ ],
+ "resources" : {
+ "devices" : [
+ {
+ "allow" : false,
+ "access" : "m"
+ },
+ {
+ "allow" : true,
+ "type" : "b",
+ "major" : 4,
+ "minor" : 2,
+ "access" : "rwm"
+ }
+ ],
+ "memory" : {
+ "limit" : 134217728,
+ "reservation" : 33554432,
+ "swap" : 268435456
+ },
+ "cpu" : {
+ "shares" : 1024,
+ "quota" : 1000000,
+ "period" : 500000,
+ "cpus" : "0-7"
+ },
+ "blockIO" : {
+ "weight" : 10,
+ "weightDevice" : [
+ {
+ "major" : 4,
+ "minor" : 2,
+ "weight" : 500
+ }
+ ],
+ "throttleReadBpsDevice" : [
+ {
+ "major" : 4,
+ "minor" : 2,
+ "rate" : 500
+ }
+ ],
+ "throttleWriteBpsDevice" : [
+ {
+ "major" : 4,
+ "minor" : 2,
+ "rate" : 500
+ }
+ ],
+ "throttleReadIOPSDevice" : [
+ {
+ "major" : 4,
+ "minor" : 2,
+ "rate" : 500
+ }
+ ],
+ "throttleWriteIOPSDevice" : [
+ {
+ "major" : 4,
+ "minor" : 2,
+ "rate" : 500
+ }
+ ]
+ },
+ "pids" : {
+ "limit" : 1024
+ }
+ },
+ "sysctl" : {
+ "kernel.domainname" : "foo.bar",
+ "vm.swappiness" : "60"
+ },
+ "seccomp" : {
+ "defaultAction" : "SCMP_ACT_ALLOW",
+ "architectures" : [
+ "SCMP_ARCH_ARM",
+ "SCMP_ARCH_X86_64"
+ ],
+ "syscalls" : [
+ {
+ "names" : [
+ "lchown",
+ "chmod"
+ ],
+ "action" : "SCMP_ACT_ERRNO",
+ "args" : [
+ {
+ "index" : 0,
+ "value" : 1,
+ "op" : "SCMP_CMP_NE"
+ },
+ {
+ "index" : 1,
+ "value" : 2,
+ "valueTwo" : 3,
+ "op" : "SCMP_CMP_MASKED_EQ"
+ }
+ ]
+ }
+ ]
+ },
+ "rootfsPropagation" : "shared",
+ "maskedPaths" : [
+ "/proc/kcore",
+ "/root/nonexistent"
+ ],
+ "readonlyPaths" : [
+ "/proc/sys",
+ "/opt/readonly"
+ ]
+ },
+ "hooks" : {
+ "prestart" : [
+ {
+ "path" : "/bin/sh",
+ "args" : [
+ "-xec",
+ "echo \$PRESTART_FOO >/prestart"
+ ],
+ "env" : [
+ "PRESTART_FOO=prestart_bar",
+ "ALSO_FOO=also_bar"
+ ],
+ "timeout" : 666
+ },
+ {
+ "path" : "/bin/touch",
+ "args" : [
+ "/tmp/also-prestart"
+ ]
+ }
+ ],
+ "poststart" : [
+ {
+ "path" : "/bin/sh",
+ "args" : [
+ "touch",
+ "/poststart"
+ ]
+ }
+ ],
+ "poststop" : [
+ {
+ "path" : "/bin/sh",
+ "args" : [
+ "touch",
+ "/poststop"
+ ]
+ }
+ ]
+ },
+ "annotations" : {
+ "hello.world" : "1",
+ "foo" : "bar"
+ }
+}
+EOF
+# Create a simple "entrypoint" script that validates that the container
+# is created correctly according to the OCI config
+cat >"$OCI/rootfs/entrypoint.sh" <<EOF
+#!/bin/sh -e
+
+# Mounts
+mountpoint /root
+mountpoint /var
+test -e /var/hello
+
+# Process
+[[ "\$PWD" == /root ]]
+[[ "\$FOO" == bar ]]
+
+# Process - rlimits
+[[ "\$(ulimit -S -n)" -eq 1024 ]]
+[[ "\$(ulimit -H -n)" -eq 1024 ]]
+[[ "\$(ulimit -S -r)" -eq 5 ]]
+[[ "\$(ulimit -H -r)" -eq 10 ]]
+[[ "\$(hostname)" == my-oci-container ]]
+
+# Linux - devices
+test -c /dev/zero
+test -b "$DEV"
+[[ "\$(stat -c '%t:%T' "$DEV")" == 4:2 ]]
+
+# Linux - maskedPaths
+test -e /proc/kcore
+cat /proc/kcore && exit 1
+test ! -e /root/nonexistent
+
+# Linux - readonlyPaths
+touch /opt/readonly/foo && exit 1
+
+exit 0
+EOF
+systemd-nspawn --oci-bundle="$OCI"
diff --git a/test/units/testsuite-13.nspawn.sh b/test/units/testsuite-13.nspawn.sh
index 76ba143751..8f8daf05cc 100755
--- a/test/units/testsuite-13.nspawn.sh
+++ b/test/units/testsuite-13.nspawn.sh
@@ -46,7 +46,7 @@ mkdir -p /var/lib/machines
mount -t tmpfs tmpfs /var/lib/machines
testcase_sanity_check() {
- local template root image oci uuid tmpdir
+ local template root image uuid tmpdir
tmpdir="$(mktemp -d)"
template="$(mktemp -d /tmp/nspawn-template.XXX)"
@@ -59,24 +59,6 @@ testcase_sanity_check() {
mount -o loop "$image" /mnt
cp -r "$template"/* /mnt/
umount /mnt
- # Create a simple OCI bundle
- oci="$(mktemp -d /var/lib/machines/testsuite-13.oci-bundle.XXX)"
- "$CREATE_BB_CONTAINER" "$oci/rootfs"
- cat >"$oci/config.json" <<EOF
-{
- "ociVersion" : "1.0.0",
- "root" : {
- "path" : "rootfs"
- },
- "mounts" : [
- {
- "destination" : "/root",
- "type" : "tmpfs",
- "source" : "tmpfs"
- }
- ]
-}
-EOF
systemd-nspawn --help --no-pager
systemd-nspawn --version
@@ -101,7 +83,6 @@ EOF
sh -xec 'touch /nope')
test ! -e "$root/nope"
systemd-nspawn --image="$image" sh -xec 'echo hello'
- systemd-nspawn --oci-bundle="$oci" sh -xec 'mountpoint /root'
# --volatile=
touch "$root/usr/has-usr"