From cd674979f9610beb2d22c4be115b5907ff8f41a6 Mon Sep 17 00:00:00 2001 From: Luca Boccassi Date: Fri, 29 May 2026 12:37:31 +0100 Subject: [PATCH] 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 (cherry picked from commit 3db89cbf0e27e3ef38a060c3c765367a700ad7f7) (cherry picked from commit 138565f8d6ad2005ae92a5bb96f7ed29e211c798) (cherry picked from commit e6337757b57cd3397f35bba7518063310033ca7f) --- src/libsystemd/sd-hwdb/sd-hwdb.c | 18 ++++++++++++------ test/fuzz/fuzz-hwdb/overlong-fnmatch-key | Bin 0 -> 2168 bytes 2 files changed, 12 insertions(+), 6 deletions(-) create mode 100644 test/fuzz/fuzz-hwdb/overlong-fnmatch-key diff --git a/src/libsystemd/sd-hwdb/sd-hwdb.c b/src/libsystemd/sd-hwdb/sd-hwdb.c index 996f253fd90..ba3be260e00 100644 --- a/src/libsystemd/sd-hwdb/sd-hwdb.c +++ b/src/libsystemd/sd-hwdb/sd-hwdb.c @@ -203,12 +203,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 0000000000000000000000000000000000000000..a1850c9d7d0b26dd9c00ba1b28d598fd67293a41 GIT binary patch literal 2168 zcmeYc_6hLt2=ZWMWB`K-4hS6pp%^5fv;Z0nlh=TXGeGrK!1z!aYAl*41A|uLC>RZa V(GVC7fzc2c4S~@R7-1p6005FA3;_TD literal 0 HcmV?d00001