CVE-2026-76844 is not in the Debian security tracker. It is a distinct bug
from CVE-2026-85091 (tracked, bug #1146895) but is resolved by the same
upstream commit df84af2 ("Fix buffer overflow bug in non-blocking gzwrite"),
already shipped in sid as zlib/1:1.3.dfsg+really1.3.2-4.
Difference between the two CVEs (per the CVE records):
- CVE-2026-85091: unchecked memmove() in gz_vacate(), reached via
gzprintf()/gzvprintf() after a *non-blocking* write stall. The vulnerable
code only exists in 1.3.1.2-1.3.2 (gz_vacate did not exist before), so
bookworm/trixie are not affected by it - as already noted in bug #1146895.
- CVE-2026-76844: stale strm.next_in in gz_write(). When the underlying
write() fails, gz_write() returns without resetting strm.next_in, which in
the direct-compression path (len >= state->size) points at the caller's
buffer. After gzclearerr(), a subsequent small gzwrite() takes the buffered
path and computes
have = (unsigned)((state->strm.next_in + state->strm.avail_in) -
state->in);
from a pointer into an unrelated allocation, so
memcpy(state->in + have, buf, copy);
writes caller-controlled data to a wild heap address. Affected range per
the CVE record: 1.2.11 through 1.3.2. Any write() failure reaches it
(ENOSPC, EPIPE on a blocking descriptor); before 1.3.1.2 the failed write
must be followed by gzclearerr(), which is a documented, supported API
call (zlib.h: "analogous to the clearerr() function in stdio. This is
useful for continuing to read a gzip file that is being written
concurrently").
Verification (ASan+UBSan, upstream release tarballs, static libz.a - full
log attached as verification-log.txt):
version unpatched patched
1.2.11 SEGV on WRITE, gzwrite.c:213 clean, write buffered
1.2.13 SEGV on WRITE, gzwrite.c:222 clean
1.3.1 SEGV on WRITE, gzwrite.c:204 clean
1.3.2 SEGV on WRITE, gzwrite.c:217 clean (df84af2)
`make check` passes on all four patched builds.
The attached PoC (poc-cve-2026-76844.c) uses /dev/full to make write() fail
with ENOSPC on the first 256 KiB flush, then gzclearerr(), then an 8-byte
gzwrite(). gzerror() confirms "No space left on device"; the second call
crashes inside memcpy(state->in + have, ...) writing to an unmapped address.
It is an out-of-bounds write, not a use-after-free (no object is freed; the
caller buffer is only rewritten).
Status assessment:
- sid 1:1.3.2-4: already fixed - the CVE-2026-85091 patch is upstream
df84af2, whose next_in/avail_in reset eliminates this vector. The PoC does
not crash there. Suggest recording CVE-2026-76844 in the tracker as fixed
in the same version, so scanners report it correctly.
- trixie 1:1.3.1, bookworm 1.2.13, bullseye 1.2.11: vulnerable, untracked,
unfixed. Backport patches attached (the same reset applied to the older
code shape). Note the "not-affected" reasoning used for 85091 on these
releases does not carry over: the bug is real there even without
gz_vacate().
- No upstream release contains the fix yet (df84af2 is post-1.3.2 on
develop), so a distro patch is required.
Patches attached (backport of df84af2; semantics identical to upstream -
the failed write() already reported 0 bytes, so discarding the stale input
position loses nothing; the caller must retry the whole write anyway):
- CVE-2026-76844-zlib-1.2.11.patch bullseye (also matches Ubuntu jammy)
- CVE-2026-76844-zlib-1.2.13.patch bookworm
- CVE-2026-76844-zlib-1.3.1.patch trixie (also matches Ubuntu noble)
- CVE-2026-76844-zlib-1.3.2.patch reference only - identical to the patch
already in sid -4
Attachments: poc-cve-2026-76844.c, verification-log.txt, and the four patch
files above.
Regards,
Raphael Paez