]> git.ipfire.org Git - thirdparty/systemd.git/commit
hwdb: bounds-check trie offsets against the mmap before dereferencing
authorjeffhuang <jeff@docker.xydrsucermoubd24xgo33yhsgd.bx.internal.cloudapp.net>
Wed, 27 May 2026 18:41:54 +0000 (18:41 +0000)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Thu, 28 May 2026 06:05:24 +0000 (15:05 +0900)
commit73fea38cf1344e08213bb10bfc1e1a98382aee78
tree4f6c7e9ea160a3665cc964442a1ddcfc2c92438a
parent6f31db9b07829dcd7f166da85405eecdf889a1c8
hwdb: bounds-check trie offsets against the mmap before dereferencing

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>
12 files changed:
src/libsystemd/meson.build
src/libsystemd/sd-hwdb/fuzz-hwdb.c [new file with mode: 0644]
src/libsystemd/sd-hwdb/sd-hwdb.c
src/libsystemd/sd-hwdb/test-sd-hwdb.c
src/systemd/sd-hwdb.h
test/fuzz/fuzz-hwdb/empty [new file with mode: 0644]
test/fuzz/fuzz-hwdb/magic-only [new file with mode: 0644]
test/fuzz/fuzz-hwdb/regression-42340-trie-fnmatch-node-oob [new file with mode: 0644]
test/fuzz/fuzz-hwdb/regression-42341-trie-search-prefix-oob [new file with mode: 0644]
test/fuzz/fuzz-hwdb/regression-42342-node-lookup-bsearch [new file with mode: 0644]
test/fuzz/fuzz-hwdb/regression-42343-hwdb-add-property-key [new file with mode: 0644]
test/fuzz/fuzz-hwdb/regression-trie-fnmatch-stack-overflow [new file with mode: 0644]