From 30030996ead37cfee5b2516b01bfef7da7de6975 Mon Sep 17 00:00:00 2001 From: bluhm Date: Mon, 5 Jan 2015 23:14:36 +0000 Subject: [PATCH] Fix CVE-2014-6272 in Libevent 1.4 from upstream: - https://github.com/libevent/libevent/commit/7b21c4eabf1f3946d3f63cce1319c490caab8ecf - 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. On top of that do: - Update libevent version to 1.4.15-stable. - Use SIZE_MAX from limits.h instead of a private define. - Do not declare 'size_t need' twice to avoid a compiler warning. OK sthen --- lib/libevent/buffer.c | 32 +++++++++++++++++++++++--------- lib/libevent/event.h | 4 ++-- 2 files changed, 25 insertions(+), 11 deletions(-) diff --git a/lib/libevent/buffer.c b/lib/libevent/buffer.c index 6085e4d8b02..c2d72065874 100644 --- a/lib/libevent/buffer.c +++ b/lib/libevent/buffer.c @@ -1,4 +1,4 @@ -/* $OpenBSD: buffer.c,v 1.27 2014/11/21 07:44:25 dlg Exp $ */ +/* $OpenBSD: buffer.c,v 1.28 2015/01/05 23:14:36 bluhm Exp $ */ /* * Copyright (c) 2002, 2003 Niels Provos @@ -33,6 +33,7 @@ #include #include +#include #include #include #include @@ -120,7 +121,8 @@ evbuffer_add_vprintf(struct evbuffer *buf, const char *fmt, va_list ap) 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; @@ -323,26 +325,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); @@ -359,10 +373,10 @@ evbuffer_expand(struct evbuffer *buf, size_t datlen) 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); } diff --git a/lib/libevent/event.h b/lib/libevent/event.h index 33b9f7b669a..cb112406ca0 100644 --- a/lib/libevent/event.h +++ b/lib/libevent/event.h @@ -1,4 +1,4 @@ -/* $OpenBSD: event.h,v 1.29 2014/10/31 16:00:44 bluhm Exp $ */ +/* $OpenBSD: event.h,v 1.30 2015/01/05 23:14:36 bluhm Exp $ */ /* * Copyright (c) 2000-2007 Niels Provos @@ -1207,7 +1207,7 @@ int evtag_unmarshal_string(struct evbuffer *evbuf, ev_uint32_t need_tag, int evtag_unmarshal_timeval(struct evbuffer *evbuf, ev_uint32_t need_tag, struct timeval *ptv); -#define _EVENT_VERSION "1.4.14b-stable" +#define _EVENT_VERSION "1.4.15-stable" #ifdef __cplusplus } -- 2.20.1