aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2019-03-22 21:06:17 +0100
committerGitHub <noreply@github.com>2019-03-22 21:06:17 +0100
commit83276695c67e4be2ccbce696d3e6c7dbd6825473 (patch)
treeac793974966be389810c49bda0a7739e3aa5255e
parentMerge pull request #12075 from keszybz/two-docs (diff)
parentnspawn-oci: fix double free (diff)
downloadsystemd-83276695c67e4be2ccbce696d3e6c7dbd6825473.tar.xz
systemd-83276695c67e4be2ccbce696d3e6c7dbd6825473.zip
Merge pull request #12079 from keszybz/fuzz-nspawn-oci
Add fuzzer for nspawn-oci
-rw-r--r--src/fuzz/fuzz-nspawn-oci.c28
-rw-r--r--src/fuzz/meson.build5
-rw-r--r--src/nspawn/nspawn-oci.c81
-rw-r--r--src/nspawn/nspawn-settings.c5
-rw-r--r--src/nspawn/nspawn-settings.h2
-rw-r--r--src/nspawn/nspawn.c4
-rw-r--r--src/test/test-tables.c2
-rw-r--r--src/udev/net/link-config-gperf.gperf66
-rw-r--r--src/udev/net/link-config.c26
-rw-r--r--src/udev/net/link-config.h22
-rw-r--r--test/fuzz/fuzz-nspawn-oci/basic.json141
-rw-r--r--test/fuzz/fuzz-nspawn-oci/crash-bffbd2085d4e95c47e9749b3f4a2dbc0580c20d35
-rw-r--r--test/fuzz/fuzz-nspawn-oci/crash-db0595479ee2e625fa5419a821009b5eb4d809b792
13 files changed, 365 insertions, 114 deletions
diff --git a/src/fuzz/fuzz-nspawn-oci.c b/src/fuzz/fuzz-nspawn-oci.c
new file mode 100644
index 00000000000..f7b59f13ba8
--- /dev/null
+++ b/src/fuzz/fuzz-nspawn-oci.c
@@ -0,0 +1,28 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include <errno.h>
+
+#include "alloc-util.h"
+#include "fd-util.h"
+#include "fuzz.h"
+#include "nspawn-oci.h"
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+ _cleanup_fclose_ FILE *f = NULL;
+ _cleanup_(settings_freep) Settings *s = NULL;
+
+ if (size == 0)
+ return 0;
+
+ f = fmemopen((char*) data, size, "re");
+ assert_se(f);
+
+ /* We don't want to fill the logs with messages about parse errors.
+ * Disable most logging if not running standalone */
+ if (!getenv("SYSTEMD_LOG_LEVEL"))
+ log_set_max_level(LOG_CRIT);
+
+ (void) oci_load(f, "/dev/null", &s);
+
+ return 0;
+}
diff --git a/src/fuzz/meson.build b/src/fuzz/meson.build
index 241fe02edbb..0d1ad2b1e1a 100644
--- a/src/fuzz/meson.build
+++ b/src/fuzz/meson.build
@@ -130,6 +130,11 @@ fuzzers += [
libnspawn_core],
[]],
+ [['src/fuzz/fuzz-nspawn-oci.c'],
+ [libshared,
+ libnspawn_core],
+ []],
+
[['src/fuzz/fuzz-calendarspec.c'],
[libshared],
[]],
diff --git a/src/nspawn/nspawn-oci.c b/src/nspawn/nspawn-oci.c
index dd191aaa292..6c35c926ab1 100644
--- a/src/nspawn/nspawn-oci.c
+++ b/src/nspawn/nspawn-oci.c
@@ -517,6 +517,20 @@ static bool oci_exclude_mount(const char *path) {
return false;
}
+typedef struct oci_mount_data {
+ char *destination;
+ char *source;
+ char *type;
+ char **options;
+} oci_mount_data;
+
+static void cleanup_oci_mount_data(oci_mount_data *data) {
+ free(data->destination);
+ free(data->source);
+ strv_free(data->options);
+ free(data->type);
+}
+
static int oci_mounts(const char *name, JsonVariant *v, JsonDispatchFlags flags, void *userdata) {
Settings *s = userdata;
JsonVariant *e;
@@ -525,56 +539,42 @@ static int oci_mounts(const char *name, JsonVariant *v, JsonDispatchFlags flags,
assert(s);
JSON_VARIANT_ARRAY_FOREACH(e, v) {
-
- struct mount_data {
- char *destination;
- char *source;
- char *type;
- char **options;
- } data = {};
-
static const JsonDispatch table[] = {
- { "destination", JSON_VARIANT_STRING, oci_absolute_path, offsetof(struct mount_data, destination), JSON_MANDATORY },
- { "source", JSON_VARIANT_STRING, json_dispatch_string, offsetof(struct mount_data, source), 0 },
- { "options", JSON_VARIANT_ARRAY, json_dispatch_strv, offsetof(struct mount_data, options), 0, },
- { "type", JSON_VARIANT_STRING, json_dispatch_string, offsetof(struct mount_data, type), 0 },
+ { "destination", JSON_VARIANT_STRING, oci_absolute_path, offsetof(oci_mount_data, destination), JSON_MANDATORY },
+ { "source", JSON_VARIANT_STRING, json_dispatch_string, offsetof(oci_mount_data, source), 0 },
+ { "options", JSON_VARIANT_ARRAY, json_dispatch_strv, offsetof(oci_mount_data, options), 0, },
+ { "type", JSON_VARIANT_STRING, json_dispatch_string, offsetof(oci_mount_data, type), 0 },
{}
};
_cleanup_free_ char *joined_options = NULL;
CustomMount *m;
+ _cleanup_(cleanup_oci_mount_data) oci_mount_data data = {};
r = json_dispatch(e, table, oci_unexpected, flags, &data);
if (r < 0)
- goto fail_item;
+ return r;
- if (!path_is_absolute(data.destination)) {
- r = json_log(e, flags, SYNTHETIC_ERRNO(EINVAL),
- "Mount destination not an absolute path: %s", data.destination);
- goto fail_item;
- }
+ if (!path_is_absolute(data.destination))
+ return json_log(e, flags, SYNTHETIC_ERRNO(EINVAL),
+ "Mount destination not an absolute path: %s", data.destination);
if (oci_exclude_mount(data.destination))
- goto skip_item;
+ continue;
if (data.options) {
joined_options = strv_join(data.options, ",");
- if (!joined_options) {
- r = log_oom();
- goto fail_item;
- }
+ if (!joined_options)
+ return log_oom();
}
if (!data.type || streq(data.type, "bind")) {
-
- if (!path_is_absolute(data.source)) {
+ if (data.source && !path_is_absolute(data.source)) {
char *joined;
joined = path_join(s->bundle, data.source);
- if (!joined) {
- r = log_oom();
- goto fail_item;
- }
+ if (!joined)
+ return log_oom();
free_and_replace(data.source, joined);
}
@@ -584,32 +584,13 @@ static int oci_mounts(const char *name, JsonVariant *v, JsonDispatchFlags flags,
m = custom_mount_add(&s->custom_mounts, &s->n_custom_mounts, CUSTOM_MOUNT_BIND);
} else
m = custom_mount_add(&s->custom_mounts, &s->n_custom_mounts, CUSTOM_MOUNT_ARBITRARY);
- if (!m) {
- r = log_oom();
- goto fail_item;
- }
+ if (!m)
+ return log_oom();
m->destination = TAKE_PTR(data.destination);
m->source = TAKE_PTR(data.source);
m->options = TAKE_PTR(joined_options);
m->type_argument = TAKE_PTR(data.type);
-
- strv_free(data.options);
- continue;
-
- fail_item:
- free(data.destination);
- free(data.source);
- strv_free(data.options);
- free(data.type);
-
- return r;
-
- skip_item:
- free(data.destination);
- free(data.source);
- strv_free(data.options);
- free(data.type);
}
return 0;
diff --git a/src/nspawn/nspawn-settings.c b/src/nspawn/nspawn-settings.c
index ab69f24c54e..476cb0779e7 100644
--- a/src/nspawn/nspawn-settings.c
+++ b/src/nspawn/nspawn-settings.c
@@ -110,7 +110,7 @@ static void free_oci_hooks(OciHook *h, size_t n) {
free(h);
}
-void device_node_free_many(DeviceNode *node, size_t n) {
+void device_node_array_free(DeviceNode *node, size_t n) {
size_t i;
for (i = 0; i < n; i++)
@@ -156,8 +156,7 @@ Settings* settings_free(Settings *s) {
sd_bus_message_unref(s->properties);
free(s->supplementary_gids);
- device_node_free_many(s->extra_nodes, s->n_extra_nodes);
- free(s->extra_nodes);
+ device_node_array_free(s->extra_nodes, s->n_extra_nodes);
free(s->network_namespace_path);
strv_free(s->sysctl);
diff --git a/src/nspawn/nspawn-settings.h b/src/nspawn/nspawn-settings.h
index cc802f77afa..231082706d4 100644
--- a/src/nspawn/nspawn-settings.h
+++ b/src/nspawn/nspawn-settings.h
@@ -254,4 +254,4 @@ TimezoneMode timezone_mode_from_string(const char *s) _pure_;
int parse_link_journal(const char *s, LinkJournal *ret_mode, bool *ret_try);
-void device_node_free_many(DeviceNode *node, size_t n);
+void device_node_array_free(DeviceNode *node, size_t n);
diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c
index ee930972ad6..5ff02130d65 100644
--- a/src/nspawn/nspawn.c
+++ b/src/nspawn/nspawn.c
@@ -3958,7 +3958,7 @@ static int merge_settings(Settings *settings, const char *path) {
arg_console_width = settings->console_width;
arg_console_height = settings->console_height;
- device_node_free_many(arg_extra_nodes, arg_n_extra_nodes);
+ 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;
@@ -5066,7 +5066,7 @@ finish:
custom_mount_free_all(arg_custom_mounts, arg_n_custom_mounts);
expose_port_free_all(arg_expose_ports);
rlimit_free_all(arg_rlimit);
- device_node_free_many(arg_extra_nodes, arg_n_extra_nodes);
+ device_node_array_free(arg_extra_nodes, arg_n_extra_nodes);
if (r < 0)
return r;
diff --git a/src/test/test-tables.c b/src/test/test-tables.c
index 070d1b4fe09..59f90b76ec4 100644
--- a/src/test/test-tables.c
+++ b/src/test/test-tables.c
@@ -70,7 +70,7 @@ int main(int argc, char **argv) {
test_table(kill_who, KILL_WHO);
test_table(locale_variable, VARIABLE_LC);
test_table(log_target, LOG_TARGET);
- test_table(mac_policy, MACPOLICY);
+ test_table(mac_address_policy, MAC_ADDRESS_POLICY);
test_table(manager_state, MANAGER_STATE);
test_table(manager_timestamp, MANAGER_TIMESTAMP);
test_table(mount_exec_command, MOUNT_EXEC_COMMAND);
diff --git a/src/udev/net/link-config-gperf.gperf b/src/udev/net/link-config-gperf.gperf
index 558996cf2e8..dff849a34af 100644
--- a/src/udev/net/link-config-gperf.gperf
+++ b/src/udev/net/link-config-gperf.gperf
@@ -19,36 +19,36 @@ struct ConfigPerfItem;
%struct-type
%includes
%%
-Match.MACAddress, config_parse_hwaddrs, 0, offsetof(link_config, match_mac)
-Match.OriginalName, config_parse_ifnames, 0, offsetof(link_config, match_name)
-Match.Path, config_parse_strv, 0, offsetof(link_config, match_path)
-Match.Driver, config_parse_strv, 0, offsetof(link_config, match_driver)
-Match.Type, config_parse_strv, 0, offsetof(link_config, match_type)
-Match.Host, config_parse_net_condition, CONDITION_HOST, offsetof(link_config, conditions)
-Match.Virtualization, config_parse_net_condition, CONDITION_VIRTUALIZATION, offsetof(link_config, conditions)
-Match.KernelCommandLine, config_parse_net_condition, CONDITION_KERNEL_COMMAND_LINE, offsetof(link_config, conditions)
-Match.KernelVersion, config_parse_net_condition, CONDITION_KERNEL_VERSION, offsetof(link_config, conditions)
-Match.Architecture, config_parse_net_condition, CONDITION_ARCHITECTURE, offsetof(link_config, conditions)
-Link.Description, config_parse_string, 0, offsetof(link_config, description)
-Link.MACAddressPolicy, config_parse_mac_policy, 0, offsetof(link_config, mac_policy)
-Link.MACAddress, config_parse_hwaddr, 0, offsetof(link_config, mac)
-Link.NamePolicy, config_parse_name_policy, 0, offsetof(link_config, name_policy)
-Link.Name, config_parse_ifname, 0, offsetof(link_config, name)
-Link.Alias, config_parse_ifalias, 0, offsetof(link_config, alias)
-Link.MTUBytes, config_parse_mtu, AF_UNSPEC, offsetof(link_config, mtu)
-Link.BitsPerSecond, config_parse_si_size, 0, offsetof(link_config, speed)
-Link.Duplex, config_parse_duplex, 0, offsetof(link_config, duplex)
-Link.AutoNegotiation, config_parse_tristate, 0, offsetof(link_config, autonegotiation)
-Link.WakeOnLan, config_parse_wol, 0, offsetof(link_config, wol)
-Link.Port, config_parse_port, 0, offsetof(link_config, port)
-Link.GenericSegmentationOffload, config_parse_tristate, 0, offsetof(link_config, features[NET_DEV_FEAT_GSO])
-Link.TCPSegmentationOffload, config_parse_tristate, 0, offsetof(link_config, features[NET_DEV_FEAT_TSO])
-Link.TCP6SegmentationOffload, config_parse_tristate, 0, offsetof(link_config, features[NET_DEV_FEAT_TSO6])
-Link.UDPSegmentationOffload, config_parse_warn_compat, DISABLED_LEGACY, 0
-Link.GenericReceiveOffload, config_parse_tristate, 0, offsetof(link_config, features[NET_DEV_FEAT_GRO])
-Link.LargeReceiveOffload, config_parse_tristate, 0, offsetof(link_config, features[NET_DEV_FEAT_LRO])
-Link.RxChannels, config_parse_channel, 0, 0
-Link.TxChannels, config_parse_channel, 0, 0
-Link.OtherChannels, config_parse_channel, 0, 0
-Link.CombinedChannels, config_parse_channel, 0, 0
-Link.Advertise, config_parse_advertise, 0, 0
+Match.MACAddress, config_parse_hwaddrs, 0, offsetof(link_config, match_mac)
+Match.OriginalName, config_parse_ifnames, 0, offsetof(link_config, match_name)
+Match.Path, config_parse_strv, 0, offsetof(link_config, match_path)
+Match.Driver, config_parse_strv, 0, offsetof(link_config, match_driver)
+Match.Type, config_parse_strv, 0, offsetof(link_config, match_type)
+Match.Host, config_parse_net_condition, CONDITION_HOST, offsetof(link_config, conditions)
+Match.Virtualization, config_parse_net_condition, CONDITION_VIRTUALIZATION, offsetof(link_config, conditions)
+Match.KernelCommandLine, config_parse_net_condition, CONDITION_KERNEL_COMMAND_LINE, offsetof(link_config, conditions)
+Match.KernelVersion, config_parse_net_condition, CONDITION_KERNEL_VERSION, offsetof(link_config, conditions)
+Match.Architecture, config_parse_net_condition, CONDITION_ARCHITECTURE, offsetof(link_config, conditions)
+Link.Description, config_parse_string, 0, offsetof(link_config, description)
+Link.MACAddressPolicy, config_parse_mac_address_policy, 0, offsetof(link_config, mac_address_policy)
+Link.MACAddress, config_parse_hwaddr, 0, offsetof(link_config, mac)
+Link.NamePolicy, config_parse_name_policy, 0, offsetof(link_config, name_policy)
+Link.Name, config_parse_ifname, 0, offsetof(link_config, name)
+Link.Alias, config_parse_ifalias, 0, offsetof(link_config, alias)
+Link.MTUBytes, config_parse_mtu, AF_UNSPEC, offsetof(link_config, mtu)
+Link.BitsPerSecond, config_parse_si_size, 0, offsetof(link_config, speed)
+Link.Duplex, config_parse_duplex, 0, offsetof(link_config, duplex)
+Link.AutoNegotiation, config_parse_tristate, 0, offsetof(link_config, autonegotiation)
+Link.WakeOnLan, config_parse_wol, 0, offsetof(link_config, wol)
+Link.Port, config_parse_port, 0, offsetof(link_config, port)
+Link.GenericSegmentationOffload, config_parse_tristate, 0, offsetof(link_config, features[NET_DEV_FEAT_GSO])
+Link.TCPSegmentationOffload, config_parse_tristate, 0, offsetof(link_config, features[NET_DEV_FEAT_TSO])
+Link.TCP6SegmentationOffload, config_parse_tristate, 0, offsetof(link_config, features[NET_DEV_FEAT_TSO6])
+Link.UDPSegmentationOffload, config_parse_warn_compat, DISABLED_LEGACY, 0
+Link.GenericReceiveOffload, config_parse_tristate, 0, offsetof(link_config, features[NET_DEV_FEAT_GRO])
+Link.LargeReceiveOffload, config_parse_tristate, 0, offsetof(link_config, features[NET_DEV_FEAT_LRO])
+Link.RxChannels, config_parse_channel, 0, 0
+Link.TxChannels, config_parse_channel, 0, 0
+Link.OtherChannels, config_parse_channel, 0, 0
+Link.CombinedChannels, config_parse_channel, 0, 0
+Link.Advertise, config_parse_advertise, 0, 0
diff --git a/src/udev/net/link-config.c b/src/udev/net/link-config.c
index 58d5d278836..daa737a68d4 100644
--- a/src/udev/net/link-config.c
+++ b/src/udev/net/link-config.c
@@ -139,7 +139,7 @@ int link_load_one(link_config_ctx *ctx, const char *filename) {
*link = (link_config) {
.filename = TAKE_PTR(name),
- .mac_policy = _MACPOLICY_INVALID,
+ .mac_address_policy = _MAC_ADDRESS_POLICY_INVALID,
.wol = _WOL_INVALID,
.duplex = _DUP_INVALID,
.port = _NET_DEV_PORT_INVALID,
@@ -280,12 +280,12 @@ int link_config_get(link_config_ctx *ctx, sd_device *device, link_config **ret)
return -ENOENT;
}
-static int get_mac(sd_device *device, MACPolicy policy, struct ether_addr *mac) {
+static int get_mac(sd_device *device, MACAddressPolicy policy, struct ether_addr *mac) {
unsigned addr_type;
- bool want_random = policy == MACPOLICY_RANDOM;
+ bool want_random = policy == MAC_ADDRESS_POLICY_RANDOM;
int r;
- assert(IN_SET(policy, MACPOLICY_RANDOM, MACPOLICY_PERSISTENT));
+ assert(IN_SET(policy, MAC_ADDRESS_POLICY_RANDOM, MAC_ADDRESS_POLICY_PERSISTENT));
r = link_unsigned_attribute(device, "addr_assign_type", &addr_type);
if (r < 0)
@@ -304,7 +304,7 @@ static int get_mac(sd_device *device, MACPolicy policy, struct ether_addr *mac)
if (want_random == (addr_type == NET_ADDR_RANDOM))
return log_device_debug(device, "MAC on the device already matches policy *%s*",
- mac_policy_to_string(policy));
+ mac_address_policy_to_string(policy));
if (want_random) {
log_device_debug(device, "Using random bytes to generate MAC");
@@ -444,8 +444,8 @@ int link_config_apply(link_config_ctx *ctx, link_config *config,
log_device_debug(device, "Policies didn't yield a name and Name= is not given, not renaming.");
no_rename:
- if (IN_SET(config->mac_policy, MACPOLICY_PERSISTENT, MACPOLICY_RANDOM)) {
- if (get_mac(device, config->mac_policy, &generated_mac) > 0)
+ if (IN_SET(config->mac_address_policy, MAC_ADDRESS_POLICY_PERSISTENT, MAC_ADDRESS_POLICY_RANDOM)) {
+ if (get_mac(device, config->mac_address_policy, &generated_mac) > 0)
mac = &generated_mac;
} else
mac = config->mac;
@@ -476,14 +476,14 @@ int link_get_driver(link_config_ctx *ctx, sd_device *device, char **ret) {
return 0;
}
-static const char* const mac_policy_table[_MACPOLICY_MAX] = {
- [MACPOLICY_PERSISTENT] = "persistent",
- [MACPOLICY_RANDOM] = "random",
- [MACPOLICY_NONE] = "none",
+static const char* const mac_address_policy_table[_MAC_ADDRESS_POLICY_MAX] = {
+ [MAC_ADDRESS_POLICY_PERSISTENT] = "persistent",
+ [MAC_ADDRESS_POLICY_RANDOM] = "random",
+ [MAC_ADDRESS_POLICY_NONE] = "none",
};
-DEFINE_STRING_TABLE_LOOKUP(mac_policy, MACPolicy);
-DEFINE_CONFIG_PARSE_ENUM(config_parse_mac_policy, mac_policy, MACPolicy,
+DEFINE_STRING_TABLE_LOOKUP(mac_address_policy, MACAddressPolicy);
+DEFINE_CONFIG_PARSE_ENUM(config_parse_mac_address_policy, mac_address_policy, MACAddressPolicy,
"Failed to parse MAC address policy");
static const char* const name_policy_table[_NAMEPOLICY_MAX] = {
diff --git a/src/udev/net/link-config.h b/src/udev/net/link-config.h
index f18b2afa79b..5dfe5b59b88 100644
--- a/src/udev/net/link-config.h
+++ b/src/udev/net/link-config.h
@@ -12,13 +12,13 @@
typedef struct link_config_ctx link_config_ctx;
typedef struct link_config link_config;
-typedef enum MACPolicy {
- MACPOLICY_PERSISTENT,
- MACPOLICY_RANDOM,
- MACPOLICY_NONE,
- _MACPOLICY_MAX,
- _MACPOLICY_INVALID = -1
-} MACPolicy;
+typedef enum MACAddressPolicy {
+ MAC_ADDRESS_POLICY_PERSISTENT,
+ MAC_ADDRESS_POLICY_RANDOM,
+ MAC_ADDRESS_POLICY_NONE,
+ _MAC_ADDRESS_POLICY_MAX,
+ _MAC_ADDRESS_POLICY_INVALID = -1
+} MACAddressPolicy;
typedef enum NamePolicy {
NAMEPOLICY_KERNEL,
@@ -44,7 +44,7 @@ struct link_config {
char *description;
struct ether_addr *mac;
- MACPolicy mac_policy;
+ MACAddressPolicy mac_address_policy;
NamePolicy *name_policy;
char *name;
char *alias;
@@ -76,11 +76,11 @@ int link_get_driver(link_config_ctx *ctx, sd_device *device, char **ret);
const char *name_policy_to_string(NamePolicy p) _const_;
NamePolicy name_policy_from_string(const char *p) _pure_;
-const char *mac_policy_to_string(MACPolicy p) _const_;
-MACPolicy mac_policy_from_string(const char *p) _pure_;
+const char *mac_address_policy_to_string(MACAddressPolicy p) _const_;
+MACAddressPolicy mac_address_policy_from_string(const char *p) _pure_;
/* gperf lookup function */
const struct ConfigPerfItem* link_config_gperf_lookup(const char *key, GPERF_LEN_TYPE length);
-CONFIG_PARSER_PROTOTYPE(config_parse_mac_policy);
+CONFIG_PARSER_PROTOTYPE(config_parse_mac_address_policy);
CONFIG_PARSER_PROTOTYPE(config_parse_name_policy);
diff --git a/test/fuzz/fuzz-nspawn-oci/basic.json b/test/fuzz/fuzz-nspawn-oci/basic.json
new file mode 100644
index 00000000000..f42739e03a0
--- /dev/null
+++ b/test/fuzz/fuzz-nspawn-oci/basic.json
@@ -0,0 +1,141 @@
+{
+ "ociVersion": "1.0.0",
+
+ "root": {
+ "path": "rootfs",
+ "readonly": true
+ },
+
+ "process": {
+ "terminal": false,
+ "consoleSize": {
+ "height":6667,
+ "width":6668
+ },
+
+ "user": {
+ "uid": 14,
+ "gid": 14,
+ "additionalGids": [59, 81]
+ },
+
+ "args": [
+ "/tmp/verify.sh"
+ ],
+
+ "env": [
+ "FOO=BAR",
+ "WITHSPACES=FOO BAR",
+ "WITHSHELLCHARS=$ASDF \\\"asdf asdf\\\" !",
+ "WITHCONTROLCHARS=\\123\\125\\010\\020",
+ "TERM=xterm"
+ ],
+
+ "cwd": "/tmp/src",
+
+ "rlimits": [
+ {
+ "type": "RLIMIT_NOFILE",
+ "hard": 1020,
+ "soft": 1020
+ }
+ ]
+ },
+
+ "mounts": [
+ {
+ "destination": "/tmp/src",
+ "source": "src",
+ "options": ["ro"]
+ },
+
+ {
+ "destination": "/tmp/verify.sh",
+ "source": "verify.sh",
+ "options": ["ro"]
+ },
+
+ {
+ "destination": "/proc",
+ "type": "proc",
+ "source": "proc"
+ },
+ {
+ "destination": "/dev",
+ "type": "tmpfs",
+ "source": "tmpfs",
+ "options": [
+ "mode=777"
+ ]
+ },
+ {
+ "destination": "/dev/pts",
+ "type": "devpts",
+ "source": "devpts",
+ "options": [
+ "mode=777"
+ ]
+ },
+ {
+ "destination": "/dev/shm",
+ "type": "tmpfs",
+ "source": "shm",
+ "options": [
+ "mode=777"
+ ]
+ },
+ {
+ "destination": "/dev/mqueue",
+ "type": "mqueue",
+ "source": "mqueue",
+ "options": [
+ "mode=777"
+ ]
+ },
+ {
+ "destination": "/sys",
+ "type": "sysfs",
+ "source": "sysfs",
+ "options": [
+ "mode=777"
+ ]
+ },
+ {
+ "destination": "/sys/fs/cgroup",
+ "type": "cgroup",
+ "source": "cgroup",
+ "options": [
+ "mode=777"
+ ]
+ }
+ ],
+
+ "hooks": {},
+
+ "linux": {
+ "resources": {
+ "devices": [
+ {
+ "allow": false,
+ "access": "rwm"
+ }
+ ]
+ },
+ "namespaces": [
+ {
+ "type": "pid"
+ },
+ {
+ "type": "ipc"
+ },
+ {
+ "type": "mount"
+ }
+ ]
+ },
+
+ "annotations": {
+ "com.example.key1": "value1",
+ "com.example.key2": "value2"
+ }
+}
diff --git a/test/fuzz/fuzz-nspawn-oci/crash-bffbd2085d4e95c47e9749b3f4a2dbc0580c20d3 b/test/fuzz/fuzz-nspawn-oci/crash-bffbd2085d4e95c47e9749b3f4a2dbc0580c20d3
new file mode 100644
index 00000000000..22e42d3bad2
--- /dev/null
+++ b/test/fuzz/fuzz-nspawn-oci/crash-bffbd2085d4e95c47e9749b3f4a2dbc0580c20d3
@@ -0,0 +1,5 @@
+{"ociVersion": "1.0.0",
+"linux": {"devices": [ { "access": "mmmw;r"}
+] }, "e": "}e"
+ }
+ \ No newline at end of file
diff --git a/test/fuzz/fuzz-nspawn-oci/crash-db0595479ee2e625fa5419a821009b5eb4d809b7 b/test/fuzz/fuzz-nspawn-oci/crash-db0595479ee2e625fa5419a821009b5eb4d809b7
new file mode 100644
index 00000000000..0bf017ce6e9
--- /dev/null
+++ b/test/fuzz/fuzz-nspawn-oci/crash-db0595479ee2e625fa5419a821009b5eb4d809b7
@@ -0,0 +1,92 @@
+{
+ "ociVersion": "1.0.0",
+
+ "root": {
+ "path": "rootfs",
+ "readonly": true
+ },
+
+ "process": {
+ "terminal": false,
+ "consoleSize": {
+ "height":6667,
+ "width":6668
+ },
+
+ "user": {
+ "uid": 14,
+ "gid": 14,
+ "additionalGids": [59, 81]
+ },
+
+ "args": [
+ "/tmp/verify.sh"
+ ],
+
+ "env": [
+ "FOO=BAR",
+ "WITHSPACES=FOO BAR",
+ "WITHSHELLCHARS=$ASDF \\\"asdf asdf\\\" !",
+ "WITHCONTROLCHARS=\\123\\125\\010\\020",
+ "TERM=xterm"
+ ],
+
+ "cwd": "/tmp/src",
+
+ "rlimits": [
+ {
+ "type": "RLIMIT_NOFILE",
+ "hard": 1020,
+ "soft": 1020
+ }
+ ]
+ },
+
+ "mounts": [
+ {
+ "destination": "/tmp/src" },
+ {
+ "source": "sysfs",
+ "options": [
+ "mode=777"
+ ]
+ },
+ {
+ "destination": "/sys/fs/cgroup",
+ "type": "cgroup",
+ "source": "cgroup",
+ "options": [
+ "mode=777"
+ ]
+ }
+ ],
+
+ "hooks": {},
+
+ "linux": {
+ "resources": {
+ "devices": [
+ {
+ "allow": false,
+ "access": "rwm"
+ }
+ ]
+ },
+ "namespaces": [
+ {
+ "type": "pid"
+ },
+ {
+ "type": "ipc"
+ },
+ {
+ "type": "mount"
+ }
+ ]
+ },
+
+ "annotations": {
+ "com.example.key1": "value1",
+ "com.example.key2": "value2"
+ }
+}