Bug 1684058
Summary: | CVE-2019-9169 glibc: regular-expression match via proceed_next_node in posix/regexec.c leads to heap-based buffer over-read [fedora-all] | ||||||
---|---|---|---|---|---|---|---|
Product: | [Fedora] Fedora | Reporter: | msiddiqu | ||||
Component: | glibc | Assignee: | DJ Delorie <dj> | ||||
Status: | CLOSED WONTFIX | QA Contact: | Fedora Extras Quality Assurance <extras-qa> | ||||
Severity: | medium | Docs Contact: | |||||
Priority: | medium | ||||||
Version: | 29 | CC: | aoliva, arjun.is, codonell, dj, fweimer, law, matt.fagnani, mfabian, pfrankli, rth, siddhesh | ||||
Target Milestone: | --- | Keywords: | Security, SecurityTracking | ||||
Target Release: | --- | ||||||
Hardware: | Unspecified | ||||||
OS: | Unspecified | ||||||
Whiteboard: | |||||||
Fixed In Version: | Doc Type: | No Doc Update | |||||
Doc Text: | Story Points: | --- | |||||
Clone Of: | Environment: | ||||||
Last Closed: | 2019-05-03 13:25:46 UTC | Type: | --- | ||||
Regression: | --- | Mount Type: | --- | ||||
Documentation: | --- | CRM: | |||||
Verified Versions: | Category: | --- | |||||
oVirt Team: | --- | RHEL 7.3 requirements from Atomic Host: | |||||
Cloudforms Team: | --- | Target Upstream Version: | |||||
Embargoed: | |||||||
Bug Depends On: | |||||||
Bug Blocks: | 1684057 | ||||||
Attachments: |
|
Description
msiddiqu
2019-02-28 10:34:28 UTC
Use the following template to for the 'fedpkg update' request to submit an update for this issue as it contains the top-level parent bug(s) as well as this tracking bug. This will ensure that all associated bugs get updated when new packages are pushed to stable. ===== # bugfix, security, enhancement, newpackage (required) type=security # low, medium, high, urgent (required) severity=medium # testing, stable request=testing # Bug numbers: 1234,9876 bugs=1684057,1684058 # Description of your update notes=Security fix for [PUT CVEs HERE] # Enable request automation based on the stable/unstable karma thresholds autokarma=True stable_karma=3 unstable_karma=-3 # Automatically close bugs when this marked as stable close_bugs=True # Suggest that users restart after update suggest_reboot=False ====== Additionally, you may opt to use the bodhi web interface to submit updates: https://bodhi.fedoraproject.org/updates/new Created attachment 1552434 [details] coredumpctl debug / gdb output for segmentation fault running echo 0 | sed '/\(\)\(\1\(\)\1\(\)\)*/c0' I read in the glibc-2.28-27.fc29 bodhi change log that CVE-2019-9169 was fixed "Record CVE-2019-9169 in NEWS and ChangeLog [BZ #24114] regex: fix read overrun [BZ #24114]" https://bodhi.fedoraproject.org/updates/FEDORA-2019-5fcc2049a1 I tested the reproducer given by Huzaifa S. Sidhpurwala at https://bugzilla.redhat.com/show_bug.cgi?id=1684057#c3 echo 0 | sed '/\(\)\(\1\(\)\1\(\)\)*/c0' with glibc-2.28-26 and after upgrading to glibc-2.28-27 and rebooting. I got segmentation faults with both 2.28-27 and 2.28-26 in check_dst_limits_calc_pos_1 at regexec.c:1945. The following output and attachment are with 2.28-27. Core was generated by `sed /\(\)\(\1\(\)\1\(\)\)*/c0'. Program terminated with signal SIGSEGV, Segmentation fault. #0 0xb7e2609b in check_dst_limits_calc_pos_1 (mctx=mctx@entry=0xbfb98584, boundaries=boundaries@entry=3, subexp_idx=subexp_idx@entry=0, from_node=6, bkref_idx=0) at regexec.c:1945 1945 cpos = The trace showed that check_dst_limits_calc_pos_1 at regexec.c:1945 repeated from #0 to #87215 with the only apparent difference being an alternation of from_node=6 to from_node=3 (gdb) bt #0 0xb7e2609b in check_dst_limits_calc_pos_1 (mctx=mctx@entry=0xbfb98584, boundaries=boundaries@entry=3, subexp_idx=subexp_idx@entry=0, from_node=6, bkref_idx=0) at regexec.c:1945 #1 0xb7e260ad in check_dst_limits_calc_pos_1 (mctx=mctx@entry=0xbfb98584, boundaries=boundaries@entry=3, subexp_idx=subexp_idx@entry=0, from_node=3, bkref_idx=0) at regexec.c:1945 #2 0xb7e260ad in check_dst_limits_calc_pos_1 (mctx=mctx@entry=0xbfb98584, boundaries=boundaries@entry=3, subexp_idx=subexp_idx@entry=0, from_node=6, bkref_idx=0) at regexec.c:1945 #3 0xb7e260ad in check_dst_limits_calc_pos_1 (mctx=mctx@entry=0xbfb98584, boundaries=boundaries@entry=3, subexp_idx=subexp_idx@entry=0, from_node=3, bkref_idx=0) at regexec.c:1945 #4 0xb7e260ad in check_dst_limits_calc_pos_1 (mctx=mctx@entry=0xbfb98584, boundaries=boundaries@entry=3, subexp_idx=subexp_idx@entry=0, from_node=6, bkref_idx=0) at regexec.c:1945 #5 0xb7e260ad in check_dst_limits_calc_pos_1 (mctx=mctx@entry=0xbfb98584, boundaries=boundaries@entry=3, subexp_idx=subexp_idx@entry=0, from_node=3, bkref_idx=0) at regexec.c:1945 #6 0xb7e260ad in check_dst_limits_calc_pos_1 (mctx=mctx@entry=0xbfb98584, boundaries=boundaries@entry=3, subexp_idx=subexp_idx@entry=0, from_node=6, bkref_idx=0) at regexec.c:1945 #7 0xb7e260ad in check_dst_limits_calc_pos_1 (mctx=mctx@entry=0xbfb98584, boundaries=boundaries@entry=3, subexp_idx=subexp_idx@entry=0, from_node=3, bkref_idx=0) at regexec.c:1945 #8 0xb7e260ad in check_dst_limits_calc_pos_1 (mctx=mctx@entry=0xbfb98584, boundaries=boundaries@entry=3, subexp_idx=subexp_idx@entry=0, from_node=6, bkref_idx=0) at regexec.c:1945 ... #87216 0xb7e260ad in check_dst_limits_calc_pos_1 (mctx=0xbfb98584, boundaries=3, subexp_idx=0, from_node=2, bkref_idx=0) at regexec.c:1945 #87217 0xb7e2619b in check_dst_limits_calc_pos (mctx=mctx@entry=0xbfb98584, limit=<optimized out>, subexp_idx=subexp_idx@entry=0, from_node=<optimized out>, str_idx=<optimized out>, bkref_idx=0) at regexec.c:2001 #87218 0xb7e27d42 in check_dst_limits (mctx=mctx@entry=0xbfb98584, dst_node=2, dst_idx=0, src_node=3, src_idx=0, limits=<optimized out>, limits=<optimized out>) at regexec.c:1879 #87219 0xb7e30982 in sift_states_bkref (candidates=0x93dc14, str_idx=0, sctx=<optimized out>, mctx=0xbfb98584) at regexec.c:2141 #87220 update_cur_sifted_state (mctx=mctx@entry=0xbfb98584, sctx=sctx@entry=0xbfb98410, str_idx=str_idx@entry=0, dest_nodes=0xbfb98390) at regexec.c:1779 #87221 0xb7e2ed03 in sift_states_backward (mctx=mctx@entry=0xbfb98584, sctx=sctx@entry=0xbfb98410) at regexec.c:1586 #87222 0xb7e309df in sift_states_bkref (candidates=0x93dc14, str_idx=0, sctx=<optimized out>, mctx=0xbfb98584) at regexec.c:2164 #87223 update_cur_sifted_state (mctx=mctx@entry=0xbfb98584, sctx=sctx@entry=0xbfb98568, str_idx=str_idx@entry=0, dest_nodes=0xbfb984a0) at regexec.c:1779 #87224 0xb7e2ed03 in sift_states_backward (mctx=mctx@entry=0xbfb98584, sctx=sctx@entry=0xbfb98568) at regexec.c:1586 #87225 0xb7e301fc in prune_impossible_nodes (mctx=0xbfb98584) at regexec.c:956 #87226 re_search_internal (preg=0x93c020, string=0x93d970 "0", length=1, start=<optimized out>, last_start=1, stop=1, nmatch=1, pmatch=0x93d910, eflags=0) at regexec.c:823 #87227 0xb7e3475d in re_search_stub (bufp=0x93c020, string=0x93d970 "0", length=length@entry=1, start=0, range=1, stop=1, regs=0x0, ret_len=false) at regexec.c:424 #87228 0xb7e350c7 in __re_search (bufp=<optimized out>, string=<optimized out>, length=1, start=<optimized out>, range=<optimized out>, regs=0x0) at regexec.c:289 #87229 0x004427b7 in match_regex (regex=0x93c020, buf=0x93d970 "0", buflen=1, buf_start_offset=<optimized out>, regarray=0x0, regsize=0) at sed/regexp.c:418 #87230 0x0044004d in match_an_address_p (addr=<optimized out>, input=input@entry=0xbfb997c8) at sed/execute.c:802 #87231 0x00440e08 in match_address_p (input=0xbfb997c8, cmd=0x93bc00) at sed/execute.c:841 #87232 execute_program (vec=vec@entry=0x93ac00, input=input@entry=0xbfb997c8) at sed/execute.c:1289 #87233 0x00441f21 in process_files (the_program=0x93ac00, argv=0xbfb9995c) at sed/execute.c:1679 #87234 0x0043caaf in main (argc=<optimized out>, argv=<optimized out>) at sed/sed.c:401 I ran echo 0 | valgrind --log-file=valgrind_sed_1.txt sed '/\(\)\(\1\(\)\1\(\)\)*/c0' , but I got a stack overflow error seemingly in valgrind itself due to the large stack size. ==2776== Stack overflow in thread #1: can't grow stack to 0xbe07e000 ==2776== ==2776== Process terminating with default action of signal 11 (SIGSEGV): dumping core ==2776== Access not within mapped region at address 0xBE07EFF4 ==2776== Stack overflow in thread #1: can't grow stack to 0xbe07e000 ==2776== at 0x4966F7A: check_dst_limits_calc_pos_1 (regexec.c:1901) ==2776== If you believe this happened as a result of a stack ==2776== overflow in your program's main thread (unlikely but ==2776== possible), you can try to increase the size of the ==2776== main thread stack using the --main-stacksize= flag. ==2776== The main thread stack size used in this run was 8388608. ==2776== Stack overflow in thread #1: can't grow stack to 0xbe07e000 --2776-- VALGRIND INTERNAL ERROR: Valgrind received a signal 11 (SIGSEGV) - exiting --2776-- si_code=1; Faulting address: 0xBE07EFE0; sp: 0x629ccf30 valgrind: the 'impossible' happened: Killed by fatal signal host stacktrace: ==2776== at 0x580A3DFA: ??? (in /usr/lib/valgrind/memcheck-x86-linux) sched status: running_tid=1 Thread 1: status = VgTs_Runnable (lwpid 2776) echo 0 | valgrind --log-file=valgrind_sed_6.txt --main-stacksize=100000000 sed '/\(\)\(\1\(\)\1\(\)\)*/c0' gave the same stack overflow error after I increased the main thread stack size from what I think were 8.3 MB to 100 MB. I can try other methods and give further information if that would help. I'm seeing this failure in rawhide as well, and it seems to be triggered by a different part of the code: #10 0x00007f17d56b2b1a in check_dst_limits_calc_pos_1 (mctx=mctx@entry=0x7ffd7df806e0, boundaries=boundaries@entry=3, subexp_idx=subexp_idx@entry=0, from_node=6, bkref_idx=bkref_idx@entry=0) at regexec.c:1945 #11 0x00007f17d56b2b1a in check_dst_limits_calc_pos_1 (mctx=mctx@entry=0x7ffd7df806e0, boundaries=boundaries@entry=3, subexp_idx=subexp_idx@entry=0, from_node=3, bkref_idx=bkref_idx@entry=0) at regexec.c:1945 #12 0x00007f17d56b2b1a in check_dst_limits_calc_pos_1 (mctx=mctx@entry=0x7ffd7df806e0, boundaries=boundaries@entry=3, subexp_idx=subexp_idx@entry=0, from_node=6, bkref_idx=bkref_idx@entry=0) at regexec.c:1945 #13 0x00007f17d56b2b1a in check_dst_limits_calc_pos_1 (mctx=mctx@entry=0x7ffd7df806e0, boundaries=boundaries@entry=3, subexp_idx=subexp_idx@entry=0, from_node=3, bkref_idx=bkref_idx@entry=0) at regexec.c:1945 Note the tic-toc of from_node between 6 and 3. In the code in question we see: /* Recurse trying to reach the OP_OPEN_SUBEXP and OP_CLOSE_SUBEXP cases below. But, if the destination node is the same node as the source node, don't recurse because it would cause an infinite loop: a regex that exhibits this behavior is ()\1*\1* */ So the source knows that such types of recursions are (1) possible, and (2) lead to inifinite recursion, but only tests for the same nodes each time, not a tic-toc of nodes. So while the test case above does eventually segfault (due to out-of-stack) it does not segfault due to buffer overflow, so I don't think it's a faithful indicator of the original CVE. DJ, I agree with your assessment. I see now that CVE-2019-9169 was assigned to the report at https://debbugs.gnu.org/cgi/bugreport.cgi?bug=34140 with reproducer ./grep -i '\(\(\)*.\)*\(\)\(\)\1' /bin/chvt with a heap-buffer overflow in proceed_next_node at regexec.c:1296. When I ran grep -i '\(\(\)*.\)*\(\)\(\)\1' /bin/chvt, the output was Binary file /bin/chvt matches. I didn't see a crash for that grep command reproducer. The crashes I referred to in comment 2 with reproducer echo 0 | ./sed '/\(\)\(\1\(\)\1\(\)\)*/c0' appear to have been reported at https://debbugs.gnu.org/cgi/bugreport.cgi?bug=34141 with a stack overflow in check_dst_limits_calc_pos_1 at regexec.c:1912. So those crashes are a different problem from CVE-2019-9169. I could make another report if that would be appropriate. Thanks. The regular expression compiler in glibc is only supposed to be exposed to trusted content, so this is not a security vulnerability: “resource exhaustion issues which can be triggered only with crafted patterns (either during compilation or execution) are not treated as security bugs” <https://sourceware.org/glibc/wiki/Security%20Exceptions> |