diff options
-rw-r--r-- | CHANGES | 4 | ||||
-rw-r--r-- | memory/unix/apr_pools.c | 22 | ||||
-rw-r--r-- | util-misc/apr_rmm.c | 29 |
3 files changed, 39 insertions, 16 deletions
@@ -1,6 +1,10 @@ -*- coding: utf-8 -*- Changes for APR 2.0.0 + *) SECURITY: CVE-2009-2412 (cve.mitre.org) + Fix overflow in pools and rmm, where size alignment was taking place. + [Matt Lewis <mattlewis@google.com>, Sander Striker] + *) Pass default environment to testflock, testoc and testpipe children, so that tests run when APR is compiled with Intel C Compiler. [Bojan Smojver] diff --git a/memory/unix/apr_pools.c b/memory/unix/apr_pools.c index a4fe887d6..1a783d118 100644 --- a/memory/unix/apr_pools.c +++ b/memory/unix/apr_pools.c @@ -191,16 +191,19 @@ APR_DECLARE(void) apr_allocator_max_free_set(apr_allocator_t *allocator, } static APR_INLINE -apr_memnode_t *allocator_alloc(apr_allocator_t *allocator, apr_size_t size) +apr_memnode_t *allocator_alloc(apr_allocator_t *allocator, apr_size_t in_size) { apr_memnode_t *node, **ref; apr_uint32_t max_index; - apr_size_t i, index; + apr_size_t size, i, index; /* Round up the block size to the next boundary, but always * allocate at least a certain size (MIN_ALLOC). */ - size = APR_ALIGN(size + APR_MEMNODE_T_SIZE, BOUNDARY_SIZE); + size = APR_ALIGN(in_size + APR_MEMNODE_T_SIZE, BOUNDARY_SIZE); + if (size < in_size) { + return NULL; + } if (size < MIN_ALLOC) size = MIN_ALLOC; @@ -628,13 +631,19 @@ APR_DECLARE(void) apr_pool_terminate(void) * Memory allocation */ -APR_DECLARE(void *) apr_palloc(apr_pool_t *pool, apr_size_t size) +APR_DECLARE(void *) apr_palloc(apr_pool_t *pool, apr_size_t in_size) { apr_memnode_t *active, *node; void *mem; - apr_size_t free_index; + apr_size_t size, free_index; - size = APR_ALIGN_DEFAULT(size); + size = APR_ALIGN_DEFAULT(in_size); + if (size < in_size) { + if (pool->abort_fn) + pool->abort_fn(APR_ENOMEM); + + return NULL; + } active = pool->active; /* If the active node has enough bytes left, use it. */ @@ -699,7 +708,6 @@ APR_DECLARE(void *) apr_pcalloc(apr_pool_t *pool, apr_size_t size) { void *mem; - size = APR_ALIGN_DEFAULT(size); if ((mem = apr_palloc(pool, size)) != NULL) { memset(mem, 0, size); } diff --git a/util-misc/apr_rmm.c b/util-misc/apr_rmm.c index e90be1e7c..91e30885f 100644 --- a/util-misc/apr_rmm.c +++ b/util-misc/apr_rmm.c @@ -306,13 +306,17 @@ APR_DECLARE(apr_status_t) apr_rmm_detach(apr_rmm_t *rmm) APR_DECLARE(apr_rmm_off_t) apr_rmm_malloc(apr_rmm_t *rmm, apr_size_t reqsize) { + apr_size_t size; apr_rmm_off_t this; - reqsize = APR_ALIGN_DEFAULT(reqsize) + RMM_BLOCK_SIZE; + size = APR_ALIGN_DEFAULT(reqsize) + RMM_BLOCK_SIZE; + if (size < reqsize) { + return 0; + } APR_ANYLOCK_LOCK(&rmm->lock); - this = find_block_of_size(rmm, reqsize); + this = find_block_of_size(rmm, size); if (this) { move_block(rmm, this, 0); @@ -325,18 +329,22 @@ APR_DECLARE(apr_rmm_off_t) apr_rmm_malloc(apr_rmm_t *rmm, apr_size_t reqsize) APR_DECLARE(apr_rmm_off_t) apr_rmm_calloc(apr_rmm_t *rmm, apr_size_t reqsize) { + apr_size_t size; apr_rmm_off_t this; - reqsize = APR_ALIGN_DEFAULT(reqsize) + RMM_BLOCK_SIZE; + size = APR_ALIGN_DEFAULT(reqsize) + RMM_BLOCK_SIZE; + if (size < reqsize) { + return 0; + } APR_ANYLOCK_LOCK(&rmm->lock); - this = find_block_of_size(rmm, reqsize); + this = find_block_of_size(rmm, size); if (this) { move_block(rmm, this, 0); this += RMM_BLOCK_SIZE; - memset((char*)rmm->base + this, 0, reqsize - RMM_BLOCK_SIZE); + memset((char*)rmm->base + this, 0, size - RMM_BLOCK_SIZE); } APR_ANYLOCK_UNLOCK(&rmm->lock); @@ -349,16 +357,19 @@ APR_DECLARE(apr_rmm_off_t) apr_rmm_realloc(apr_rmm_t *rmm, void *entity, apr_rmm_off_t this; apr_rmm_off_t old; struct rmm_block_t *blk; - apr_size_t oldsize; + apr_size_t size, oldsize; if (!entity) { return apr_rmm_malloc(rmm, reqsize); } - reqsize = APR_ALIGN_DEFAULT(reqsize); + size = APR_ALIGN_DEFAULT(reqsize); + if (size < reqsize) { + return 0; + } old = apr_rmm_offset_get(rmm, entity); - if ((this = apr_rmm_malloc(rmm, reqsize)) == 0) { + if ((this = apr_rmm_malloc(rmm, size)) == 0) { return 0; } @@ -366,7 +377,7 @@ APR_DECLARE(apr_rmm_off_t) apr_rmm_realloc(apr_rmm_t *rmm, void *entity, oldsize = blk->size; memcpy(apr_rmm_addr_get(rmm, this), - apr_rmm_addr_get(rmm, old), oldsize < reqsize ? oldsize : reqsize); + apr_rmm_addr_get(rmm, old), oldsize < size ? oldsize : size); apr_rmm_free(rmm, old); return this; |