SECURITY: CVE-2009-2412 (cve.mitre.org) Fix overflow in pools, where size alignment was taking place. Reported by: Matt Lewis * memory/unix/apr_pools.c (allocator_alloc, apr_palloc): Check for overflow after aligning size. (apr_pcalloc): Drop aligning of size; clearing what the caller asked for should suffice. SEE ALSO: apr-util-0.9-CVE-2009-2412.patch Index: memory/unix/apr_pools.c =================================================================== --- memory/unix/apr_pools.c (revision 800657) +++ memory/unix/apr_pools.c (working copy) @@ -189,15 +189,19 @@ } 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 i, index, max_index; + apr_size_t size; /* 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; @@ -625,13 +629,19 @@ * 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_uint32_t free_index; + apr_size_t size; - 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. */ @@ -696,7 +706,6 @@ { void *mem; - size = APR_ALIGN_DEFAULT(size); if ((mem = apr_palloc(pool, size)) != NULL) { memset(mem, 0, size); }