summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGES4
-rw-r--r--memory/unix/apr_pools.c22
-rw-r--r--util-misc/apr_rmm.c29
3 files changed, 39 insertions, 16 deletions
diff --git a/CHANGES b/CHANGES
index cc47a0c08..0c498d015 100644
--- a/CHANGES
+++ b/CHANGES
@@ -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;