From 7f5aa4f35e23fd37425b3a5041737cdf58f87385 Mon Sep 17 00:00:00 2001 From: Xi Wang Date: Wed, 14 Mar 2012 02:48:39 -0400 Subject: [PATCH] bionic: fix integer overflows in chk_malloc(), leak_malloc(), and leak_memalign() The allocation size in chk_malloc(), leak_malloc(), and leak_memalign() functions may be rounded up to a small value, leading to buffer overflows. The code only runs in debugging mode. This patch complements commit 6f04a0f4 (CVE-2009-0607). Change-Id: Id899bcd2bcd2ea2205e5753c433390710032dc83 Signed-off-by: Xi Wang --- libc/bionic/malloc_debug_leak.c | 37 ++++++++++++++++++++++----------- 1 file changed, 25 insertions(+), 12 deletions(-) diff --git a/libc/bionic/malloc_debug_leak.c b/libc/bionic/malloc_debug_leak.c index e0bcee946..e5845023d 100644 --- a/libc/bionic/malloc_debug_leak.c +++ b/libc/bionic/malloc_debug_leak.c @@ -25,26 +25,26 @@ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ + +#include #include +#include #include +#include +#include +#include #include -#include -#include #include #include #include -#include -#include -#include -#include #include -#include -#include -#include +#include #include -#include +#include #include +#include +#include #include "dlmalloc.h" #include "logd.h" @@ -372,7 +372,11 @@ static int chk_mem_check(void* mem, void* chk_malloc(size_t bytes) { - char* buffer = (char*)dlmalloc(bytes + CHK_OVERHEAD_SIZE); + size_t size = bytes + CHK_OVERHEAD_SIZE; + if (size < bytes) { // Overflow. + return NULL; + } + uint8_t* buffer = (uint8_t*) dlmalloc(size); if (buffer) { memset(buffer, CHK_SENTINEL_VALUE, bytes + CHK_OVERHEAD_SIZE); size_t offset = dlmalloc_usable_size(buffer) - sizeof(size_t); @@ -505,7 +509,12 @@ void* leak_malloc(size_t bytes) // 1. allocate enough memory and include our header // 2. set the base pointer to be right after our header - void* base = dlmalloc(bytes + sizeof(AllocationEntry)); + size_t size = bytes + sizeof(AllocationEntry); + if (size < bytes) { // Overflow. + return NULL; + } + + void* base = dlmalloc(size); if (base != NULL) { pthread_mutex_lock(&gAllocationsMutex); @@ -615,6 +624,10 @@ void* leak_memalign(size_t alignment, size_t bytes) // we will align by at least MALLOC_ALIGNMENT bytes // and at most alignment-MALLOC_ALIGNMENT bytes size_t size = (alignment-MALLOC_ALIGNMENT) + bytes; + if (size < bytes) { // Overflow. + return NULL; + } + void* base = leak_malloc(size); if (base != NULL) { intptr_t ptr = (intptr_t)base;