forked from pool/coreutils
217 lines
8.0 KiB
Diff
217 lines
8.0 KiB
Diff
|
# Upstream fix on top of coreutils-v8.27:
|
||
|
# Add upstream patch to fix an heap overflow security issue
|
||
|
# in date(1) and touch(1) with a large TZ variable
|
||
|
# (CVE-2017-7476, rh#1444774, boo#1037124).
|
||
|
|
||
|
This issue is already fixed upstream, so here in openSUSE
|
||
|
we're just picking up the patches:
|
||
|
|
||
|
* [PATCH 1/2] Upstream gnulib fix:
|
||
|
http://git.sv.gnu.org/cgit/gnulib.git/commit/?id=94e015715078
|
||
|
|
||
|
FWIW, this patch has been picked up by upstream coreutils by
|
||
|
the following update to latest gnulib:
|
||
|
http://git.sv.gnu.org/cgit/coreutils.git/commit/?id=5d4be52a982e
|
||
|
|
||
|
* [PATCH 2/2] Upstream coreutils test:
|
||
|
http://git.sv.gnu.org/cgit/coreutils.git/commit/?id=9287ef2b1707
|
||
|
|
||
|
This downstream patch squashes both commits into one.
|
||
|
Here are the original commit messages.
|
||
|
|
||
|
================================================================================
|
||
|
From 94e01571507835ff59dd8ce2a0b56a4b566965a4 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
|
||
|
|
||
|
================================================================================
|
||
|
From 9287ef2b1707e2a222f8ae776ce3785abcb16fba 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.
|
||
|
|
||
|
---
|
||
|
NEWS | 9 +++++++++
|
||
|
gnulib-tests/test-parse-datetime.c | 16 ++++++++++++++++
|
||
|
lib/time_rz.c | 15 +++++++++++++--
|
||
|
tests/local.mk | 1 +
|
||
|
tests/misc/date-tz.sh | 26 ++++++++++++++++++++++++++
|
||
|
5 files changed, 65 insertions(+), 2 deletions(-)
|
||
|
|
||
|
Index: NEWS
|
||
|
===================================================================
|
||
|
--- NEWS.orig
|
||
|
+++ NEWS
|
||
|
@@ -1,5 +1,14 @@
|
||
|
GNU coreutils NEWS -*- outline -*-
|
||
|
|
||
|
+* Noteworthy openSUSE changes after release 8.27 [downstream]
|
||
|
+
|
||
|
+** Bug fixes
|
||
|
+
|
||
|
+ date and touch no longer overwrite the heap with large
|
||
|
+ user specified TZ values (CVE-2017-7476).
|
||
|
+ [bug introduced in coreutils-8.27]
|
||
|
+
|
||
|
+
|
||
|
* Noteworthy changes in release 8.27 (2017-03-08) [stable]
|
||
|
|
||
|
** Bug fixes
|
||
|
Index: gnulib-tests/test-parse-datetime.c
|
||
|
===================================================================
|
||
|
--- gnulib-tests/test-parse-datetime.c.orig
|
||
|
+++ 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;
|
||
|
}
|
||
|
Index: lib/time_rz.c
|
||
|
===================================================================
|
||
|
--- lib/time_rz.c.orig
|
||
|
+++ 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
|
||
|
{
|
||
|
Index: tests/local.mk
|
||
|
===================================================================
|
||
|
--- tests/local.mk.orig
|
||
|
+++ 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 \
|
||
|
Index: tests/misc/date-tz.sh
|
||
|
===================================================================
|
||
|
--- /dev/null
|
||
|
+++ 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
|