From mboxrd@z Thu Jan 1 00:00:00 1970 X-Msuck: nntp://news.gmane.org/gmane.linux.lib.musl.general/10641 Path: news.gmane.org!.POSTED!not-for-mail From: Rich Felker Newsgroups: gmane.linux.lib.musl.general,gmane.comp.security.oss.general Subject: CVE Request - TRE & musl libc regex integer overflows in buffer size computations Date: Tue, 18 Oct 2016 19:06:13 -0400 Message-ID: <20161018230613.GH19318@brightrain.aerifal.cx> Reply-To: musl@lists.openwall.com NNTP-Posting-Host: blaine.gmane.org Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="fdj2RfSjLxBAspz7" X-Trace: blaine.gmane.org 1476832003 18707 195.159.176.226 (18 Oct 2016 23:06:43 GMT) X-Complaints-To: usenet@blaine.gmane.org NNTP-Posting-Date: Tue, 18 Oct 2016 23:06:43 +0000 (UTC) User-Agent: Mutt/1.5.21 (2010-09-15) Cc: musl@lists.openwall.com, Ville Laurikari To: oss-security@lists.openwall.com Original-X-From: musl-return-10654-gllmg-musl=m.gmane.org@lists.openwall.com Wed Oct 19 01:06:39 2016 Return-path: Envelope-to: gllmg-musl@m.gmane.org Original-Received: from mother.openwall.net ([195.42.179.200]) by blaine.gmane.org with smtp (Exim 4.84_2) (envelope-from ) id 1bwdSm-0003E1-1V for gllmg-musl@m.gmane.org; Wed, 19 Oct 2016 01:06:28 +0200 Original-Received: (qmail 32366 invoked by uid 550); 18 Oct 2016 23:06:27 -0000 Mailing-List: contact musl-help@lists.openwall.com; run by ezmlm Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: List-ID: Original-Received: (qmail 32330 invoked from network); 18 Oct 2016 23:06:26 -0000 Content-Disposition: inline Original-Sender: Rich Felker Xref: news.gmane.org gmane.linux.lib.musl.general:10641 gmane.comp.security.oss.general:20753 Archived-At: --fdj2RfSjLxBAspz7 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Due to incorrect use of integer types and missing overflow checks in the tre_tnfa_run_parallel function's buffer overflow logic, the TRE regex implementation (both original version and the one used in musl libc) are subject to integer overflows in buffer size computation. If the caller passes to regcomp a regular expression whose internal representation requires a large number of states and/or a large number of tags, too little space will be allocated during regexec, resulting in out-of-bound memory writes. An attacker who controls the regular expression and/or the string being searched can potentially exploit these writes to achieve controlled heap corruption. All versions of the TRE library and musl libc are affected. The attached patch fixes the issue in musl and should be easy to adapt for use with original TRE. musl git master is fixed as of commit c3edc06d1e1360f3570db9155d6b318ae0d0f0f7. Rich --fdj2RfSjLxBAspz7 Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="0001-fix-missing-integer-overflow-checks-in-regexec-buffe.patch" >From c3edc06d1e1360f3570db9155d6b318ae0d0f0f7 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Thu, 6 Oct 2016 18:34:58 -0400 Subject: [PATCH] fix missing integer overflow checks in regexec buffer size computations most of the possible overflows were already ruled out in practice by regcomp having already succeeded performing larger allocations. however at least the num_states*num_tags multiplication can clearly overflow in practice. for safety, check them all, and use the proper type, size_t, rather than int. also improve comments, use calloc in place of malloc+memset, and remove bogus casts. --- src/regex/regexec.c | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/src/regex/regexec.c b/src/regex/regexec.c index 16c5d0a..dd52319 100644 --- a/src/regex/regexec.c +++ b/src/regex/regexec.c @@ -34,6 +34,7 @@ #include #include #include +#include #include @@ -206,11 +207,24 @@ tre_tnfa_run_parallel(const tre_tnfa_t *tnfa, const void *string, /* Allocate memory for temporary data required for matching. This needs to be done for every matching operation to be thread safe. This allocates - everything in a single large block from the stack frame using alloca() - or with malloc() if alloca is unavailable. */ + everything in a single large block with calloc(). */ { - int tbytes, rbytes, pbytes, xbytes, total_bytes; + size_t tbytes, rbytes, pbytes, xbytes, total_bytes; char *tmp_buf; + + /* Ensure that tbytes and xbytes*num_states cannot overflow, and that + * they don't contribute more than 1/8 of SIZE_MAX to total_bytes. */ + if (num_tags > SIZE_MAX/(8 * sizeof(int) * tnfa->num_states)) + goto error_exit; + + /* Likewise check rbytes. */ + if (tnfa->num_states+1 > SIZE_MAX/(8 * sizeof(*reach_next))) + goto error_exit; + + /* Likewise check pbytes. */ + if (tnfa->num_states > SIZE_MAX/(8 * sizeof(*reach_pos))) + goto error_exit; + /* Compute the length of the block we need. */ tbytes = sizeof(*tmp_tags) * num_tags; rbytes = sizeof(*reach_next) * (tnfa->num_states + 1); @@ -221,10 +235,9 @@ tre_tnfa_run_parallel(const tre_tnfa_t *tnfa, const void *string, + (rbytes + xbytes * tnfa->num_states) * 2 + tbytes + pbytes; /* Allocate the memory. */ - buf = xmalloc((unsigned)total_bytes); + buf = calloc(total_bytes, 1); if (buf == NULL) return REG_ESPACE; - memset(buf, 0, (size_t)total_bytes); /* Get the various pointers within tmp_buf (properly aligned). */ tmp_tags = (void *)buf; -- 2.10.0 --fdj2RfSjLxBAspz7--