Control: tags -1 + patch Hi Anibal,
Please find attached debdiff for unstable. I have *not* uploaded it to any delayed queue so far. Are you working on th update yourself? Regards, Salvatore
diff -Nru libevent-2.0.21-stable/debian/changelog libevent-2.0.21-stable/debian/changelog --- libevent-2.0.21-stable/debian/changelog 2014-08-25 18:04:19.000000000 +0200 +++ libevent-2.0.21-stable/debian/changelog 2015-01-07 13:03:24.000000000 +0100 @@ -1,3 +1,12 @@ +libevent (2.0.21-stable-1.2) unstable; urgency=high + + * Non-maintainer upload by the Security Team. + * Add 0001-Fix-CVE-2014-6272-in-Libevent-2.0.patch. + CVE-2014-6272: potential heap overflow in buffer/bufferevent APIs + (Closes: #774645) + + -- Salvatore Bonaccorso <car...@debian.org> Wed, 07 Jan 2015 12:43:40 +0100 + libevent (2.0.21-stable-1.1) unstable; urgency=low * Non-maintainer upload. diff -Nru libevent-2.0.21-stable/debian/patches/0001-Fix-CVE-2014-6272-in-Libevent-2.0.patch libevent-2.0.21-stable/debian/patches/0001-Fix-CVE-2014-6272-in-Libevent-2.0.patch --- libevent-2.0.21-stable/debian/patches/0001-Fix-CVE-2014-6272-in-Libevent-2.0.patch 1970-01-01 01:00:00.000000000 +0100 +++ libevent-2.0.21-stable/debian/patches/0001-Fix-CVE-2014-6272-in-Libevent-2.0.patch 2015-01-07 13:03:24.000000000 +0100 @@ -0,0 +1,265 @@ +From 20d6d4458bee5d88bda1511c225c25b2d3198d6c Mon Sep 17 00:00:00 2001 +From: Nick Mathewson <ni...@torproject.org> +Date: Mon, 5 Jan 2015 08:42:32 -0500 +Subject: [PATCH] Fix CVE-2014-6272 in Libevent 2.0 + +For this fix, we need to make sure that passing too-large inputs to +the evbuffer functions can't make us do bad things with the heap. + +Also, lower the maximum chunk size to the lower of off_t, size_t maximum. + +This is necessary since otherwise we could get into an infinite loop +if we make a chunk that 'misalign' cannot index into. +--- + +--- a/buffer.c ++++ b/buffer.c +@@ -157,12 +157,20 @@ evbuffer_chain_new(size_t size) + struct evbuffer_chain *chain; + size_t to_alloc; + ++ if (size > EVBUFFER_CHAIN_MAX - EVBUFFER_CHAIN_SIZE) ++ return (NULL); ++ + size += EVBUFFER_CHAIN_SIZE; + + /* get the next largest memory that can hold the buffer */ +- to_alloc = MIN_BUFFER_SIZE; +- while (to_alloc < size) +- to_alloc <<= 1; ++ if (size < EVBUFFER_CHAIN_MAX / 2) { ++ to_alloc = MIN_BUFFER_SIZE; ++ while (to_alloc < size) { ++ to_alloc <<= 1; ++ } ++ } else { ++ to_alloc = size; ++ } + + /* we get everything in one chunk */ + if ((chain = mm_malloc(to_alloc)) == NULL) +@@ -1002,6 +1010,7 @@ evbuffer_drain(struct evbuffer *buf, size_t len) + + buf->first = chain; + if (chain) { ++ EVUTIL_ASSERT(remaining <= chain->off); + chain->misalign += remaining; + chain->off -= remaining; + } +@@ -1068,6 +1077,7 @@ evbuffer_copyout(struct evbuffer *buf, void *data_out, size_t datlen) + + if (datlen) { + EVUTIL_ASSERT(chain); ++ EVUTIL_ASSERT(datlen <= chain->off); + memcpy(data, chain->buffer + chain->misalign, datlen); + } + +@@ -1543,6 +1553,10 @@ evbuffer_add(struct evbuffer *buf, const void *data_in, size_t datlen) + if (buf->freeze_end) { + goto done; + } ++ /* Prevent buf->total_len overflow */ ++ if (datlen > EV_SIZE_MAX - buf->total_len) { ++ goto done; ++ } + + chain = buf->last; + +@@ -1556,7 +1570,10 @@ evbuffer_add(struct evbuffer *buf, const void *data_in, size_t datlen) + } + + if ((chain->flags & EVBUFFER_IMMUTABLE) == 0) { +- remain = (size_t)(chain->buffer_len - chain->misalign - chain->off); ++ /* Always true for mutable buffers */ ++ EVUTIL_ASSERT(chain->misalign >= 0 && ++ (ev_uint64_t)chain->misalign <= EVBUFFER_CHAIN_MAX); ++ remain = chain->buffer_len - (size_t)chain->misalign - chain->off; + if (remain >= datlen) { + /* there's enough space to hold all the data in the + * current last chain */ +@@ -1627,6 +1644,9 @@ evbuffer_prepend(struct evbuffer *buf, const void *data, size_t datlen) + if (buf->freeze_start) { + goto done; + } ++ if (datlen > EV_SIZE_MAX - buf->total_len) { ++ goto done; ++ } + + chain = buf->first; + +@@ -1639,6 +1659,10 @@ evbuffer_prepend(struct evbuffer *buf, const void *data, size_t datlen) + + /* we cannot touch immutable buffers */ + if ((chain->flags & EVBUFFER_IMMUTABLE) == 0) { ++ /* Always true for mutable buffers */ ++ EVUTIL_ASSERT(chain->misalign >= 0 && ++ (ev_uint64_t)chain->misalign <= EVBUFFER_CHAIN_MAX); ++ + /* If this chain is empty, we can treat it as + * 'empty at the beginning' rather than 'empty at the end' */ + if (chain->off == 0) +@@ -1676,6 +1700,7 @@ evbuffer_prepend(struct evbuffer *buf, const void *data, size_t datlen) + tmp->next = chain; + + tmp->off = datlen; ++ EVUTIL_ASSERT(datlen <= tmp->buffer_len); + tmp->misalign = tmp->buffer_len - datlen; + + memcpy(tmp->buffer + tmp->misalign, data, datlen); +@@ -1774,7 +1799,9 @@ evbuffer_expand_singlechain(struct evbuffer *buf, size_t datlen) + + /* Would expanding this chunk be affordable and worthwhile? */ + if (CHAIN_SPACE_LEN(chain) < chain->buffer_len / 8 || +- chain->off > MAX_TO_COPY_IN_EXPAND) { ++ chain->off > MAX_TO_COPY_IN_EXPAND || ++ (datlen < EVBUFFER_CHAIN_MAX && ++ EVBUFFER_CHAIN_MAX - datlen >= chain->off)) { + /* It's not worth resizing this chain. Can the next one be + * used? */ + if (chain->next && CHAIN_SPACE_LEN(chain->next) >= datlen) { +@@ -1902,6 +1929,8 @@ _evbuffer_expand_fast(struct evbuffer *buf, size_t datlen, int n) + rmv_all = 1; + avail = 0; + } else { ++ /* can't overflow, since only mutable chains have ++ * huge misaligns. */ + avail = (size_t) CHAIN_SPACE_LEN(chain); + chain = chain->next; + } +@@ -1912,6 +1941,7 @@ _evbuffer_expand_fast(struct evbuffer *buf, size_t datlen, int n) + EVUTIL_ASSERT(chain->off == 0); + evbuffer_chain_free(chain); + } ++ EVUTIL_ASSERT(datlen >= avail); + tmp = evbuffer_chain_new(datlen - avail); + if (tmp == NULL) { + if (rmv_all) { +@@ -2041,6 +2071,7 @@ get_n_bytes_readable_on_socket(evutil_socket_t fd) + unsigned long lng = EVBUFFER_MAX_READ; + if (ioctlsocket(fd, FIONREAD, &lng) < 0) + return -1; ++ /* Can overflow, but mostly harmlessly. XXXX */ + return (int)lng; + #elif defined(FIONREAD) + int n = EVBUFFER_MAX_READ; +@@ -2153,8 +2184,14 @@ evbuffer_read(struct evbuffer *buf, evutil_socket_t fd, int howmuch) + #ifdef USE_IOVEC_IMPL + remaining = n; + for (i=0; i < nvecs; ++i) { +- ev_ssize_t space = (ev_ssize_t) CHAIN_SPACE_LEN(*chainp); +- if (space < remaining) { ++ /* can't overflow, since only mutable chains have ++ * huge misaligns. */ ++ size_t space = (size_t) CHAIN_SPACE_LEN(*chainp); ++ /* XXXX This is a kludge that can waste space in perverse ++ * situations. */ ++ if (space > EVBUFFER_CHAIN_MAX) ++ space = EVBUFFER_CHAIN_MAX; ++ if ((ev_ssize_t)space < remaining) { + (*chainp)->off += space; + remaining -= (int)space; + } else { +@@ -2427,12 +2464,17 @@ evbuffer_ptr_set(struct evbuffer *buf, struct evbuffer_ptr *pos, + case EVBUFFER_PTR_ADD: + /* this avoids iterating over all previous chains if + we just want to advance the position */ ++ if (pos->pos < 0 || EV_SIZE_MAX - position < (size_t)pos->pos) { ++ EVBUFFER_UNLOCK(buf); ++ return -1; ++ } + chain = pos->_internal.chain; + pos->pos += position; + position = pos->_internal.pos_in_chain; + break; + } + ++ EVUTIL_ASSERT(EV_SIZE_MAX - left >= position); + while (chain && position + left >= chain->off) { + left -= chain->off - position; + chain = chain->next; +@@ -2465,7 +2507,9 @@ evbuffer_ptr_memcmp(const struct evbuffer *buf, const struct evbuffer_ptr *pos, + + ASSERT_EVBUFFER_LOCKED(buf); + +- if (pos->pos + len > buf->total_len) ++ if (pos->pos < 0 || ++ EV_SIZE_MAX - len < (size_t)pos->pos || ++ pos->pos + len > buf->total_len) + return -1; + + chain = pos->_internal.chain; +@@ -2656,6 +2700,9 @@ evbuffer_add_vprintf(struct evbuffer *buf, const char *fmt, va_list ap) + + if (sz < 0) + goto done; ++ if (INT_MAX >= EVBUFFER_CHAIN_MAX && ++ (size_t)sz >= EVBUFFER_CHAIN_MAX) ++ goto done; + if ((size_t)sz < space) { + chain->off += sz; + buf->total_len += sz; +@@ -2749,6 +2796,11 @@ evbuffer_add_file(struct evbuffer *outbuf, int fd, + #endif + int ok = 1; + ++ if (offset < 0 || length < 0 || ++ ((ev_uint64_t)length > EVBUFFER_CHAIN_MAX) || ++ (ev_uint64_t)offset > (ev_uint64_t)(EVBUFFER_CHAIN_MAX - length)) ++ return (-1); ++ + #if defined(USE_SENDFILE) + if (use_sendfile) { + EVBUFFER_LOCK(outbuf); +@@ -2854,7 +2906,8 @@ evbuffer_add_file(struct evbuffer *outbuf, int fd, + * can abort without side effects if the read fails. + */ + while (length) { +- read = evbuffer_readfile(tmp, fd, (ev_ssize_t)length); ++ ev_ssize_t to_read = length > EV_SSIZE_MAX ? EV_SSIZE_MAX : (ev_ssize_t)length; ++ read = evbuffer_readfile(tmp, fd, to_read); + if (read == -1) { + evbuffer_free(tmp); + return (-1); +--- a/configure.in ++++ b/configure.in +@@ -553,6 +553,7 @@ AC_CHECK_SIZEOF(int) + AC_CHECK_SIZEOF(short) + AC_CHECK_SIZEOF(size_t) + AC_CHECK_SIZEOF(void *) ++AC_CHECK_SIZEOF(off_t) + + AC_CHECK_TYPES([struct in6_addr, struct sockaddr_in6, sa_family_t, struct addrinfo, struct sockaddr_storage], , , + [#define _GNU_SOURCE +--- a/evbuffer-internal.h ++++ b/evbuffer-internal.h +@@ -153,6 +153,18 @@ struct evbuffer { + struct bufferevent *parent; + }; + ++#if _EVENT_SIZEOF_OFF_T < _EVENT_SIZEOF_SIZE_T ++typedef ev_ssize_t ev_misalign_t; ++#define EVBUFFER_CHAIN_MAX ((size_t)EV_SSIZE_MAX) ++#else ++typedef ev_off_t ev_misalign_t; ++#if _EVENT_SIZEOF_OFF_T > _EVENT_SIZEOF_SIZE_T ++#define EVBUFFER_CHAIN_MAX EV_SIZE_MAX ++#else ++#define EVBUFFER_CHAIN_MAX ((size_t)EV_SSIZE_MAX) ++#endif ++#endif ++ + /** A single item in an evbuffer. */ + struct evbuffer_chain { + /** points to next buffer in the chain */ +@@ -163,7 +175,7 @@ struct evbuffer_chain { + + /** unused space at the beginning of buffer or an offset into a + * file for sendfile buffers. */ +- ev_off_t misalign; ++ ev_misalign_t misalign; + + /** Offset into buffer + misalign at which to start writing. + * In other words, the total number of bytes actually stored +-- +2.1.4 + 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 2014-08-25 18:04:48.000000000 +0200 +++ libevent-2.0.21-stable/debian/patches/series 2015-01-07 13:03:24.000000000 +0100 @@ -1,2 +1,3 @@ build_with_no_undefined.patch dh-autoreconf +0001-Fix-CVE-2014-6272-in-Libevent-2.0.patch