]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/commit
fflush: correct buffer handling in __sflush
authorDag-Erling Smørgrav <des@FreeBSD.org>
Thu, 3 Aug 2023 15:08:03 +0000 (15:08 +0000)
committerEd Maste <emaste@FreeBSD.org>
Wed, 8 Nov 2023 00:48:03 +0000 (19:48 -0500)
commitd51a39b13ee4de5410f6c01a357eafc6248f6724
treeb23ba7dd27aaef713fa53be17f3b37ae5a767329
parentd20ece445acfc5d29ca096b38e30e4c0cb0b0d95
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.

(cherry picked from commit 1f90b4edffe815aebb35e74b79e10593b31f6b75)
(cherry picked from commit 1e99535be2ea9c0ef8bc57fc885e9c01fa95d2dd)
(cherry picked from commit ccdd8337f9cbd7d34e2e95df1440dd5f7225d0b4)
(cherry picked from commit d09a3bf72c0b5f1779c52269671872368c99f02a)
(cherry picked from commit 92709431b14df6c0687446247ac57cfc189ee827)
(cherry picked from commit 6cb5690b3495741e9ece6f42ba4a85732932aa83)
(cherry picked from commit 418f026bd5a5084c1c4e2e91ad38051f6caa928c)
(cherry picked from commit abe12d2f4ce31c3da0961b1b0a58df11f5a41e19)
(cherry picked from commit 59ec3ffdd7ce85f32ea833e8024f7bacd36d4e97)
(cherry picked from commit 4e0e01bf6511c28212d7dff94fe131a502e13026)
(cherry picked from commit d2c65a1c948648f11342274029a3f18b90aa58d2)
(cherry picked from commit 0b7939d725ba0ca903c5f8a3ca6d74347eb88690)

Approved by: so
Approved by: re (implicit)
Security: SA-23:15.stdio
Sponsored by: The FreeBSD Foundation
lib/libc/stdio/fflush.c
lib/libc/stdio/fvwrite.c
lib/libc/stdio/wbuf.c