|
|
Message-ID: <20140322183518.GA3735@brightrain.aerifal.cx>
Date: Sat, 22 Mar 2014 14:35:18 -0400
From: Rich Felker <dalias@...ifal.cx>
To: musl@...ts.openwall.com
Subject: Stack-based buffer overflow in musl libc versions 0.9.15 and earlier
An off-by-one error in the size of a buffer used by musl's
implementation of the printf-family functions for converting floating
point number to decimal leads to a buffer overflow when printing the
extremely small floating point values with extremely high precision.
In order to trigger the overflow, a value which is denormal when
represented as long double has to be printed to exact or near-exact
precision. On i386 and x86_64 targets where long double is 80-bit
extended precision, this means the precision must be more than 16381
places past the decimal point and the value printed must be below
2^-16381 to trigger the overflow. The overflow is impossible to
trigger on these targets with values of type double. On other targets
where long double has the same size and representation as double,
values below 2^-1021 with 1021 or more places past the decimal point
may trigger the overflow.
In testing, I was unable to cause the overflow, which only writes one
slot past the end of an array of 32-bit integers, to overwrite any
sensitive data such as return addresses. In fact, testing has always
shown that musl prints the smallest denormals correctly, which is why
this bug was not caught earlier. However, since the layout of objects
on the stack depends on the particular compiler used, it is possible
that some compilers may arrange the stack such that the overflow does
clobber the return address or a pointer through which the results are
later written, possibly leading to arbitrary code execution.
This issue was reported by Ryan Juckett (http://www.ryanjuckett.com)
who found it while comparing and evaluating different floating point
to decimal implementations.
The following commit fixes the issue and should apply cleanly to any
recent version of musl.
-------------------------------------------------------------------------------
commit ba231cf9e5923b6216081e9a626465c6643ce4d3
Author: Rich Felker <dalias@...ifal.cx>
Date: Sun Mar 9 01:38:52 2014 -0500
fix buffer overflow in printf formatting of denormals with low bit set
empirically the overflow was an off-by-one, and it did not seem to be
overwriting meaningful data. rather than simply increasing the buffer
size by one, however, I have attempted to make the size obviously
correct in terms of bounds on the number of iterations for the loops
that fill the buffer. this still results in no more than a negligible
size increase of the buffer on the stack (6-7 32-bit slots) and is a
"safer" fix unless/until somebody wants to do the proof that a smaller
buffer would suffice.
diff --git a/src/stdio/vfprintf.c b/src/stdio/vfprintf.c
index b5948bd..8570172 100644
--- a/src/stdio/vfprintf.c
+++ b/src/stdio/vfprintf.c
@@ -207,7 +207,8 @@ typedef char compiler_defines_long_double_incorrectly[9-(int)sizeof(long double)
static int fmt_fp(FILE *f, long double y, int w, int p, int fl, int t)
{
- uint32_t big[(LDBL_MAX_EXP+LDBL_MANT_DIG)/9+1];
+ uint32_t big[(LDBL_MANT_DIG+28)/29 + 1 // mantissa expansion
+ + (LDBL_MAX_EXP+LDBL_MANT_DIG+28+8)/9]; // exponent expansion
uint32_t *a, *d, *r, *z;
int e2=0, e, i, j, l;
char buf[9+LDBL_MANT_DIG/4], *s;
Powered by blists - more mailing lists
Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.