From 34549d299f80c1cb713ea3c10f690bf1572c3f9a Mon Sep 17 00:00:00 2001 From: dcashman Date: Tue, 18 Oct 2016 14:31:51 -0700 Subject: [PATCH] libsepol: cil: cil_strpool: Allow multiple strpool users. cil_strpool currently provides an interface to a statically stored global data structure. This interface does not accomodate multiple consumers, however, as two calls to cil_strpool_init() will lead to a memory leak and a call to cil_strpool_destroy() by one consumer will remove data from use by others, and subsequently lead to a segfault on the next cil_strpool_destroy() invocation. Add a reference counter so that the strpool is only initialized once and protect the exported interface with a mutex. Tested by calling cil_db_init() on two cil_dbs and then calling cil_db_destroy() on each. Signed-off-by: Daniel Cashman --- libsepol/cil/src/cil_strpool.c | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/libsepol/cil/src/cil_strpool.c b/libsepol/cil/src/cil_strpool.c index ad2a334f8ebf..5b7df8c6e0ce 100644 --- a/libsepol/cil/src/cil_strpool.c +++ b/libsepol/cil/src/cil_strpool.c @@ -27,6 +27,7 @@ * either expressed or implied, of Tresys Technology, LLC. */ +#include #include #include #include @@ -40,6 +41,8 @@ struct cil_strpool_entry { char *str; }; +static pthread_mutex_t cil_strpool_mutex = PTHREAD_MUTEX_INITIALIZER; +static unsigned int cil_strpool_readers = 0; static hashtab_t cil_strpool_tab = NULL; static unsigned int cil_strpool_hash(hashtab_t h, hashtab_key_t key) @@ -68,16 +71,21 @@ char *cil_strpool_add(const char *str) { struct cil_strpool_entry *strpool_ref = NULL; + pthread_mutex_lock(&cil_strpool_mutex); + strpool_ref = hashtab_search(cil_strpool_tab, (hashtab_key_t)str); if (strpool_ref == NULL) { strpool_ref = cil_malloc(sizeof(*strpool_ref)); strpool_ref->str = cil_strdup(str); int rc = hashtab_insert(cil_strpool_tab, (hashtab_key_t)strpool_ref->str, strpool_ref); if (rc != SEPOL_OK) { + pthread_mutex_unlock(&cil_strpool_mutex); (*cil_mem_error_handler)(); + pthread_mutex_lock(&cil_strpool_mutex); } } + pthread_mutex_unlock(&cil_strpool_mutex); return strpool_ref->str; } @@ -91,14 +99,26 @@ static int cil_strpool_entry_destroy(hashtab_key_t k __attribute__ ((unused)), h void cil_strpool_init(void) { - cil_strpool_tab = hashtab_create(cil_strpool_hash, cil_strpool_compare, CIL_STRPOOL_TABLE_SIZE); + pthread_mutex_lock(&cil_strpool_mutex); if (cil_strpool_tab == NULL) { - (*cil_mem_error_handler)(); + cil_strpool_tab = hashtab_create(cil_strpool_hash, cil_strpool_compare, CIL_STRPOOL_TABLE_SIZE); + if (cil_strpool_tab == NULL) { + pthread_mutex_unlock(&cil_strpool_mutex); + (*cil_mem_error_handler)(); + return; + } } + cil_strpool_readers++; + pthread_mutex_unlock(&cil_strpool_mutex); } void cil_strpool_destroy(void) { - hashtab_map(cil_strpool_tab, cil_strpool_entry_destroy, NULL); - hashtab_destroy(cil_strpool_tab); + pthread_mutex_lock(&cil_strpool_mutex); + cil_strpool_readers--; + if (cil_strpool_readers == 0) { + hashtab_map(cil_strpool_tab, cil_strpool_entry_destroy, NULL); + hashtab_destroy(cil_strpool_tab); + } + pthread_mutex_unlock(&cil_strpool_mutex); } -- 2.10.2