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 73fea38cf1

Fixes https://github.com/systemd/systemd/issues/42376

Co-developed-by: Claude Opus 4.8 <noreply@anthropic.com>
(cherry picked from commit 3db89cbf0e)
(cherry picked from commit 138565f8d6)
(cherry picked from commit e6337757b5)
This commit is contained in:
Luca Boccassi
2026-05-29 12:37:31 +01:00
parent 5221cc3fb2
commit cd674979f9
2 changed files with 12 additions and 6 deletions

View File

@@ -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;

Binary file not shown.