| From c397ed69715b09ea6cd5f605855be3c42d0dd7f9 Mon Sep 17 00:00:00 2001 |
| From: Paul Moore <paul@paul-moore.com> |
| Date: Mon, 9 Dec 2019 20:39:46 -0500 |
| Subject: [PATCH] selinux: ensure we cleanup the internal AVC counters on error |
| in avc_insert() |
| |
| commit d8db60cb23e49a92cf8cada3297395c7fa50fdf8 upstream. |
| |
| Fix avc_insert() to call avc_node_kill() if we've already allocated |
| an AVC node and the code fails to insert the node in the cache. |
| |
| Fixes: fa1aa143ac4a ("selinux: extended permissions for ioctls") |
| Reported-by: rsiddoji@codeaurora.org |
| Suggested-by: Stephen Smalley <sds@tycho.nsa.gov> |
| Acked-by: Stephen Smalley <sds@tycho.nsa.gov> |
| Signed-off-by: Paul Moore <paul@paul-moore.com> |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/security/selinux/avc.c b/security/selinux/avc.c |
| index 23dc888ae305..6646300f7ccb 100644 |
| --- a/security/selinux/avc.c |
| +++ b/security/selinux/avc.c |
| @@ -617,40 +617,37 @@ static struct avc_node *avc_insert(struct selinux_avc *avc, |
| struct avc_node *pos, *node = NULL; |
| int hvalue; |
| unsigned long flag; |
| + spinlock_t *lock; |
| + struct hlist_head *head; |
| |
| if (avc_latest_notif_update(avc, avd->seqno, 1)) |
| - goto out; |
| + return NULL; |
| |
| node = avc_alloc_node(avc); |
| - if (node) { |
| - struct hlist_head *head; |
| - spinlock_t *lock; |
| - int rc = 0; |
| - |
| - hvalue = avc_hash(ssid, tsid, tclass); |
| - avc_node_populate(node, ssid, tsid, tclass, avd); |
| - rc = avc_xperms_populate(node, xp_node); |
| - if (rc) { |
| - kmem_cache_free(avc_node_cachep, node); |
| - return NULL; |
| - } |
| - head = &avc->avc_cache.slots[hvalue]; |
| - lock = &avc->avc_cache.slots_lock[hvalue]; |
| + if (!node) |
| + return NULL; |
| |
| - spin_lock_irqsave(lock, flag); |
| - hlist_for_each_entry(pos, head, list) { |
| - if (pos->ae.ssid == ssid && |
| - pos->ae.tsid == tsid && |
| - pos->ae.tclass == tclass) { |
| - avc_node_replace(avc, node, pos); |
| - goto found; |
| - } |
| + avc_node_populate(node, ssid, tsid, tclass, avd); |
| + if (avc_xperms_populate(node, xp_node)) { |
| + avc_node_kill(avc, node); |
| + return NULL; |
| + } |
| + |
| + hvalue = avc_hash(ssid, tsid, tclass); |
| + head = &avc->avc_cache.slots[hvalue]; |
| + lock = &avc->avc_cache.slots_lock[hvalue]; |
| + spin_lock_irqsave(lock, flag); |
| + hlist_for_each_entry(pos, head, list) { |
| + if (pos->ae.ssid == ssid && |
| + pos->ae.tsid == tsid && |
| + pos->ae.tclass == tclass) { |
| + avc_node_replace(avc, node, pos); |
| + goto found; |
| } |
| - hlist_add_head_rcu(&node->list, head); |
| -found: |
| - spin_unlock_irqrestore(lock, flag); |
| } |
| -out: |
| + hlist_add_head_rcu(&node->list, head); |
| +found: |
| + spin_unlock_irqrestore(lock, flag); |
| return node; |
| } |
| |
| -- |
| 2.7.4 |
| |