From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from goalie.tycho.ncsc.mil (goalie [144.51.242.250]) by tarius.tycho.ncsc.mil (8.14.4/8.14.4) with ESMTP id u9ILWUdj005981 for ; Tue, 18 Oct 2016 17:32:30 -0400 Received: by mail-pf0-f169.google.com with SMTP id 128so2980021pfz.0 for ; Tue, 18 Oct 2016 14:32:04 -0700 (PDT) From: Daniel Cashman To: selinux@tycho.nsa.gov Cc: jwcart2@tycho.nsa.gov, jeffv@google.com, sds@tycho.nsa.gov, dcashman Subject: [PATCH] libsepol: cil: cil_strpool: Allow multiple strpool users. Date: Tue, 18 Oct 2016 14:31:51 -0700 Message-Id: <1476826311-31992-1-git-send-email-dcashman@android.com> List-Id: "Security-Enhanced Linux \(SELinux\) mailing list" List-Post: List-Help: From: dcashman 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 ad2a334..5b7df8c 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.8.0.rc3.226.g39d4020