diff --git a/meson.build b/meson.build index 1c4febfa4b..02e230415d 100644 --- a/meson.build +++ b/meson.build @@ -781,6 +781,7 @@ conf.set10('ENABLE_DEBUG_HASHMAP', enable_debug_hashmap) conf.set10('ENABLE_DEBUG_MMAP_CACHE', enable_debug_mmap_cache) conf.set10('VALGRIND', get_option('valgrind')) +conf.set10('LOG_TRACE', get_option('log-trace')) ##################################################################### @@ -1476,7 +1477,7 @@ foreach tuple : [['myhostname', 'ENABLE_NSS_MYHOSTNAME'], module = tuple[0] sym = 'src/nss-@0@/nss-@0@.sym'.format(module) - version_script_arg = join_paths(meson.current_source_dir(), sym) + version_script_arg = join_paths(meson.source_root(), sym) nss = shared_library( 'nss_' + module, @@ -1731,7 +1732,7 @@ if conf.get('ENABLE_LOGIND') == 1 public_programs += exe if conf.get('HAVE_PAM') == 1 - version_script_arg = join_paths(meson.current_source_dir(), pam_systemd_sym) + version_script_arg = join_paths(meson.source_root(), pam_systemd_sym) pam_systemd = shared_library( 'pam_systemd', pam_systemd_c, @@ -2847,9 +2848,7 @@ foreach tuple : sanitizers test('@0@:@1@:@2@'.format(b, c, sanitizer), env, args : [exe.full_path(), - join_paths(meson.source_root(), - 'test/fuzz-regressions', - p)]) + join_paths(meson.source_root(), p)]) endif endforeach endif @@ -2861,7 +2860,7 @@ endforeach if git.found() all_files = run_command( git, - ['--git-dir=@0@/.git'.format(meson.current_source_dir()), + ['--git-dir=@0@/.git'.format(meson.source_root()), 'ls-files', ':/*.[ch]']) all_files = files(all_files.stdout().split()) @@ -2869,10 +2868,10 @@ if git.found() custom_target( 'tags', output : 'tags', - command : [env, 'etags', '-o', '@0@/TAGS'.format(meson.current_source_dir())] + all_files) + command : [env, 'etags', '-o', '@0@/TAGS'.format(meson.source_root())] + all_files) run_target( 'ctags', - command : [env, 'ctags', '-o', '@0@/tags'.format(meson.current_source_dir())] + all_files) + command : [env, 'ctags', '-o', '@0@/tags'.format(meson.source_root())] + all_files) endif if git.found() @@ -2885,17 +2884,17 @@ endif if git.found() git_head = run_command( git, - ['--git-dir=@0@/.git'.format(meson.current_source_dir()), + ['--git-dir=@0@/.git'.format(meson.source_root()), 'rev-parse', 'HEAD']).stdout().strip() git_head_short = run_command( git, - ['--git-dir=@0@/.git'.format(meson.current_source_dir()), + ['--git-dir=@0@/.git'.format(meson.source_root()), 'rev-parse', '--short=7', 'HEAD']).stdout().strip() run_target( 'git-snapshot', command : ['git', 'archive', - '-o', '@0@/systemd-@1@.tar.gz'.format(meson.current_source_dir(), + '-o', '@0@/systemd-@1@.tar.gz'.format(meson.source_root(), git_head_short), '--prefix', 'systemd-@0@/'.format(git_head), 'HEAD']) @@ -3053,10 +3052,10 @@ foreach tuple : [ ['blkid'], ['dbus'], ['glib'], - ['nss-myhostname', conf.get('ENABLE_NSS_MYHOSTNAME') == 1], - ['nss-mymachines', conf.get('ENABLE_NSS_MYMACHINES') == 1], - ['nss-resolve', conf.get('ENABLE_NSS_RESOLVE') == 1], - ['nss-systemd', conf.get('ENABLE_NSS_SYSTEMD') == 1], + ['nss-myhostname'], + ['nss-mymachines'], + ['nss-resolve'], + ['nss-systemd'], ['hwdb'], ['tpm'], ['man pages', want_man], @@ -3072,6 +3071,7 @@ foreach tuple : [ ['debug hashmap'], ['debug mmap cache'], ['valgrind', conf.get('VALGRIND') == 1], + ['trace logging', conf.get('LOG_TRACE') == 1], ] if tuple.length() >= 2 diff --git a/meson_options.txt b/meson_options.txt index 0407b97b5b..83ade5bea4 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -51,6 +51,8 @@ option('memory-accounting-default', type : 'boolean', description : 'enable MemoryAccounting= by default') option('valgrind', type : 'boolean', value : false, description : 'do extra operations to avoid valgrind warnings') +option('log-trace', type : 'boolean', value : false, + description : 'enable low level debug logging') option('utmp', type : 'boolean', description : 'support for utmp/wtmp log handling') diff --git a/src/basic/string-util.c b/src/basic/string-util.c index 0a40683493..dfa739996f 100644 --- a/src/basic/string-util.c +++ b/src/basic/string-util.c @@ -1004,7 +1004,7 @@ int free_and_strdup(char **p, const char *s) { assert(p); - /* Replaces a string pointer with an strdup()ed new string, + /* Replaces a string pointer with a strdup()ed new string, * possibly freeing the old one. */ if (streq_ptr(*p, s)) @@ -1023,6 +1023,32 @@ int free_and_strdup(char **p, const char *s) { return 1; } +int free_and_strndup(char **p, const char *s, size_t l) { + char *t; + + assert(p); + assert(s || l == 0); + + /* Replaces a string pointer with a strndup()ed new string, + * freeing the old one. */ + + if (!*p && !s) + return 0; + + if (*p && s && strneq(*p, s, l) && (l > strlen(*p) || (*p)[l] == '\0')) + return 0; + + if (s) { + t = strndup(s, l); + if (!t) + return -ENOMEM; + } else + t = NULL; + + free_and_replace(*p, t); + return 1; +} + #if !HAVE_EXPLICIT_BZERO /* * Pointer to memset is volatile so that compiler must de-reference diff --git a/src/basic/string-util.h b/src/basic/string-util.h index fcd12f3a30..72c075aa39 100644 --- a/src/basic/string-util.h +++ b/src/basic/string-util.h @@ -176,6 +176,7 @@ char *strrep(const char *s, unsigned n); int split_pair(const char *s, const char *sep, char **l, char **r); int free_and_strdup(char **p, const char *s); +int free_and_strndup(char **p, const char *s, size_t l); /* Normal memmem() requires haystack to be nonnull, which is annoying for zero-length buffers */ static inline void *memmem_safe(const void *haystack, size_t haystacklen, const void *needle, size_t needlelen) { diff --git a/src/fuzz/fuzz-bus-message.c b/src/fuzz/fuzz-bus-message.c new file mode 100644 index 0000000000..9842c62a6f --- /dev/null +++ b/src/fuzz/fuzz-bus-message.c @@ -0,0 +1,47 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include + +#include "alloc-util.h" +#include "bus-dump.h" +#include "bus-message.h" +#include "env-util.h" +#include "fd-util.h" +#include "fuzz.h" + +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + _cleanup_free_ char *out = NULL; /* out should be freed after g */ + size_t out_size; + _cleanup_fclose_ FILE *g = NULL; + _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; + _cleanup_free_ void *buffer = NULL; + int r; + + /* 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); + + r = sd_bus_new(&bus); + assert_se(r >= 0); + + assert_se(buffer = memdup(data, size)); + + r = bus_message_from_malloc(bus, buffer, size, NULL, 0, NULL, &m); + if (r == -EBADMSG) + return 0; + assert_se(r >= 0); + TAKE_PTR(buffer); + + if (getenv_bool("SYSTEMD_FUZZ_OUTPUT") <= 0) + assert_se(g = open_memstream(&out, &out_size)); + + bus_message_dump(m, g ?: stdout, BUS_MESSAGE_DUMP_WITH_HEADER); + + r = sd_bus_message_rewind(m, true); + assert_se(r >= 0); + + return 0; +} diff --git a/src/fuzz/meson.build b/src/fuzz/meson.build index 066737c175..31ee41cbe0 100644 --- a/src/fuzz/meson.build +++ b/src/fuzz/meson.build @@ -1,6 +1,10 @@ # SPDX-License-Identifier: LGPL-2.1+ fuzzers += [ + [['src/fuzz/fuzz-bus-message.c'], + [libshared], + []], + [['src/fuzz/fuzz-dns-packet.c', dns_type_headers], [libsystemd_resolve_core, diff --git a/src/libsystemd/sd-bus/bus-dump.c b/src/libsystemd/sd-bus/bus-dump.c index 888f161768..506ed0d73c 100644 --- a/src/libsystemd/sd-bus/bus-dump.c +++ b/src/libsystemd/sd-bus/bus-dump.c @@ -57,8 +57,14 @@ int bus_message_dump(sd_bus_message *m, FILE *f, unsigned flags) { "%s%s%s Type=%s%s%s Endian=%c Flags=%u Version=%u Priority=%"PRIi64, m->header->type == SD_BUS_MESSAGE_METHOD_ERROR ? ansi_highlight_red() : m->header->type == SD_BUS_MESSAGE_METHOD_RETURN ? ansi_highlight_green() : - m->header->type != SD_BUS_MESSAGE_SIGNAL ? ansi_highlight() : "", special_glyph(TRIANGULAR_BULLET), ansi_normal(), - ansi_highlight(), bus_message_type_to_string(m->header->type), ansi_normal(), + m->header->type != SD_BUS_MESSAGE_SIGNAL ? ansi_highlight() : "", + special_glyph(TRIANGULAR_BULLET), + ansi_normal(), + + ansi_highlight(), + bus_message_type_to_string(m->header->type) ?: "(unknown)", + ansi_normal(), + m->header->endian, m->header->flags, m->header->version, diff --git a/src/libsystemd/sd-bus/bus-message.c b/src/libsystemd/sd-bus/bus-message.c index 6e404367db..697553e74e 100644 --- a/src/libsystemd/sd-bus/bus-message.c +++ b/src/libsystemd/sd-bus/bus-message.c @@ -75,19 +75,38 @@ static void message_reset_parts(sd_bus_message *m) { m->cached_rindex_part_begin = 0; } -static void message_reset_containers(sd_bus_message *m) { - unsigned i; - +static struct bus_container *message_get_last_container(sd_bus_message *m) { assert(m); - for (i = 0; i < m->n_containers; i++) { - free(m->containers[i].signature); - free(m->containers[i].offsets); - } + if (m->n_containers == 0) + return &m->root_container; + + assert(m->containers); + return m->containers + m->n_containers - 1; +} + +static void message_free_last_container(sd_bus_message *m) { + struct bus_container *c; + + c = message_get_last_container(m); + + free(c->signature); + free(c->peeked_signature); + free(c->offsets); + + /* Move to previous container, but not if we are on root container */ + if (m->n_containers > 0) + m->n_containers--; +} + +static void message_reset_containers(sd_bus_message *m) { + assert(m); + + while (m->n_containers > 0) + message_free_last_container(m); m->containers = mfree(m->containers); - - m->n_containers = m->containers_allocated = 0; + m->containers_allocated = 0; m->root_container.index = 0; } @@ -110,10 +129,8 @@ static sd_bus_message* message_free(sd_bus_message *m) { free(m->iovec); message_reset_containers(m); - free(m->root_container.signature); - free(m->root_container.offsets); - - free(m->root_container.peeked_signature); + assert(m->n_containers == 0); + message_free_last_container(m); bus_creds_done(&m->creds); return mfree(m); @@ -208,7 +225,7 @@ static int message_append_field_string( /* dbus1 doesn't allow strings over 32bit, let's enforce this * globally, to not risk convertability */ l = strlen(s); - if (l > (size_t) (uint32_t) -1) + if (l > UINT32_MAX) return -EINVAL; /* Signature "(yv)" where the variant contains "s" */ @@ -1088,16 +1105,6 @@ _public_ int sd_bus_message_set_allow_interactive_authorization(sd_bus_message * return 0; } -static struct bus_container *message_get_container(sd_bus_message *m) { - assert(m); - - if (m->n_containers == 0) - return &m->root_container; - - assert(m->containers); - return m->containers + m->n_containers - 1; -} - struct bus_body_part *message_append_part(sd_bus_message *m) { struct bus_body_part *part; @@ -1188,7 +1195,7 @@ static int message_add_offset(sd_bus_message *m, size_t offset) { /* Add offset to current container, unless this is the first * item in it, which will have the 0 offset, which we can * ignore. */ - c = message_get_container(m); + c = message_get_last_container(m); if (!c->need_offsets) return 0; @@ -1360,7 +1367,7 @@ int message_append_basic(sd_bus_message *m, char type, const void *p, const void assert_return(bus_type_is_basic(type), -EINVAL); assert_return(!m->poisoned, -ESTALE); - c = message_get_container(m); + c = message_get_last_container(m); if (c->signature && c->signature[c->index]) { /* Container signature is already set */ @@ -1553,7 +1560,7 @@ _public_ int sd_bus_message_append_string_space( assert_return(!m->sealed, -EPERM); assert_return(!m->poisoned, -ESTALE); - c = message_get_container(m); + c = message_get_last_container(m); if (c->signature && c->signature[c->index]) { /* Container signature is already set */ @@ -1924,7 +1931,7 @@ _public_ int sd_bus_message_open_container( char type, const char *contents) { - struct bus_container *c, *w; + struct bus_container *c; uint32_t *array_size = NULL; _cleanup_free_ char *signature = NULL; size_t before, begin = 0; @@ -1942,7 +1949,7 @@ _public_ int sd_bus_message_open_container( return -ENOMEM; } - c = message_get_container(m); + c = message_get_last_container(m); signature = strdup(contents); if (!signature) { @@ -1969,16 +1976,14 @@ _public_ int sd_bus_message_open_container( return r; /* OK, let's fill it in */ - w = m->containers + m->n_containers++; - w->enclosing = type; - w->signature = TAKE_PTR(signature); - w->index = 0; - w->array_size = array_size; - w->before = before; - w->begin = begin; - w->n_offsets = w->offsets_allocated = 0; - w->offsets = NULL; - w->need_offsets = need_offsets; + m->containers[m->n_containers++] = (struct bus_container) { + .enclosing = type, + .signature = TAKE_PTR(signature), + .array_size = array_size, + .before = before, + .begin = begin, + .need_offsets = need_offsets, + }; return 0; } @@ -2169,7 +2174,7 @@ _public_ int sd_bus_message_close_container(sd_bus_message *m) { assert_return(m->n_containers > 0, -EINVAL); assert_return(!m->poisoned, -ESTALE); - c = message_get_container(m); + c = message_get_last_container(m); if (c->enclosing != SD_BUS_TYPE_ARRAY) if (c->signature && c->signature[c->index] != 0) @@ -2439,11 +2444,6 @@ _public_ int sd_bus_message_append(sd_bus_message *m, const char *types, ...) { va_list ap; int r; - assert_return(m, -EINVAL); - assert_return(types, -EINVAL); - assert_return(!m->sealed, -EPERM); - assert_return(!m->poisoned, -ESTALE); - va_start(ap, types); r = sd_bus_message_appendv(m, types, ap); va_end(ap); @@ -2673,7 +2673,7 @@ _public_ int sd_bus_message_append_string_memfd( if (size > (uint64_t) (uint32_t) -1) return -EINVAL; - c = message_get_container(m); + c = message_get_last_container(m); if (c->signature && c->signature[c->index]) { /* Container signature is already set */ @@ -3006,7 +3006,7 @@ static bool message_end_of_signature(sd_bus_message *m) { assert(m); - c = message_get_container(m); + c = message_get_last_container(m); return !c->signature || c->signature[c->index] == 0; } @@ -3015,7 +3015,7 @@ static bool message_end_of_array(sd_bus_message *m, size_t index) { assert(m); - c = message_get_container(m); + c = message_get_last_container(m); if (c->enclosing != SD_BUS_TYPE_ARRAY) return false; @@ -3110,6 +3110,7 @@ static int container_next_item(sd_bus_message *m, struct bus_container *c, size_ assert(alignment > 0); *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment); + assert(c->offsets[c->offset_index+1] >= *rindex); c->item_size = c->offsets[c->offset_index+1] - *rindex; } else { @@ -3149,6 +3150,7 @@ static int container_next_item(sd_bus_message *m, struct bus_container *c, size_ assert(alignment > 0); *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment); + assert(c->offsets[c->offset_index+1] >= *rindex); c->item_size = c->offsets[c->offset_index+1] - *rindex; c->offset_index++; @@ -3276,7 +3278,7 @@ _public_ int sd_bus_message_read_basic(sd_bus_message *m, char type, void *p) { if (message_end_of_array(m, m->rindex)) return 0; - c = message_get_container(m); + c = message_get_last_container(m); if (c->signature[c->index] != type) return -ENXIO; @@ -3287,6 +3289,12 @@ _public_ int sd_bus_message_read_basic(sd_bus_message *m, char type, void *p) { if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE)) { bool ok; + /* D-Bus spec: The marshalling formats for the string-like types all end + * with a single zero (NUL) byte, but that byte is not considered to be part + * of the text. */ + if (c->item_size == 0) + return -EBADMSG; + r = message_peek_body(m, &rindex, 1, c->item_size, &q); if (r < 0) return r; @@ -3381,6 +3389,10 @@ _public_ int sd_bus_message_read_basic(sd_bus_message *m, char type, void *p) { return r; l = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q); + if (l == UINT32_MAX) + /* avoid overflow right below */ + return -EBADMSG; + r = message_peek_body(m, &rindex, 1, l+1, &q); if (r < 0) return r; @@ -3403,6 +3415,10 @@ _public_ int sd_bus_message_read_basic(sd_bus_message *m, char type, void *p) { return r; l = *(uint8_t*) q; + if (l == UINT8_MAX) + /* avoid overflow right below */ + return -EBADMSG; + r = message_peek_body(m, &rindex, 1, l+1, &q); if (r < 0) return r; @@ -3494,7 +3510,7 @@ static int bus_message_enter_array( size_t rindex; void *q; - int r, alignment; + int r; assert(m); assert(c); @@ -3520,6 +3536,7 @@ static int bus_message_enter_array( if (!BUS_MESSAGE_IS_GVARIANT(m)) { /* dbus1 */ + int alignment; r = message_peek_body(m, &rindex, 4, 4, &q); if (r < 0) @@ -3553,7 +3570,8 @@ static int bus_message_enter_array( *n_offsets = 0; } else { - size_t where, p = 0, framing, sz; + size_t where, previous = 0, framing, sz; + int alignment; unsigned i; /* gvariant: variable length array */ @@ -3581,17 +3599,22 @@ static int bus_message_enter_array( if (!*offsets) return -ENOMEM; + alignment = bus_gvariant_get_alignment(c->signature); + assert(alignment > 0); + for (i = 0; i < *n_offsets; i++) { - size_t x; + size_t x, start; + + start = ALIGN_TO(previous, alignment); x = bus_gvariant_read_word_le((uint8_t*) q + i * sz, sz); if (x > c->item_size - sz) return -EBADMSG; - if (x < p) + if (x < start) return -EBADMSG; (*offsets)[i] = rindex + x; - p = x; + previous = x; } *item_size = (*offsets)[0] - rindex; @@ -3661,6 +3684,10 @@ static int bus_message_enter_variant( return r; l = *(uint8_t*) q; + if (l == UINT8_MAX) + /* avoid overflow right below */ + return -EBADMSG; + r = message_peek_body(m, &rindex, 1, l+1, &q); if (r < 0) return r; @@ -3689,7 +3716,7 @@ static int build_struct_offsets( size_t *n_offsets) { unsigned n_variable = 0, n_total = 0, v; - size_t previous = 0, where; + size_t previous, where; const char *p; size_t sz; void *q; @@ -3768,6 +3795,7 @@ static int build_struct_offsets( /* Second, loop again and build an offset table */ p = signature; + previous = m->rindex; while (*p != 0) { size_t n, offset; int k; @@ -3781,37 +3809,37 @@ static int build_struct_offsets( memcpy(t, p, n); t[n] = 0; + size_t align = bus_gvariant_get_alignment(t); + assert(align > 0); + + /* The possible start of this member after including alignment */ + size_t start = ALIGN_TO(previous, align); + k = bus_gvariant_get_size(t); if (k < 0) { size_t x; - /* variable size */ + /* Variable size */ if (v > 0) { v--; x = bus_gvariant_read_word_le((uint8_t*) q + v*sz, sz); if (x >= size) return -EBADMSG; - if (m->rindex + x < previous) - return -EBADMSG; } else - /* The last item's end - * is determined from - * the start of the - * offset array */ + /* The last item's end is determined + * from the start of the offset array */ x = size - (n_variable * sz); offset = m->rindex + x; - - } else { - size_t align; - - /* fixed size */ - align = bus_gvariant_get_alignment(t); - assert(align > 0); - - offset = (*n_offsets == 0 ? m->rindex : ALIGN_TO((*offsets)[*n_offsets-1], align)) + k; - } + if (offset < start) { + log_debug("For type %s with alignment %zu, message specifies offset %zu which is smaller than previous end %zu + alignment = %zu", + t, align, offset, previous, start); + return -EBADMSG; + } + } else + /* Fixed size */ + offset = start + k; } previous = (*offsets)[(*n_offsets)++] = offset; @@ -3941,10 +3969,10 @@ static int bus_message_enter_dict_entry( _public_ int sd_bus_message_enter_container(sd_bus_message *m, char type, const char *contents) { - struct bus_container *c, *w; + struct bus_container *c; uint32_t *array_size = NULL; _cleanup_free_ char *signature = NULL; - size_t before; + size_t before, end; _cleanup_free_ size_t *offsets = NULL; size_t n_offsets = 0, item_size = 0; int r; @@ -4000,7 +4028,7 @@ _public_ int sd_bus_message_enter_container(sd_bus_message *m, if (message_end_of_array(m, m->rindex)) return 0; - c = message_get_container(m); + c = message_get_last_container(m); signature = strdup(contents); if (!signature) @@ -4023,28 +4051,26 @@ _public_ int sd_bus_message_enter_container(sd_bus_message *m, return r; /* OK, let's fill it in */ - w = m->containers + m->n_containers++; - w->enclosing = type; - w->signature = TAKE_PTR(signature); - w->peeked_signature = NULL; - w->index = 0; - - w->before = before; - w->begin = m->rindex; - - /* Unary type has fixed size of 1, but virtual size of 0 */ if (BUS_MESSAGE_IS_GVARIANT(m) && type == SD_BUS_TYPE_STRUCT && isempty(signature)) - w->end = m->rindex + 0; + end = m->rindex + 0; else - w->end = m->rindex + c->item_size; + end = m->rindex + c->item_size; + + m->containers[m->n_containers++] = (struct bus_container) { + .enclosing = type, + .signature = TAKE_PTR(signature), - w->array_size = array_size; - w->item_size = item_size; - w->offsets = TAKE_PTR(offsets); - w->n_offsets = n_offsets; - w->offset_index = 0; + .before = before, + .begin = m->rindex, + /* Unary type has fixed size of 1, but virtual size of 0 */ + .end = end, + .array_size = array_size, + .item_size = item_size, + .offsets = TAKE_PTR(offsets), + .n_offsets = n_offsets, + }; return 1; } @@ -4058,7 +4084,7 @@ _public_ int sd_bus_message_exit_container(sd_bus_message *m) { assert_return(m->sealed, -EPERM); assert_return(m->n_containers > 0, -ENXIO); - c = message_get_container(m); + c = message_get_last_container(m); if (c->enclosing != SD_BUS_TYPE_ARRAY) { if (c->signature && c->signature[c->index] != 0) @@ -4077,13 +4103,9 @@ _public_ int sd_bus_message_exit_container(sd_bus_message *m) { return -EBUSY; } - free(c->signature); - free(c->peeked_signature); - free(c->offsets); - m->n_containers--; - - c = message_get_container(m); + message_free_last_container(m); + c = message_get_last_container(m); saved = c->index; c->index = c->saved_index; r = container_next_item(m, c, &m->rindex); @@ -4101,19 +4123,16 @@ static void message_quit_container(sd_bus_message *m) { assert(m->sealed); assert(m->n_containers > 0); - c = message_get_container(m); - /* Undo seeks */ + c = message_get_last_container(m); assert(m->rindex >= c->before); m->rindex = c->before; /* Free container */ - free(c->signature); - free(c->offsets); - m->n_containers--; + message_free_last_container(m); /* Correct index of new top-level container */ - c = message_get_container(m); + c = message_get_last_container(m); c->index = c->saved_index; } @@ -4130,7 +4149,7 @@ _public_ int sd_bus_message_peek_type(sd_bus_message *m, char *type, const char if (message_end_of_array(m, m->rindex)) goto eof; - c = message_get_container(m); + c = message_get_last_container(m); if (bus_type_is_basic(c->signature[c->index])) { if (contents) @@ -4144,20 +4163,20 @@ _public_ int sd_bus_message_peek_type(sd_bus_message *m, char *type, const char if (contents) { size_t l; - char *sig; r = signature_element_length(c->signature+c->index+1, &l); if (r < 0) return r; - assert(l >= 1); + /* signature_element_length does verification internally */ - sig = strndup(c->signature + c->index + 1, l); - if (!sig) + /* The array element must not be empty */ + assert(l >= 1); + if (free_and_strndup(&c->peeked_signature, + c->signature + c->index + 1, l) < 0) return -ENOMEM; - free(c->peeked_signature); - *contents = c->peeked_signature = sig; + *contents = c->peeked_signature; } if (type) @@ -4170,19 +4189,17 @@ _public_ int sd_bus_message_peek_type(sd_bus_message *m, char *type, const char if (contents) { size_t l; - char *sig; r = signature_element_length(c->signature+c->index, &l); if (r < 0) return r; - assert(l >= 2); - sig = strndup(c->signature + c->index + 1, l - 2); - if (!sig) + assert(l >= 3); + if (free_and_strndup(&c->peeked_signature, + c->signature + c->index + 1, l - 2) < 0) return -ENOMEM; - free(c->peeked_signature); - *contents = c->peeked_signature = sig; + *contents = c->peeked_signature; } if (type) @@ -4222,9 +4239,8 @@ _public_ int sd_bus_message_peek_type(sd_bus_message *m, char *type, const char if (k > c->item_size) return -EBADMSG; - free(c->peeked_signature); - c->peeked_signature = strndup((char*) q + 1, k - 1); - if (!c->peeked_signature) + if (free_and_strndup(&c->peeked_signature, + (char*) q + 1, k - 1) < 0) return -ENOMEM; if (!signature_is_valid(c->peeked_signature, true)) @@ -4240,6 +4256,10 @@ _public_ int sd_bus_message_peek_type(sd_bus_message *m, char *type, const char return r; l = *(uint8_t*) q; + if (l == UINT8_MAX) + /* avoid overflow right below */ + return -EBADMSG; + r = message_peek_body(m, &rindex, 1, l+1, &q); if (r < 0) return r; @@ -4277,11 +4297,10 @@ _public_ int sd_bus_message_rewind(sd_bus_message *m, int complete) { message_reset_containers(m); m->rindex = 0; - c = message_get_container(m); + c = message_get_last_container(m); } else { - c = message_get_container(m); + c = message_get_last_container(m); - c->offset_index = 0; c->index = 0; m->rindex = c->begin; } @@ -4496,10 +4515,6 @@ _public_ int sd_bus_message_read(sd_bus_message *m, const char *types, ...) { va_list ap; int r; - assert_return(m, -EINVAL); - assert_return(m->sealed, -EPERM); - assert_return(types, -EINVAL); - va_start(ap, types); r = sd_bus_message_readv(m, types, ap); va_end(ap); @@ -4524,7 +4539,7 @@ _public_ int sd_bus_message_skip(sd_bus_message *m, const char *types) { if (message_end_of_array(m, m->rindex)) return 0; - c = message_get_container(m); + c = message_get_last_container(m); r = signature_element_length(c->signature + c->index, &l); if (r < 0) @@ -4690,7 +4705,7 @@ _public_ int sd_bus_message_read_array( if (r <= 0) return r; - c = message_get_container(m); + c = message_get_last_container(m); if (BUS_MESSAGE_IS_GVARIANT(m)) { align = bus_gvariant_get_alignment(CHAR_TO_STR(type)); @@ -4827,6 +4842,10 @@ static int message_peek_field_string( if (r < 0) return r; + if (l == UINT32_MAX) + /* avoid overflow right below */ + return -EBADMSG; + r = message_peek_fields(m, ri, 1, l+1, &q); if (r < 0) return r; @@ -4878,6 +4897,10 @@ static int message_peek_field_signature( return r; l = *(uint8_t*) q; + if (l == UINT8_MAX) + /* avoid overflow right below */ + return -EBADMSG; + r = message_peek_fields(m, ri, 1, l+1, &q); if (r < 0) return r; @@ -4959,18 +4982,18 @@ static int message_skip_fields( } else if (t == SD_BUS_TYPE_ARRAY) { - r = signature_element_length(*signature+1, &l); + r = signature_element_length(*signature + 1, &l); if (r < 0) return r; assert(l >= 1); { - char sig[l-1], *s; + char sig[l + 1], *s = sig; uint32_t nas; int alignment; - strncpy(sig, *signature + 1, l-1); - s = sig; + strncpy(sig, *signature + 1, l); + sig[l] = '\0'; alignment = bus_type_get_alignment(sig[0]); if (alignment < 0) @@ -5014,9 +5037,9 @@ static int message_skip_fields( assert(l >= 2); { - char sig[l-1], *s; - strncpy(sig, *signature + 1, l-1); - s = sig; + char sig[l + 1], *s = sig; + strncpy(sig, *signature + 1, l); + sig[l] = '\0'; r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s); if (r < 0) @@ -5025,7 +5048,7 @@ static int message_skip_fields( *signature += l; } else - return -EINVAL; + return -EBADMSG; } } @@ -5056,25 +5079,21 @@ int bus_message_parse_fields(sd_bus_message *m) { if (*p == 0) { size_t l; - char *c; /* We found the beginning of the signature * string, yay! We require the body to be a * structure, so verify it and then strip the * opening/closing brackets. */ - l = ((char*) m->footer + m->footer_accessible) - p - (1 + sz); + l = (char*) m->footer + m->footer_accessible - p - (1 + sz); if (l < 2 || p[1] != SD_BUS_TYPE_STRUCT_BEGIN || p[1 + l - 1] != SD_BUS_TYPE_STRUCT_END) return -EBADMSG; - c = strndup(p + 1 + 1, l - 2); - if (!c) + if (free_and_strndup(&m->root_container.signature, + p + 1 + 1, l - 2) < 0) return -ENOMEM; - - free(m->root_container.signature); - m->root_container.signature = c; break; } @@ -5396,6 +5415,8 @@ int bus_message_parse_fields(sd_bus_message *m) { &m->root_container.item_size, &m->root_container.offsets, &m->root_container.n_offsets); + if (r == -EINVAL) + return -EBADMSG; if (r < 0) return r; } @@ -5591,7 +5612,7 @@ _public_ const char* sd_bus_message_get_signature(sd_bus_message *m, int complet assert_return(m, NULL); - c = complete ? &m->root_container : message_get_container(m); + c = complete ? &m->root_container : message_get_last_container(m); return strempty(c->signature); } diff --git a/src/libsystemd/sd-bus/bus-signature.c b/src/libsystemd/sd-bus/bus-signature.c index 06ef1ee4cb..1ecd6e8b7e 100644 --- a/src/libsystemd/sd-bus/bus-signature.c +++ b/src/libsystemd/sd-bus/bus-signature.c @@ -56,6 +56,12 @@ static int signature_element_length_internal( p += t; } + if (p - s < 2) + /* D-Bus spec: Empty structures are not allowed; there + * must be at least one type code between the parentheses. + */ + return -EINVAL; + *l = p - s + 1; return 0; } diff --git a/src/libsystemd/sd-bus/test-bus-gvariant.c b/src/libsystemd/sd-bus/test-bus-gvariant.c index 92324bff29..1a9a35d56b 100644 --- a/src/libsystemd/sd-bus/test-bus-gvariant.c +++ b/src/libsystemd/sd-bus/test-bus-gvariant.c @@ -17,8 +17,10 @@ #include "util.h" static void test_bus_gvariant_is_fixed_size(void) { + log_info("/* %s */", __func__); + assert_se(bus_gvariant_is_fixed_size("") > 0); - assert_se(bus_gvariant_is_fixed_size("()") > 0); + assert_se(bus_gvariant_is_fixed_size("()") == -EINVAL); assert_se(bus_gvariant_is_fixed_size("y") > 0); assert_se(bus_gvariant_is_fixed_size("u") > 0); assert_se(bus_gvariant_is_fixed_size("b") > 0); @@ -42,8 +44,10 @@ static void test_bus_gvariant_is_fixed_size(void) { } static void test_bus_gvariant_get_size(void) { + log_info("/* %s */", __func__); + assert_se(bus_gvariant_get_size("") == 0); - assert_se(bus_gvariant_get_size("()") == 1); + assert_se(bus_gvariant_get_size("()") == -EINVAL); assert_se(bus_gvariant_get_size("y") == 1); assert_se(bus_gvariant_get_size("u") == 4); assert_se(bus_gvariant_get_size("b") == 1); @@ -74,8 +78,10 @@ static void test_bus_gvariant_get_size(void) { } static void test_bus_gvariant_get_alignment(void) { + log_info("/* %s */", __func__); + assert_se(bus_gvariant_get_alignment("") == 1); - assert_se(bus_gvariant_get_alignment("()") == 1); + assert_se(bus_gvariant_get_alignment("()") == -EINVAL); assert_se(bus_gvariant_get_alignment("y") == 1); assert_se(bus_gvariant_get_alignment("b") == 1); assert_se(bus_gvariant_get_alignment("u") == 4); @@ -129,7 +135,10 @@ static int test_marshal(void) { bus->message_version = 2; /* dirty hack to enable gvariant */ - assert_se(sd_bus_message_new_method_call(bus, &m, "a.service.name", "/an/object/path/which/is/really/really/long/so/that/we/hit/the/eight/bit/boundary/by/quite/some/margin/to/test/this/stuff/that/it/really/works", "an.interface.name", "AMethodName") >= 0); + r = sd_bus_message_new_method_call(bus, &m, "a.service.name", + "/an/object/path/which/is/really/really/long/so/that/we/hit/the/eight/bit/boundary/by/quite/some/margin/to/test/this/stuff/that/it/really/works", + "an.interface.name", "AMethodName"); + assert_se(r >= 0); assert_cc(sizeof(struct bus_header) == 16); @@ -202,7 +211,7 @@ static int test_marshal(void) { } int main(int argc, char *argv[]) { - test_setup_logging(LOG_INFO); + test_setup_logging(LOG_DEBUG); test_bus_gvariant_is_fixed_size(); test_bus_gvariant_get_size(); diff --git a/src/libsystemd/sd-bus/test-bus-marshal.c b/src/libsystemd/sd-bus/test-bus-marshal.c index 020a5e51e5..d1c674b223 100644 --- a/src/libsystemd/sd-bus/test-bus-marshal.c +++ b/src/libsystemd/sd-bus/test-bus-marshal.c @@ -18,8 +18,8 @@ #include "bus-label.h" #include "bus-message.h" #include "bus-util.h" +#include "escape.h" #include "fd-util.h" -#include "hexdecoct.h" #include "log.h" #include "tests.h" #include "util.h" @@ -111,7 +111,7 @@ int main(int argc, char *argv[]) { uint8_t u, v; void *buffer = NULL; size_t sz; - char *h; + _cleanup_free_ char *h = NULL; const int32_t integer_array[] = { -1, -2, 0, 1, 2 }, *return_array; char *s; _cleanup_free_ char *first = NULL, *second = NULL, *third = NULL; @@ -154,7 +154,7 @@ int main(int argc, char *argv[]) { assert_se(r >= 0); r = sd_bus_message_append(m, "()"); - assert_se(r >= 0); + assert_se(r == -EINVAL); r = sd_bus_message_append(m, "ba(ss)", 255, 3, "aaa", "1", "bbb", "2", "ccc", "3"); assert_se(r >= 0); @@ -197,11 +197,9 @@ int main(int argc, char *argv[]) { r = bus_message_get_blob(m, &buffer, &sz); assert_se(r >= 0); - h = hexmem(buffer, sz); + h = cescape_length(buffer, sz); assert_se(h); - log_info("message size = %zu, contents =\n%s", sz, h); - free(h); #if HAVE_GLIB #ifndef __SANITIZE_ADDRESS__ @@ -298,7 +296,7 @@ int main(int argc, char *argv[]) { assert_se(v == 10); r = sd_bus_message_read(m, "()"); - assert_se(r > 0); + assert_se(r < 0); r = sd_bus_message_read(m, "ba(ss)", &boolean, 3, &x, &y, &a, &b, &c, &d); assert_se(r > 0); @@ -379,7 +377,7 @@ int main(int argc, char *argv[]) { assert_se(sd_bus_message_verify_type(m, 'a', "{yv}") > 0); - r = sd_bus_message_skip(m, "a{yv}y(ty)y(yt)y()"); + r = sd_bus_message_skip(m, "a{yv}y(ty)y(yt)y"); assert_se(r >= 0); assert_se(sd_bus_message_verify_type(m, 'b', NULL) > 0); diff --git a/src/libsystemd/sd-bus/test-bus-signature.c b/src/libsystemd/sd-bus/test-bus-signature.c index ab59d04e20..84648dbc2a 100644 --- a/src/libsystemd/sd-bus/test-bus-signature.c +++ b/src/libsystemd/sd-bus/test-bus-signature.c @@ -14,9 +14,9 @@ int main(int argc, char *argv[]) { assert_se(signature_is_single("v", false)); assert_se(signature_is_single("as", false)); assert_se(signature_is_single("(ss)", false)); - assert_se(signature_is_single("()", false)); - assert_se(signature_is_single("(()()()()())", false)); - assert_se(signature_is_single("(((())))", false)); + assert_se(!signature_is_single("()", false)); + assert_se(!signature_is_single("(()()()()())", false)); + assert_se(!signature_is_single("(((())))", false)); assert_se(signature_is_single("((((s))))", false)); assert_se(signature_is_single("{ss}", true)); assert_se(signature_is_single("a{ss}", false)); @@ -61,7 +61,7 @@ int main(int argc, char *argv[]) { assert_se(signature_is_valid("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaas", false)); assert_se(!signature_is_valid("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaau", false)); - assert_se(signature_is_valid("(((((((((((((((((((((((((((((((())))))))))))))))))))))))))))))))", false)); + assert_se(signature_is_valid("((((((((((((((((((((((((((((((((s))))))))))))))))))))))))))))))))", false)); assert_se(!signature_is_valid("((((((((((((((((((((((((((((((((()))))))))))))))))))))))))))))))))", false)); assert_se(namespace_complex_pattern("", "")); diff --git a/src/test/test-string-util.c b/src/test/test-string-util.c index a9f261839c..8c1f91d4ef 100644 --- a/src/test/test-string-util.c +++ b/src/test/test-string-util.c @@ -5,6 +5,7 @@ #include "macro.h" #include "string-util.h" #include "strv.h" +#include "tests.h" #include "utf8.h" static void test_string_erase(void) { @@ -30,6 +31,64 @@ static void test_string_erase(void) { assert_se(x[9] == '\0'); } +static void test_free_and_strndup_one(char **t, const char *src, size_t l, const char *expected, bool change) { + int r; + + log_debug("%s: \"%s\", \"%s\", %zd (expect \"%s\", %s)", + __func__, strnull(*t), strnull(src), l, strnull(expected), yes_no(change)); + + r = free_and_strndup(t, src, l); + assert_se(streq_ptr(*t, expected)); + assert_se(r == change); /* check that change occurs only when necessary */ +} + +static void test_free_and_strndup(void) { + static const struct test_case { + const char *src; + size_t len; + const char *expected; + } cases[] = { + {"abc", 0, ""}, + {"abc", 0, ""}, + {"abc", 1, "a"}, + {"abc", 2, "ab"}, + {"abc", 3, "abc"}, + {"abc", 4, "abc"}, + {"abc", 5, "abc"}, + {"abc", 5, "abc"}, + {"abc", 4, "abc"}, + {"abc", 3, "abc"}, + {"abc", 2, "ab"}, + {"abc", 1, "a"}, + {"abc", 0, ""}, + + {"", 0, ""}, + {"", 1, ""}, + {"", 2, ""}, + {"", 0, ""}, + {"", 1, ""}, + {"", 2, ""}, + {"", 2, ""}, + {"", 1, ""}, + {"", 0, ""}, + + {NULL, 0, NULL}, + + {"foo", 3, "foo"}, + {"foobar", 6, "foobar"}, + }; + + _cleanup_free_ char *t = NULL; + const char *prev_expected = t; + + for (unsigned i = 0; i < ELEMENTSOF(cases); i++) { + test_free_and_strndup_one(&t, + cases[i].src, cases[i].len, cases[i].expected, + !streq_ptr(cases[i].expected, prev_expected)); + prev_expected = t; + } +} + static void test_ascii_strcasecmp_n(void) { assert_se(ascii_strcasecmp_n("", "", 0) == 0); @@ -520,7 +579,10 @@ static void test_memory_startswith_no_case(void) { } int main(int argc, char *argv[]) { + test_setup_logging(LOG_DEBUG); + test_string_erase(); + test_free_and_strndup(); test_ascii_strcasecmp_n(); test_ascii_strcasecmp_nn(); test_cellescape(); diff --git a/test/fuzz-regressions/.gitattributes b/test/fuzz-regressions/.gitattributes deleted file mode 100644 index 7b1b3e1835..0000000000 --- a/test/fuzz-regressions/.gitattributes +++ /dev/null @@ -1 +0,0 @@ -/*/* -whitespace diff --git a/test/fuzz-regressions/meson.build b/test/fuzz-regressions/meson.build deleted file mode 100644 index 043d3f3154..0000000000 --- a/test/fuzz-regressions/meson.build +++ /dev/null @@ -1,43 +0,0 @@ -# SPDX-License-Identifier: LGPL-2.1+ - -sanitize_address = custom_target( - 'sanitize-address-fuzzers', - output : 'sanitize-address-fuzzers', - command : [meson_build_sh, - meson.source_root(), - '@OUTPUT@', - 'fuzzers', - '-Db_lundef=false -Db_sanitize=address']) - -sanitizers = [['address', sanitize_address]] - -fuzz_regression_tests = ''' - fuzz-dhcp6-client/crash-4003c06fce43a11fbd22f02584df2807ac333eae - fuzz-dhcp6-client/crash-6e88fcb6b85c9436bcbe05219aa8e550194645ef - fuzz-dns-packet/issue-7888 - fuzz-dns-packet/oss-fuzz-5465 - fuzz-journal-remote/crash-5a8f03d4c3a46fcded39527084f437e8e4b54b76 - fuzz-journal-remote/crash-96dee870ea66d03e89ac321eee28ea63a9b9aa45 - fuzz-journal-remote/oss-fuzz-8659 - fuzz-journal-remote/oss-fuzz-8686 - fuzz-journald-syslog/github-9795 - fuzz-journald-syslog/github-9820 - fuzz-journald-syslog/github-9827 - fuzz-journald-syslog/github-9829 - fuzz-ndisc-rs/timeout-2815b773c712fa33bea62f541dfa3017c64ea2f1 - fuzz-ndisc-rs/timeout-61fff7fd1e5dcc07e1b656baab29065ce634ad5b - fuzz-unit-file/oss-fuzz-6884 - fuzz-unit-file/oss-fuzz-6885 - fuzz-unit-file/oss-fuzz-6886 - fuzz-unit-file/oss-fuzz-6892 - fuzz-unit-file/oss-fuzz-6897 - fuzz-unit-file/oss-fuzz-6897-evverx - fuzz-unit-file/oss-fuzz-6908 - fuzz-unit-file/oss-fuzz-6917 - fuzz-unit-file/oss-fuzz-6977 - fuzz-unit-file/oss-fuzz-6977-unminimized - fuzz-unit-file/oss-fuzz-7004 - fuzz-unit-file/oss-fuzz-8064 - fuzz-unit-file/oss-fuzz-8827 - fuzz-unit-file/oss-fuzz-10007 -'''.split() diff --git a/test/fuzz-corpus/.gitattributes b/test/fuzz/.gitattributes similarity index 100% rename from test/fuzz-corpus/.gitattributes rename to test/fuzz/.gitattributes diff --git a/test/fuzz/fuzz-bus-message/crash-26bba7182dedc8848939931d9fcefcb7922f2e56 b/test/fuzz/fuzz-bus-message/crash-26bba7182dedc8848939931d9fcefcb7922f2e56 new file mode 100644 index 0000000000..f1bf3229ef Binary files /dev/null and b/test/fuzz/fuzz-bus-message/crash-26bba7182dedc8848939931d9fcefcb7922f2e56 differ diff --git a/test/fuzz/fuzz-bus-message/crash-29ed3c202e0ffade3cad42c8bbeb6cc68a21eb8e b/test/fuzz/fuzz-bus-message/crash-29ed3c202e0ffade3cad42c8bbeb6cc68a21eb8e new file mode 100644 index 0000000000..4488f0a6c6 Binary files /dev/null and b/test/fuzz/fuzz-bus-message/crash-29ed3c202e0ffade3cad42c8bbeb6cc68a21eb8e differ diff --git a/test/fuzz/fuzz-bus-message/crash-32bf69483cbd4f2e6d46c25a2f92a472109aee45 b/test/fuzz/fuzz-bus-message/crash-32bf69483cbd4f2e6d46c25a2f92a472109aee45 new file mode 100644 index 0000000000..aa0c6ff7f7 Binary files /dev/null and b/test/fuzz/fuzz-bus-message/crash-32bf69483cbd4f2e6d46c25a2f92a472109aee45 differ diff --git a/test/fuzz/fuzz-bus-message/crash-37449529b1ad867f0c2671fa80aca5d7812a2b70 b/test/fuzz/fuzz-bus-message/crash-37449529b1ad867f0c2671fa80aca5d7812a2b70 new file mode 100644 index 0000000000..6a20265a39 Binary files /dev/null and b/test/fuzz/fuzz-bus-message/crash-37449529b1ad867f0c2671fa80aca5d7812a2b70 differ diff --git a/test/fuzz/fuzz-bus-message/crash-4162a61a79e4c5a832ca5232212f75fa560a1f75 b/test/fuzz/fuzz-bus-message/crash-4162a61a79e4c5a832ca5232212f75fa560a1f75 new file mode 100644 index 0000000000..5faf3308e7 Binary files /dev/null and b/test/fuzz/fuzz-bus-message/crash-4162a61a79e4c5a832ca5232212f75fa560a1f75 differ diff --git a/test/fuzz/fuzz-bus-message/crash-4f0211eb269e28db941961061494bfdbf3345e54 b/test/fuzz/fuzz-bus-message/crash-4f0211eb269e28db941961061494bfdbf3345e54 new file mode 100644 index 0000000000..865b29507c Binary files /dev/null and b/test/fuzz/fuzz-bus-message/crash-4f0211eb269e28db941961061494bfdbf3345e54 differ diff --git a/test/fuzz/fuzz-bus-message/crash-603dfd98252375ac7dbced53c2ec312671939a36 b/test/fuzz/fuzz-bus-message/crash-603dfd98252375ac7dbced53c2ec312671939a36 new file mode 100644 index 0000000000..b3fee9e07a Binary files /dev/null and b/test/fuzz/fuzz-bus-message/crash-603dfd98252375ac7dbced53c2ec312671939a36 differ diff --git a/test/fuzz/fuzz-bus-message/crash-b88ad9ecf4aacf4a0caca5b5543953265367f084 b/test/fuzz/fuzz-bus-message/crash-b88ad9ecf4aacf4a0caca5b5543953265367f084 new file mode 100644 index 0000000000..52469650b5 Binary files /dev/null and b/test/fuzz/fuzz-bus-message/crash-b88ad9ecf4aacf4a0caca5b5543953265367f084 differ diff --git a/test/fuzz/fuzz-bus-message/crash-c1b37b4729b42c0c05b23cba4eed5d8102498a1e b/test/fuzz/fuzz-bus-message/crash-c1b37b4729b42c0c05b23cba4eed5d8102498a1e new file mode 100644 index 0000000000..2ae1a8715a Binary files /dev/null and b/test/fuzz/fuzz-bus-message/crash-c1b37b4729b42c0c05b23cba4eed5d8102498a1e differ diff --git a/test/fuzz/fuzz-bus-message/crash-d8f3941c74219b4c03532c9b244d5ea539c61af5 b/test/fuzz/fuzz-bus-message/crash-d8f3941c74219b4c03532c9b244d5ea539c61af5 new file mode 100644 index 0000000000..26262e1149 Binary files /dev/null and b/test/fuzz/fuzz-bus-message/crash-d8f3941c74219b4c03532c9b244d5ea539c61af5 differ diff --git a/test/fuzz/fuzz-bus-message/crash-e1b811da5ca494e494b77c6bd8e1c2f2989425c5 b/test/fuzz/fuzz-bus-message/crash-e1b811da5ca494e494b77c6bd8e1c2f2989425c5 new file mode 100644 index 0000000000..9d3fa0035f Binary files /dev/null and b/test/fuzz/fuzz-bus-message/crash-e1b811da5ca494e494b77c6bd8e1c2f2989425c5 differ diff --git a/test/fuzz/fuzz-bus-message/leak-c09c0e2256d43bc5e2d02748c8d8760e7bc25d20 b/test/fuzz/fuzz-bus-message/leak-c09c0e2256d43bc5e2d02748c8d8760e7bc25d20 new file mode 100644 index 0000000000..c371824ffb Binary files /dev/null and b/test/fuzz/fuzz-bus-message/leak-c09c0e2256d43bc5e2d02748c8d8760e7bc25d20 differ diff --git a/test/fuzz/fuzz-bus-message/message1 b/test/fuzz/fuzz-bus-message/message1 new file mode 100644 index 0000000000..2df70fd7cb Binary files /dev/null and b/test/fuzz/fuzz-bus-message/message1 differ diff --git a/test/fuzz/fuzz-bus-message/timeout-08ee8f6446a4064db064e8e0b3d220147f7d0b5b b/test/fuzz/fuzz-bus-message/timeout-08ee8f6446a4064db064e8e0b3d220147f7d0b5b new file mode 100644 index 0000000000..c975f906ee Binary files /dev/null and b/test/fuzz/fuzz-bus-message/timeout-08ee8f6446a4064db064e8e0b3d220147f7d0b5b differ diff --git a/test/fuzz-corpus/dhcp-server/discover-existing b/test/fuzz/fuzz-dhcp-server/discover-existing similarity index 100% rename from test/fuzz-corpus/dhcp-server/discover-existing rename to test/fuzz/fuzz-dhcp-server/discover-existing diff --git a/test/fuzz-corpus/dhcp-server/discover-new b/test/fuzz/fuzz-dhcp-server/discover-new similarity index 100% rename from test/fuzz-corpus/dhcp-server/discover-new rename to test/fuzz/fuzz-dhcp-server/discover-new diff --git a/test/fuzz-corpus/dhcp-server/release b/test/fuzz/fuzz-dhcp-server/release similarity index 100% rename from test/fuzz-corpus/dhcp-server/release rename to test/fuzz/fuzz-dhcp-server/release diff --git a/test/fuzz-corpus/dhcp-server/request-existing b/test/fuzz/fuzz-dhcp-server/request-existing similarity index 100% rename from test/fuzz-corpus/dhcp-server/request-existing rename to test/fuzz/fuzz-dhcp-server/request-existing diff --git a/test/fuzz-corpus/dhcp-server/request-new b/test/fuzz/fuzz-dhcp-server/request-new similarity index 100% rename from test/fuzz-corpus/dhcp-server/request-new rename to test/fuzz/fuzz-dhcp-server/request-new diff --git a/test/fuzz-corpus/dhcp-server/request-reboot b/test/fuzz/fuzz-dhcp-server/request-reboot similarity index 100% rename from test/fuzz-corpus/dhcp-server/request-reboot rename to test/fuzz/fuzz-dhcp-server/request-reboot diff --git a/test/fuzz-corpus/dhcp-server/request-renew b/test/fuzz/fuzz-dhcp-server/request-renew similarity index 100% rename from test/fuzz-corpus/dhcp-server/request-renew rename to test/fuzz/fuzz-dhcp-server/request-renew diff --git a/test/fuzz-regressions/fuzz-dhcp6-client/crash-4003c06fce43a11fbd22f02584df2807ac333eae b/test/fuzz/fuzz-dhcp6-client/crash-4003c06fce43a11fbd22f02584df2807ac333eae similarity index 100% rename from test/fuzz-regressions/fuzz-dhcp6-client/crash-4003c06fce43a11fbd22f02584df2807ac333eae rename to test/fuzz/fuzz-dhcp6-client/crash-4003c06fce43a11fbd22f02584df2807ac333eae diff --git a/test/fuzz-regressions/fuzz-dhcp6-client/crash-6e88fcb6b85c9436bcbe05219aa8e550194645ef b/test/fuzz/fuzz-dhcp6-client/crash-6e88fcb6b85c9436bcbe05219aa8e550194645ef similarity index 100% rename from test/fuzz-regressions/fuzz-dhcp6-client/crash-6e88fcb6b85c9436bcbe05219aa8e550194645ef rename to test/fuzz/fuzz-dhcp6-client/crash-6e88fcb6b85c9436bcbe05219aa8e550194645ef diff --git a/test/fuzz-regressions/fuzz-dns-packet/issue-7888 b/test/fuzz/fuzz-dns-packet/issue-7888 similarity index 100% rename from test/fuzz-regressions/fuzz-dns-packet/issue-7888 rename to test/fuzz/fuzz-dns-packet/issue-7888 diff --git a/test/fuzz-regressions/fuzz-dns-packet/oss-fuzz-5465 b/test/fuzz/fuzz-dns-packet/oss-fuzz-5465 similarity index 100% rename from test/fuzz-regressions/fuzz-dns-packet/oss-fuzz-5465 rename to test/fuzz/fuzz-dns-packet/oss-fuzz-5465 diff --git a/test/fuzz-regressions/fuzz-journal-remote/crash-5a8f03d4c3a46fcded39527084f437e8e4b54b76 b/test/fuzz/fuzz-journal-remote/crash-5a8f03d4c3a46fcded39527084f437e8e4b54b76 similarity index 100% rename from test/fuzz-regressions/fuzz-journal-remote/crash-5a8f03d4c3a46fcded39527084f437e8e4b54b76 rename to test/fuzz/fuzz-journal-remote/crash-5a8f03d4c3a46fcded39527084f437e8e4b54b76 diff --git a/test/fuzz-regressions/fuzz-journal-remote/crash-96dee870ea66d03e89ac321eee28ea63a9b9aa45 b/test/fuzz/fuzz-journal-remote/crash-96dee870ea66d03e89ac321eee28ea63a9b9aa45 similarity index 100% rename from test/fuzz-regressions/fuzz-journal-remote/crash-96dee870ea66d03e89ac321eee28ea63a9b9aa45 rename to test/fuzz/fuzz-journal-remote/crash-96dee870ea66d03e89ac321eee28ea63a9b9aa45 diff --git a/test/fuzz-corpus/journal-remote/invalid-ts.txt b/test/fuzz/fuzz-journal-remote/invalid-ts.txt similarity index 100% rename from test/fuzz-corpus/journal-remote/invalid-ts.txt rename to test/fuzz/fuzz-journal-remote/invalid-ts.txt diff --git a/test/fuzz-regressions/fuzz-journal-remote/oss-fuzz-8659 b/test/fuzz/fuzz-journal-remote/oss-fuzz-8659 similarity index 100% rename from test/fuzz-regressions/fuzz-journal-remote/oss-fuzz-8659 rename to test/fuzz/fuzz-journal-remote/oss-fuzz-8659 diff --git a/test/fuzz-regressions/fuzz-journal-remote/oss-fuzz-8686 b/test/fuzz/fuzz-journal-remote/oss-fuzz-8686 similarity index 100% rename from test/fuzz-regressions/fuzz-journal-remote/oss-fuzz-8686 rename to test/fuzz/fuzz-journal-remote/oss-fuzz-8686 diff --git a/test/fuzz-corpus/journal-remote/sample.txt b/test/fuzz/fuzz-journal-remote/sample.txt similarity index 100% rename from test/fuzz-corpus/journal-remote/sample.txt rename to test/fuzz/fuzz-journal-remote/sample.txt diff --git a/test/fuzz-regressions/fuzz-journald-syslog/github-9795 b/test/fuzz/fuzz-journald-syslog/github-9795 similarity index 100% rename from test/fuzz-regressions/fuzz-journald-syslog/github-9795 rename to test/fuzz/fuzz-journald-syslog/github-9795 diff --git a/test/fuzz-regressions/fuzz-journald-syslog/github-9820 b/test/fuzz/fuzz-journald-syslog/github-9820 similarity index 100% rename from test/fuzz-regressions/fuzz-journald-syslog/github-9820 rename to test/fuzz/fuzz-journald-syslog/github-9820 diff --git a/test/fuzz-regressions/fuzz-journald-syslog/github-9827 b/test/fuzz/fuzz-journald-syslog/github-9827 similarity index 100% rename from test/fuzz-regressions/fuzz-journald-syslog/github-9827 rename to test/fuzz/fuzz-journald-syslog/github-9827 diff --git a/test/fuzz-regressions/fuzz-journald-syslog/github-9829 b/test/fuzz/fuzz-journald-syslog/github-9829 similarity index 100% rename from test/fuzz-regressions/fuzz-journald-syslog/github-9829 rename to test/fuzz/fuzz-journald-syslog/github-9829 diff --git a/test/fuzz-regressions/fuzz-ndisc-rs/timeout-2815b773c712fa33bea62f541dfa3017c64ea2f1 b/test/fuzz/fuzz-ndisc-rs/timeout-2815b773c712fa33bea62f541dfa3017c64ea2f1 similarity index 100% rename from test/fuzz-regressions/fuzz-ndisc-rs/timeout-2815b773c712fa33bea62f541dfa3017c64ea2f1 rename to test/fuzz/fuzz-ndisc-rs/timeout-2815b773c712fa33bea62f541dfa3017c64ea2f1 diff --git a/test/fuzz-regressions/fuzz-ndisc-rs/timeout-61fff7fd1e5dcc07e1b656baab29065ce634ad5b b/test/fuzz/fuzz-ndisc-rs/timeout-61fff7fd1e5dcc07e1b656baab29065ce634ad5b similarity index 100% rename from test/fuzz-regressions/fuzz-ndisc-rs/timeout-61fff7fd1e5dcc07e1b656baab29065ce634ad5b rename to test/fuzz/fuzz-ndisc-rs/timeout-61fff7fd1e5dcc07e1b656baab29065ce634ad5b diff --git "a/test/fuzz-corpus/unit-file/dev-mapper-fedora_krowka\\x2dswap.swap" "b/test/fuzz/fuzz-unit-file/dev-mapper-fedora_krowka\\x2dswap.swap" similarity index 100% rename from "test/fuzz-corpus/unit-file/dev-mapper-fedora_krowka\\x2dswap.swap" rename to "test/fuzz/fuzz-unit-file/dev-mapper-fedora_krowka\\x2dswap.swap" diff --git a/test/fuzz-corpus/unit-file/directives.service b/test/fuzz/fuzz-unit-file/directives.service similarity index 100% rename from test/fuzz-corpus/unit-file/directives.service rename to test/fuzz/fuzz-unit-file/directives.service diff --git a/test/fuzz-corpus/unit-file/empty.scope b/test/fuzz/fuzz-unit-file/empty.scope similarity index 100% rename from test/fuzz-corpus/unit-file/empty.scope rename to test/fuzz/fuzz-unit-file/empty.scope diff --git a/test/fuzz-corpus/unit-file/machine.slice b/test/fuzz/fuzz-unit-file/machine.slice similarity index 100% rename from test/fuzz-corpus/unit-file/machine.slice rename to test/fuzz/fuzz-unit-file/machine.slice diff --git a/test/fuzz-regressions/fuzz-unit-file/oss-fuzz-10007 b/test/fuzz/fuzz-unit-file/oss-fuzz-10007 similarity index 100% rename from test/fuzz-regressions/fuzz-unit-file/oss-fuzz-10007 rename to test/fuzz/fuzz-unit-file/oss-fuzz-10007 diff --git a/test/fuzz-regressions/fuzz-unit-file/oss-fuzz-6884 b/test/fuzz/fuzz-unit-file/oss-fuzz-6884 similarity index 100% rename from test/fuzz-regressions/fuzz-unit-file/oss-fuzz-6884 rename to test/fuzz/fuzz-unit-file/oss-fuzz-6884 diff --git a/test/fuzz-regressions/fuzz-unit-file/oss-fuzz-6885 b/test/fuzz/fuzz-unit-file/oss-fuzz-6885 similarity index 100% rename from test/fuzz-regressions/fuzz-unit-file/oss-fuzz-6885 rename to test/fuzz/fuzz-unit-file/oss-fuzz-6885 diff --git a/test/fuzz-regressions/fuzz-unit-file/oss-fuzz-6886 b/test/fuzz/fuzz-unit-file/oss-fuzz-6886 similarity index 100% rename from test/fuzz-regressions/fuzz-unit-file/oss-fuzz-6886 rename to test/fuzz/fuzz-unit-file/oss-fuzz-6886 diff --git a/test/fuzz-regressions/fuzz-unit-file/oss-fuzz-6892 b/test/fuzz/fuzz-unit-file/oss-fuzz-6892 similarity index 100% rename from test/fuzz-regressions/fuzz-unit-file/oss-fuzz-6892 rename to test/fuzz/fuzz-unit-file/oss-fuzz-6892 diff --git a/test/fuzz-regressions/fuzz-unit-file/oss-fuzz-6897 b/test/fuzz/fuzz-unit-file/oss-fuzz-6897 similarity index 100% rename from test/fuzz-regressions/fuzz-unit-file/oss-fuzz-6897 rename to test/fuzz/fuzz-unit-file/oss-fuzz-6897 diff --git a/test/fuzz-regressions/fuzz-unit-file/oss-fuzz-6897-evverx b/test/fuzz/fuzz-unit-file/oss-fuzz-6897-evverx similarity index 100% rename from test/fuzz-regressions/fuzz-unit-file/oss-fuzz-6897-evverx rename to test/fuzz/fuzz-unit-file/oss-fuzz-6897-evverx diff --git a/test/fuzz-regressions/fuzz-unit-file/oss-fuzz-6908 b/test/fuzz/fuzz-unit-file/oss-fuzz-6908 similarity index 100% rename from test/fuzz-regressions/fuzz-unit-file/oss-fuzz-6908 rename to test/fuzz/fuzz-unit-file/oss-fuzz-6908 diff --git a/test/fuzz-regressions/fuzz-unit-file/oss-fuzz-6917 b/test/fuzz/fuzz-unit-file/oss-fuzz-6917 similarity index 100% rename from test/fuzz-regressions/fuzz-unit-file/oss-fuzz-6917 rename to test/fuzz/fuzz-unit-file/oss-fuzz-6917 diff --git a/test/fuzz-regressions/fuzz-unit-file/oss-fuzz-6977 b/test/fuzz/fuzz-unit-file/oss-fuzz-6977 similarity index 100% rename from test/fuzz-regressions/fuzz-unit-file/oss-fuzz-6977 rename to test/fuzz/fuzz-unit-file/oss-fuzz-6977 diff --git a/test/fuzz-regressions/fuzz-unit-file/oss-fuzz-6977-unminimized b/test/fuzz/fuzz-unit-file/oss-fuzz-6977-unminimized similarity index 100% rename from test/fuzz-regressions/fuzz-unit-file/oss-fuzz-6977-unminimized rename to test/fuzz/fuzz-unit-file/oss-fuzz-6977-unminimized diff --git a/test/fuzz-regressions/fuzz-unit-file/oss-fuzz-7004 b/test/fuzz/fuzz-unit-file/oss-fuzz-7004 similarity index 100% rename from test/fuzz-regressions/fuzz-unit-file/oss-fuzz-7004 rename to test/fuzz/fuzz-unit-file/oss-fuzz-7004 diff --git a/test/fuzz-regressions/fuzz-unit-file/oss-fuzz-8064 b/test/fuzz/fuzz-unit-file/oss-fuzz-8064 similarity index 100% rename from test/fuzz-regressions/fuzz-unit-file/oss-fuzz-8064 rename to test/fuzz/fuzz-unit-file/oss-fuzz-8064 diff --git a/test/fuzz-regressions/fuzz-unit-file/oss-fuzz-8827 b/test/fuzz/fuzz-unit-file/oss-fuzz-8827 similarity index 100% rename from test/fuzz-regressions/fuzz-unit-file/oss-fuzz-8827 rename to test/fuzz/fuzz-unit-file/oss-fuzz-8827 diff --git a/test/fuzz-corpus/unit-file/proc-sys-fs-binfmt_misc.automount b/test/fuzz/fuzz-unit-file/proc-sys-fs-binfmt_misc.automount similarity index 100% rename from test/fuzz-corpus/unit-file/proc-sys-fs-binfmt_misc.automount rename to test/fuzz/fuzz-unit-file/proc-sys-fs-binfmt_misc.automount diff --git a/test/fuzz-corpus/unit-file/syslog.socket b/test/fuzz/fuzz-unit-file/syslog.socket similarity index 100% rename from test/fuzz-corpus/unit-file/syslog.socket rename to test/fuzz/fuzz-unit-file/syslog.socket diff --git a/test/fuzz-corpus/unit-file/systemd-ask-password-console.path b/test/fuzz/fuzz-unit-file/systemd-ask-password-console.path similarity index 100% rename from test/fuzz-corpus/unit-file/systemd-ask-password-console.path rename to test/fuzz/fuzz-unit-file/systemd-ask-password-console.path diff --git a/test/fuzz-corpus/unit-file/systemd-machined.service b/test/fuzz/fuzz-unit-file/systemd-machined.service similarity index 100% rename from test/fuzz-corpus/unit-file/systemd-machined.service rename to test/fuzz/fuzz-unit-file/systemd-machined.service diff --git a/test/fuzz-corpus/unit-file/systemd-resolved.service b/test/fuzz/fuzz-unit-file/systemd-resolved.service similarity index 100% rename from test/fuzz-corpus/unit-file/systemd-resolved.service rename to test/fuzz/fuzz-unit-file/systemd-resolved.service diff --git a/test/fuzz-corpus/unit-file/systemd-tmpfiles-clean.timer b/test/fuzz/fuzz-unit-file/systemd-tmpfiles-clean.timer similarity index 100% rename from test/fuzz-corpus/unit-file/systemd-tmpfiles-clean.timer rename to test/fuzz/fuzz-unit-file/systemd-tmpfiles-clean.timer diff --git a/test/fuzz-corpus/unit-file/timers.target b/test/fuzz/fuzz-unit-file/timers.target similarity index 100% rename from test/fuzz-corpus/unit-file/timers.target rename to test/fuzz/fuzz-unit-file/timers.target diff --git a/test/fuzz-corpus/unit-file/var-lib-machines.mount b/test/fuzz/fuzz-unit-file/var-lib-machines.mount similarity index 100% rename from test/fuzz-corpus/unit-file/var-lib-machines.mount rename to test/fuzz/fuzz-unit-file/var-lib-machines.mount diff --git a/test/fuzz/meson.build b/test/fuzz/meson.build new file mode 100644 index 0000000000..56d0f69660 --- /dev/null +++ b/test/fuzz/meson.build @@ -0,0 +1,33 @@ +# SPDX-License-Identifier: LGPL-2.1+ + +sanitize_address = custom_target( + 'sanitize-address-fuzzers', + output : 'sanitize-address-fuzzers', + command : [meson_build_sh, + meson.source_root(), + '@OUTPUT@', + 'fuzzers', + '-Db_lundef=false -Db_sanitize=address']) + +sanitizers = [['address', sanitize_address]] + +if git.found() + out = run_command( + git, + '--git-dir=@0@/.git'.format(meson.source_root()), + 'ls-files', ':/test/fuzz/*/*') +else + out = run_command( + 'sh', '-c', 'ls @0@/*/*'.format(meson.current_source_dir())) +endif + +fuzz_regression_tests = [] +foreach p : out.stdout().split() + # Remove the last entry which is ''. + # + # Also, backslashes get mangled, so skip test. See + # https://github.com/mesonbuild/meson/issues/1564. + if not p.contains('\\') + fuzz_regression_tests += p + endif +endforeach diff --git a/test/meson.build b/test/meson.build index 9750ff22b9..37034fca96 100644 --- a/test/meson.build +++ b/test/meson.build @@ -256,4 +256,4 @@ if conf.get('ENABLE_HWDB') == 1 endif endif -subdir('fuzz-regressions') +subdir('fuzz') diff --git a/tools/oss-fuzz.sh b/tools/oss-fuzz.sh index 2db5b4cc44..4d11e81ed6 100755 --- a/tools/oss-fuzz.sh +++ b/tools/oss-fuzz.sh @@ -35,8 +35,10 @@ fi meson $build -D$fuzzflag -Db_lundef=false ninja -C $build fuzzers -for d in "$(dirname "$0")/../test/fuzz-corpus/"*; do - zip -jqr $OUT/fuzz-$(basename "$d")_seed_corpus.zip "$d" +# The seed corpus is a separate flat archive for each fuzzer, +# with a fixed name ${fuzzer}_seed_corpus.zip. +for d in "$(dirname "$0")/../test/fuzz/fuzz-"*; do + zip -jqr $OUT/$(basename "$d")_seed_corpus.zip "$d" done # get fuzz-dns-packet corpus