dovecot-1.1: DEBUG: Added buffer overflow checking to alloconly ...

dovecot at dovecot.org dovecot at dovecot.org
Tue Apr 1 20:34:57 EEST 2008


details:   http://hg.dovecot.org/dovecot-1.1/rev/45884655c0c4
changeset: 7448:45884655c0c4
user:      Timo Sirainen <tss at iki.fi>
date:      Tue Apr 01 20:34:51 2008 +0300
description:
DEBUG: Added buffer overflow checking to alloconly memory pools.

diffstat:

1 file changed, 65 insertions(+), 23 deletions(-)
src/lib/mempool-alloconly.c |   88 +++++++++++++++++++++++++++++++------------

diffs (149 lines):

diff -r 70cf4172af74 -r 45884655c0c4 src/lib/mempool-alloconly.c
--- a/src/lib/mempool-alloconly.c	Tue Apr 01 20:26:19 2008 +0300
+++ b/src/lib/mempool-alloconly.c	Tue Apr 01 20:34:51 2008 +0300
@@ -40,9 +40,16 @@ struct pool_block {
 #define SIZEOF_POOLBLOCK (MEM_ALIGN(sizeof(struct pool_block)))
 
 #define POOL_BLOCK_DATA(block) \
-	((char *) (block) + SIZEOF_POOLBLOCK)
+	((unsigned char *) (block) + SIZEOF_POOLBLOCK)
 
 #define DEFAULT_BASE_SIZE MEM_ALIGN(sizeof(struct alloconly_pool))
+
+#ifdef DEBUG
+#  define CLEAR_CHR 0xde
+#  define SENTRY_COUNT (4*8)
+#else
+#  define CLEAR_CHR 0
+#endif
 
 static const char *pool_alloconly_get_name(pool_t pool);
 static void pool_alloconly_ref(pool_t pool);
@@ -79,17 +86,36 @@ static const struct pool static_alloconl
 };
 
 #ifdef DEBUG
-static void check_nuls(struct pool_block *block)
-{
-	const char *data = POOL_BLOCK_DATA(block);
-	size_t i;
-
-	for (i = block->size - block->left; i < block->size; i++) {
+static void check_sentries(struct pool_block *block)
+{
+	const unsigned char *data = POOL_BLOCK_DATA(block);
+	size_t i, max_pos, alloc_size, used_size;
+
+	used_size = block->size - block->left;
+	for (i = 0; i < used_size; ) {
+		alloc_size = *(size_t *)(data + i);
+		if (alloc_size == 0 || used_size - i < alloc_size)
+			i_panic("mempool-alloconly: saved alloc size broken");
+		i += MEM_ALIGN(sizeof(alloc_size));
+		max_pos = i + MEM_ALIGN(alloc_size + SENTRY_COUNT);
+		i += alloc_size;
+
+		for (; i < max_pos; i++) {
+			if (data[i] != CLEAR_CHR)
+				i_panic("mempool-alloconly: buffer overflow");
+		}
+	}
+
+	if (i != used_size)
+		i_panic("mempool-alloconly: used_size wrong");
+
+	/* The unused data must be NULs */
+	for (; i < block->size; i++) {
 		if (data[i] != '\0')
 			i_unreached();
 	}
 	if (block->prev != NULL)
-		check_nuls(block->prev);
+		check_sentries(block->prev);
 }
 #endif
 
@@ -153,10 +179,12 @@ static void pool_alloconly_destroy(struc
 	/* destroy the last block */
 	block = apool->block;
 #ifdef DEBUG
-	safe_memset(block, 0xde, SIZEOF_POOLBLOCK + apool->block->size);
-#else
-	if (apool->clean_frees)
-		safe_memset(block, 0, SIZEOF_POOLBLOCK + apool->block->size);
+	safe_memset(block, CLEAR_CHR, SIZEOF_POOLBLOCK + apool->block->size);
+#else
+	if (apool->clean_frees) {
+		safe_memset(block, CLEAR_CHR,
+			    SIZEOF_POOLBLOCK + apool->block->size);
+	}
 #endif
 
 #ifndef USE_GC
@@ -238,22 +266,34 @@ static void *pool_alloconly_malloc(pool_
 {
 	struct alloconly_pool *apool = (struct alloconly_pool *)pool;
 	void *mem;
+	size_t alloc_size;
 
 	if (unlikely(size == 0 || size > SSIZE_T_MAX))
 		i_panic("Trying to allocate %"PRIuSIZE_T" bytes", size);
 
-	size = MEM_ALIGN(size);
-
-	if (apool->block->left < size) {
+#ifndef DEBUG
+	alloc_size = MEM_ALIGN(size);
+#else
+	alloc_size = MEM_ALIGN(sizeof(size)) + MEM_ALIGN(size + SENTRY_COUNT);
+#endif
+
+	if (apool->block->left < alloc_size) {
 		/* we need a new block */
-		block_alloc(apool, size + SIZEOF_POOLBLOCK);
+		block_alloc(apool, alloc_size + SIZEOF_POOLBLOCK);
 	}
 
 	mem = POOL_BLOCK_DATA(apool->block) +
 		(apool->block->size - apool->block->left);
 
-	apool->block->left -= size;
-	apool->block->last_alloc_size = size;
+	apool->block->left -= alloc_size;
+	apool->block->last_alloc_size = alloc_size;
+#ifdef DEBUG
+	memcpy(mem, &size, sizeof(size));
+	mem = PTR_OFFSET(mem, MEM_ALIGN(sizeof(size)));
+	/* write CLEAR_CHRs to sentry */
+	memset(PTR_OFFSET(mem, size), CLEAR_CHR,
+	       MEM_ALIGN(size + SENTRY_COUNT) - size);
+#endif
 	return mem;
 }
 
@@ -325,7 +365,7 @@ static void pool_alloconly_clear(pool_t 
 	size_t base_size, avail_size;
 
 #ifdef DEBUG
-	check_nuls(apool->block);
+	check_sentries(apool->block);
 #endif
 
 	/* destroy all blocks but the oldest, which contains the
@@ -335,10 +375,12 @@ static void pool_alloconly_clear(pool_t 
 		apool->block = block->prev;
 
 #ifdef DEBUG
-		safe_memset(block, 0xde, SIZEOF_POOLBLOCK + block->size);
-#else
-		if (apool->clean_frees)
-			safe_memset(block, 0, SIZEOF_POOLBLOCK + block->size);
+		safe_memset(block, CLEAR_CHR, SIZEOF_POOLBLOCK + block->size);
+#else
+		if (apool->clean_frees) {
+			safe_memset(block, CLEAR_CHR,
+				    SIZEOF_POOLBLOCK + block->size);
+		}
 #endif
 #ifndef USE_GC
 		free(block);


More information about the dovecot-cvs mailing list