Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Make time zone file parser more robust [BZ #17715]
  • Loading branch information
Florian Weimer committed Apr 24, 2015
1 parent ed15967 commit 42261ad
Show file tree
Hide file tree
Showing 11 changed files with 456 additions and 214 deletions.
27 changes: 27 additions & 0 deletions ChangeLog
@@ -1,3 +1,30 @@
2015-04-24 Florian Weimer <fweimer@redhat.com>

[BZ #17715]
* time/tzfile.c (__tzfile_read): Check for large values of
tzh_ttisstdcnt and tzh_ttisgmtcnt. Use malloc instead of alloca.
* time/tzset.c (__tzstring_len): New function, based on the old
__tzstring function.
(__tzstring): Call __tzstring_len.
(parse_tzname): New helper function extracted from
__tzset_parse_tz. Call __tzstring_len, without making a copy of
the input string.
(parse_offset): New helper function extracted from
__tzset_parse_tz. Replace switch with fallthrough with
initialization before sscanf.
(parse_rule): Likewise.
(__tzset_parse_tz): Rewrite using the new helper functions. Use
new-style function definition.
* timezone/Makefile (tests): Add tst-tzset.
(tst-tzset.out): Dependencies on time zone files.
(tst-tzset-ENV): Set TZDIR.
(testdata/XT%): Copy crafted time zone files.
* timezone/README: Mention crafted time zone files.
* timezone/testdata/XT1, timezone/testdata/XT2,
timezone/testdata/XT3, timezone/testdata/XT4: New time zone test
files.
* timezone/tst-tzset.c: New test.

2015-04-24 Florian Weimer <fweimer@redhat.com>

* Makeconfig (+gccwarn): Remove -Winline.
Expand Down
18 changes: 12 additions & 6 deletions NEWS
Expand Up @@ -11,12 +11,12 @@ Version 2.22

4719, 6792, 13064, 14094, 14841, 14906, 15319, 15467, 15790, 15969, 16351,
16512, 16560, 16783, 16850, 17090, 17195, 17269, 17523, 17542, 17569,
17588, 17596, 17620, 17621, 17628, 17631, 17711, 17776, 17779, 17792,
17836, 17912, 17916, 17930, 17932, 17944, 17949, 17964, 17965, 17967,
17969, 17978, 17987, 17991, 17996, 17998, 17999, 18019, 18020, 18029,
18030, 18032, 18036, 18038, 18039, 18042, 18043, 18046, 18047, 18068,
18080, 18093, 18100, 18104, 18110, 18111, 18128, 18138, 18185, 18197,
18206, 18210, 18211, 18247, 18287.
17588, 17596, 17620, 17621, 17628, 17631, 17711, 17715, 17776, 17779,
17792, 17836, 17912, 17916, 17930, 17932, 17944, 17949, 17964, 17965,
17967, 17969, 17978, 17987, 17991, 17996, 17998, 17999, 18019, 18020,
18029, 18030, 18032, 18036, 18038, 18039, 18042, 18043, 18046, 18047,
18068, 18080, 18093, 18100, 18104, 18110, 18111, 18128, 18138, 18185,
18197, 18206, 18210, 18211, 18247, 18287.

* Cache information can be queried via sysconf() function on s390 e.g. with
_SC_LEVEL1_ICACHE_SIZE as argument.
Expand All @@ -28,6 +28,12 @@ Version 2.22
potentially arbitrary code execution, using crafted, but syntactically
valid DNS responses. (CVE-2015-1781)

* The time zone file parser has been made more robust against crafted time
zone files, avoiding heap buffer overflows related to the processing of
the tzh_ttisstdcnt and tzh_ttisgmtcnt fields, and a stack overflow due to
large time zone data files. Overly long time zone specifiers in the TZ
variable no longer result in stack overflows and crashes.

* A powerpc and powerpc64 optimization for TLS, similar to TLS descriptors
for LD and GD on x86 and x86-64, has been implemented. You will need
binutils-2.24 or later to enable this optimization.
Expand Down
15 changes: 13 additions & 2 deletions time/tzfile.c
Expand Up @@ -200,6 +200,9 @@ __tzfile_read (const char *file, size_t extra, char **extrap)
num_isstd = (size_t) decode (tzhead.tzh_ttisstdcnt);
num_isgmt = (size_t) decode (tzhead.tzh_ttisgmtcnt);

if (__glibc_unlikely (num_isstd > num_types || num_isgmt > num_types))
goto lose;

/* For platforms with 64-bit time_t we use the new format if available. */
if (sizeof (time_t) == 8 && trans_width == 4
&& tzhead.tzh_version[0] != '\0')
Expand Down Expand Up @@ -434,13 +437,21 @@ __tzfile_read (const char *file, size_t extra, char **extrap)
goto lose;

tzspec_len = st.st_size - off - 1;
char *tzstr = alloca (tzspec_len);
if (tzspec_len == 0)
goto lose;
char *tzstr = malloc (tzspec_len);
if (tzstr == NULL)
goto lose;
if (getc_unlocked (f) != '\n'
|| (__fread_unlocked (tzstr, 1, tzspec_len - 1, f)
!= tzspec_len - 1))
goto lose;
{
free (tzstr);
goto lose;
}
tzstr[tzspec_len - 1] = '\0';
tzspec = __tzstring (tzstr);
free (tzstr);
}

/* Don't use an empty TZ string. */
Expand Down

0 comments on commit 42261ad

Please sign in to comment.