1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
2 /* egg-secure-memory.h - library for allocating memory that is non-pageable
4 Copyright (C) 2007 Stefan Walter
6 The Gnome Keyring Library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Library General Public License as
8 published by the Free Software Foundation; either version 2 of the
9 License, or (at your option) any later version.
11 The Gnome Keyring Library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Library General Public License for more details.
16 You should have received a copy of the GNU Library General Public
17 License along with the Gnome Library; see the file COPYING.LIB. If not,
18 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA.
21 Author: Stef Walter <stef@memberwebs.com>
25 * IMPORTANT: This is pure vanila standard C, no glib. We need this
26 * because certain consumers of this protocol need to be built
27 * without linking in any special libraries. ie: the PKCS#11 module.
32 #include "egg-secure-memory.h"
34 #include <sys/types.h>
45 #include <valgrind/valgrind.h>
46 #include <valgrind/memcheck.h>
49 #define DEBUG_SECURE_MEMORY 0
51 #if DEBUG_SECURE_MEMORY
52 #define DEBUG_ALLOC(msg, n) fprintf(stderr, "%s %lu bytes\n", msg, n);
54 #define DEBUG_ALLOC(msg, n)
57 #define DEFAULT_BLOCK_SIZE 16384
59 /* Use our own assert to guarantee no glib allocations */
61 #ifdef G_DISABLE_ASSERT
64 #define ASSERT(x) assert(x)
69 EGG_SECURE_GLOBALS.lock ();
72 EGG_SECURE_GLOBALS.unlock ();
74 static int show_warning = 1;
75 int egg_secure_warnings = 1;
78 * We allocate all memory in units of sizeof(void*). This
79 * is our definition of 'word'.
83 /* The amount of extra words we can allocate */
87 * Track allocated memory or a free block. This structure is not stored
88 * in the secure memory area. It is allocated from a pool of other
89 * memory. See meta_pool_xxx ().
91 typedef struct _Cell {
92 word_t *words; /* Pointer to secure memory */
93 size_t n_words; /* Amount of secure memory in words */
94 size_t requested; /* Amount actually requested by app, in bytes, 0 if unused */
95 const char *tag; /* Tag which describes the allocation */
96 struct _Cell *next; /* Next in memory ring */
97 struct _Cell *prev; /* Previous in memory ring */
101 * A block of secure memory. This structure is the header in that block.
103 typedef struct _Block {
104 word_t *words; /* Actual memory hangs off here */
105 size_t n_words; /* Number of words in block */
106 size_t n_used; /* Number of used allocations */
107 struct _Cell* used_cells; /* Ring of used allocations */
108 struct _Cell* unused_cells; /* Ring of unused allocations */
109 struct _Block *next; /* Next block in list */
112 /* -----------------------------------------------------------------------------
117 unused_push (void **stack, void *ptr)
121 *((void**)ptr) = *stack;
126 unused_pop (void **stack)
131 *stack = *(void**)ptr;
137 unused_peek (void **stack)
143 /* -----------------------------------------------------------------------------
144 * POOL META DATA ALLOCATION
146 * A pool for memory meta data. We allocate fixed size blocks. There are actually
147 * two different structures stored in this pool: Cell and Block. Cell is allocated
148 * way more often, and is bigger so we just allocate that size for both.
151 /* Pool allocates this data type */
152 typedef union _Item {
157 typedef struct _Pool {
158 struct _Pool *next; /* Next pool in list */
159 size_t length; /* Length in bytes of the pool */
160 size_t used; /* Number of cells used in pool */
161 void *unused; /* Unused stack of unused stuff */
162 size_t n_items; /* Total number of items in pool */
163 Item items[1]; /* Actual items hang off here */
173 if (!EGG_SECURE_GLOBALS.pool_version ||
174 strcmp (EGG_SECURE_GLOBALS.pool_version, EGG_SECURE_POOL_VER_STR) != 0) {
175 if (show_warning && egg_secure_warnings)
176 fprintf (stderr, "the secure memory pool version does not match the code '%s' != '%s'\n",
177 EGG_SECURE_GLOBALS.pool_version ? EGG_SECURE_GLOBALS.pool_version : "(null)",
178 EGG_SECURE_POOL_VER_STR);
183 /* A pool with an available item */
184 for (pool = EGG_SECURE_GLOBALS.pool_data; pool; pool = pool->next) {
185 if (unused_peek (&pool->unused))
189 /* Create a new pool */
191 len = getpagesize () * 2;
192 pages = mmap (0, len, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
193 if (pages == MAP_FAILED)
196 /* Fill in the block header, and inlude in block list */
198 pool->next = EGG_SECURE_GLOBALS.pool_data;
199 EGG_SECURE_GLOBALS.pool_data = pool;
204 /* Fill block with unused items */
205 pool->n_items = (len - sizeof (Pool)) / sizeof (Item);
206 for (i = 0; i < pool->n_items; ++i)
207 unused_push (&pool->unused, pool->items + i);
210 VALGRIND_CREATE_MEMPOOL(pool, 0, 0);
215 ASSERT (unused_peek (&pool->unused));
216 item = unused_pop (&pool->unused);
219 VALGRIND_MEMPOOL_ALLOC (pool, item, sizeof (Item));
222 return memset (item, 0, sizeof (Item));
226 pool_free (void* item)
229 char *ptr, *beg, *end;
233 /* Find which block this one belongs to */
234 for (at = (Pool **)&EGG_SECURE_GLOBALS.pool_data, pool = *at;
235 pool != NULL; at = &pool->next, pool = *at) {
236 beg = (char*)pool->items;
237 end = (char*)pool + pool->length - sizeof (Item);
238 if (ptr >= beg && ptr <= end) {
239 ASSERT ((ptr - beg) % sizeof (Item) == 0);
244 /* Otherwise invalid meta */
247 ASSERT (pool->used > 0);
249 /* No more meta cells used in this block, remove from list, destroy */
250 if (pool->used == 1) {
254 VALGRIND_DESTROY_MEMPOOL (pool);
257 munmap (pool, pool->length);
262 VALGRIND_MEMPOOL_FREE (pool, item);
263 VALGRIND_MAKE_MEM_UNDEFINED (item, sizeof (Item));
267 memset (item, 0xCD, sizeof (Item));
268 unused_push (&pool->unused, item);
271 #ifndef G_DISABLE_ASSERT
274 pool_valid (void* item)
277 char *ptr, *beg, *end;
281 /* Find which block this one belongs to */
282 for (pool = EGG_SECURE_GLOBALS.pool_data; pool; pool = pool->next) {
283 beg = (char*)pool->items;
284 end = (char*)pool + pool->length - sizeof (Item);
285 if (ptr >= beg && ptr <= end)
286 return (pool->used && (ptr - beg) % sizeof (Item) == 0);
292 #endif /* G_DISABLE_ASSERT */
294 /* -----------------------------------------------------------------------------
297 * Each memory cell begins and ends with a pointer to its metadata. These are also
298 * used as guards or red zones. Since they're treated as redzones by valgrind we
299 * have to jump through a few hoops before reading and/or writing them.
303 sec_size_to_words (size_t length)
305 return (length % sizeof (void*) ? 1 : 0) + (length / sizeof (void*));
309 sec_write_guards (Cell *cell)
312 VALGRIND_MAKE_MEM_UNDEFINED (cell->words, sizeof (word_t));
313 VALGRIND_MAKE_MEM_UNDEFINED (cell->words + cell->n_words - 1, sizeof (word_t));
316 ((void**)cell->words)[0] = (void*)cell;
317 ((void**)cell->words)[cell->n_words - 1] = (void*)cell;
320 VALGRIND_MAKE_MEM_NOACCESS (cell->words, sizeof (word_t));
321 VALGRIND_MAKE_MEM_NOACCESS (cell->words + cell->n_words - 1, sizeof (word_t));
326 sec_check_guards (Cell *cell)
329 VALGRIND_MAKE_MEM_DEFINED (cell->words, sizeof (word_t));
330 VALGRIND_MAKE_MEM_DEFINED (cell->words + cell->n_words - 1, sizeof (word_t));
333 ASSERT(((void**)cell->words)[0] == (void*)cell);
334 ASSERT(((void**)cell->words)[cell->n_words - 1] == (void*)cell);
337 VALGRIND_MAKE_MEM_NOACCESS (cell->words, sizeof (word_t));
338 VALGRIND_MAKE_MEM_NOACCESS (cell->words + cell->n_words - 1, sizeof (word_t));
343 sec_insert_cell_ring (Cell **ring, Cell *cell)
347 ASSERT (cell != *ring);
348 ASSERT (cell->next == NULL);
349 ASSERT (cell->prev == NULL);
351 /* Insert back into the mix of available memory */
353 cell->next = (*ring)->next;
355 cell->next->prev = cell;
356 cell->prev->next = cell;
363 ASSERT (cell->next->prev == cell);
364 ASSERT (cell->prev->next == cell);
368 sec_remove_cell_ring (Cell **ring, Cell *cell)
375 ASSERT (cell->next->prev == cell);
376 ASSERT (cell->prev->next == cell);
380 if (cell->next == cell) {
381 ASSERT (cell->prev == cell);
384 /* Just pointing to this meta */
386 ASSERT (cell->prev != cell);
391 cell->next->prev = cell->prev;
392 cell->prev->next = cell->next;
393 cell->next = cell->prev = NULL;
395 ASSERT (*ring != cell);
399 sec_cell_to_memory (Cell *cell)
401 return cell->words + 1;
405 sec_is_valid_word (Block *block, word_t *word)
407 return (word >= block->words && word < block->words + block->n_words);
411 sec_clear_undefined (void *memory,
418 VALGRIND_MAKE_MEM_UNDEFINED (ptr + from, to - from);
420 memset (ptr + from, 0, to - from);
422 VALGRIND_MAKE_MEM_UNDEFINED (ptr + from, to - from);
426 sec_clear_noaccess (void *memory, size_t from, size_t to)
431 VALGRIND_MAKE_MEM_UNDEFINED (ptr + from, to - from);
433 memset (ptr + from, 0, to - from);
435 VALGRIND_MAKE_MEM_NOACCESS (ptr + from, to - from);
440 sec_neighbor_before (Block *block, Cell *cell)
447 word = cell->words - 1;
448 if (!sec_is_valid_word (block, word))
452 VALGRIND_MAKE_MEM_DEFINED (word, sizeof (word_t));
456 sec_check_guards (cell);
459 VALGRIND_MAKE_MEM_NOACCESS (word, sizeof (word_t));
466 sec_neighbor_after (Block *block, Cell *cell)
473 word = cell->words + cell->n_words;
474 if (!sec_is_valid_word (block, word))
478 VALGRIND_MAKE_MEM_DEFINED (word, sizeof (word_t));
482 sec_check_guards (cell);
485 VALGRIND_MAKE_MEM_NOACCESS (word, sizeof (word_t));
492 sec_alloc (Block *block,
504 if (!block->unused_cells)
508 * Each memory allocation is aligned to a pointer size, and
509 * then, sandwidched between two pointers to its meta data.
510 * These pointers also act as guards.
512 * We allocate memory in units of sizeof (void*)
515 n_words = sec_size_to_words (length) + 2;
517 /* Look for a cell of at least our required size */
518 cell = block->unused_cells;
519 while (cell->n_words < n_words) {
521 if (cell == block->unused_cells) {
530 ASSERT (cell->tag == NULL);
531 ASSERT (cell->requested == 0);
533 ASSERT (cell->words);
534 sec_check_guards (cell);
536 /* Steal from the cell if it's too long */
537 if (cell->n_words > n_words + WASTE) {
538 other = pool_alloc ();
541 other->n_words = n_words;
542 other->words = cell->words;
543 cell->n_words -= n_words;
544 cell->words += n_words;
546 sec_write_guards (other);
547 sec_write_guards (cell);
553 sec_remove_cell_ring (&block->unused_cells, cell);
557 cell->requested = length;
558 sec_insert_cell_ring (&block->used_cells, cell);
559 memory = sec_cell_to_memory (cell);
562 VALGRIND_MAKE_MEM_UNDEFINED (memory, length);
565 return memset (memory, 0, length);
569 sec_free (Block *block, void *memory)
581 VALGRIND_MAKE_MEM_DEFINED (word, sizeof (word_t));
584 /* Lookup the meta for this memory block (using guard pointer) */
585 ASSERT (sec_is_valid_word (block, word));
586 ASSERT (pool_valid (*word));
590 VALGRIND_MAKE_MEM_DEFINED (cell->words, cell->n_words * sizeof (word_t));
593 sec_check_guards (cell);
594 sec_clear_noaccess (memory, 0, cell->requested);
596 sec_check_guards (cell);
597 ASSERT (cell->requested > 0);
598 ASSERT (cell->tag != NULL);
600 /* Remove from the used cell ring */
601 sec_remove_cell_ring (&block->used_cells, cell);
603 /* Find previous unallocated neighbor, and merge if possible */
604 other = sec_neighbor_before (block, cell);
605 if (other && other->requested == 0) {
606 ASSERT (other->tag == NULL);
607 ASSERT (other->next && other->prev);
608 other->n_words += cell->n_words;
609 sec_write_guards (other);
614 /* Find next unallocated neighbor, and merge if possible */
615 other = sec_neighbor_after (block, cell);
616 if (other && other->requested == 0) {
617 ASSERT (other->tag == NULL);
618 ASSERT (other->next && other->prev);
619 other->n_words += cell->n_words;
620 other->words = cell->words;
622 sec_remove_cell_ring (&block->unused_cells, cell);
623 sec_write_guards (other);
628 /* Add to the unused list if not already there */
630 sec_insert_cell_ring (&block->unused_cells, cell);
639 memcpy_with_vbits (void *dest,
647 if (RUNNING_ON_VALGRIND) {
648 vbits = malloc (length);
650 vbits_setup = VALGRIND_GET_VBITS (src, vbits, length);
651 VALGRIND_MAKE_MEM_DEFINED (src, length);
655 memcpy (dest, src, length);
658 if (vbits_setup == 1) {
659 VALGRIND_SET_VBITS (dest, vbits, length);
660 VALGRIND_SET_VBITS (src, vbits, length);
667 sec_realloc (Block *block,
678 /* Standard realloc behavior, should have been handled elsewhere */
679 ASSERT (memory != NULL);
681 ASSERT (tag != NULL);
683 /* Dig out where the meta should be */
688 VALGRIND_MAKE_MEM_DEFINED (word, sizeof (word_t));
691 ASSERT (sec_is_valid_word (block, word));
692 ASSERT (pool_valid (*word));
695 /* Validate that it's actually for real */
696 sec_check_guards (cell);
697 ASSERT (cell->requested > 0);
698 ASSERT (cell->tag != NULL);
700 /* The amount of valid data */
701 valid = cell->requested;
703 /* How many words we actually want */
704 n_words = sec_size_to_words (length) + 2;
706 /* Less memory is required than is in the cell */
707 if (n_words <= cell->n_words) {
709 /* TODO: No shrinking behavior yet */
710 cell->requested = length;
711 alloc = sec_cell_to_memory (cell);
714 * Even though we may be reusing the same cell, that doesn't
715 * mean that the allocation is shrinking. It could have shrunk
716 * and is now expanding back some.
719 sec_clear_undefined (alloc, length, valid);
724 /* Need braaaaaiiiiiinsss... */
725 while (cell->n_words < n_words) {
727 /* See if we have a neighbor who can give us some memory */
728 other = sec_neighbor_after (block, cell);
729 if (!other || other->requested != 0)
732 /* Eat the whole neighbor if not too big */
733 if (n_words - cell->n_words + WASTE >= other->n_words) {
734 cell->n_words += other->n_words;
735 sec_write_guards (cell);
736 sec_remove_cell_ring (&block->unused_cells, other);
739 /* Steal from the neighbor */
741 other->words += n_words - cell->n_words;
742 other->n_words -= n_words - cell->n_words;
743 sec_write_guards (other);
744 cell->n_words = n_words;
745 sec_write_guards (cell);
749 if (cell->n_words >= n_words) {
750 cell->requested = length;
752 alloc = sec_cell_to_memory (cell);
753 sec_clear_undefined (alloc, valid, length);
757 /* That didn't work, try alloc/free */
758 alloc = sec_alloc (block, tag, length);
760 memcpy_with_vbits (alloc, memory, valid);
761 sec_free (block, memory);
769 sec_allocated (Block *block, void *memory)
781 VALGRIND_MAKE_MEM_DEFINED (word, sizeof (word_t));
784 /* Lookup the meta for this memory block (using guard pointer) */
785 ASSERT (sec_is_valid_word (block, word));
786 ASSERT (pool_valid (*word));
789 sec_check_guards (cell);
790 ASSERT (cell->requested > 0);
791 ASSERT (cell->tag != NULL);
794 VALGRIND_MAKE_MEM_NOACCESS (word, sizeof (word_t));
797 return cell->requested;
801 sec_validate (Block *block)
807 if (RUNNING_ON_VALGRIND)
812 last = word + block->n_words;
815 ASSERT (word < last);
817 ASSERT (sec_is_valid_word (block, word));
818 ASSERT (pool_valid (*word));
821 /* Validate that it's actually for real */
822 sec_check_guards (cell);
824 /* Is it an allocated block? */
825 if (cell->requested > 0) {
826 ASSERT (cell->tag != NULL);
827 ASSERT (cell->next != NULL);
828 ASSERT (cell->prev != NULL);
829 ASSERT (cell->next->prev == cell);
830 ASSERT (cell->prev->next == cell);
831 ASSERT (cell->requested <= (cell->n_words - 2) * sizeof (word_t));
833 /* An unused block */
835 ASSERT (cell->tag == NULL);
836 ASSERT (cell->next != NULL);
837 ASSERT (cell->prev != NULL);
838 ASSERT (cell->next->prev == cell);
839 ASSERT (cell->prev->next == cell);
842 word += cell->n_words;
848 /* -----------------------------------------------------------------------------
853 sec_acquire_pages (size_t *sz,
854 const char *during_tag)
857 unsigned long pgsize;
863 /* Make sure sz is a multiple of the page size */
864 pgsize = getpagesize ();
865 *sz = (*sz + pgsize -1) & ~(pgsize - 1);
867 #if defined(HAVE_MLOCK)
868 pages = mmap (0, *sz, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
869 if (pages == MAP_FAILED) {
870 if (show_warning && egg_secure_warnings)
871 fprintf (stderr, "couldn't map %lu bytes of memory (%s): %s\n",
872 (unsigned long)*sz, during_tag, strerror (errno));
877 if (mlock (pages, *sz) < 0) {
878 if (show_warning && egg_secure_warnings && errno != EPERM) {
879 fprintf (stderr, "couldn't lock %lu bytes of memory (%s): %s\n",
880 (unsigned long)*sz, during_tag, strerror (errno));
887 DEBUG_ALLOC ("gkr-secure-memory: new block ", *sz);
893 if (show_warning && egg_secure_warnings)
894 fprintf (stderr, "your system does not support private memory");
902 sec_release_pages (void *pages, size_t sz)
905 ASSERT (sz % getpagesize () == 0);
907 #if defined(HAVE_MLOCK)
908 if (munlock (pages, sz) < 0 && egg_secure_warnings)
909 fprintf (stderr, "couldn't unlock private memory: %s\n", strerror (errno));
911 if (munmap (pages, sz) < 0 && egg_secure_warnings)
912 fprintf (stderr, "couldn't unmap private anonymous memory: %s\n", strerror (errno));
914 DEBUG_ALLOC ("gkr-secure-memory: freed block ", sz);
921 /* -----------------------------------------------------------------------------
922 * MANAGE DIFFERENT BLOCKS
925 static Block *all_blocks = NULL;
928 sec_block_create (size_t size,
929 const char *during_tag)
936 /* We can force all all memory to be malloced */
937 if (getenv ("SECMEM_FORCE_FALLBACK"))
940 block = pool_alloc ();
944 cell = pool_alloc ();
950 /* The size above is a minimum, we're free to go bigger */
951 if (size < DEFAULT_BLOCK_SIZE)
952 size = DEFAULT_BLOCK_SIZE;
954 block->words = sec_acquire_pages (&size, during_tag);
955 block->n_words = size / sizeof (word_t);
963 VALGRIND_MAKE_MEM_DEFINED (block->words, size);
966 /* The first cell to allocate from */
967 cell->words = block->words;
968 cell->n_words = block->n_words;
970 sec_write_guards (cell);
971 sec_insert_cell_ring (&block->unused_cells, cell);
973 block->next = all_blocks;
980 sec_block_destroy (Block *block)
986 ASSERT (block->words);
987 ASSERT (block->n_used == 0);
989 /* Remove from the list */
990 for (at = &all_blocks, bl = *at; bl; at = &bl->next, bl = *at) {
997 /* Must have been found */
998 ASSERT (bl == block);
999 ASSERT (block->used_cells == NULL);
1001 /* Release all the meta data cells */
1002 while (block->unused_cells) {
1003 cell = block->unused_cells;
1004 sec_remove_cell_ring (&block->unused_cells, cell);
1008 /* Release all pages of secure memory */
1009 sec_release_pages (block->words, block->n_words * sizeof (word_t));
1014 /* ------------------------------------------------------------------------
1015 * PUBLIC FUNCTIONALITY
1019 egg_secure_alloc_full (const char *tag,
1024 void *memory = NULL;
1029 if (length > 0xFFFFFFFF / 2) {
1030 if (egg_secure_warnings)
1031 fprintf (stderr, "tried to allocate an insane amount of memory: %lu\n",
1032 (unsigned long)length);
1036 /* Can't allocate zero bytes */
1042 for (block = all_blocks; block; block = block->next) {
1043 memory = sec_alloc (block, tag, length);
1048 /* None of the current blocks have space, allocate new */
1050 block = sec_block_create (length, tag);
1052 memory = sec_alloc (block, tag, length);
1055 #ifdef WITH_VALGRIND
1057 VALGRIND_MALLOCLIKE_BLOCK (memory, length, sizeof (void*), 1);
1062 if (!memory && (flags & EGG_SECURE_USE_FALLBACK) && EGG_SECURE_GLOBALS.fallback != NULL) {
1063 memory = EGG_SECURE_GLOBALS.fallback (NULL, length);
1064 if (memory) /* Our returned memory is always zeroed */
1065 memset (memory, 0, length);
1075 egg_secure_realloc_full (const char *tag,
1080 Block *block = NULL;
1081 size_t previous = 0;
1088 if (length > 0xFFFFFFFF / 2) {
1089 if (egg_secure_warnings)
1090 fprintf (stderr, "tried to allocate an insane amount of memory: %lu\n",
1091 (unsigned long)length);
1096 return egg_secure_alloc_full (tag, length, flags);
1098 egg_secure_free_full (memory, flags);
1104 /* Find out where it belongs to */
1105 for (block = all_blocks; block; block = block->next) {
1106 if (sec_is_valid_word (block, memory)) {
1107 previous = sec_allocated (block, memory);
1109 #ifdef WITH_VALGRIND
1110 /* Let valgrind think we are unallocating so that it'll validate */
1111 VALGRIND_FREELIKE_BLOCK (memory, sizeof (word_t));
1114 alloc = sec_realloc (block, tag, memory, length);
1116 #ifdef WITH_VALGRIND
1117 /* Now tell valgrind about either the new block or old one */
1118 VALGRIND_MALLOCLIKE_BLOCK (alloc ? alloc : memory,
1119 alloc ? length : previous,
1120 sizeof (word_t), 1);
1126 /* If it didn't work we may need to allocate a new block */
1127 if (block && !alloc)
1130 if (block && block->n_used == 0)
1131 sec_block_destroy (block);
1136 if ((flags & EGG_SECURE_USE_FALLBACK) && EGG_SECURE_GLOBALS.fallback) {
1138 * In this case we can't zero the returned memory,
1139 * because we don't know what the block size was.
1141 return EGG_SECURE_GLOBALS.fallback (memory, length);
1143 if (egg_secure_warnings)
1144 fprintf (stderr, "memory does not belong to secure memory pool: 0x%08lx\n",
1145 (unsigned long)memory);
1146 ASSERT (0 && "memory does does not belong to secure memory pool");
1152 alloc = egg_secure_alloc_full (tag, length, flags);
1154 memcpy_with_vbits (alloc, memory, previous);
1155 egg_secure_free_full (memory, flags);
1166 egg_secure_free (void *memory)
1168 egg_secure_free_full (memory, EGG_SECURE_USE_FALLBACK);
1172 egg_secure_free_full (void *memory, int flags)
1174 Block *block = NULL;
1181 /* Find out where it belongs to */
1182 for (block = all_blocks; block; block = block->next) {
1183 if (sec_is_valid_word (block, memory))
1187 #ifdef WITH_VALGRIND
1188 /* We like valgrind's warnings, so give it a first whack at checking for errors */
1189 if (block != NULL || !(flags & EGG_SECURE_USE_FALLBACK))
1190 VALGRIND_FREELIKE_BLOCK (memory, sizeof (word_t));
1193 if (block != NULL) {
1194 sec_free (block, memory);
1195 if (block->n_used == 0)
1196 sec_block_destroy (block);
1202 if ((flags & EGG_SECURE_USE_FALLBACK) && EGG_SECURE_GLOBALS.fallback) {
1203 EGG_SECURE_GLOBALS.fallback (memory, 0);
1205 if (egg_secure_warnings)
1206 fprintf (stderr, "memory does not belong to secure memory pool: 0x%08lx\n",
1207 (unsigned long)memory);
1208 ASSERT (0 && "memory does does not belong to secure memory pool");
1214 egg_secure_check (const void *memory)
1216 Block *block = NULL;
1220 /* Find out where it belongs to */
1221 for (block = all_blocks; block; block = block->next) {
1222 if (sec_is_valid_word (block, (word_t*)memory))
1228 return block == NULL ? 0 : 1;
1232 egg_secure_validate (void)
1234 Block *block = NULL;
1238 for (block = all_blocks; block; block = block->next)
1239 sec_validate (block);
1245 static egg_secure_rec *
1246 records_for_ring (Cell *cell_ring,
1247 egg_secure_rec *records,
1248 unsigned int *count,
1249 unsigned int *total)
1251 egg_secure_rec *new_rec;
1252 unsigned int allocated = *count;
1257 if (*count >= allocated) {
1258 new_rec = realloc (records, sizeof (egg_secure_rec) * (allocated + 32));
1259 if (new_rec == NULL) {
1270 records[*count].request_length = cell->requested;
1271 records[*count].block_length = cell->n_words * sizeof (word_t);
1272 records[*count].tag = cell->tag;
1274 (*total) += cell->n_words;
1277 } while (cell != NULL && cell != cell_ring);
1283 egg_secure_records (unsigned int *count)
1285 egg_secure_rec *records = NULL;
1286 Block *block = NULL;
1293 for (block = all_blocks; block != NULL; block = block->next) {
1296 records = records_for_ring (block->unused_cells, records, count, &total);
1297 if (records == NULL)
1299 records = records_for_ring (block->used_cells, records, count, &total);
1300 if (records == NULL)
1303 /* Make sure this actualy accounts for all memory */
1304 ASSERT (total == block->n_words);
1313 egg_secure_strdup_full (const char *tag,
1323 len = strlen (str) + 1;
1324 res = (char *)egg_secure_alloc_full (tag, len, options);
1330 egg_secure_strndup_full (const char *tag,
1342 end = memchr (str, '\0', length);
1344 length = (end - str);
1346 res = (char *)egg_secure_alloc_full (tag, len, options);
1347 memcpy (res, str, len);
1352 egg_secure_clear (void *p, size_t length)
1359 vp = (volatile char*)p;
1368 egg_secure_strclear (char *str)
1372 egg_secure_clear ((unsigned char*)str, strlen (str));
1376 egg_secure_strfree (char *str)
1379 * If we're using unpageable 'secure' memory, then the free call
1380 * should zero out the memory, but because on certain platforms
1381 * we may be using normal memory, zero it out here just in case.
1384 egg_secure_strclear (str);
1385 egg_secure_free_full (str, EGG_SECURE_USE_FALLBACK);