Changeset View
Changeset View
Standalone View
Standalone View
files/security/cve-2017-7476.patch
- This file was added.
| From fc286e2b3af5b2ed9aec44b520265bb0968f1660 Mon Sep 17 00:00:00 2001 | |||||
| From: =?UTF-8?q?P=C3=A1draig=20Brady?= <P@draigBrady.com> | |||||
| Date: Mon, 24 Apr 2017 01:43:36 -0700 | |||||
| Subject: [PATCH 1/2] time_rz: fix heap buffer overflow vulnerability | |||||
| This issue has been assigned CVE-2017-7476 and was | |||||
| detected with American Fuzzy Lop 2.41b run on the | |||||
| coreutils date(1) program with ASAN enabled. | |||||
| ERROR: AddressSanitizer: heap-buffer-overflow on address 0x... | |||||
| WRITE of size 8 at 0x60d00000cff8 thread T0 | |||||
| #1 0x443020 in extend_abbrs lib/time_rz.c:88 | |||||
| #2 0x443356 in save_abbr lib/time_rz.c:155 | |||||
| #3 0x44393f in localtime_rz lib/time_rz.c:290 | |||||
| #4 0x41e4fe in parse_datetime2 lib/parse-datetime.y:1798 | |||||
| A minimized reproducer is the following 120 byte TZ value, | |||||
| which goes beyond the value of ABBR_SIZE_MIN (119) on x86_64. | |||||
| Extend the aa...b portion to overwrite more of the heap. | |||||
| date -d $(printf 'TZ="aaa%020daaaaaab%089d"') | |||||
| localtime_rz and mktime_z were affected since commit 4bc76593. | |||||
| parse_datetime was affected since commit 4e6e16b3f. | |||||
| * lib/time_rz.c (save_abbr): Rearrange the calculation determining | |||||
| whether there is enough buffer space available. The rearrangement | |||||
| ensures we're only dealing with positive numbers, thus avoiding | |||||
| the problematic promotion of signed to unsigned causing an invalid | |||||
| comparison when zone_copy is more than ABBR_SIZE_MIN bytes beyond | |||||
| the start of the buffer. | |||||
| * tests/test-parse-datetime.c (main): Add a test case written by | |||||
| Paul Eggert, which overwrites enough of the heap so that | |||||
| standard glibc will fail with "free(): invalid pointer" | |||||
| without the patch applied. | |||||
| Reported and analyzed at https://bugzilla.redhat.com/1444774 | |||||
| Upstream-commit: 94e01571507835ff59dd8ce2a0b56a4b566965a4 | |||||
| Signed-off-by: Kamil Dudka <kdudka@redhat.com> | |||||
| --- | |||||
| gnulib-tests/test-parse-datetime.c | 16 ++++++++++++++++ | |||||
| lib/time_rz.c | 15 +++++++++++++-- | |||||
| 2 files changed, 29 insertions(+), 2 deletions(-) | |||||
| diff --git a/gnulib-tests/test-parse-datetime.c b/gnulib-tests/test-parse-datetime.c | |||||
| index b42a51c..b6fe457 100644 | |||||
| --- a/gnulib-tests/test-parse-datetime.c | |||||
| +++ b/gnulib-tests/test-parse-datetime.c | |||||
| @@ -432,5 +432,21 @@ main (int argc _GL_UNUSED, char **argv) | |||||
| ASSERT ( parse_datetime (&result, "TZ=\"\\\\\"", &now)); | |||||
| ASSERT ( parse_datetime (&result, "TZ=\"\\\"\"", &now)); | |||||
| + /* Outlandishly-long time zone abbreviations should not cause problems. */ | |||||
| + { | |||||
| + static char const bufprefix[] = "TZ=\""; | |||||
| + enum { tzname_len = 2000 }; | |||||
| + static char const bufsuffix[] = "0\" 1970-01-01 01:02:03.123456789"; | |||||
| + enum { bufsize = sizeof bufprefix - 1 + tzname_len + sizeof bufsuffix }; | |||||
| + char buf[bufsize]; | |||||
| + memcpy (buf, bufprefix, sizeof bufprefix - 1); | |||||
| + memset (buf + sizeof bufprefix - 1, 'X', tzname_len); | |||||
| + strcpy (buf + bufsize - sizeof bufsuffix, bufsuffix); | |||||
| + ASSERT (parse_datetime (&result, buf, &now)); | |||||
| + LOG (buf, now, result); | |||||
| + ASSERT (result.tv_sec == 1 * 60 * 60 + 2 * 60 + 3 | |||||
| + && result.tv_nsec == 123456789); | |||||
| + } | |||||
| + | |||||
| return 0; | |||||
| } | |||||
| diff --git a/lib/time_rz.c b/lib/time_rz.c | |||||
| index adb9c1c..c41a8ef 100644 | |||||
| --- a/lib/time_rz.c | |||||
| +++ b/lib/time_rz.c | |||||
| @@ -27,6 +27,7 @@ | |||||
| #include <time.h> | |||||
| #include <errno.h> | |||||
| +#include <limits.h> | |||||
| #include <stdbool.h> | |||||
| #include <stddef.h> | |||||
| #include <stdlib.h> | |||||
| @@ -35,6 +36,10 @@ | |||||
| #include "flexmember.h" | |||||
| #include "time-internal.h" | |||||
| +#ifndef SIZE_MAX | |||||
| +# define SIZE_MAX ((size_t) -1) | |||||
| +#endif | |||||
| + | |||||
| #if !HAVE_TZSET | |||||
| static void tzset (void) { } | |||||
| #endif | |||||
| @@ -43,7 +48,7 @@ static void tzset (void) { } | |||||
| the largest "small" request for the GNU C library malloc. */ | |||||
| enum { DEFAULT_MXFAST = 64 * sizeof (size_t) / 4 }; | |||||
| -/* Minimum size of the ABBRS member of struct abbr. ABBRS is larger | |||||
| +/* Minimum size of the ABBRS member of struct tm_zone. ABBRS is larger | |||||
| only in the unlikely case where an abbreviation longer than this is | |||||
| used. */ | |||||
| enum { ABBR_SIZE_MIN = DEFAULT_MXFAST - offsetof (struct tm_zone, abbrs) }; | |||||
| @@ -150,7 +155,13 @@ save_abbr (timezone_t tz, struct tm *tm) | |||||
| if (! (*zone_copy || (zone_copy == tz->abbrs && tz->tz_is_set))) | |||||
| { | |||||
| size_t zone_size = strlen (zone) + 1; | |||||
| - if (zone_size < tz->abbrs + ABBR_SIZE_MIN - zone_copy) | |||||
| + size_t zone_used = zone_copy - tz->abbrs; | |||||
| + if (SIZE_MAX - zone_used < zone_size) | |||||
| + { | |||||
| + errno = ENOMEM; | |||||
| + return false; | |||||
| + } | |||||
| + if (zone_used + zone_size < ABBR_SIZE_MIN) | |||||
| extend_abbrs (zone_copy, zone, zone_size); | |||||
| else | |||||
| { | |||||
| -- | |||||
| 2.9.3 | |||||
| From 9579f90484c71e5a22f32f35189192a82e47550e Mon Sep 17 00:00:00 2001 | |||||
| From: =?UTF-8?q?P=C3=A1draig=20Brady?= <P@draigBrady.com> | |||||
| Date: Wed, 26 Apr 2017 20:51:39 -0700 | |||||
| Subject: [PATCH 2/2] date,touch: test and document large TZ security issue | |||||
| Add a test for CVE-2017-7476 which was fixed in gnulib at: | |||||
| http://git.sv.gnu.org/gitweb/?p=gnulib.git;a=commitdiff;h=94e01571 | |||||
| * tests/misc/date-tz.sh: Add a new test which overwrites enough | |||||
| of the heap to trigger a segfault, even without ASAN enabled. | |||||
| * tests/local.mk: Reference the new test. | |||||
| * NEWS: Mention the bug fix. | |||||
| Upstream-commit: 9287ef2b1707e2a222f8ae776ce3785abcb16fba | |||||
| Signed-off-by: Kamil Dudka <kdudka@redhat.com> | |||||
| --- | |||||
| tests/local.mk | 1 + | |||||
| tests/misc/date-tz.sh | 26 ++++++++++++++++++++++++++ | |||||
| 2 files changed, 27 insertions(+) | |||||
| create mode 100755 tests/misc/date-tz.sh | |||||
| diff --git a/tests/local.mk b/tests/local.mk | |||||
| index 9f1a853..ec0b414 100644 | |||||
| --- a/tests/local.mk | |||||
| +++ b/tests/local.mk | |||||
| @@ -282,6 +282,7 @@ all_tests = \ | |||||
| tests/misc/csplit-suppress-matched.pl \ | |||||
| tests/misc/date-debug.sh \ | |||||
| tests/misc/date-sec.sh \ | |||||
| + tests/misc/date-tz.sh \ | |||||
| tests/misc/dircolors.pl \ | |||||
| tests/misc/dirname.pl \ | |||||
| tests/misc/env-null.sh \ | |||||
| diff --git a/tests/misc/date-tz.sh b/tests/misc/date-tz.sh | |||||
| new file mode 100755 | |||||
| index 0000000..3fe1579 | |||||
| --- /dev/null | |||||
| +++ b/tests/misc/date-tz.sh | |||||
| @@ -0,0 +1,26 @@ | |||||
| +#!/bin/sh | |||||
| +# Verify TZ processing. | |||||
| + | |||||
| +# Copyright (C) 2017 Free Software Foundation, Inc. | |||||
| + | |||||
| +# This program is free software: you can redistribute it and/or modify | |||||
| +# it under the terms of the GNU General Public License as published by | |||||
| +# the Free Software Foundation, either version 3 of the License, or | |||||
| +# (at your option) any later version. | |||||
| + | |||||
| +# This program is distributed in the hope that it will be useful, | |||||
| +# but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
| +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
| +# GNU General Public License for more details. | |||||
| + | |||||
| +# You should have received a copy of the GNU General Public License | |||||
| +# along with this program. If not, see <http://www.gnu.org/licenses/>. | |||||
| + | |||||
| +. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src | |||||
| +print_ver_ date | |||||
| + | |||||
| +# coreutils-8.27 would overwrite the heap with large TZ values | |||||
| +tz_long=$(printf '%2000s' | tr ' ' a) | |||||
| +date -d "TZ=\"${tz_long}0\" 2017" || fail=1 | |||||
| + | |||||
| +Exit $fail | |||||
| -- | |||||
| 2.9.3 | |||||
Copyright © 2015-2021 Solus Project. The Solus logo is Copyright © 2016-2021 Solus Project. All Rights Reserved.