]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
hwdb: reject overlong fnmatch key instead of passing NULL to fnmatch()
authorLuca Boccassi <luca.boccassi@gmail.com>
Fri, 29 May 2026 11:37:31 +0000 (12:37 +0100)
committerLuca Boccassi <luca.boccassi@gmail.com>
Fri, 29 May 2026 16:21:31 +0000 (17:21 +0100)
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 <noreply@anthropic.com>
src/libsystemd/sd-hwdb/sd-hwdb.c
test/fuzz/fuzz-hwdb/overlong-fnmatch-key [new file with mode: 0644]

index 2a265aae874e0743e0bd966d05bb730f71bcd7d9..938d02f3b79afc59944954c41d2fd3dd31a22574 100644 (file)
@@ -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 (file)
index 0000000..a1850c9
Binary files /dev/null and b/test/fuzz/fuzz-hwdb/overlong-fnmatch-key differ