Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 1 | Upstream-Status: Backport |
| 2 | |
| 3 | Backport patch to fix CVE-2015-1345. |
| 4 | http://git.savannah.gnu.org/cgit/grep.git/commit/?id=83a95bd |
| 5 | |
| 6 | Signed-off-by: Kai Kang <kai.kang@windriver.com> |
| 7 | --- |
| 8 | From 83a95bd8c8561875b948cadd417c653dbe7ef2e2 Mon Sep 17 00:00:00 2001 |
| 9 | From: Yuliy Pisetsky <ypisetsky@fb.com> |
| 10 | Date: Thu, 1 Jan 2015 15:36:55 -0800 |
| 11 | Subject: [PATCH] grep -F: fix a heap buffer (read) overrun |
| 12 | |
| 13 | grep's read buffer is often filled to its full size, except when |
| 14 | reading the final buffer of a file. In that case, the number of |
| 15 | bytes read may be far less than the size of the buffer. However, for |
| 16 | certain unusual pattern/text combinations, grep -F would mistakenly |
| 17 | examine bytes in that uninitialized region of memory when searching |
| 18 | for a match. With carefully chosen inputs, one can cause grep -F to |
| 19 | read beyond the end of that buffer altogether. This problem arose via |
| 20 | commit v2.18-90-g73893ff with the introduction of a more efficient |
| 21 | heuristic using what is now the memchr_kwset function. The use of |
| 22 | that function in bmexec_trans could leave TP much larger than EP, |
| 23 | and the subsequent call to bm_delta2_search would mistakenly access |
| 24 | beyond end of the main input read buffer. |
| 25 | |
| 26 | * src/kwset.c (bmexec_trans): When TP reaches or exceeds EP, |
| 27 | do not call bm_delta2_search. |
| 28 | * tests/kwset-abuse: New file. |
| 29 | * tests/Makefile.am (TESTS): Add it. |
| 30 | * THANKS.in: Update. |
| 31 | * NEWS (Bug fixes): Mention it. |
| 32 | |
| 33 | Prior to this patch, this command would trigger a UMR: |
| 34 | |
| 35 | printf %0360db 0 | valgrind src/grep -F $(printf %019dXb 0) |
| 36 | |
| 37 | Use of uninitialised value of size 8 |
| 38 | at 0x4142BE: bmexec_trans (kwset.c:657) |
| 39 | by 0x4143CA: bmexec (kwset.c:678) |
| 40 | by 0x414973: kwsexec (kwset.c:848) |
| 41 | by 0x414DC4: Fexecute (kwsearch.c:128) |
| 42 | by 0x404E2E: grepbuf (grep.c:1238) |
| 43 | by 0x4054BF: grep (grep.c:1417) |
| 44 | by 0x405CEB: grepdesc (grep.c:1645) |
| 45 | by 0x405EC1: grep_command_line_arg (grep.c:1692) |
| 46 | by 0x4077D4: main (grep.c:2570) |
| 47 | |
| 48 | See the accompanying test for how to trigger the heap buffer overrun. |
| 49 | |
| 50 | Thanks to Nima Aghdaii for testing and finding numerous |
| 51 | ways to break early iterations of this patch. |
| 52 | --- |
| 53 | NEWS | 5 +++++ |
| 54 | THANKS.in | 1 + |
| 55 | src/kwset.c | 2 ++ |
| 56 | tests/Makefile.am | 1 + |
| 57 | tests/kwset-abuse | 32 ++++++++++++++++++++++++++++++++ |
| 58 | 5 files changed, 41 insertions(+) |
| 59 | create mode 100755 tests/kwset-abuse |
| 60 | |
| 61 | diff --git a/NEWS b/NEWS |
| 62 | index 975440d..3835d8d 100644 |
| 63 | --- a/NEWS |
| 64 | +++ b/NEWS |
| 65 | @@ -2,6 +2,11 @@ GNU grep NEWS -*- outline -*- |
| 66 | |
| 67 | * Noteworthy changes in release ?.? (????-??-??) [?] |
| 68 | |
| 69 | +** Bug fixes |
| 70 | + |
| 71 | + grep no longer reads from uninitialized memory or from beyond the end |
| 72 | + of the heap-allocated input buffer. |
| 73 | + |
| 74 | |
| 75 | * Noteworthy changes in release 2.21 (2014-11-23) [stable] |
| 76 | |
| 77 | diff --git a/THANKS.in b/THANKS.in |
| 78 | index aeaf516..624478d 100644 |
| 79 | --- a/THANKS.in |
| 80 | +++ b/THANKS.in |
| 81 | @@ -62,6 +62,7 @@ Michael Aichlmayr mikla@nx.com |
| 82 | Miles Bader miles@ccs.mt.nec.co.jp |
| 83 | Mirraz Mirraz mirraz1@rambler.ru |
| 84 | Nelson H. F. Beebe beebe@math.utah.edu |
| 85 | +Nima Aghdaii naghdaii@fb.com |
| 86 | Olaf Kirch okir@ns.lst.de |
| 87 | Paul Kimoto kimoto@spacenet.tn.cornell.edu |
| 88 | Péter Radics mitchnull@gmail.com |
| 89 | diff --git a/src/kwset.c b/src/kwset.c |
| 90 | index 4003c8d..376f7c3 100644 |
| 91 | --- a/src/kwset.c |
| 92 | +++ b/src/kwset.c |
| 93 | @@ -643,6 +643,8 @@ bmexec_trans (kwset_t kwset, char const *text, size_t size) |
| 94 | if (! tp) |
| 95 | return -1; |
| 96 | tp++; |
| 97 | + if (ep <= tp) |
| 98 | + break; |
| 99 | } |
| 100 | } |
| 101 | } |
| 102 | diff --git a/tests/Makefile.am b/tests/Makefile.am |
| 103 | index 2cba2cd..0508cd2 100644 |
| 104 | --- a/tests/Makefile.am |
| 105 | +++ b/tests/Makefile.am |
| 106 | @@ -75,6 +75,7 @@ TESTS = \ |
| 107 | inconsistent-range \ |
| 108 | invalid-multibyte-infloop \ |
| 109 | khadafy \ |
| 110 | + kwset-abuse \ |
| 111 | long-line-vs-2GiB-read \ |
| 112 | match-lines \ |
| 113 | max-count-overread \ |
| 114 | diff --git a/tests/kwset-abuse b/tests/kwset-abuse |
| 115 | new file mode 100755 |
| 116 | index 0000000..6d8ec0c |
| 117 | --- /dev/null |
| 118 | +++ b/tests/kwset-abuse |
| 119 | @@ -0,0 +1,32 @@ |
| 120 | +#! /bin/sh |
| 121 | +# Evoke a segfault in a hard-to-reach code path of kwset.c. |
| 122 | +# This bug affected grep versions 2.19 through 2.21. |
| 123 | +# |
| 124 | +# Copyright (C) 2015 Free Software Foundation, Inc. |
| 125 | +# |
| 126 | +# This program is free software: you can redistribute it and/or modify |
| 127 | +# it under the terms of the GNU General Public License as published by |
| 128 | +# the Free Software Foundation, either version 3 of the License, or |
| 129 | +# (at your option) any later version. |
| 130 | + |
| 131 | +# This program is distributed in the hope that it will be useful, |
| 132 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 133 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 134 | +# GNU General Public License for more details. |
| 135 | + |
| 136 | +# You should have received a copy of the GNU General Public License |
| 137 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
| 138 | + |
| 139 | +. "${srcdir=.}/init.sh"; path_prepend_ ../src |
| 140 | + |
| 141 | +fail=0 |
| 142 | + |
| 143 | +# This test case chooses a haystack of size 260,000, since prodding |
| 144 | +# with gdb showed a reallocation slightly larger than that in fillbuf. |
| 145 | +# To reach the buggy code, the needle must have length < 1/11 that of |
| 146 | +# the haystack, and 10,000 is a nice round number that fits the bill. |
| 147 | +printf '%0260000dXy\n' 0 | grep -F $(printf %010000dy 0) |
| 148 | + |
| 149 | +test $? = 1 || fail=1 |
| 150 | + |
| 151 | +Exit $fail |
| 152 | -- |
| 153 | 2.4.1 |
| 154 | |