From: purushottam Choudhary <purushottamchoudhary29@xxxxxxxxx> 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@xxxxxxxxx> --- libselinux/src/avc.c | 7 +++++-- libselinux/src/stringrep.c | 24 ++++++++++++++++++------ 2 files changed, 23 insertions(+), 8 deletions(-) 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, -- 2.17.1