[gcr] egg: Make secure memory pool shared across modules



commit 007f81cb2856fdfa8879e39f8032057e521867b4
Author: Stef Walter <stefw collabora co uk>
Date:   Mon Dec 5 14:31:39 2011 +0100

    egg: Make secure memory pool shared across modules
    
     * The globals for the secure memory pool need to be shared across linked
       modules. So that for example gck, gcr, and gsecret libraries can
       share the same pool, even though code is compiled into each library.
     * There's versioning so they'll only work with each other if they all
       share the same code.

 egg/Makefile.am          |    4 ++
 egg/egg-secure-memory.c  |   69 ++++++++++++++++++++++++++--------------------
 egg/egg-secure-memory.h  |   38 +++++++++++++------------
 egg/tests/test-dh.c      |    2 +-
 egg/tests/test-hkdf.c    |   12 +++++++-
 egg/tests/test-openssl.c |    2 +-
 egg/tests/test-secmem.c  |    2 +-
 egg/tests/test-symkey.c  |    2 +-
 gck/Makefile.am          |    3 +-
 gck/gck-misc.c           |    4 ++
 gck/gck.symbols          |    1 +
 gcr/Makefile.am          |    2 +-
 gcr/gcr-memory.c         |   66 +-------------------------------------------
 13 files changed, 87 insertions(+), 120 deletions(-)
---
diff --git a/egg/Makefile.am b/egg/Makefile.am
index a9de41a..64b0934 100644
--- a/egg/Makefile.am
+++ b/egg/Makefile.am
@@ -5,6 +5,7 @@ noinst_LTLIBRARIES = \
 	libegg-asn1x.la \
 	libegg-entry-buffer.la \
 	libegg-hex.la \
+	libegg-secmem.la \
 	libegg-test.la
 
 ASN_FILES = \
@@ -79,6 +80,9 @@ libegg_hex_la_CFLAGS = \
 libegg_hex_la_LIBS = \
 	$(GLIB_LIBS)
 
+libegg_secmem_la_SOURCES = \
+	egg-secure-memory.c egg-secure-memory.h
+
 libegg_test_la_SOURCES = \
 	egg-testing.c egg-testing.h
 
diff --git a/egg/egg-secure-memory.c b/egg/egg-secure-memory.c
index dca9bac..ca5e38d 100644
--- a/egg/egg-secure-memory.c
+++ b/egg/egg-secure-memory.c
@@ -66,12 +66,12 @@
 #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;
 
 /* 
@@ -163,17 +163,25 @@ 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;
 	}
@@ -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;
@@ -223,7 +231,8 @@ pool_free (void* item)
 	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) {
@@ -270,7 +279,7 @@ pool_valid (void* item)
 	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) 
@@ -858,18 +867,18 @@ sec_acquire_pages (size_t *sz,
 #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;
@@ -877,13 +886,13 @@ sec_acquire_pages (size_t *sz,
 	
 	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
 
@@ -1050,8 +1059,8 @@ egg_secure_alloc_full (const char *tag,
 	
 	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);
 	}
@@ -1124,17 +1133,17 @@ egg_secure_realloc_full (const char *tag,
 	DO_UNLOCK ();		
 	
 	if (!block) {
-		if ((flags & EGG_SECURE_USE_FALLBACK)) {
+		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;
 		}
 	}
@@ -1190,13 +1199,13 @@ egg_secure_free_full (void *memory, int flags)
 	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");
 		}
 	}
 } 
diff --git a/egg/egg-secure-memory.h b/egg/egg-secure-memory.h
index 682811d..3ef0ab5 100644
--- a/egg/egg-secure-memory.h
+++ b/egg/egg-secure-memory.h
@@ -39,30 +39,32 @@
  * 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
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..d8002f4 100644
--- a/egg/tests/test-hkdf.c
+++ b/egg/tests/test-hkdf.c
@@ -33,7 +33,17 @@
 
 #include <gcrypt.h>
 
-EGG_SECURE_GLIB_DEFINITIONS ();
+/*
+	static GStaticMutex memory_mutex = G_STATIC_MUTEX_INIT;
+	static void egg_memory_lock (void)
+		{ g_static_mutex_lock (&memory_mutex); }
+	static void egg_memory_unlock (void)
+		{ g_static_mutex_unlock (&memory_mutex); }
+	EGG_SECURE_DEFINE_GLOBALS (egg_memory_lock, egg_memory_unlock, g_realloc);
+*/
+
+EGG_SECURE_DEFINE_GLIB_GLOBALS ();
+
 
 static void
 test_hkdf_test_case_1 (void)
diff --git a/egg/tests/test-openssl.c b/egg/tests/test-openssl.c
index 6c39496..87596fd 100644
--- a/egg/tests/test-openssl.c
+++ b/egg/tests/test-openssl.c
@@ -38,7 +38,7 @@
 
 #include <egg/egg-bytes.h>
 
-EGG_SECURE_GLIB_DEFINITIONS ();
+EGG_SECURE_DEFINE_GLIB_GLOBALS ();
 
 typedef struct {
 	EggBytes *input;
diff --git a/egg/tests/test-secmem.c b/egg/tests/test-secmem.c
index 3a66fc4..e0b6e24 100644
--- a/egg/tests/test-secmem.c
+++ b/egg/tests/test-secmem.c
@@ -32,7 +32,7 @@
 #include <string.h>
 
 
-EGG_SECURE_GLIB_DEFINITIONS ();
+EGG_SECURE_DEFINE_GLIB_GLOBALS ();
 
 /* Declared in egg-secure-memory.c */
 extern int egg_secure_warnings;
diff --git a/egg/tests/test-symkey.c b/egg/tests/test-symkey.c
index 409ec44..b4c1e2d 100644
--- a/egg/tests/test-symkey.c
+++ b/egg/tests/test-symkey.c
@@ -33,7 +33,7 @@
 #include <stdio.h>
 #include <string.h>
 
-EGG_SECURE_GLIB_DEFINITIONS ();
+EGG_SECURE_DEFINE_GLIB_GLOBALS ();
 
 static const struct {
 	const gchar *password;
diff --git a/gck/Makefile.am b/gck/Makefile.am
index 9d83836..aab5feb 100644
--- a/gck/Makefile.am
+++ b/gck/Makefile.am
@@ -63,10 +63,11 @@ libgck_ GCK_MAJOR@_la_SOURCES = \
 libgck_ GCK_MAJOR@_la_LDFLAGS = \
 	-version-info $(GCK_LT_RELEASE) \
 	-no-undefined \
-	-export-symbols-regex '^gck_*'
+	-export-symbols-regex '^gck_.*|^SECMEM_.*'
 
 libgck_ GCK_MAJOR@_la_LIBADD = \
 	$(top_builddir)/egg/libegg-hex.la \
+	$(top_builddir)/egg/libegg-secmem.la \
 	$(P11_KIT_LIBS) \
 	$(GTHREAD_LIBS) \
 	$(GIO_LIBS) \
diff --git a/gck/gck-misc.c b/gck/gck-misc.c
index 47d444e..1049142 100644
--- a/gck/gck-misc.c
+++ b/gck/gck-misc.c
@@ -26,10 +26,14 @@
 #include "gck.h"
 #include "gck-private.h"
 
+#include "egg/egg-secure-memory.h"
+
 #include <p11-kit/p11-kit.h>
 
 #include <glib/gi18n-lib.h>
 
+EGG_SECURE_DEFINE_GLIB_GLOBALS ();
+
 /**
  * SECTION:gck-error
  * @title: Errors
diff --git a/gck/gck.symbols b/gck/gck.symbols
index d3aef3e..8d18816 100644
--- a/gck/gck.symbols
+++ b/gck/gck.symbols
@@ -257,3 +257,4 @@ gck_uri_get_error_quark
 gck_uri_parse
 gck_value_to_boolean
 gck_value_to_ulong
+SECMEM_pool_data_v1_0
\ No newline at end of file
diff --git a/gcr/Makefile.am b/gcr/Makefile.am
index 924056c..544063e 100644
--- a/gcr/Makefile.am
+++ b/gcr/Makefile.am
@@ -190,7 +190,7 @@ libgcr_ GCR_MAJOR@_la_CFLAGS = \
 libgcr_base_ GCR_MAJOR@_la_LDFLAGS = \
 	-version-info $(GCR_LT_RELEASE) \
 	-no-undefined \
-	-export-symbols-regex '^gcr_*'
+	-export-symbols-regex '^gcr_.*|^SECMEM_.*'
 
 libgcr_ GCR_MAJOR@_la_LDFLAGS = \
 	$(libgcr_base_ GCR_MAJOR@_la_LDFLAGS)
diff --git a/gcr/gcr-memory.c b/gcr/gcr-memory.c
index 04d216d..0e378a4 100644
--- a/gcr/gcr-memory.c
+++ b/gcr/gcr-memory.c
@@ -25,68 +25,4 @@
 
 #include <glib.h>
 
-/* -----------------------------------------------------------------------------
- * MEMORY
- */
-
-static gboolean do_warning = TRUE;
-#define WARNING  "couldn't allocate secure memory to keep passwords " \
-		 "and or keys from being written to the disk"
-
-#define ABORTMSG "The GNOME_KEYRING_PARANOID environment variable was set. " \
-                 "Exiting..."
-
-static G_LOCK_DEFINE (memory_lock);
-
-/*
- * These are called from egg-secure-memory.c to provide appropriate
- * locking for memory between threads
- */
-
-void
-egg_memory_lock (void)
-{
-	G_LOCK (memory_lock);
-}
-
-void
-egg_memory_unlock (void)
-{
-	G_UNLOCK (memory_lock);
-}
-
-void*
-egg_memory_fallback (void *p, size_t sz)
-{
-	const gchar *env;
-
-	/* We were asked to free memory */
-	if (!sz) {
-		g_free (p);
-		return NULL;
-	}
-
-	/* We were asked to allocate */
-	if (!p) {
-		if (do_warning) {
-			g_message (WARNING);
-			do_warning = FALSE;
-		}
-
-		env = g_getenv ("GNOME_KEYRING_PARANOID");
-		if (env && *env)
-			g_error (ABORTMSG);
-
-		return g_malloc0 (sz);
-	}
-
-	/*
-	 * Reallocation is a bit of a gray area, as we can be asked
-	 * by external libraries (like libgcrypt) to reallocate a
-	 * non-secure block into secure memory. We cannot satisfy
-	 * this request (as we don't know the size of the original
-	 * block) so we just try our best here.
-	 */
-
-	return g_realloc (p, sz);
-}
+EGG_SECURE_DEFINE_GLIB_GLOBALS ();



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