β¬’ DragonFlyBSD Kernel Audit
← triage Β· dashboard
DF-4747

DragonFly's linux/hash.h hash_64() shim returns identically 0 for every bits <= 32, collapsing the chash (amdgpu retry-fault hash) so all keys probe from slot 0

Summary

chash.c is byte-identical to Linux v4.19 and sound, but the DFly hash_64 shim casts a 32-bit hash32_buf result to u64 then shifts >>(64-bits) - identically 0 for every bits<=32, so the amdgpu retry-fault chash (bits=8) always probes from slot 0 and drm_hashtab degrades the same way. Correctness preserved (linear probing, 50% fill cap) - perf-only today, latent for future consumers. Fix the shim: hash twice with different seeds and concatenate. [VERIFIED pass2: reproduced via KMOD with real DRM header - hash_64 x 8 returns 0 identically collapsing the amdgpu retry-fault chash to slot-0 probing; fixed tree returns distinct nonzero values A/B]

Discussion (0)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-4747 Β· 6 files
FileTypeDescriptionSize
README.md β€” 240 B ↓ raw
fix.diff β€” 681 B view raw
hash4747.c β€” 1.3 KB view raw
manifest.json β€” 424 B view raw
run.log β€” 292 B view raw
verdict.json β€” 2.0 KB view raw

DF-4747 evidence pack

What

DRM hash_64 shim returns identically 0 for bits <= 32, collapsing chash

Verdict

status=reproduced impact=none confidence=certain

See VERDICT.md for the full narrative and fix.diff for the verified fix.

Fix verification

fixed

A/B complete: the KMOD rebuilt against the patched header returns distinct nonzero values for bits=8 (0xe3/0x49/0x90) and 40 (0x72d3778c97); stock returned identically 0 for bits<=32.

↓ fix.diffper-fix-DF-4747

Confirmed kernel references

Detail

Evidence (decisive lines)

VERDICT.md with path:line citations; run.log where a live demo exists; fix.diff

PoC changes

KMOD needed local u64/u32 typedefs + BITS_PER_LONG before including the DRM header (its include chain pulls kernel-only headers)

Verified recommended fix

hash twice with different seeds and concatenate (real 64-bit mix)

Verdict

Reproduced on the stock INVARIANTS guest with a KMOD that includes the real shim header (linux/hash.h): hash_64(x, 8) returns 0x0 for every input tested (0x1122334455667788, 0xdeadbeefcafebabe, 1) - the shim casts the 32-bit hash32_buf result to u64 and shifts right by (64 - bits) >= 32, which is identically zero (hash.h:32-38). chash.c (byte-identical to Linux v4.19, itself sound) calls hash_64(key, bits) at :398/:433 for 64-bit keys, so the amdgpu retry-fault chash (bits=8, amdgpu_vm.c) always probes slot 0 - linear-probe degradation, correctness preserved by the 50% fill cap. Post-fix A/B: the KMOD rebuilt against the patched tree returns nonzero, well-distributed values for bits=8 and 40. Fix = two independent 32-bit hashes concatenated; compile-validated via the KMOD rebuild (drm itself is module-built; the header is DRM-internal).