HomeFreeBSD

fflush: correct buffer handling in __sflush

Description

fflush: correct buffer handling in __sflush

This fixes CVE-2014-8611 correctly.

The commit that purported to fix CVE-2014-8611 (805288c2f062) only hid
it behind another bug. Two later commits, 86a16ada1ea6 and
44cf1e5eb470, attempted to address this new bug but mostly just confused
the issue. This commit rolls back the three previous changes and fixes
CVE-2014-8611 correctly.

The key to understanding the bug (and the fix) is that _w has
different meanings for different stream modes. If the stream is
unbuffered, it is always zero. If the stream is fully buffered, it is
the amount of space remaining in the buffer (equal to the buffer size
when the buffer is empty and zero when the buffer is full). If the
stream is line-buffered, it is a negative number reflecting the amount
of data in the buffer (zero when the buffer is empty and negative buffer
size when the buffer is full).

At the heart of fflush(), we call the stream's write function in a
loop, where t represents the return value from the last call and n
the amount of data that remains to be written. When the write function
fails, we need to move the unwritten data to the top of the buffer
(unless nothing was written) and adjust _p (which points to the next
free location in the buffer) and _w accordingly. These variables have
already been set to the values they should have after a successful
flush, so instead of adjusting them down to reflect what was written,
we're adjusting them up to reflect what remains.

The bug was that while _p was always adjusted, we only adjusted _w
if the stream was fully buffered. The fix is to also adjust _w for
line-buffered streams. Everything else is just noise.

Fixes: 805288c2f062
Fixes: 86a16ada1ea6
Fixes: 44cf1e5eb470
Sponsored by: Klara, Inc.

Details

Provenance
desAuthored on Aug 3 2023, 3:13 PM
emasteCommitted on Nov 7 2023, 1:21 PM
Parents
rG96cb1d70008e: linuxkpi linux_work: use 'true' instead of 'non-zero'
Branches
Unknown
Tags
Unknown

Event Timeline