[libsecret] Bring over a new version of the secure memory code from gcr



commit 7cea18071bd33d70834cc05b8bcdcaee05194270
Author: Stef Walter <stefw gnome org>
Date:   Sat Oct 27 11:58:13 2012 +0200

    Bring over a new version of the secure memory code from gcr
    
     * This allows libraries to share the pool if they have the same
       version of the secure memory code.

 egg/egg-secure-memory.c    |  453 ++++++++++++++++++++++----------------------
 egg/egg-secure-memory.h    |  110 ++++++------
 egg/tests/test-dh.c        |    2 +-
 egg/tests/test-hkdf.c      |    2 +-
 egg/tests/test-secmem.c    |   20 +-
 libsecret/secret-service.c |    2 +-
 6 files changed, 300 insertions(+), 289 deletions(-)
---
diff --git a/egg/egg-secure-memory.c b/egg/egg-secure-memory.c
index 490f10c..9e605ff 100644
--- a/egg/egg-secure-memory.c
+++ b/egg/egg-secure-memory.c
@@ -1,29 +1,29 @@
 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
 /* egg-secure-memory.h - library for allocating memory that is non-pageable
- *
- * Copyright (C) 2007 Stefan Walter
- * 
- * This program is free software; you can redistribute it and/or modify 
- * it under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *  
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *  
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301 USA
- *
- * Author: Stef Walter <stef thewalter net>
- */
+
+   Copyright (C) 2007 Stefan Walter
+
+   The Gnome Keyring Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The Gnome Keyring Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the Gnome Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.
+
+   Author: Stef Walter <stef memberwebs com>
+*/
 
 /*
- * IMPORTANT: This is pure vanila standard C, no glib. We need this 
- * because certain consumers of this protocol need to be built 
+ * IMPORTANT: This is pure vanila standard C, no glib. We need this
+ * because certain consumers of this protocol need to be built
  * without linking in any special libraries. ie: the PKCS#11 module.
  */
 
@@ -48,8 +48,8 @@
 
 #define DEBUG_SECURE_MEMORY 0
 
-#if DEBUG_SECURE_MEMORY 
-#define DEBUG_ALLOC(msg, n) 	fprintf(stderr, "%s %lu bytes\n", msg, n); 
+#if DEBUG_SECURE_MEMORY
+#define DEBUG_ALLOC(msg, n) 	fprintf(stderr, "%s %lu bytes\n", msg, n);
 #else
 #define DEBUG_ALLOC(msg, n)
 #endif
@@ -59,33 +59,33 @@
 /* Use our own assert to guarantee no glib allocations */
 #ifndef ASSERT
 #ifdef G_DISABLE_ASSERT
-#define ASSERT(x) 
-#else 
+#define ASSERT(x)
+#else
 #define ASSERT(x) assert(x)
 #endif
 #endif
 
 #define DO_LOCK() \
-	egg_memory_lock (); 
-	
+	EGG_SECURE_GLOBALS.lock ();
+
 #define DO_UNLOCK() \
-	egg_memory_unlock ();
+	EGG_SECURE_GLOBALS.unlock ();
 
-static int lock_warning = 1;
+static int show_warning = 1;
 int egg_secure_warnings = 1;
 
-/* 
- * We allocate all memory in units of sizeof(void*). This 
+/*
+ * We allocate all memory in units of sizeof(void*). This
  * is our definition of 'word'.
  */
 typedef void* word_t;
 
-/* The amount of extra words we can allocate */ 
+/* The amount of extra words we can allocate */
 #define WASTE   4
 
-/* 
- * Track allocated memory or a free block. This structure is not stored 
- * in the secure memory area. It is allocated from a pool of other 
+/*
+ * Track allocated memory or a free block. This structure is not stored
+ * in the secure memory area. It is allocated from a pool of other
  * memory. See meta_pool_xxx ().
  */
 typedef struct _Cell {
@@ -97,7 +97,7 @@ typedef struct _Cell {
 	struct _Cell *prev;     /* Previous in memory ring */
 } Cell;
 
-/* 
+/*
  * A block of secure memory. This structure is the header in that block.
  */
 typedef struct _Block {
@@ -130,20 +130,20 @@ unused_pop (void **stack)
 	ptr = *stack;
 	*stack = *(void**)ptr;
 	return ptr;
-	
+
 }
 
 static inline void*
 unused_peek (void **stack)
 {
 	ASSERT (stack);
-	return *stack; 
+	return *stack;
 }
 
 /* -----------------------------------------------------------------------------
  * POOL META DATA ALLOCATION
- * 
- * A pool for memory meta data. We allocate fixed size blocks. There are actually 
+ *
+ * A pool for memory meta data. We allocate fixed size blocks. There are actually
  * two different structures stored in this pool: Cell and Block. Cell is allocated
  * way more often, and is bigger so we just allocate that size for both.
  */
@@ -163,21 +163,29 @@ typedef struct _Pool {
 	Item items[1];         /* Actual items hang off here */
 } Pool;
 
-static Pool *all_pools = NULL;
-
-static void*
+static void *
 pool_alloc (void)
 {
 	Pool *pool;
 	void *pages, *item;
 	size_t len, i;
-	
+
+	if (!EGG_SECURE_GLOBALS.pool_version ||
+	    strcmp (EGG_SECURE_GLOBALS.pool_version, EGG_SECURE_POOL_VER_STR) != 0) {
+		if (show_warning && egg_secure_warnings)
+			fprintf (stderr, "the secure memory pool version does not match the code '%s' != '%s'\n",
+			         EGG_SECURE_GLOBALS.pool_version ? EGG_SECURE_GLOBALS.pool_version : "(null)",
+			         EGG_SECURE_POOL_VER_STR);
+		show_warning = 0;
+		return NULL;
+	}
+
 	/* A pool with an available item */
-	for (pool = all_pools; pool; pool = pool->next) {
+	for (pool = EGG_SECURE_GLOBALS.pool_data; pool; pool = pool->next) {
 		if (unused_peek (&pool->unused))
 			break;
 	}
-	
+
 	/* Create a new pool */
 	if (pool == NULL) {
 		len = getpagesize () * 2;
@@ -187,8 +195,8 @@ pool_alloc (void)
 
 		/* Fill in the block header, and inlude in block list */
 		pool = pages;
-		pool->next = all_pools;
-		all_pools = pool;
+		pool->next = EGG_SECURE_GLOBALS.pool_data;
+		EGG_SECURE_GLOBALS.pool_data = pool;
 		pool->length = len;
 		pool->used = 0;
 		pool->unused = NULL;
@@ -197,7 +205,7 @@ pool_alloc (void)
 		pool->n_items = (len - sizeof (Pool)) / sizeof (Item);
 		for (i = 0; i < pool->n_items; ++i)
 			unused_push (&pool->unused, pool->items + i);
-		
+
 #ifdef WITH_VALGRIND
 		VALGRIND_CREATE_MEMPOOL(pool, 0, 0);
 #endif
@@ -219,11 +227,12 @@ pool_free (void* item)
 {
 	Pool *pool, **at;
 	char *ptr, *beg, *end;
-	
+
 	ptr = item;
-	
+
 	/* Find which block this one belongs to */
-	for (at = &all_pools, pool = *at; pool; at = &pool->next, pool = *at) {
+	for (at = (Pool **)&EGG_SECURE_GLOBALS.pool_data, pool = *at;
+	     pool != NULL; at = &pool->next, pool = *at) {
 		beg = (char*)pool->items;
 		end = (char*)pool + pool->length - sizeof (Item);
 		if (ptr >= beg && ptr <= end) {
@@ -266,17 +275,17 @@ pool_valid (void* item)
 {
 	Pool *pool;
 	char *ptr, *beg, *end;
-	
+
 	ptr = item;
-	
+
 	/* Find which block this one belongs to */
-	for (pool = all_pools; pool; pool = pool->next) {
+	for (pool = EGG_SECURE_GLOBALS.pool_data; pool; pool = pool->next) {
 		beg = (char*)pool->items;
 		end = (char*)pool + pool->length - sizeof (Item);
-		if (ptr >= beg && ptr <= end) 
+		if (ptr >= beg && ptr <= end)
 			return (pool->used && (ptr - beg) % sizeof (Item) == 0);
 	}
-	
+
 	return 0;
 }
 
@@ -284,9 +293,9 @@ pool_valid (void* item)
 
 /* -----------------------------------------------------------------------------
  * SEC ALLOCATION
- * 
+ *
  * Each memory cell begins and ends with a pointer to its metadata. These are also
- * used as guards or red zones. Since they're treated as redzones by valgrind we 
+ * used as guards or red zones. Since they're treated as redzones by valgrind we
  * have to jump through a few hoops before reading and/or writing them.
  */
 
@@ -306,11 +315,11 @@ sec_write_guards (Cell *cell)
 
 	((void**)cell->words)[0] = (void*)cell;
 	((void**)cell->words)[cell->n_words - 1] = (void*)cell;
-	
+
 #ifdef WITH_VALGRIND
 	VALGRIND_MAKE_MEM_NOACCESS (cell->words, sizeof (word_t));
 	VALGRIND_MAKE_MEM_NOACCESS (cell->words + cell->n_words - 1, sizeof (word_t));
-#endif	
+#endif
 }
 
 static inline void
@@ -318,16 +327,16 @@ sec_check_guards (Cell *cell)
 {
 #ifdef WITH_VALGRIND
 	VALGRIND_MAKE_MEM_DEFINED (cell->words, sizeof (word_t));
-	VALGRIND_MAKE_MEM_DEFINED (cell->words + cell->n_words - 1, sizeof (word_t)); 
-#endif	
-	
+	VALGRIND_MAKE_MEM_DEFINED (cell->words + cell->n_words - 1, sizeof (word_t));
+#endif
+
 	ASSERT(((void**)cell->words)[0] == (void*)cell);
 	ASSERT(((void**)cell->words)[cell->n_words - 1] == (void*)cell);
-	
+
 #ifdef WITH_VALGRIND
 	VALGRIND_MAKE_MEM_NOACCESS (cell->words, sizeof (word_t));
 	VALGRIND_MAKE_MEM_NOACCESS (cell->words + cell->n_words - 1, sizeof (word_t));
-#endif	
+#endif
 }
 
 static void
@@ -338,9 +347,9 @@ sec_insert_cell_ring (Cell **ring, Cell *cell)
 	ASSERT (cell != *ring);
 	ASSERT (cell->next == NULL);
 	ASSERT (cell->prev == NULL);
-	
-	/* Insert back into the mix of available memory */ 
-	if (*ring) { 
+
+	/* Insert back into the mix of available memory */
+	if (*ring) {
 		cell->next = (*ring)->next;
 		cell->prev = *ring;
 		cell->next->prev = cell;
@@ -349,7 +358,7 @@ sec_insert_cell_ring (Cell **ring, Cell *cell)
 		cell->next = cell;
 		cell->prev = cell;
 	}
-	
+
 	*ring = cell;
 	ASSERT (cell->next->prev == cell);
 	ASSERT (cell->prev->next == cell);
@@ -382,7 +391,7 @@ sec_remove_cell_ring (Cell **ring, Cell *cell)
 	cell->next->prev = cell->prev;
 	cell->prev->next = cell->next;
 	cell->next = cell->prev = NULL;
-	
+
 	ASSERT (*ring != cell);
 }
 
@@ -431,10 +440,10 @@ static Cell*
 sec_neighbor_before (Block *block, Cell *cell)
 {
 	word_t *word;
-	
+
 	ASSERT (cell);
 	ASSERT (block);
-	
+
 	word = cell->words - 1;
 	if (!sec_is_valid_word (block, word))
 		return NULL;
@@ -442,7 +451,7 @@ sec_neighbor_before (Block *block, Cell *cell)
 #ifdef WITH_VALGRIND
 	VALGRIND_MAKE_MEM_DEFINED (word, sizeof (word_t));
 #endif
-	
+
 	cell = *word;
 	sec_check_guards (cell);
 
@@ -453,14 +462,14 @@ sec_neighbor_before (Block *block, Cell *cell)
 	return cell;
 }
 
-static Cell* 
+static Cell*
 sec_neighbor_after (Block *block, Cell *cell)
 {
 	word_t *word;
-	
+
 	ASSERT (cell);
 	ASSERT (block);
-	
+
 	word = cell->words + cell->n_words;
 	if (!sec_is_valid_word (block, word))
 		return NULL;
@@ -471,7 +480,7 @@ sec_neighbor_after (Block *block, Cell *cell)
 
 	cell = *word;
 	sec_check_guards (cell);
-	
+
 #ifdef WITH_VALGRIND
 	VALGRIND_MAKE_MEM_NOACCESS (word, sizeof (word_t));
 #endif
@@ -487,7 +496,7 @@ sec_alloc (Block *block,
 	Cell *cell, *other;
 	size_t n_words;
 	void *memory;
-	
+
 	ASSERT (block);
 	ASSERT (length);
 	ASSERT (tag);
@@ -495,16 +504,16 @@ sec_alloc (Block *block,
 	if (!block->unused_cells)
 		return NULL;
 
-	/* 
-	 * Each memory allocation is aligned to a pointer size, and 
+	/*
+	 * Each memory allocation is aligned to a pointer size, and
 	 * then, sandwidched between two pointers to its meta data.
 	 * These pointers also act as guards.
 	 *
-	 * We allocate memory in units of sizeof (void*) 
+	 * We allocate memory in units of sizeof (void*)
 	 */
-	
+
 	n_words = sec_size_to_words (length) + 2;
-	
+
 	/* Look for a cell of at least our required size */
 	cell = block->unused_cells;
 	while (cell->n_words < n_words) {
@@ -514,7 +523,7 @@ sec_alloc (Block *block,
 			break;
 		}
 	}
-	
+
 	if (!cell)
 		return NULL;
 
@@ -523,7 +532,7 @@ sec_alloc (Block *block,
 	ASSERT (cell->prev);
 	ASSERT (cell->words);
 	sec_check_guards (cell);
-	
+
 	/* Steal from the cell if it's too long */
 	if (cell->n_words > n_words + WASTE) {
 		other = pool_alloc ();
@@ -533,13 +542,13 @@ sec_alloc (Block *block,
 		other->words = cell->words;
 		cell->n_words -= n_words;
 		cell->words += n_words;
-		
+
 		sec_write_guards (other);
 		sec_write_guards (cell);
-		
+
 		cell = other;
 	}
-	
+
 	if (cell->next)
 		sec_remove_cell_ring (&block->unused_cells, cell);
 
@@ -548,11 +557,11 @@ sec_alloc (Block *block,
 	cell->requested = length;
 	sec_insert_cell_ring (&block->used_cells, cell);
 	memory = sec_cell_to_memory (cell);
-	
+
 #ifdef WITH_VALGRIND
 	VALGRIND_MAKE_MEM_UNDEFINED (memory, length);
 #endif
-	
+
 	return memset (memory, 0, length);
 }
 
@@ -561,13 +570,13 @@ sec_free (Block *block, void *memory)
 {
 	Cell *cell, *other;
 	word_t *word;
-	
+
 	ASSERT (block);
 	ASSERT (memory);
-	
+
 	word = memory;
 	--word;
-	
+
 #ifdef WITH_VALGRIND
 	VALGRIND_MAKE_MEM_DEFINED (word, sizeof (word_t));
 #endif
@@ -591,39 +600,39 @@ sec_free (Block *block, void *memory)
 	/* Remove from the used cell ring */
 	sec_remove_cell_ring (&block->used_cells, cell);
 
-        /* Find previous unallocated neighbor, and merge if possible */
-        other = sec_neighbor_before (block, cell);
-        if (other && other->requested == 0) {
-        	ASSERT (other->tag == NULL);
-        	ASSERT (other->next && other->prev);
-        	other->n_words += cell->n_words;
-        	sec_write_guards (other);
-        	pool_free (cell);
-        	cell = other;
-        } 
-        
-        /* Find next unallocated neighbor, and merge if possible */
-        other = sec_neighbor_after (block, cell);
-        if (other && other->requested == 0) {
-        	ASSERT (other->tag == NULL);
-        	ASSERT (other->next && other->prev);
-        	other->n_words += cell->n_words;
-        	other->words = cell->words;
-        	if (cell->next)
-        		sec_remove_cell_ring (&block->unused_cells, cell);
-        	sec_write_guards (other);
-        	pool_free (cell);
-        	cell = other;
-        }
-
-        /* Add to the unused list if not already there */
-        if (!cell->next)
-        	sec_insert_cell_ring (&block->unused_cells, cell);
-
-        cell->tag = NULL;
-        cell->requested = 0;
-        --block->n_used;
-        return NULL;
+	/* Find previous unallocated neighbor, and merge if possible */
+	other = sec_neighbor_before (block, cell);
+	if (other && other->requested == 0) {
+		ASSERT (other->tag == NULL);
+		ASSERT (other->next && other->prev);
+		other->n_words += cell->n_words;
+		sec_write_guards (other);
+		pool_free (cell);
+		cell = other;
+	}
+
+	/* Find next unallocated neighbor, and merge if possible */
+	other = sec_neighbor_after (block, cell);
+	if (other && other->requested == 0) {
+		ASSERT (other->tag == NULL);
+		ASSERT (other->next && other->prev);
+		other->n_words += cell->n_words;
+		other->words = cell->words;
+		if (cell->next)
+			sec_remove_cell_ring (&block->unused_cells, cell);
+		sec_write_guards (other);
+		pool_free (cell);
+		cell = other;
+	}
+
+	/* Add to the unused list if not already there */
+	if (!cell->next)
+		sec_insert_cell_ring (&block->unused_cells, cell);
+
+	cell->tag = NULL;
+	cell->requested = 0;
+	--block->n_used;
+	return NULL;
 }
 
 static void
@@ -674,7 +683,7 @@ sec_realloc (Block *block,
 	/* Dig out where the meta should be */
 	word = memory;
 	--word;
-	
+
 #ifdef WITH_VALGRIND
 	VALGRIND_MAKE_MEM_DEFINED (word, sizeof (word_t));
 #endif
@@ -682,7 +691,7 @@ sec_realloc (Block *block,
 	ASSERT (sec_is_valid_word (block, word));
 	ASSERT (pool_valid (*word));
 	cell = *word;
-	
+
 	/* Validate that it's actually for real */
 	sec_check_guards (cell);
 	ASSERT (cell->requested > 0);
@@ -701,17 +710,17 @@ sec_realloc (Block *block,
 		cell->requested = length;
 		alloc = sec_cell_to_memory (cell);
 
-		/* 
+		/*
 		 * Even though we may be reusing the same cell, that doesn't
 		 * mean that the allocation is shrinking. It could have shrunk
-		 * and is now expanding back some. 
-		 */ 
+		 * and is now expanding back some.
+		 */
 		if (length < valid)
 			sec_clear_undefined (alloc, length, valid);
 
 		return alloc;
 	}
-	
+
 	/* Need braaaaaiiiiiinsss... */
 	while (cell->n_words < n_words) {
 
@@ -719,7 +728,7 @@ sec_realloc (Block *block,
 		other = sec_neighbor_after (block, cell);
 		if (!other || other->requested != 0)
 			break;
-		
+
 		/* Eat the whole neighbor if not too big */
 		if (n_words - cell->n_words + WASTE >= other->n_words) {
 			cell->n_words += other->n_words;
@@ -736,7 +745,7 @@ sec_realloc (Block *block,
 			sec_write_guards (cell);
 		}
 	}
-	
+
 	if (cell->n_words >= n_words) {
 		cell->requested = length;
 		cell->tag = tag;
@@ -751,7 +760,7 @@ sec_realloc (Block *block,
 		memcpy_with_vbits (alloc, memory, valid);
 		sec_free (block, memory);
 	}
-	
+
 	return alloc;
 }
 
@@ -761,7 +770,7 @@ sec_allocated (Block *block, void *memory)
 {
 	Cell *cell;
 	word_t *word;
-	
+
 	ASSERT (block);
 	ASSERT (memory);
 
@@ -771,12 +780,12 @@ sec_allocated (Block *block, void *memory)
 #ifdef WITH_VALGRIND
 	VALGRIND_MAKE_MEM_DEFINED (word, sizeof (word_t));
 #endif
-	
+
 	/* Lookup the meta for this memory block (using guard pointer) */
 	ASSERT (sec_is_valid_word (block, word));
 	ASSERT (pool_valid (*word));
 	cell = *word;
-	
+
 	sec_check_guards (cell);
 	ASSERT (cell->requested > 0);
 	ASSERT (cell->tag != NULL);
@@ -808,10 +817,10 @@ sec_validate (Block *block)
 		ASSERT (sec_is_valid_word (block, word));
 		ASSERT (pool_valid (*word));
 		cell = *word;
-	
+
 		/* Validate that it's actually for real */
 		sec_check_guards (cell);
-	
+
 		/* Is it an allocated block? */
 		if (cell->requested > 0) {
 			ASSERT (cell->tag != NULL);
@@ -820,7 +829,7 @@ sec_validate (Block *block)
 			ASSERT (cell->next->prev == cell);
 			ASSERT (cell->prev->next == cell);
 			ASSERT (cell->requested <= (cell->n_words - 2) * sizeof (word_t));
-		
+
 		/* An unused block */
 		} else {
 			ASSERT (cell->tag == NULL);
@@ -829,7 +838,7 @@ sec_validate (Block *block)
 			ASSERT (cell->next->prev == cell);
 			ASSERT (cell->prev->next == cell);
 		}
-		
+
 		word += cell->n_words;
 		if (word == last)
 			break;
@@ -846,7 +855,7 @@ sec_acquire_pages (size_t *sz,
 {
 	void *pages;
 	unsigned long pgsize;
-	
+
 	ASSERT (sz);
 	ASSERT (*sz);
 	ASSERT (during_tag);
@@ -854,56 +863,56 @@ sec_acquire_pages (size_t *sz,
 	/* Make sure sz is a multiple of the page size */
 	pgsize = getpagesize ();
 	*sz = (*sz + pgsize -1) & ~(pgsize - 1);
-	
+
 #if defined(HAVE_MLOCK)
 	pages = mmap (0, *sz, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
 	if (pages == MAP_FAILED) {
-		if (lock_warning && egg_secure_warnings)
+		if (show_warning && egg_secure_warnings)
 			fprintf (stderr, "couldn't map %lu bytes of memory (%s): %s\n",
 			         (unsigned long)*sz, during_tag, strerror (errno));
-		lock_warning = 0;
+		show_warning = 0;
 		return NULL;
 	}
-	
+
 	if (mlock (pages, *sz) < 0) {
-		if (lock_warning && egg_secure_warnings && errno != EPERM) {
+		if (show_warning && egg_secure_warnings && errno != EPERM) {
 			fprintf (stderr, "couldn't lock %lu bytes of memory (%s): %s\n",
 			         (unsigned long)*sz, during_tag, strerror (errno));
-			lock_warning = 0;
+			show_warning = 0;
 		}
 		munmap (pages, *sz);
 		return NULL;
 	}
-	
+
 	DEBUG_ALLOC ("gkr-secure-memory: new block ", *sz);
-	
-	lock_warning = 1;
+
+	show_warning = 1;
 	return pages;
-	
+
 #else
-	if (lock_warning && egg_secure_warnings)
+	if (show_warning && egg_secure_warnings)
 		fprintf (stderr, "your system does not support private memory");
-	lock_warning = 0;
+	show_warning = 0;
 	return NULL;
 #endif
 
 }
 
-static void 
+static void
 sec_release_pages (void *pages, size_t sz)
 {
 	ASSERT (pages);
 	ASSERT (sz % getpagesize () == 0);
-	
+
 #if defined(HAVE_MLOCK)
 	if (munlock (pages, sz) < 0 && egg_secure_warnings)
 		fprintf (stderr, "couldn't unlock private memory: %s\n", strerror (errno));
-		
+
 	if (munmap (pages, sz) < 0 && egg_secure_warnings)
 		fprintf (stderr, "couldn't unmap private anonymous memory: %s\n", strerror (errno));
-		
+
 	DEBUG_ALLOC ("gkr-secure-memory: freed block ", sz);
-	
+
 #else
 	ASSERT (FALSE);
 #endif
@@ -915,7 +924,7 @@ sec_release_pages (void *pages, size_t sz)
 
 static Block *all_blocks = NULL;
 
-static Block* 
+static Block*
 sec_block_create (size_t size,
                   const char *during_tag)
 {
@@ -941,7 +950,7 @@ sec_block_create (size_t size,
 	/* The size above is a minimum, we're free to go bigger */
 	if (size < DEFAULT_BLOCK_SIZE)
 		size = DEFAULT_BLOCK_SIZE;
-		
+
 	block->words = sec_acquire_pages (&size, during_tag);
 	block->n_words = size / sizeof (word_t);
 	if (!block->words) {
@@ -949,11 +958,11 @@ sec_block_create (size_t size,
 		pool_free (cell);
 		return NULL;
 	}
-	
+
 #ifdef WITH_VALGRIND
 	VALGRIND_MAKE_MEM_DEFINED (block->words, size);
 #endif
-	
+
 	/* The first cell to allocate from */
 	cell->words = block->words;
 	cell->n_words = block->n_words;
@@ -963,7 +972,7 @@ sec_block_create (size_t size,
 
 	block->next = all_blocks;
 	all_blocks = block;
-	
+
 	return block;
 }
 
@@ -976,7 +985,7 @@ sec_block_destroy (Block *block)
 	ASSERT (block);
 	ASSERT (block->words);
 	ASSERT (block->n_used == 0);
-	
+
 	/* Remove from the list */
 	for (at = &all_blocks, bl = *at; bl; at = &bl->next, bl = *at) {
 		if (bl == block) {
@@ -984,7 +993,7 @@ sec_block_destroy (Block *block)
 			break;
 		}
 	}
-	
+
 	/* Must have been found */
 	ASSERT (bl == block);
 	ASSERT (block->used_cells == NULL);
@@ -995,7 +1004,7 @@ sec_block_destroy (Block *block)
 		sec_remove_cell_ring (&block->unused_cells, cell);
 		pool_free (cell);
 	}
-	
+
 	/* Release all pages of secure memory */
 	sec_release_pages (block->words, block->n_words * sizeof (word_t));
 
@@ -1019,46 +1028,46 @@ egg_secure_alloc_full (const char *tag,
 
 	if (length > 0xFFFFFFFF / 2) {
 		if (egg_secure_warnings)
-			fprintf (stderr, "tried to allocate an insane amount of memory: %lu\n", 
-			         (unsigned long)length);   
+			fprintf (stderr, "tried to allocate an insane amount of memory: %lu\n",
+			         (unsigned long)length);
 		return NULL;
 	}
 
 	/* Can't allocate zero bytes */
 	if (length == 0)
 		return NULL;
-	
+
 	DO_LOCK ();
-	
+
 		for (block = all_blocks; block; block = block->next) {
 			memory = sec_alloc (block, tag, length);
 			if (memory)
-				break;	
+				break;
 		}
-	
+
 		/* None of the current blocks have space, allocate new */
 		if (!memory) {
 			block = sec_block_create (length, tag);
 			if (block)
 				memory = sec_alloc (block, tag, length);
 		}
-		
+
 #ifdef WITH_VALGRIND
 		if (memory != NULL)
 			VALGRIND_MALLOCLIKE_BLOCK (memory, length, sizeof (void*), 1);
 #endif
-	
+
 	DO_UNLOCK ();
 
-	if (!memory && (flags & EGG_SECURE_USE_FALLBACK)) {
-		memory = egg_memory_fallback (NULL, length);
+	if (!memory && (flags & EGG_SECURE_USE_FALLBACK) && EGG_SECURE_GLOBALS.fallback != NULL) {
+		memory = EGG_SECURE_GLOBALS.fallback (NULL, length);
 		if (memory) /* Our returned memory is always zeroed */
 			memset (memory, 0, length);
 	}
-	
+
 	if (!memory)
 		errno = ENOMEM;
-	
+
 	return memory;
 }
 
@@ -1078,20 +1087,20 @@ egg_secure_realloc_full (const char *tag,
 
 	if (length > 0xFFFFFFFF / 2) {
 		if (egg_secure_warnings)
-			fprintf (stderr, "tried to allocate an insane amount of memory: %lu\n", 
+			fprintf (stderr, "tried to allocate an insane amount of memory: %lu\n",
 			         (unsigned long)length);
 		return NULL;
 	}
-	
+
 	if (memory == NULL)
 		return egg_secure_alloc_full (tag, length, flags);
 	if (!length) {
 		egg_secure_free_full (memory, flags);
 		return NULL;
 	}
-	
+
 	DO_LOCK ();
-	
+
 		/* Find out where it belongs to */
 		for (block = all_blocks; block; block = block->next) {
 			if (sec_is_valid_word (block, memory)) {
@@ -1106,10 +1115,10 @@ egg_secure_realloc_full (const char *tag,
 
 #ifdef WITH_VALGRIND
 				/* Now tell valgrind about either the new block or old one */
-				VALGRIND_MALLOCLIKE_BLOCK (alloc ? alloc : memory, 
-				                           alloc ? length : previous, 
+				VALGRIND_MALLOCLIKE_BLOCK (alloc ? alloc : memory,
+				                           alloc ? length : previous,
 				                           sizeof (word_t), 1);
-#endif					
+#endif
 				break;
 			}
 		}
@@ -1120,21 +1129,21 @@ egg_secure_realloc_full (const char *tag,
 
 		if (block && block->n_used == 0)
 			sec_block_destroy (block);
-		
-	DO_UNLOCK ();		
-	
+
+	DO_UNLOCK ();
+
 	if (!block) {
-		if ((flags & EGG_SECURE_USE_FALLBACK)) {
-			/* 
-			 * In this case we can't zero the returned memory, 
+		if ((flags & EGG_SECURE_USE_FALLBACK) && EGG_SECURE_GLOBALS.fallback) {
+			/*
+			 * In this case we can't zero the returned memory,
 			 * because we don't know what the block size was.
 			 */
-			return egg_memory_fallback (memory, length);
+			return EGG_SECURE_GLOBALS.fallback (memory, length);
 		} else {
 			if (egg_secure_warnings)
-				fprintf (stderr, "memory does not belong to gnome-keyring: 0x%08lx\n", 
+				fprintf (stderr, "memory does not belong to secure memory pool: 0x%08lx\n",
 				         (unsigned long)memory);
-			ASSERT (0 && "memory does does not belong to gnome-keyring");
+			ASSERT (0 && "memory does does not belong to secure memory pool");
 			return NULL;
 		}
 	}
@@ -1146,7 +1155,7 @@ egg_secure_realloc_full (const char *tag,
 			egg_secure_free_full (memory, flags);
 		}
 	}
-	
+
 	if (!alloc)
 		errno = ENOMEM;
 
@@ -1163,12 +1172,12 @@ void
 egg_secure_free_full (void *memory, int flags)
 {
 	Block *block = NULL;
-	
+
 	if (memory == NULL)
 		return;
-	
+
 	DO_LOCK ();
-	
+
 		/* Find out where it belongs to */
 		for (block = all_blocks; block; block = block->next) {
 			if (sec_is_valid_word (block, memory))
@@ -1186,49 +1195,49 @@ egg_secure_free_full (void *memory, int flags)
 			if (block->n_used == 0)
 				sec_block_destroy (block);
 		}
-			
+
 	DO_UNLOCK ();
-	
+
 	if (!block) {
-		if ((flags & EGG_SECURE_USE_FALLBACK)) {
-			egg_memory_fallback (memory, 0);
+		if ((flags & EGG_SECURE_USE_FALLBACK) && EGG_SECURE_GLOBALS.fallback) {
+			EGG_SECURE_GLOBALS.fallback (memory, 0);
 		} else {
 			if (egg_secure_warnings)
-				fprintf (stderr, "memory does not belong to gnome-keyring: 0x%08lx\n", 
+				fprintf (stderr, "memory does not belong to secure memory pool: 0x%08lx\n",
 				         (unsigned long)memory);
-			ASSERT (0 && "memory does does not belong to gnome-keyring");
+			ASSERT (0 && "memory does does not belong to secure memory pool");
 		}
 	}
-} 
+}
 
-int  
+int
 egg_secure_check (const void *memory)
 {
 	Block *block = NULL;
 
 	DO_LOCK ();
-	
+
 		/* Find out where it belongs to */
 		for (block = all_blocks; block; block = block->next) {
 			if (sec_is_valid_word (block, (word_t*)memory))
 				break;
 		}
-		
+
 	DO_UNLOCK ();
-	
+
 	return block == NULL ? 0 : 1;
-} 
+}
 
 void
 egg_secure_validate (void)
 {
 	Block *block = NULL;
-	
+
 	DO_LOCK ();
-	
+
 		for (block = all_blocks; block; block = block->next)
 			sec_validate (block);
-		
+
 	DO_UNLOCK ();
 }
 
@@ -1311,7 +1320,7 @@ egg_secure_strdup_full (const char *tag,
 	if (!str)
 		return NULL;
 
-	len = strlen (str) + 1;	
+	len = strlen (str) + 1;
 	res = (char *)egg_secure_alloc_full (tag, len, options);
 	strcpy (res, str);
 	return res;
@@ -1343,10 +1352,10 @@ void
 egg_secure_clear (void *p, size_t length)
 {
 	volatile char *vp;
-	
+
 	if (p == NULL)
 		return;
-		
+
         vp = (volatile char*)p;
         while (length) {
 	        *vp = 0xAA;
@@ -1368,10 +1377,10 @@ egg_secure_strfree (char *str)
 {
 	/*
 	 * If we're using unpageable 'secure' memory, then the free call
-	 * should zero out the memory, but because on certain platforms 
+	 * should zero out the memory, but because on certain platforms
 	 * we may be using normal memory, zero it out here just in case.
 	 */
-	
+
 	egg_secure_strclear (str);
 	egg_secure_free_full (str, EGG_SECURE_USE_FALLBACK);
 }
diff --git a/egg/egg-secure-memory.h b/egg/egg-secure-memory.h
index 1bfa82e..969dbd7 100644
--- a/egg/egg-secure-memory.h
+++ b/egg/egg-secure-memory.h
@@ -1,25 +1,25 @@
 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
 /* egg-secure-memory.h - library for allocating memory that is non-pageable
- *
- * Copyright (C) 2007 Stefan Walter
- * 
- * This program is free software; you can redistribute it and/or modify 
- * it under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *  
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *  
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301 USA
- *
- * Author: Stef Walter <stef thewalter net>
- */
+
+   Copyright (C) 2007 Stefan Walter
+
+   The Gnome Keyring Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The Gnome Keyring Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the Gnome Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.
+
+   Author: Stef Walter <stef memberwebs com>
+*/
 
 #ifndef EGG_SECURE_MEMORY_H
 #define EGG_SECURE_MEMORY_H
@@ -27,49 +27,51 @@
 #include <stdlib.h>
 
 /* -------------------------------------------------------------------
- * Low Level Secure Memory 
- * 
- * IMPORTANT: This is pure vanila standard C, no glib. We need this 
- * because certain consumers of this protocol need to be built 
+ * Low Level Secure Memory
+ *
+ * IMPORTANT: This is pure vanila standard C, no glib. We need this
+ * because certain consumers of this protocol need to be built
  * without linking in any special libraries. ie: the PKCS#11 module.
- * 
+ *
  * Thread locking
- * 
+ *
  * In order to use these functions in a module the following functions
- * must be defined somewhere, and provide appropriate locking for 
+ * must be defined somewhere, and provide appropriate locking for
  * secure memory between threads:
  */
- 
-extern void   egg_memory_lock (void);
 
-extern void   egg_memory_unlock (void);
-
-/*
- * Allocation Fallbacks
- * 
- * If we cannot allocate secure memory, then this function
- * (defined elsewhere) will be called which has a chance to 
- * allocate other memory abort or do whatever.
- * 
- * Same call semantics as realloc with regard to NULL and zeros 
- */
-extern void*  egg_memory_fallback (void *p, size_t length);
-
-#define EGG_SECURE_GLIB_DEFINITIONS() \
+typedef struct {
+	void       (* lock)        (void);
+	void       (* unlock)      (void);
+	void *     (* fallback)    (void *pointer,
+	                            size_t length);
+	void *        pool_data;
+	const char *  pool_version;
+} egg_secure_glob;
+
+#define EGG_SECURE_POOL_VER_STR             "1.0"
+#define EGG_SECURE_GLOBALS SECMEM_pool_data_v1_0
+
+#define EGG_SECURE_DEFINE_GLOBALS(lock, unlock, fallback) \
+	egg_secure_glob EGG_SECURE_GLOBALS = { \
+		lock, unlock, fallback, NULL, EGG_SECURE_POOL_VER_STR };
+
+#define EGG_SECURE_DEFINE_GLIB_GLOBALS() \
 	static GStaticMutex memory_mutex = G_STATIC_MUTEX_INIT; \
-	void egg_memory_lock (void) \
+	static void egg_memory_lock (void) \
 		{ g_static_mutex_lock (&memory_mutex); } \
-	void egg_memory_unlock (void) \
+	static void egg_memory_unlock (void) \
 		{ g_static_mutex_unlock (&memory_mutex); } \
-	void* egg_memory_fallback (void *p, size_t sz) \
-		{ return g_realloc (p, sz); } \
+	EGG_SECURE_DEFINE_GLOBALS (egg_memory_lock, egg_memory_unlock, g_realloc);
 
-/* 
+extern egg_secure_glob EGG_SECURE_GLOBALS;
+
+/*
  * Main functionality
- *  
+ *
  * Allocations return NULL on failure.
- */ 
- 
+ */
+
 #define EGG_SECURE_USE_FALLBACK     0x0001
 
 #define EGG_SECURE_DECLARE(tag) \
@@ -90,13 +92,13 @@ void*  egg_secure_alloc_full   (const char *tag, size_t length, int options);
 
 void*  egg_secure_realloc_full (const char *tag, void *p, size_t length, int options);
 
-void   egg_secure_free         (void* p); 
+void   egg_secure_free         (void* p);
 
-void   egg_secure_free_full    (void* p, int fallback); 
+void   egg_secure_free_full    (void* p, int fallback);
 
 void   egg_secure_clear        (void *p, size_t length);
 
-int    egg_secure_check        (const void* p); 
+int    egg_secure_check        (const void* p);
 
 void   egg_secure_validate     (void);
 
diff --git a/egg/tests/test-dh.c b/egg/tests/test-dh.c
index ba9fcfc..a676f93 100644
--- a/egg/tests/test-dh.c
+++ b/egg/tests/test-dh.c
@@ -34,7 +34,7 @@
 #include <glib.h>
 #include <gcrypt.h>
 
-EGG_SECURE_GLIB_DEFINITIONS ();
+EGG_SECURE_DEFINE_GLIB_GLOBALS ();
 
 static void
 test_perform (void)
diff --git a/egg/tests/test-hkdf.c b/egg/tests/test-hkdf.c
index 93f16df..de1d196 100644
--- a/egg/tests/test-hkdf.c
+++ b/egg/tests/test-hkdf.c
@@ -33,7 +33,7 @@
 
 #include <gcrypt.h>
 
-EGG_SECURE_GLIB_DEFINITIONS ();
+EGG_SECURE_DEFINE_GLIB_GLOBALS ();
 
 static void
 test_hkdf_test_case_1 (void)
diff --git a/egg/tests/test-secmem.c b/egg/tests/test-secmem.c
index cee5bd9..e0b6e24 100644
--- a/egg/tests/test-secmem.c
+++ b/egg/tests/test-secmem.c
@@ -32,14 +32,14 @@
 #include <string.h>
 
 
-EGG_SECURE_GLIB_DEFINITIONS ();
+EGG_SECURE_DEFINE_GLIB_GLOBALS ();
 
 /* Declared in egg-secure-memory.c */
 extern int egg_secure_warnings;
 
 EGG_SECURE_DECLARE (tests);
 
-/* 
+/*
  * Each test looks like (on one line):
  *     void unit_test_xxxxx (CuTest* cu)
  *
@@ -93,7 +93,7 @@ test_realloc_across (void)
 	g_assert (p != NULL);
 	g_assert_cmpint (G_MAXSIZE, ==, find_non_zero (p, 1088));
 
-	/* Reallocate to a large one, will have to have changed blocks */	
+	/* Reallocate to a large one, will have to have changed blocks */
 	p2 = egg_secure_realloc_full ("tests", p, 16200, 0);
 	g_assert (p2 != NULL);
 	g_assert_cmpint (G_MAXSIZE, ==, find_non_zero (p2, 16200));
@@ -182,26 +182,25 @@ test_multialloc (void)
 		case 0: /* Allocate some memory */
 			size = g_random_int_range (1, 16384);
 			data = egg_secure_alloc (size);
-			g_assert (data);
+			g_assert (data != NULL);
 			memset (data, 0xCAFEBABE, size);
 			g_ptr_array_add (memory, data);
 			break;
 		case 1: /* Reallocate some memory */
 			index = g_random_int_range (0, memory->len);
 			data = g_ptr_array_index (memory, index);
-			g_assert (data);
+			g_assert (data != NULL);
 			size = g_random_int_range (1, 16384);
 			data = egg_secure_realloc (data, size);
-			g_assert (data);
+			g_assert (data != NULL);
 			memset (data, 0xCAFEBABE, size);
 			g_ptr_array_index (memory, index) = data;
 			break;
 		case 2: /* Free some memory */
 			index = g_random_int_range (0, memory->len);
-			data = g_ptr_array_index (memory, index);
-			g_assert (data);
+			data = g_ptr_array_remove_index_fast (memory, index);
+			g_assert (data != NULL);
 			egg_secure_free (data);
-			g_ptr_array_remove_index_fast (memory, index);
 			break;
 		default:
 			g_assert_not_reached ();
@@ -214,7 +213,8 @@ test_multialloc (void)
 	}
 
 	g_assert (memory->len == 0);
-	g_ptr_array_set_free_func (memory, egg_secure_free);
+	for (i = 0; i < memory->len; i++)
+		egg_secure_free (memory->pdata[i]);
 	g_ptr_array_free (memory, TRUE);
 
 	egg_secure_warnings = 1;
diff --git a/libsecret/secret-service.c b/libsecret/secret-service.c
index 9234db2..1d45fc4 100644
--- a/libsecret/secret-service.c
+++ b/libsecret/secret-service.c
@@ -104,7 +104,7 @@
  * during a secret_service_get() or secret_service_new() operation.
  */
 
-EGG_SECURE_GLIB_DEFINITIONS ();
+EGG_SECURE_DEFINE_GLIB_GLOBALS ();
 
 GQuark _secret_error_quark = 0;
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]