hammer2 zlib port drops zcalloc's zero-initialization: deflate window/state kmalloc'd unzeroed, leaving stale-heap reads whose output-independence rests on subtle invariants
| Field | Value |
|---|---|
| ID | DF-2656 |
| Status | new |
| Severity | Info |
| CVSS 3.1 | CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:N/I:N/A:N |
| CWE | CWE-908 Use of Uninitialized Resource |
| File | sys/vfs/hammer2/zlib/hammer2_zlib_deflate.c |
| Lines | 239, 254-256, 262 (inflate state :196) |
| Area | vfs |
| Confidence | certain |
| Discovered | 2026-08-29 |
| Pass | 2 (GLM 5.3 second pass) |
| Bucket | hammer2 |
| Reported | pending |
| Known CVE | none |
| CVE match | novel |
Summary
Stock zlib 1.2.8 allocates deflate's window/prev/head/overlay via
zcalloc (which returns zeroed memory). The port replaced these with
kmalloc(..., M_INTWAIT) — none zeroed. Every algorithm-read field was
verified still initialized before use EXCEPT the deflate sliding window
beyond the data written so far: longest_match scans up to
strstart+MAX_MATCH ignoring lookahead (deflate.c:641-757; the code
itself documents the uninitialized accesses at :669-676) and
fill_window's hash re-init reads window[str..str+MIN_MATCH-1]
(:883-901, bounded in-bounds of written data). No leak into output is
possible today: match length is capped to lookahead at return
(:743-758) and match_start+length < strstart+lookahead bounds every
emitted (length,distance) pair to written bytes, so decompressed output
always equals the input. Residual risk: compression CHOICES (hence
comp_size and on-disk compressed bytes) depend on stale heap contents —
a nondeterminism surface with no observable channel found (physical
compressed bytes, dedup XXH64 hashes, and failed-decompress reads are
not exposed to unprivileged users).
Threat model & preconditions
Defense-in-depth only. The concern is fragility: any future edit that lets a match/literal reference window data beyond strstart+lookahead instantly becomes a cross-user kernel-heap disclosure into user-readable file contents, because the structural zeroing upstream zlib relies on is absent. Distinct from DF-0266 (inflate-side window).
Recommended fix
Restore stock zcalloc semantics — add | M_ZERO to the five kmalloc
sites (deflate.c:239,254-256,262; optionally the inflate state at
inflate.c:196, though every inflate field read is explicitly reset
today).
References
- DF-0266 (inflate-side window leak), DF-2655 (error-path behavior surfaced in the same batch audit)
Timeline
- 2026-08-29 Discovered during the pass-2 zlib batch audit (GLM 5.3).
No comments yet.