diff mbox series

[libselinux] libselinux: make threadsafe for discover_class_cache

Message ID 20220120073329.15234-1-purushottamchoudhary29@gmail.com (mailing list archive)
State New, archived
Headers show
Series [libselinux] libselinux: make threadsafe for discover_class_cache | expand

Commit Message

Purushottam Choudhary Jan. 20, 2022, 7:33 a.m. UTC
From: purushottam Choudhary <purushottamchoudhary29@gmail.com>

Crash is observed in process dbus-daemon while accessing name
from discover_class_cache structure variable,
discover_class_cache->name vairable found NULL
during backtrace analysis.
Add mutex lock for the discover_class_cache to handle multiple
threads for the function which uses discover_class_cache
This avoids variable corruption during parallel access
in the multiple thread environment.

Signed-off-by: Purushottam Choudhary <purushottamchoudhary29@gmail.com>
---
 libselinux/src/avc.c       |  7 +++++--
 libselinux/src/stringrep.c | 24 ++++++++++++++++++------
 2 files changed, 23 insertions(+), 8 deletions(-)
diff mbox series

Patch

diff --git a/libselinux/src/avc.c b/libselinux/src/avc.c
index 7493e4b2..4fbaa30d 100644
--- a/libselinux/src/avc.c
+++ b/libselinux/src/avc.c
@@ -685,8 +685,11 @@  static void avc_dump_query(security_id_t ssid, security_id_t tsid,
 		   ssid->ctx, tsid->ctx);
 
 	avc_release_lock(avc_lock);
-	log_append(avc_audit_buf, " tclass=%s",
-		   security_class_to_string(tclass));
+	char *tclass_name = security_class_to_string(tclass);
+	log_append(avc_audit_buf, " tclass=%s", tclass_name);
+	if (tclass_name != NULL) {
+		free(tclass_name);
+	}
 }
 
 void avc_audit(security_id_t ssid, security_id_t tsid,
diff --git a/libselinux/src/stringrep.c b/libselinux/src/stringrep.c
index 2fe69f43..52ae3f2d 100644
--- a/libselinux/src/stringrep.c
+++ b/libselinux/src/stringrep.c
@@ -19,6 +19,7 @@ 
 
 #define MAXVECTORS 8*sizeof(access_vector_t)
 
+pthread_mutex_t cache_mutex = PTHREAD_MUTEX_INITIALIZER;
 struct discover_class_node {
 	char *name;
 	security_class_t value;
@@ -140,9 +141,10 @@  static struct discover_class_node * discover_class(const char *s)
 	}
 	closedir(dir);
 
+	__pthread_mutex_lock(&cache_mutex);
 	node->next = discover_class_cache;
 	discover_class_cache = node;
-
+	__pthread_mutex_unlock(&cache_mutex);
 	return node;
 
 err4:
@@ -160,6 +162,7 @@  err1:
 
 void selinux_flush_class_cache(void)
 {
+	__pthread_mutex_lock(&cache_mutex);
 	struct discover_class_node *cur = discover_class_cache, *prev = NULL;
 	size_t i;
 
@@ -178,6 +181,7 @@  void selinux_flush_class_cache(void)
 	}
 
 	discover_class_cache = NULL;
+	__pthread_mutex_unlock(&cache_mutex);
 }
 
 
@@ -185,6 +189,7 @@  security_class_t string_to_security_class(const char *s)
 {
 	struct discover_class_node *node;
 
+	__pthread_mutex_lock(&cache_mutex);
 	node = get_class_cache_entry_name(s);
 	if (node == NULL) {
 		node = discover_class(s);
@@ -195,7 +200,9 @@  security_class_t string_to_security_class(const char *s)
 		}
 	}
 
-	return map_class(node->value);
+	security_class_t ret_value = map_class(node->name);
+	__pthread_mutex_unlock(&cache_mutex);
+	return ret_value;
 }
 
 security_class_t mode_to_security_class(mode_t m) {
@@ -224,6 +231,7 @@  access_vector_t string_to_av_perm(security_class_t tclass, const char *s)
 	struct discover_class_node *node;
 	security_class_t kclass = unmap_class(tclass);
 
+	__pthread_mutex_lock(&cache_mutex);
 	node = get_class_cache_entry_value(kclass);
 	if (node != NULL) {
 		size_t i;
@@ -233,6 +241,7 @@  access_vector_t string_to_av_perm(security_class_t tclass, const char *s)
 	}
 
 	errno = EINVAL;
+	__pthread_mutex_unlock(&cache_mutex);
 	return 0;
 }
 
@@ -242,11 +251,14 @@  const char *security_class_to_string(security_class_t tclass)
 
 	tclass = unmap_class(tclass);
 
+	__pthread_mutex_lock(&cache_mutex);
+	char *node_name = NULL;
 	node = get_class_cache_entry_value(tclass);
-	if (node == NULL)
-		return NULL;
-	else
-		return node->name;
+	if (node != NULL) {
+		node_name = strdup(node->name);
+	}
+	__pthread_mutex_unlock(&cache_mutex);
+	return node_name;
 }
 
 const char *security_av_perm_to_string(security_class_t tclass,