This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
integer overflow to heap overrun exploit in glibc
- From: Jeff Law <law at redhat dot com>
- To: libc-alpha at sources dot redhat dot com
- Date: Thu, 15 Dec 2011 12:46:41 -0700
- Subject: integer overflow to heap overrun exploit in glibc
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
As y'all may be aware, there's an integer overflow which can be used
to trigger a heap overrun/corruption in time/tzfile.c
http://dividead.wordpress.com/2009/06/01/glibc-timezone-integer-overflow/
http://rcvalle.com/post/14169476482/exploiting-glibc-tzfile-read-integer-overflow-to
I'm not terribly familiar with the code in question, but ISTM we have
to verify the intermediate computations to determine the amount of
memory to malloc don't overflow/wrap.
Here's a WIP. It catches the cases I've been made aware of
(overflowing total_size to 0 by creating a tzfile with a very large
tzh_charcnt). But there may be further overflows I've missed.
Obviously it's not commented and it's unclear to me if we also want to
put in some kind of sanity checks on total_size to prevent it from
trying to malloc unreasoanble amounts of memory.
Your feedback would be greatly appreciated.
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.11 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/
iQEcBAEBAgAGBQJO6k6gAAoJEBRtltQi2kC7ASQH/0UmQm0wqk3NRmlsVr5M1r3f
fUelY55y8OQssaFCLDZ9LX1vybam9j85gmvGtRJUU4MJ3134hn/v73k8TYCd3rHJ
/QIQY10zPBHkmEwp8G56+3l9QRl418C+ajTq0W4NAzM1rIHtPUgrqZ3AkNJgFVYU
OAF+2afFDGE5vJ3HR7LSL62tuxjDf7m66r4tHHkbhkSSZgkyW/YxfFUPDupZnlz8
Wl87JU/RWHdMJ+RR+fB1ofgFKrNZnGpIsD3sAc07KWTp63S358DSRpZ1IaF2o3vh
N93z28eCQQKIVciOKgAE5q/qYr1KmcyU/6M4xPk+Pqv5YFdKOz8uNiw5NQu2rv0=
=RKgA
-----END PGP SIGNATURE-----
diff -rup a/time/tzfile.c b/time/tzfile.c
--- a/time/tzfile.c 2011-10-19 05:03:31.000000000 -0600
+++ b/time/tzfile.c 2011-12-15 11:49:26.763121459 -0700
@@ -107,7 +107,7 @@ __tzfile_read (const char *file, size_t
size_t num_isstd, num_isgmt;
register FILE *f;
struct tzhead tzhead;
- size_t chars;
+ size_t chars, tmp;
register size_t i;
size_t total_size;
size_t types_idx;
@@ -238,11 +238,25 @@ __tzfile_read (const char *file, size_t
total_size = ((total_size + __alignof__ (struct ttinfo) - 1)
& ~(__alignof__ (struct ttinfo) - 1));
types_idx = total_size;
- total_size += num_types * sizeof (struct ttinfo) + chars;
+
+ tmp = num_types * sizeof (struct ttinfo);
+ if (total_size + tmp < tmp)
+ goto lose;
+ total_size += tmp;
+
+ if (total_size + chars < chars)
+ goto lose;
+ total_size += chars;
+
total_size = ((total_size + __alignof__ (struct leap) - 1)
& ~(__alignof__ (struct leap) - 1));
leaps_idx = total_size;
- total_size += num_leaps * sizeof (struct leap);
+
+ tmp = num_leaps * sizeof (struct leap);
+ if (total_size + tmp < tmp)
+ goto lose;
+ total_size += tmp;
+
tzspec_len = (sizeof (time_t) == 8 && trans_width == 8
? st.st_size - (ftello (f)
+ num_transitions * (8 + 1)
@@ -254,7 +268,15 @@ __tzfile_read (const char *file, size_t
/* Allocate enough memory including the extra block requested by the
caller. */
- transitions = (time_t *) malloc (total_size + tzspec_len + extra);
+ if (total_size + tzspec_len < total_size)
+ goto lose;
+ total_size += tzspec_len;
+
+ if (total_size + extra < extra)
+ goto lose;
+ total_size += extra;
+
+ transitions = (time_t *) malloc (total_size);
if (transitions == NULL)
goto lose;