|
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.