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)
74 static int lock_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 */
166 static Pool *all_pools = NULL;
175 /* A pool with an available item */
176 for (pool = all_pools; pool; pool = pool->next) {
177 if (unused_peek (&pool->unused))
181 /* Create a new pool */
183 len = getpagesize () * 2;
184 pages = mmap (0, len, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
185 if (pages == MAP_FAILED)
188 /* Fill in the block header, and inlude in block list */
190 pool->next = all_pools;
196 /* Fill block with unused items */
197 pool->n_items = (len - sizeof (Pool)) / sizeof (Item);
198 for (i = 0; i < pool->n_items; ++i)
199 unused_push (&pool->unused, pool->items + i);
202 VALGRIND_CREATE_MEMPOOL(pool, 0, 0);
207 ASSERT (unused_peek (&pool->unused));
208 item = unused_pop (&pool->unused);
211 VALGRIND_MEMPOOL_ALLOC (pool, item, sizeof (Item));
214 return memset (item, 0, sizeof (Item));
218 pool_free (void* item)
221 char *ptr, *beg, *end;
225 /* Find which block this one belongs to */
226 for (at = &all_pools, pool = *at; pool; at = &pool->next, pool = *at) {
227 beg = (char*)pool->items;
228 end = (char*)pool + pool->length - sizeof (Item);
229 if (ptr >= beg && ptr <= end) {
230 ASSERT ((ptr - beg) % sizeof (Item) == 0);
235 /* Otherwise invalid meta */
238 ASSERT (pool->used > 0);
240 /* No more meta cells used in this block, remove from list, destroy */
241 if (pool->used == 1) {
245 VALGRIND_DESTROY_MEMPOOL (pool);
248 munmap (pool, pool->length);
253 VALGRIND_MEMPOOL_FREE (pool, item);
254 VALGRIND_MAKE_MEM_UNDEFINED (item, sizeof (Item));
258 memset (item, 0xCD, sizeof (Item));
259 unused_push (&pool->unused, item);
262 #ifndef G_DISABLE_ASSERT
265 pool_valid (void* item)
268 char *ptr, *beg, *end;
272 /* Find which block this one belongs to */
273 for (pool = all_pools; pool; pool = pool->next) {
274 beg = (char*)pool->items;
275 end = (char*)pool + pool->length - sizeof (Item);
276 if (ptr >= beg && ptr <= end)
277 return (pool->used && (ptr - beg) % sizeof (Item) == 0);
283 #endif /* G_DISABLE_ASSERT */
285 /* -----------------------------------------------------------------------------
288 * Each memory cell begins and ends with a pointer to its metadata. These are also
289 * used as guards or red zones. Since they're treated as redzones by valgrind we
290 * have to jump through a few hoops before reading and/or writing them.
294 sec_size_to_words (size_t length)
296 return (length % sizeof (void*) ? 1 : 0) + (length / sizeof (void*));
300 sec_write_guards (Cell *cell)
303 VALGRIND_MAKE_MEM_UNDEFINED (cell->words, sizeof (word_t));
304 VALGRIND_MAKE_MEM_UNDEFINED (cell->words + cell->n_words - 1, sizeof (word_t));
307 ((void**)cell->words)[0] = (void*)cell;
308 ((void**)cell->words)[cell->n_words - 1] = (void*)cell;
311 VALGRIND_MAKE_MEM_NOACCESS (cell->words, sizeof (word_t));
312 VALGRIND_MAKE_MEM_NOACCESS (cell->words + cell->n_words - 1, sizeof (word_t));
317 sec_check_guards (Cell *cell)
320 VALGRIND_MAKE_MEM_DEFINED (cell->words, sizeof (word_t));
321 VALGRIND_MAKE_MEM_DEFINED (cell->words + cell->n_words - 1, sizeof (word_t));
324 ASSERT(((void**)cell->words)[0] == (void*)cell);
325 ASSERT(((void**)cell->words)[cell->n_words - 1] == (void*)cell);
328 VALGRIND_MAKE_MEM_NOACCESS (cell->words, sizeof (word_t));
329 VALGRIND_MAKE_MEM_NOACCESS (cell->words + cell->n_words - 1, sizeof (word_t));
334 sec_insert_cell_ring (Cell **ring, Cell *cell)
338 ASSERT (cell != *ring);
339 ASSERT (cell->next == NULL);
340 ASSERT (cell->prev == NULL);
342 /* Insert back into the mix of available memory */
344 cell->next = (*ring)->next;
346 cell->next->prev = cell;
347 cell->prev->next = cell;
354 ASSERT (cell->next->prev == cell);
355 ASSERT (cell->prev->next == cell);
359 sec_remove_cell_ring (Cell **ring, Cell *cell)
366 ASSERT (cell->next->prev == cell);
367 ASSERT (cell->prev->next == cell);
371 if (cell->next == cell) {
372 ASSERT (cell->prev == cell);
375 /* Just pointing to this meta */
377 ASSERT (cell->prev != cell);
382 cell->next->prev = cell->prev;
383 cell->prev->next = cell->next;
384 cell->next = cell->prev = NULL;
386 ASSERT (*ring != cell);
390 sec_cell_to_memory (Cell *cell)
392 return cell->words + 1;
396 sec_is_valid_word (Block *block, word_t *word)
398 return (word >= block->words && word < block->words + block->n_words);
402 sec_clear_undefined (void *memory,
409 VALGRIND_MAKE_MEM_UNDEFINED (ptr + from, to - from);
411 memset (ptr + from, 0, to - from);
413 VALGRIND_MAKE_MEM_UNDEFINED (ptr + from, to - from);
417 sec_clear_noaccess (void *memory, size_t from, size_t to)
422 VALGRIND_MAKE_MEM_UNDEFINED (ptr + from, to - from);
424 memset (ptr + from, 0, to - from);
426 VALGRIND_MAKE_MEM_NOACCESS (ptr + from, to - from);
431 sec_neighbor_before (Block *block, Cell *cell)
438 word = cell->words - 1;
439 if (!sec_is_valid_word (block, word))
443 VALGRIND_MAKE_MEM_DEFINED (word, sizeof (word_t));
447 sec_check_guards (cell);
450 VALGRIND_MAKE_MEM_NOACCESS (word, sizeof (word_t));
457 sec_neighbor_after (Block *block, Cell *cell)
464 word = cell->words + cell->n_words;
465 if (!sec_is_valid_word (block, word))
469 VALGRIND_MAKE_MEM_DEFINED (word, sizeof (word_t));
473 sec_check_guards (cell);
476 VALGRIND_MAKE_MEM_NOACCESS (word, sizeof (word_t));
483 sec_alloc (Block *block,
495 if (!block->unused_cells)
499 * Each memory allocation is aligned to a pointer size, and
500 * then, sandwidched between two pointers to its meta data.
501 * These pointers also act as guards.
503 * We allocate memory in units of sizeof (void*)
506 n_words = sec_size_to_words (length) + 2;
508 /* Look for a cell of at least our required size */
509 cell = block->unused_cells;
510 while (cell->n_words < n_words) {
512 if (cell == block->unused_cells) {
521 ASSERT (cell->tag == NULL);
522 ASSERT (cell->requested == 0);
524 ASSERT (cell->words);
525 sec_check_guards (cell);
527 /* Steal from the cell if it's too long */
528 if (cell->n_words > n_words + WASTE) {
529 other = pool_alloc ();
532 other->n_words = n_words;
533 other->words = cell->words;
534 cell->n_words -= n_words;
535 cell->words += n_words;
537 sec_write_guards (other);
538 sec_write_guards (cell);
544 sec_remove_cell_ring (&block->unused_cells, cell);
548 cell->requested = length;
549 sec_insert_cell_ring (&block->used_cells, cell);
550 memory = sec_cell_to_memory (cell);
553 VALGRIND_MAKE_MEM_UNDEFINED (memory, length);
556 return memset (memory, 0, length);
560 sec_free (Block *block, void *memory)
572 VALGRIND_MAKE_MEM_DEFINED (word, sizeof (word_t));
575 /* Lookup the meta for this memory block (using guard pointer) */
576 ASSERT (sec_is_valid_word (block, word));
577 ASSERT (pool_valid (*word));
581 VALGRIND_MAKE_MEM_DEFINED (cell->words, cell->n_words * sizeof (word_t));
584 sec_check_guards (cell);
585 sec_clear_noaccess (memory, 0, cell->requested);
587 sec_check_guards (cell);
588 ASSERT (cell->requested > 0);
589 ASSERT (cell->tag != NULL);
591 /* Remove from the used cell ring */
592 sec_remove_cell_ring (&block->used_cells, cell);
594 /* Find previous unallocated neighbor, and merge if possible */
595 other = sec_neighbor_before (block, cell);
596 if (other && other->requested == 0) {
597 ASSERT (other->tag == NULL);
598 ASSERT (other->next && other->prev);
599 other->n_words += cell->n_words;
600 sec_write_guards (other);
605 /* Find next unallocated neighbor, and merge if possible */
606 other = sec_neighbor_after (block, cell);
607 if (other && other->requested == 0) {
608 ASSERT (other->tag == NULL);
609 ASSERT (other->next && other->prev);
610 other->n_words += cell->n_words;
611 other->words = cell->words;
613 sec_remove_cell_ring (&block->unused_cells, cell);
614 sec_write_guards (other);
619 /* Add to the unused list if not already there */
621 sec_insert_cell_ring (&block->unused_cells, cell);
630 memcpy_with_vbits (void *dest,
638 if (RUNNING_ON_VALGRIND) {
639 vbits = malloc (length);
641 vbits_setup = VALGRIND_GET_VBITS (src, vbits, length);
642 VALGRIND_MAKE_MEM_DEFINED (src, length);
646 memcpy (dest, src, length);
649 if (vbits_setup == 1) {
650 VALGRIND_SET_VBITS (dest, vbits, length);
651 VALGRIND_SET_VBITS (src, vbits, length);
658 sec_realloc (Block *block,
669 /* Standard realloc behavior, should have been handled elsewhere */
670 ASSERT (memory != NULL);
672 ASSERT (tag != NULL);
674 /* Dig out where the meta should be */
679 VALGRIND_MAKE_MEM_DEFINED (word, sizeof (word_t));
682 ASSERT (sec_is_valid_word (block, word));
683 ASSERT (pool_valid (*word));
686 /* Validate that it's actually for real */
687 sec_check_guards (cell);
688 ASSERT (cell->requested > 0);
689 ASSERT (cell->tag != NULL);
691 /* The amount of valid data */
692 valid = cell->requested;
694 /* How many words we actually want */
695 n_words = sec_size_to_words (length) + 2;
697 /* Less memory is required than is in the cell */
698 if (n_words <= cell->n_words) {
700 /* TODO: No shrinking behavior yet */
701 cell->requested = length;
702 alloc = sec_cell_to_memory (cell);
705 * Even though we may be reusing the same cell, that doesn't
706 * mean that the allocation is shrinking. It could have shrunk
707 * and is now expanding back some.
710 sec_clear_undefined (alloc, length, valid);
715 /* Need braaaaaiiiiiinsss... */
716 while (cell->n_words < n_words) {
718 /* See if we have a neighbor who can give us some memory */
719 other = sec_neighbor_after (block, cell);
720 if (!other || other->requested != 0)
723 /* Eat the whole neighbor if not too big */
724 if (n_words - cell->n_words + WASTE >= other->n_words) {
725 cell->n_words += other->n_words;
726 sec_write_guards (cell);
727 sec_remove_cell_ring (&block->unused_cells, other);
730 /* Steal from the neighbor */
732 other->words += n_words - cell->n_words;
733 other->n_words -= n_words - cell->n_words;
734 sec_write_guards (other);
735 cell->n_words = n_words;
736 sec_write_guards (cell);
740 if (cell->n_words >= n_words) {
741 cell->requested = length;
743 alloc = sec_cell_to_memory (cell);
744 sec_clear_undefined (alloc, valid, length);
748 /* That didn't work, try alloc/free */
749 alloc = sec_alloc (block, tag, length);
751 memcpy_with_vbits (alloc, memory, valid);
752 sec_free (block, memory);
760 sec_allocated (Block *block, void *memory)
772 VALGRIND_MAKE_MEM_DEFINED (word, sizeof (word_t));
775 /* Lookup the meta for this memory block (using guard pointer) */
776 ASSERT (sec_is_valid_word (block, word));
777 ASSERT (pool_valid (*word));
780 sec_check_guards (cell);
781 ASSERT (cell->requested > 0);
782 ASSERT (cell->tag != NULL);
785 VALGRIND_MAKE_MEM_NOACCESS (word, sizeof (word_t));
788 return cell->requested;
792 sec_validate (Block *block)
797 if (RUNNING_ON_VALGRIND)
801 last = word + block->n_words;
804 ASSERT (word < last);
806 ASSERT (sec_is_valid_word (block, word));
807 ASSERT (pool_valid (*word));
810 /* Validate that it's actually for real */
811 sec_check_guards (cell);
813 /* Is it an allocated block? */
814 if (cell->requested > 0) {
815 ASSERT (cell->tag != NULL);
816 ASSERT (cell->next != NULL);
817 ASSERT (cell->prev != NULL);
818 ASSERT (cell->next->prev == cell);
819 ASSERT (cell->prev->next == cell);
820 ASSERT (cell->requested <= (cell->n_words - 2) * sizeof (word_t));
822 /* An unused block */
824 ASSERT (cell->tag == NULL);
825 ASSERT (cell->next != NULL);
826 ASSERT (cell->prev != NULL);
827 ASSERT (cell->next->prev == cell);
828 ASSERT (cell->prev->next == cell);
831 word += cell->n_words;
837 /* -----------------------------------------------------------------------------
842 sec_acquire_pages (size_t *sz,
843 const char *during_tag)
846 unsigned long pgsize;
852 /* Make sure sz is a multiple of the page size */
853 pgsize = getpagesize ();
854 *sz = (*sz + pgsize -1) & ~(pgsize - 1);
856 #if defined(HAVE_MLOCK)
857 pages = mmap (0, *sz, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
858 if (pages == MAP_FAILED) {
859 if (lock_warning && egg_secure_warnings)
860 fprintf (stderr, "couldn't map %lu bytes of memory (%s): %s\n",
861 (unsigned long)*sz, during_tag, strerror (errno));
866 if (mlock (pages, *sz) < 0) {
867 if (lock_warning && egg_secure_warnings && errno != EPERM) {
868 fprintf (stderr, "couldn't lock %lu bytes of memory (%s): %s\n",
869 (unsigned long)*sz, during_tag, strerror (errno));
876 DEBUG_ALLOC ("gkr-secure-memory: new block ", *sz);
882 if (lock_warning && egg_secure_warnings)
883 fprintf (stderr, "your system does not support private memory");
891 sec_release_pages (void *pages, size_t sz)
894 ASSERT (sz % getpagesize () == 0);
896 #if defined(HAVE_MLOCK)
897 if (munlock (pages, sz) < 0 && egg_secure_warnings)
898 fprintf (stderr, "couldn't unlock private memory: %s\n", strerror (errno));
900 if (munmap (pages, sz) < 0 && egg_secure_warnings)
901 fprintf (stderr, "couldn't unmap private anonymous memory: %s\n", strerror (errno));
903 DEBUG_ALLOC ("gkr-secure-memory: freed block ", sz);
910 /* -----------------------------------------------------------------------------
911 * MANAGE DIFFERENT BLOCKS
914 static Block *all_blocks = NULL;
917 sec_block_create (size_t size,
918 const char *during_tag)
925 /* We can force all all memory to be malloced */
926 if (getenv ("SECMEM_FORCE_FALLBACK"))
929 block = pool_alloc ();
933 cell = pool_alloc ();
939 /* The size above is a minimum, we're free to go bigger */
940 if (size < DEFAULT_BLOCK_SIZE)
941 size = DEFAULT_BLOCK_SIZE;
943 block->words = sec_acquire_pages (&size, during_tag);
944 block->n_words = size / sizeof (word_t);
952 VALGRIND_MAKE_MEM_DEFINED (block->words, size);
955 /* The first cell to allocate from */
956 cell->words = block->words;
957 cell->n_words = block->n_words;
959 sec_write_guards (cell);
960 sec_insert_cell_ring (&block->unused_cells, cell);
962 block->next = all_blocks;
969 sec_block_destroy (Block *block)
975 ASSERT (block->words);
976 ASSERT (block->n_used == 0);
978 /* Remove from the list */
979 for (at = &all_blocks, bl = *at; bl; at = &bl->next, bl = *at) {
986 /* Must have been found */
987 ASSERT (bl == block);
988 ASSERT (block->used_cells == NULL);
990 /* Release all the meta data cells */
991 while (block->unused_cells) {
992 cell = block->unused_cells;
993 sec_remove_cell_ring (&block->unused_cells, cell);
997 /* Release all pages of secure memory */
998 sec_release_pages (block->words, block->n_words * sizeof (word_t));
1003 /* ------------------------------------------------------------------------
1004 * PUBLIC FUNCTIONALITY
1008 egg_secure_alloc_full (const char *tag,
1013 void *memory = NULL;
1018 if (length > 0xFFFFFFFF / 2) {
1019 if (egg_secure_warnings)
1020 fprintf (stderr, "tried to allocate an insane amount of memory: %lu\n",
1021 (unsigned long)length);
1025 /* Can't allocate zero bytes */
1031 for (block = all_blocks; block; block = block->next) {
1032 memory = sec_alloc (block, tag, length);
1037 /* None of the current blocks have space, allocate new */
1039 block = sec_block_create (length, tag);
1041 memory = sec_alloc (block, tag, length);
1044 #ifdef WITH_VALGRIND
1046 VALGRIND_MALLOCLIKE_BLOCK (memory, length, sizeof (void*), 1);
1051 if (!memory && (flags & EGG_SECURE_USE_FALLBACK)) {
1052 memory = egg_memory_fallback (NULL, length);
1053 if (memory) /* Our returned memory is always zeroed */
1054 memset (memory, 0, length);
1064 egg_secure_realloc_full (const char *tag,
1069 Block *block = NULL;
1070 size_t previous = 0;
1077 if (length > 0xFFFFFFFF / 2) {
1078 if (egg_secure_warnings)
1079 fprintf (stderr, "tried to allocate an insane amount of memory: %lu\n",
1080 (unsigned long)length);
1085 return egg_secure_alloc_full (tag, length, flags);
1087 egg_secure_free_full (memory, flags);
1093 /* Find out where it belongs to */
1094 for (block = all_blocks; block; block = block->next) {
1095 if (sec_is_valid_word (block, memory)) {
1096 previous = sec_allocated (block, memory);
1098 #ifdef WITH_VALGRIND
1099 /* Let valgrind think we are unallocating so that it'll validate */
1100 VALGRIND_FREELIKE_BLOCK (memory, sizeof (word_t));
1103 alloc = sec_realloc (block, tag, memory, length);
1105 #ifdef WITH_VALGRIND
1106 /* Now tell valgrind about either the new block or old one */
1107 VALGRIND_MALLOCLIKE_BLOCK (alloc ? alloc : memory,
1108 alloc ? length : previous,
1109 sizeof (word_t), 1);
1115 /* If it didn't work we may need to allocate a new block */
1116 if (block && !alloc)
1119 if (block && block->n_used == 0)
1120 sec_block_destroy (block);
1125 if ((flags & EGG_SECURE_USE_FALLBACK)) {
1127 * In this case we can't zero the returned memory,
1128 * because we don't know what the block size was.
1130 return egg_memory_fallback (memory, length);
1132 if (egg_secure_warnings)
1133 fprintf (stderr, "memory does not belong to gnome-keyring: 0x%08lx\n",
1134 (unsigned long)memory);
1135 ASSERT (0 && "memory does does not belong to gnome-keyring");
1141 alloc = egg_secure_alloc_full (tag, length, flags);
1143 memcpy_with_vbits (alloc, memory, previous);
1144 egg_secure_free_full (memory, flags);
1155 egg_secure_free (void *memory)
1157 egg_secure_free_full (memory, EGG_SECURE_USE_FALLBACK);
1161 egg_secure_free_full (void *memory, int flags)
1163 Block *block = NULL;
1170 /* Find out where it belongs to */
1171 for (block = all_blocks; block; block = block->next) {
1172 if (sec_is_valid_word (block, memory))
1176 #ifdef WITH_VALGRIND
1177 /* We like valgrind's warnings, so give it a first whack at checking for errors */
1178 if (block != NULL || !(flags & EGG_SECURE_USE_FALLBACK))
1179 VALGRIND_FREELIKE_BLOCK (memory, sizeof (word_t));
1182 if (block != NULL) {
1183 sec_free (block, memory);
1184 if (block->n_used == 0)
1185 sec_block_destroy (block);
1191 if ((flags & EGG_SECURE_USE_FALLBACK)) {
1192 egg_memory_fallback (memory, 0);
1194 if (egg_secure_warnings)
1195 fprintf (stderr, "memory does not belong to gnome-keyring: 0x%08lx\n",
1196 (unsigned long)memory);
1197 ASSERT (0 && "memory does does not belong to gnome-keyring");
1203 egg_secure_check (const void *memory)
1205 Block *block = NULL;
1209 /* Find out where it belongs to */
1210 for (block = all_blocks; block; block = block->next) {
1211 if (sec_is_valid_word (block, (word_t*)memory))
1217 return block == NULL ? 0 : 1;
1221 egg_secure_validate (void)
1223 Block *block = NULL;
1227 for (block = all_blocks; block; block = block->next)
1228 sec_validate (block);
1234 static egg_secure_rec *
1235 records_for_ring (Cell *cell_ring,
1236 egg_secure_rec *records,
1237 unsigned int *count,
1238 unsigned int *total)
1240 egg_secure_rec *new_rec;
1241 unsigned int allocated = *count;
1246 if (*count >= allocated) {
1247 new_rec = realloc (records, sizeof (egg_secure_rec) * (allocated + 32));
1248 if (new_rec == NULL) {
1259 records[*count].request_length = cell->requested;
1260 records[*count].block_length = cell->n_words * sizeof (word_t);
1261 records[*count].tag = cell->tag;
1263 (*total) += cell->n_words;
1266 } while (cell != NULL && cell != cell_ring);
1272 egg_secure_records (unsigned int *count)
1274 egg_secure_rec *records = NULL;
1275 Block *block = NULL;
1282 for (block = all_blocks; block != NULL; block = block->next) {
1285 records = records_for_ring (block->unused_cells, records, count, &total);
1286 if (records == NULL)
1288 records = records_for_ring (block->used_cells, records, count, &total);
1289 if (records == NULL)
1292 /* Make sure this actualy accounts for all memory */
1293 ASSERT (total == block->n_words);
1302 egg_secure_strdup_full (const char *tag,
1312 len = strlen (str) + 1;
1313 res = (char *)egg_secure_alloc_full (tag, len, options);
1319 egg_secure_clear (void *p, size_t length)
1326 vp = (volatile char*)p;
1335 egg_secure_strclear (char *str)
1339 egg_secure_clear ((unsigned char*)str, strlen (str));
1343 egg_secure_strfree (char *str)
1346 * If we're using unpageable 'secure' memory, then the free call
1347 * should zero out the memory, but because on certain platforms
1348 * we may be using normal memory, zero it out here just in case.
1351 egg_secure_strclear (str);
1352 egg_secure_free_full (str, EGG_SECURE_USE_FALLBACK);