BSDSec

deadsimple BSD Security Advisories and Announcements

libevent errata

Patches are now available for 5.5 and 5.6 which fix libevent.

5.5 errata 20 and 5.6 errata 15:
Fix CVE-2014-6272 in libevent 1.4 event buffer handling.  OpenBSD
base uses it for the programs: cu tmux ftp-proxy httpd ldapd relayd
tftp-proxy tftpd

Links:

http://www.openbsd.org/errata55.html
http://ftp.openbsd.org/pub/OpenBSD/patches/5.5/common/020_libevent.patch.sig

and

http://www.openbsd.org/errata56.html
http://ftp.openbsd.org/pub/OpenBSD/patches/5.6/common/015_libevent.patch.sig

untrusted comment: signature from openbsd 5.6 base private key
RWR0EANmo9nqhpu5mEMdLuZ056ynwx+qvxaVbodk7LsWqC0UCch3P2Ll0uGzfyJl/FSN9KH7tQgwwjbPwyss35EQNAlUAULiYgU
OpenBSD 5.6 errata 15, Jan 8, 2015

Fix CVE-2014-6272 in libevent 1.4 event buffer handling.  OpenBSD
base uses it for the programs: cu tmux ftp-proxy httpd ldapd relayd
tftp-proxy tftpd

A defect in the Libevent evbuffer API leaves some programs that
pass insanely large inputs to evbuffers open to a possible heap
overflow or infinite loop.

Apply patch using:

    signify -Vep /etc/signify/openbsd-56-base.pub -x 015_libevent.patch.sig \
	-m - | (cd /usr/src && patch -p0)

Then build and install libevent

    cd /usr/src/lib/libevent
    make obj
    make
    make install


Index: lib/libevent/buffer.c
===================================================================
RCS file: /mount/cvsdev/cvs/openbsd/src/lib/libevent/buffer.c,v
retrieving revision 1.19
diff -u -p -r1.19 buffer.c
--- lib/libevent/buffer.c	17 Jul 2010 17:16:47 -0000	1.19
+++ lib/libevent/buffer.c	7 Jan 2015 19:11:19 -0000
@@ -53,6 +53,7 @@
 
 #include <assert.h>
 #include <errno.h>
+#include <limits.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -145,7 +146,8 @@ evbuffer_add_vprintf(struct evbuffer *bu
 	va_list aq;
 
 	/* make sure that at least some space is available */
-	evbuffer_expand(buf, 64);
+	if (evbuffer_expand(buf, 64) < 0)
+		return (-1);
 	for (;;) {
 		size_t used = buf->misalign + buf->off;
 		buffer = (char *)buf->buffer + buf->off;
@@ -351,26 +353,38 @@ evbuffer_align(struct evbuffer *buf)
 int
 evbuffer_expand(struct evbuffer *buf, size_t datlen)
 {
-	size_t need = buf->misalign + buf->off + datlen;
+	size_t used = buf->misalign + buf->off;
+
+	assert(buf->totallen >= used);
 
 	/* If we can fit all the data, then we don't have to do anything */
-	if (buf->totallen >= need)
+	if (buf->totallen - used >= datlen)
 		return (0);
+	/* If we would need to overflow to fit this much data, we can't
+	 * do anything. */
+	if (datlen > SIZE_MAX - buf->off)
+		return (-1);
 
 	/*
 	 * If the misalignment fulfills our data needs, we just force an
 	 * alignment to happen.  Afterwards, we have enough space.
 	 */
-	if (buf->misalign >= datlen) {
+	if (buf->totallen - buf->off >= datlen) {
 		evbuffer_align(buf);
 	} else {
 		void *newbuf;
 		size_t length = buf->totallen;
+		size_t need = buf->off + datlen;
 
 		if (length < 256)
 			length = 256;
-		while (length < need)
-			length <<= 1;
+		if (need < SIZE_MAX / 2) {
+			while (length < need) {
+				length <<= 1;
+			}
+		} else {
+			length = need;
+		}
 
 		if (buf->orig_buffer != buf->buffer)
 			evbuffer_align(buf);
@@ -387,10 +401,10 @@ evbuffer_expand(struct evbuffer *buf, si
 int
 evbuffer_add(struct evbuffer *buf, const void *data, size_t datlen)
 {
-	size_t need = buf->misalign + buf->off + datlen;
+	size_t used = buf->misalign + buf->off;
 	size_t oldoff = buf->off;
 
-	if (buf->totallen < need) {
+	if (buf->totallen - used < datlen) {
 		if (evbuffer_expand(buf, datlen) == -1)
 			return (-1);
 	}