--- libselinux-2.0.94/src/matchpathcon.c.leak 2011-02-04 08:49:46.498334051 +0100
+++ libselinux-2.0.94/src/matchpathcon.c 2011-02-04 08:52:48.979090294 +0100
@@ -16,6 +16,9 @@
static __thread int con_array_size;
static __thread int con_array_used;
+static pthread_once_t once = PTHREAD_ONCE_INIT;
+static pthread_key_t destructor_key;
+
static int add_array_elt(char *con)
{
if (con_array_size) {
@@ -283,11 +286,19 @@
fl_head = NULL;
}
+static void matchpathcon_init_once(void)
+{
+ __selinux_key_create(&destructor_key, free_array_elts);
+}
+
int matchpathcon_init_prefix(const char *path, const char *subset)
{
if (!mycanoncon)
mycanoncon = default_canoncon;
+ __selinux_once(once, matchpathcon_init_once);
+ __selinux_setspecific(destructor_key, (void *)1);
+
options[SELABEL_OPT_SUBSET].type = SELABEL_OPT_SUBSET;
options[SELABEL_OPT_SUBSET].value = subset;
options[SELABEL_OPT_PATH].type = SELABEL_OPT_PATH;
--- libselinux-2.0.94/src/selinux_internal.h.leak 2011-02-04 08:53:00.618332791 +0100
+++ libselinux-2.0.94/src/selinux_internal.h 2011-02-04 08:56:24.917090558 +0100
@@ -97,6 +97,8 @@
/* Make pthread_once optional */
#pragma weak pthread_once
+#pragma weak pthread_key_create
+#pragma weak pthread_setspecific
/* Call handler iff the first call. */
#define __selinux_once(ONCE_CONTROL, INIT_FUNCTION) \
@@ -109,4 +111,15 @@
} \
} while (0)
+/* Pthread key macros */
+#define __selinux_key_create(KEY, DESTRUCTOR) \
+ do { \
+ if (pthread_key_create != NULL) \
+ pthread_key_create(KEY, DESTRUCTOR); \
+ } while (0)
+#define __selinux_setspecific(KEY, VALUE) \
+ do { \
+ if (pthread_setspecific != NULL) \
+ pthread_setspecific(KEY, VALUE); \
+ } while (0)
--- libselinux-2.0.94/src/setrans_client.c.leak 2011-02-04 08:56:43.229330202 +0100
+++ libselinux-2.0.94/src/setrans_client.c 2011-02-04 09:00:04.176174970 +0100
@@ -34,6 +34,8 @@
static __thread security_context_t prev_r2c_raw = NULL;
static pthread_once_t once = PTHREAD_ONCE_INIT;
+static pthread_key_t destructor_key;
+static __thread char destructor_initialized;
/*
* setransd_open
@@ -240,8 +242,27 @@
return ret;
}
+static void setrans_thread_destructor(void __attribute__((unused)) *unused)
+{
+ free(prev_t2r_trans);
+ free(prev_t2r_raw);
+ free(prev_r2t_trans);
+ free(prev_r2t_raw);
+ free(prev_r2c_trans);
+ free(prev_r2c_raw);
+}
+
+static inline void init_thread_destructor(void)
+{
+ if (destructor_initialized == 0) {
+ __selinux_setspecific(destructor_key, (void *)1);
+ destructor_initialized = 1;
+ }
+}
+
static void init_context_translations(void)
{
+ __selinux_key_create(&destructor_key, setrans_thread_destructor);
mls_enabled = is_selinux_mls_enabled();
}
@@ -254,6 +275,7 @@
}
__selinux_once(once, init_context_translations);
+ init_thread_destructor();
if (!mls_enabled) {
*rawp = strdup(trans);
@@ -295,6 +317,7 @@
}
__selinux_once(once, init_context_translations);
+ init_thread_destructor();
if (!mls_enabled) {
*transp = strdup(raw);
@@ -334,6 +357,9 @@
return -1;
}
+ __selinux_once(once, init_context_translations);
+ init_thread_destructor();
+
if (prev_r2c_raw && strcmp(prev_r2c_raw, raw) == 0) {
*transp = strdup(prev_r2c_trans);
} else {