void* egg_secure_alloc_full (const char *tag, size_t length, int flags) { Block *block; void *memory = NULL; if (tag == NULL) tag = "?"; if (length > 0xFFFFFFFF / 2) { if (egg_secure_warnings) 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; } /* 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) /* Our returned memory is always zeroed */ memset (memory, 0, length); } if (!memory) errno = ENOMEM; return memory; }
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)) break; } #ifdef WITH_VALGRIND /* We like valgrind's warnings, so give it a first whack at checking for errors */ if (block != NULL || !(flags & GKR_SECURE_USE_FALLBACK)) VALGRIND_FREELIKE_BLOCK (memory, sizeof (word_t)); #endif if (block != NULL) { sec_free (block, memory); if (block->used == 0) sec_block_destroy (block); } DO_UNLOCK (); if (!block) { if ((flags & GKR_SECURE_USE_FALLBACK)) { egg_memory_fallback (memory, 0); } else { if (egg_secure_warnings) fprintf (stderr, "memory does not belong to mate-keyring: 0x%08lx\n", (unsigned long)memory); ASSERT (0 && "memory does does not belong to mate-keyring"); } } }
void* egg_secure_realloc_full (void *memory, size_t length, int flags) { Block *block = NULL; size_t previous = 0; int donew = 0; void *alloc = NULL; if (length > 0xFFFFFFFF / 2) { if (egg_secure_warnings) 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 (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)) { previous = sec_allocated (block, memory); #ifdef WITH_VALGRIND /* Let valgrind think we are unallocating so that it'll validate */ VALGRIND_FREELIKE_BLOCK (memory, sizeof (word_t)); #endif alloc = sec_realloc (block, memory, length); #ifdef WITH_VALGRIND /* Now tell valgrind about either the new block or old one */ VALGRIND_MALLOCLIKE_BLOCK (alloc ? alloc : memory, alloc ? length : previous, sizeof (word_t), 1); #endif break; } } /* If it didn't work we may need to allocate a new block */ if (block && !alloc) donew = 1; if (block && block->used == 0) sec_block_destroy (block); DO_UNLOCK (); if (!block) { if ((flags & GKR_SECURE_USE_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); } else { if (egg_secure_warnings) fprintf (stderr, "memory does not belong to mate-keyring: 0x%08lx\n", (unsigned long)memory); ASSERT (0 && "memory does does not belong to mate-keyring"); return NULL; } } if (donew) { alloc = egg_secure_alloc_full (length, flags); if (alloc) { memcpy (alloc, memory, previous); egg_secure_free_full (memory, flags); } } if (!alloc) errno = ENOMEM; return alloc; }