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