diff -Nru libevent-2.0.21-stable/debian/changelog libevent-2.0.21-stable/debian/changelog --- libevent-2.0.21-stable/debian/changelog 2015-01-16 14:48:14.000000000 +0000 +++ libevent-2.0.21-stable/debian/changelog 2017-03-10 19:17:29.000000000 +0000 @@ -1,3 +1,20 @@ +libevent (2.0.21-stable-1ubuntu1.14.04.2) trusty-security; urgency=medium + + * SECURITY UPDATE: buffer overread in name_parse() + - debian/patches/CVE-2016-10195.patch: fix length check in evdns.c. + - CVE-2016-10195 + * SECURITY UPDATE: integer overflow in evutil_parse_sockaddr_port() + - debian/patches/CVE-2016-10196.patch: use size_t for length in + evutil.c. + - CVE-2016-10196 + * SECURITY UPDATE: OOB read via empty hostname + - debian/patches/CVE-2016-10197-1.patch: check result in evdns.c. + - debian/patches/CVE-2016-10197-2.patch: add test to + test/regress_dns.c. + - CVE-2016-10197 + + -- Marc Deslauriers Fri, 10 Mar 2017 14:17:29 -0500 + libevent (2.0.21-stable-1ubuntu1.14.04.1) trusty-security; urgency=medium * SECURITY UPDATE: arbitrary code execution via evbuffer API diff -Nru libevent-2.0.21-stable/debian/patches/CVE-2016-10195.patch libevent-2.0.21-stable/debian/patches/CVE-2016-10195.patch --- libevent-2.0.21-stable/debian/patches/CVE-2016-10195.patch 1970-01-01 00:00:00.000000000 +0000 +++ libevent-2.0.21-stable/debian/patches/CVE-2016-10195.patch 2017-03-10 19:17:12.000000000 +0000 @@ -0,0 +1,112 @@ +From 96f64a022014a208105ead6c8a7066018449d86d Mon Sep 17 00:00:00 2001 +From: Azat Khuzhin +Date: Mon, 1 Feb 2016 17:32:09 +0300 +Subject: [PATCH] evdns: name_parse(): fix remote stack overread + +@asn-the-goblin-slayer: + "the name_parse() function in libevent's DNS code is vulnerable to a buffer overread. + + 971 if (cp != name_out) { + 972 if (cp + 1 >= end) return -1; + 973 *cp++ = '.'; + 974 } + 975 if (cp + label_len >= end) return -1; + 976 memcpy(cp, packet + j, label_len); + 977 cp += label_len; + 978 j += label_len; + No check is made against length before the memcpy occurs. + + This was found through the Tor bug bounty program and the discovery should be credited to 'Guido Vranken'." + +Reproducer for gdb (https://gist.github.com/azat/e4fcf540e9b89ab86d02): + set $PROT_NONE=0x0 + set $PROT_READ=0x1 + set $PROT_WRITE=0x2 + set $MAP_ANONYMOUS=0x20 + set $MAP_SHARED=0x01 + set $MAP_FIXED=0x10 + set $MAP_32BIT=0x40 + + start + + set $length=202 + # overread + set $length=2 + # allocate with mmap to have a seg fault on page boundary + set $l=(1<<20)*2 + p mmap(0, $l, $PROT_READ|$PROT_WRITE, $MAP_ANONYMOUS|$MAP_SHARED|$MAP_32BIT, -1, 0) + set $packet=(char *)$1+$l-$length + # hack the packet + set $packet[0]=63 + set $packet[1]='/' + + p malloc(sizeof(int)) + set $idx=(int *)$2 + set $idx[0]=0 + set $name_out_len=202 + + p malloc($name_out_len) + set $name_out=$3 + + # have WRITE only mapping to fail on read + set $end=$1+$l + p (void *)mmap($end, 1<<12, $PROT_NONE, $MAP_ANONYMOUS|$MAP_SHARED|$MAP_FIXED|$MAP_32BIT, -1, 0) + set $m=$4 + + p name_parse($packet, $length, $idx, $name_out, $name_out_len) + x/2s (char *)$name_out + +Before this patch: +$ gdb -ex 'source gdb' dns-example +$1 = 1073741824 +$2 = (void *) 0x633010 +$3 = (void *) 0x633030 +$4 = (void *) 0x40200000 + +Program received signal SIGSEGV, Segmentation fault. +__memcpy_sse2_unaligned () at memcpy-sse2-unaligned.S:33 + +After this patch: +$ gdb -ex 'source gdb' dns-example +$1 = 1073741824 +$2 = (void *) 0x633010 +$3 = (void *) 0x633030 +$4 = (void *) 0x40200000 +$5 = -1 +0x633030: "/" +0x633032: "" +(gdb) p $m +$6 = (void *) 0x40200000 +(gdb) p $1 +$7 = 1073741824 +(gdb) p/x $1 +$8 = 0x40000000 +(gdb) quit + +P.S. plus drop one condition duplicate. + +Fixes: #317 +--- + evdns.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +Index: libevent-2.0.21-stable/evdns.c +=================================================================== +--- libevent-2.0.21-stable.orig/evdns.c 2017-03-10 14:09:10.366238145 -0500 ++++ libevent-2.0.21-stable/evdns.c 2017-03-10 14:09:10.366238145 -0500 +@@ -952,7 +952,6 @@ + + for (;;) { + u8 label_len; +- if (j >= length) return -1; + GET8(label_len); + if (!label_len) break; + if (label_len & 0xc0) { +@@ -973,6 +972,7 @@ + *cp++ = '.'; + } + if (cp + label_len >= end) return -1; ++ if (j + label_len > length) return -1; + memcpy(cp, packet + j, label_len); + cp += label_len; + j += label_len; diff -Nru libevent-2.0.21-stable/debian/patches/CVE-2016-10196.patch libevent-2.0.21-stable/debian/patches/CVE-2016-10196.patch --- libevent-2.0.21-stable/debian/patches/CVE-2016-10196.patch 1970-01-01 00:00:00.000000000 +0000 +++ libevent-2.0.21-stable/debian/patches/CVE-2016-10196.patch 2017-03-10 19:17:16.000000000 +0000 @@ -0,0 +1,85 @@ +From 329acc18a0768c21ba22522f01a5c7f46cacc4d5 Mon Sep 17 00:00:00 2001 +From: Azat Khuzhin +Date: Sun, 31 Jan 2016 00:57:16 +0300 +Subject: [PATCH] evutil_parse_sockaddr_port(): fix buffer overflow + +@asn-the-goblin-slayer: + "Length between '[' and ']' is cast to signed 32 bit integer on line 1815. Is + the length is more than 2<<31 (INT_MAX), len will hold a negative value. + Consequently, it will pass the check at line 1816. Segfault happens at line + 1819. + + Generate a resolv.conf with generate-resolv.conf, then compile and run + poc.c. See entry-functions.txt for functions in tor that might be + vulnerable. + + Please credit 'Guido Vranken' for this discovery through the Tor bug bounty + program." + +Reproducer for gdb (https://gist.github.com/azat/be2b0d5e9417ba0dfe2c): + start + p (1ULL<<31)+1ULL + # $1 = 2147483649 + p malloc(sizeof(struct sockaddr)) + # $2 = (void *) 0x646010 + p malloc(sizeof(int)) + # $3 = (void *) 0x646030 + p malloc($1) + # $4 = (void *) 0x7fff76a2a010 + p memset($4, 1, $1) + # $5 = 1990369296 + p (char *)$4 + # $6 = 0x7fff76a2a010 '\001' ... + set $6[0]='[' + set $6[$1]=']' + p evutil_parse_sockaddr_port($4, $2, $3) + # $7 = -1 + +Before: + $ gdb bin/http-connect < gdb + (gdb) $1 = 2147483649 + (gdb) (gdb) $2 = (void *) 0x646010 + (gdb) (gdb) $3 = (void *) 0x646030 + (gdb) (gdb) $4 = (void *) 0x7fff76a2a010 + (gdb) (gdb) $5 = 1990369296 + (gdb) (gdb) $6 = 0x7fff76a2a010 '\001' ... + (gdb) (gdb) (gdb) (gdb) + Program received signal SIGSEGV, Segmentation fault. + __memcpy_sse2_unaligned () at memcpy-sse2-unaligned.S:36 + +After: + $ gdb bin/http-connect < gdb + (gdb) $1 = 2147483649 + (gdb) (gdb) $2 = (void *) 0x646010 + (gdb) (gdb) $3 = (void *) 0x646030 + (gdb) (gdb) $4 = (void *) 0x7fff76a2a010 + (gdb) (gdb) $5 = 1990369296 + (gdb) (gdb) $6 = 0x7fff76a2a010 '\001' ... + (gdb) (gdb) (gdb) (gdb) $7 = -1 + (gdb) (gdb) quit + +Fixes: #318 +--- + evutil.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +Index: libevent-2.0.21-stable/evutil.c +=================================================================== +--- libevent-2.0.21-stable.orig/evutil.c 2017-03-10 14:09:16.570314788 -0500 ++++ libevent-2.0.21-stable/evutil.c 2017-03-10 14:09:16.566314739 -0500 +@@ -1808,12 +1808,12 @@ + + cp = strchr(ip_as_string, ':'); + if (*ip_as_string == '[') { +- int len; ++ size_t len; + if (!(cp = strchr(ip_as_string, ']'))) { + return -1; + } +- len = (int) ( cp-(ip_as_string + 1) ); +- if (len > (int)sizeof(buf)-1) { ++ len = ( cp-(ip_as_string + 1) ); ++ if (len > sizeof(buf)-1) { + return -1; + } + memcpy(buf, ip_as_string+1, len); diff -Nru libevent-2.0.21-stable/debian/patches/CVE-2016-10197-1.patch libevent-2.0.21-stable/debian/patches/CVE-2016-10197-1.patch --- libevent-2.0.21-stable/debian/patches/CVE-2016-10197-1.patch 1970-01-01 00:00:00.000000000 +0000 +++ libevent-2.0.21-stable/debian/patches/CVE-2016-10197-1.patch 2017-03-10 19:17:20.000000000 +0000 @@ -0,0 +1,62 @@ +From ec65c42052d95d2c23d1d837136d1cf1d9ecef9e Mon Sep 17 00:00:00 2001 +From: Azat Khuzhin +Date: Fri, 25 Mar 2016 00:33:47 +0300 +Subject: [PATCH] evdns: fix searching empty hostnames + +From #332: + Here follows a bug report by **Guido Vranken** via the _Tor bug bounty program_. Please credit Guido accordingly. + + ## Bug report + + The DNS code of Libevent contains this rather obvious OOB read: + + ```c + static char * + search_make_new(const struct search_state *const state, int n, const char *const base_name) { + const size_t base_len = strlen(base_name); + const char need_to_append_dot = base_name[base_len - 1] == '.' ? 0 : 1; + ``` + + If the length of ```base_name``` is 0, then line 3125 reads 1 byte before the buffer. This will trigger a crash on ASAN-protected builds. + + To reproduce: + + Build libevent with ASAN: + ``` + $ CFLAGS='-fomit-frame-pointer -fsanitize=address' ./configure && make -j4 + ``` + Put the attached ```resolv.conf``` and ```poc.c``` in the source directory and then do: + + ``` + $ gcc -fsanitize=address -fomit-frame-pointer poc.c .libs/libevent.a + $ ./a.out + ================================================================= + ==22201== ERROR: AddressSanitizer: heap-buffer-overflow on address 0x60060000efdf at pc 0x4429da bp 0x7ffe1ed47300 sp 0x7ffe1ed472f8 + READ of size 1 at 0x60060000efdf thread T0 + ``` + +P.S. we can add a check earlier, but since this is very uncommon, I didn't add it. + +Fixes: #332 +--- + evdns.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +Index: libevent-2.0.21-stable/evdns.c +=================================================================== +--- libevent-2.0.21-stable.orig/evdns.c 2017-03-10 14:09:22.298385542 -0500 ++++ libevent-2.0.21-stable/evdns.c 2017-03-10 14:09:22.294385492 -0500 +@@ -3107,9 +3107,12 @@ + static char * + search_make_new(const struct search_state *const state, int n, const char *const base_name) { + const size_t base_len = strlen(base_name); +- const char need_to_append_dot = base_name[base_len - 1] == '.' ? 0 : 1; ++ char need_to_append_dot; + struct search_domain *dom; + ++ if (!base_len) return NULL; ++ need_to_append_dot = base_name[base_len - 1] == '.' ? 0 : 1; ++ + for (dom = state->head; dom; dom = dom->next) { + if (!n--) { + /* this is the postfix we want */ diff -Nru libevent-2.0.21-stable/debian/patches/CVE-2016-10197-2.patch libevent-2.0.21-stable/debian/patches/CVE-2016-10197-2.patch --- libevent-2.0.21-stable/debian/patches/CVE-2016-10197-2.patch 1970-01-01 00:00:00.000000000 +0000 +++ libevent-2.0.21-stable/debian/patches/CVE-2016-10197-2.patch 2017-03-10 19:17:24.000000000 +0000 @@ -0,0 +1,51 @@ +Backport of: + +From d7348bab602cf4dbdf65b9eeba2fb9ce4646bc0b Mon Sep 17 00:00:00 2001 +From: Azat Khuzhin +Date: Fri, 25 Mar 2016 00:21:06 +0300 +Subject: [PATCH] test/dns: regression for empty hostname + +Refs: #332 +--- + test/regress_dns.c | 21 +++++++++++++++++++++ + 1 file changed, 21 insertions(+) + +Index: libevent-2.0.21-stable/test/regress_dns.c +=================================================================== +--- libevent-2.0.21-stable.orig/test/regress_dns.c 2017-03-10 14:11:11.871737631 -0500 ++++ libevent-2.0.21-stable/test/regress_dns.c 2017-03-10 14:11:46.852168776 -0500 +@@ -506,6 +506,26 @@ + }; + + static void ++dns_search_empty_test(void *arg) ++{ ++ struct basic_test_data *data = arg; ++ struct event_base *base = data->base; ++ struct evdns_base *dns = NULL; ++ ++ dns = evdns_base_new(base, 0); ++ ++ evdns_base_search_add(dns, "whatever.example.com"); ++ ++ n_replies_left = 1; ++ exit_base = base; ++ ++ tt_ptr_op(evdns_base_resolve_ipv4(dns, "", 0, generic_dns_callback, NULL), ==, NULL); ++ ++end: ++ if (dns) ++ evdns_base_free(dns, 0); ++} ++static void + dns_search_test(void *arg) + { + struct basic_test_data *data = arg; +@@ -1831,6 +1851,7 @@ + DNS_LEGACY(gethostbyname6, TT_FORK|TT_NEED_BASE|TT_NEED_DNS), + DNS_LEGACY(gethostbyaddr, TT_FORK|TT_NEED_BASE|TT_NEED_DNS), + { "resolve_reverse", dns_resolve_reverse, TT_FORK, NULL, NULL }, ++ { "search_empty", dns_search_empty_test, TT_FORK|TT_NEED_BASE, &basic_setup, NULL }, + { "search", dns_search_test, TT_FORK|TT_NEED_BASE, &basic_setup, NULL }, + { "search_cancel", dns_search_cancel_test, + TT_FORK|TT_NEED_BASE, &basic_setup, NULL }, diff -Nru libevent-2.0.21-stable/debian/patches/series libevent-2.0.21-stable/debian/patches/series --- libevent-2.0.21-stable/debian/patches/series 2015-01-16 14:47:51.000000000 +0000 +++ libevent-2.0.21-stable/debian/patches/series 2017-03-10 19:17:24.000000000 +0000 @@ -1,3 +1,7 @@ build_with_no_undefined.patch automake.diff CVE-2014-6272.patch +CVE-2016-10195.patch +CVE-2016-10196.patch +CVE-2016-10197-1.patch +CVE-2016-10197-2.patch