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

Reply via email to