summaryrefslogtreecommitdiff
path: root/egg/egg-secure-memory.c
diff options
context:
space:
mode:
authorStef Walter <stefw@gnome.org>2012-10-27 11:58:13 +0200
committerStef Walter <stefw@gnome.org>2012-10-27 12:23:39 +0200
commit7cea18071bd33d70834cc05b8bcdcaee05194270 (patch)
tree8c14d2452cca841af24f8e25b22032e6c4dada22 /egg/egg-secure-memory.c
parent275d314d5706e412c346fe85027b888cf7d99f76 (diff)
downloadlibsecret-7cea18071bd33d70834cc05b8bcdcaee05194270.tar.gz
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.
Diffstat (limited to 'egg/egg-secure-memory.c')
-rw-r--r--egg/egg-secure-memory.c453
1 files changed, 231 insertions, 222 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);
}