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>
The file name of the reproducer is used for test name, and the test name
is messed when the file name is too long.
Also, the mentioned issues are not regressions, but long standing bugs.
Follow-up for 73fea38cf1.
Fixes a family of OOB reads in the trie walker where attacker-controlled
offsets are loaded from a (possibly hostile) hwdb.bin and added to
hwdb->map without first checking that the resulting pointer stays inside
the mapping. Crash sites:
- trie_fnmatch_f sd-hwdb.c:187 (#42340)
- trie_search_f sd-hwdb.c:233 (#42341)
- trie_children_cmp_f /bsearch sd-hwdb.c:94 (#42342)
- hwdb_add_property sd-hwdb.c:121 (#42343)
- trie_node_from_off (UBSAN) sd-hwdb.c:83
- trie_fnmatch_f stack overflow on cyclic children (CIFuzz finding)
Commit b45a897edc ("hwdb: reject out-of-bounds fnmatch prefixes")
plugged the first site only at the prefix_off-content level, but the
crash on the read of node->prefix_off itself still happens when node is
already OOB. This is the structural fix: a single hwdb_at() helper
validates that [off, off + size) lies inside the mapping, and
trie_node_from_off() / trie_string() return NULL on OOB; every caller
treats the result as nullable and surfaces -EBADMSG.
trie_fnmatch_f() additionally caps its recursion depth at 2048; without
the cap a corrupt trie whose child offsets form a cycle (or just a deep
linear chain) drives the parser into stack-overflow rather than
returning -EBADMSG (caught by CIFuzz address sanitizer on this branch).
Additions:
- A fuzz-hwdb libFuzzer harness that drives sd_hwdb_new_from_path,
sd_hwdb_get, sd_hwdb_seek, and sd_hwdb_enumerate on attacker bytes.
- Five hand-crafted unit tests in test-sd-hwdb.c (one per crash
bucket, plus the cyclic-trie recursion case) that build a malformed
in-memory hwdb.bin and assert -EBADMSG rather than SIGSEGV /
stack-overflow.
- Regression corpus files under test/fuzz/fuzz-hwdb/ pinning each
fixed bucket, including the CIFuzz stack-overflow reproducer.
Closes#42340.
Closes#42341.
Closes#42342.
Closes#42343.
Reported-by: AI-assisted libFuzzer campaign
Co-developed-by: Claude Opus 4.7 <noreply@anthropic.com>