Compress path heap buffer overflow via incorrect worst-case expansion bound
Summary
Input size check at :397 uses PRED1_BUF_SIZE*8/9+1+4=3645 but mathematically correct maximum guaranteeing worst-case compressed output fits in outbuf+2(4094 bytes) is 3639. For inlen=3645 with all-wrong dictionary guesses on freshly-initialized node Pred1Compress writes 4101 bytes to outbuf+2 overflowing 7 bytes past 4096-byte outbuf boundary. Overflow lands in struct padding between outbuf and stats field on x86-64 no observable effect. Overflow path write-only compressed output never sent on wire (uncompressed branch taken when len>=inlen). Off by 6 in formula producing 6 extra input bytes each adding ~1.125 output bytes = ~7 bytes overflow. [VERIFIED pass2: reproduced padding-exact - adversarial all-wrong-guess input at inlen 3645 writes exactly 7 compressed bytes landing entirely in struct padding as the finding predicted, stats intact]
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-2563 Β· 5 files| File | Type | Description | Size | |
|---|---|---|---|---|
| harness.c | β | 8.2 KB | view raw | |
| build.sh | β | 91 B | view raw | |
| worstcase.h | β | 12.8 KB | view raw | |
| run.log | β | 1.3 KB | view raw | |
| run.2.log | β | 0 B | β download |
Fix verification
not_testableConfirmed kernel references
Detail
Evidence (decisive lines)
pred1_all.log: outbuf[4096..4102] nonzero with inlen=3645; layout printout (padding); control clean at 3639
PoC changes
adversarial worst-case input generated by simulating the real hash; harness module
Verified recommended fix
bound inputs at 3639 (PRED1_BUF_SIZE - 2 - ceil((PRED1_BUF_SIZE-2)/9))
Verdict
The compress input bound (ng_pred1.c:397) is PRED1_BUF_SIZE*8/9+1+4 = 3645, but the worst-case Pred1Compress output is n+ceil(n/8) = 4101 at outbuf+2 -- 7 bytes past the 4096-byte outbuf. Verified with the REAL ng_pred1.c compiled into the harness and an adversarial 3645-byte input generated against the real HASH(x)=(Hash<<4)^x (every guess wrong, confirmed by offline simulation): the kernel log shows compressed-stream bytes at outbuf[4096..4102] (8d 8e 8f d0 d6 01...), exactly 7 bytes -- and &stats-&outbuf=4103 proves those bytes land entirely in STRUCT PADDING (sizeof(cfg)=1 alignment), leaving stats.FramesPlain intact: no observable effect, precisely as the finding itself states. Control inlen=3639: zero bytes past outbuf. Netgraph7 latent file (compiled via module; not in stock kernel config).
No comments yet.