From: Luca Boccassi Date: Fri, 29 May 2026 11:37:31 +0000 (+0100) Subject: hwdb: reject overlong fnmatch key instead of passing NULL to fnmatch() X-Git-Tag: v261-rc3~45 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3db89cbf0e27e3ef38a060c3c765367a700ad7f7;p=thirdparty%2Fsystemd.git hwdb: reject overlong fnmatch key instead of passing NULL to fnmatch() When the accumulated trie key exceeds the fixed-size line buffer, linebuf_get() returns NULL. trie_fnmatch_f() passed that NULL straight into fnmatch() as the pattern, causing a SIGSEGV on a crafted hwdb.bin (reachable now that recursion is capped rather than overflowing the stack first). Treat the NULL like the other corruption checks and return -EBADMSG. Follow-up for 73fea38cf1344e08213bb10bfc1e1a98382aee78 Fixes https://github.com/systemd/systemd/issues/42376 Co-developed-by: Claude Opus 4.8 --- diff --git a/src/libsystemd/sd-hwdb/sd-hwdb.c b/src/libsystemd/sd-hwdb/sd-hwdb.c index 2a265aae874..938d02f3b79 100644 --- a/src/libsystemd/sd-hwdb/sd-hwdb.c +++ b/src/libsystemd/sd-hwdb/sd-hwdb.c @@ -286,12 +286,18 @@ static int trie_fnmatch_f(sd_hwdb *hwdb, const struct trie_node_f *node, size_t linebuf_rem_char(buf); } - if (le64toh(node->values_count) && fnmatch(linebuf_get(buf), search, 0) == 0) - for (i = 0; i < le64toh(node->values_count); i++) { - err = hwdb_add_property(hwdb, trie_node_value(hwdb, node, i)); - if (err < 0) - return err; - } + if (le64toh(node->values_count) != 0) { + const char *line = linebuf_get(buf); + if (!line) + return -EBADMSG; + + if (fnmatch(line, search, 0) == 0) + for (i = 0; i < le64toh(node->values_count); i++) { + err = hwdb_add_property(hwdb, trie_node_value(hwdb, node, i)); + if (err < 0) + return err; + } + } linebuf_rem(buf, len); return 0; diff --git a/test/fuzz/fuzz-hwdb/overlong-fnmatch-key b/test/fuzz/fuzz-hwdb/overlong-fnmatch-key new file mode 100644 index 00000000000..a1850c9d7d0 Binary files /dev/null and b/test/fuzz/fuzz-hwdb/overlong-fnmatch-key differ