selinux: slow_avc_audit has become non-blocking
authorAl Viro <viro@zeniv.linux.org.uk>
Sat, 16 Jan 2021 20:40:54 +0000 (15:40 -0500)
committerPaul Moore <paul@paul-moore.com>
Fri, 11 Jun 2021 17:05:18 +0000 (13:05 -0400)
dump_common_audit_data() is safe to use under rcu_read_lock() now;
no need for AVC_NONBLOCKING and games around it

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Paul Moore <paul@paul-moore.com>
security/selinux/avc.c
security/selinux/hooks.c
security/selinux/include/avc.h

index 6417ed4..9322687 100644 (file)
@@ -759,7 +759,11 @@ static void avc_audit_post_callback(struct audit_buffer *ab, void *a)
        }
 }
 
-/* This is the slow part of avc audit with big stack footprint */
+/*
+ * This is the slow part of avc audit with big stack footprint.
+ * Note that it is non-blocking and can be called from under
+ * rcu_read_lock().
+ */
 noinline int slow_avc_audit(struct selinux_state *state,
                            u32 ssid, u32 tsid, u16 tclass,
                            u32 requested, u32 audited, u32 denied, int result,
@@ -826,7 +830,7 @@ out:
  * @ssid,@tsid,@tclass : identifier of an AVC entry
  * @seqno : sequence number when decision was made
  * @xpd: extended_perms_decision to be added to the node
- * @flags: the AVC_* flags, e.g. AVC_NONBLOCKING, AVC_EXTENDED_PERMS, or 0.
+ * @flags: the AVC_* flags, e.g. AVC_EXTENDED_PERMS, or 0.
  *
  * if a valid AVC entry doesn't exist,this function returns -ENOENT.
  * if kmalloc() called internal returns NULL, this function returns -ENOMEM.
@@ -845,21 +849,6 @@ static int avc_update_node(struct selinux_avc *avc,
        struct hlist_head *head;
        spinlock_t *lock;
 
-       /*
-        * If we are in a non-blocking code path, e.g. VFS RCU walk,
-        * then we must not add permissions to a cache entry
-        * because we will not audit the denial.  Otherwise,
-        * during the subsequent blocking retry (e.g. VFS ref walk), we
-        * will find the permissions already granted in the cache entry
-        * and won't audit anything at all, leading to silent denials in
-        * permissive mode that only appear when in enforcing mode.
-        *
-        * See the corresponding handling of MAY_NOT_BLOCK in avc_audit()
-        * and selinux_inode_permission().
-        */
-       if (flags & AVC_NONBLOCKING)
-               return 0;
-
        node = avc_alloc_node(avc);
        if (!node) {
                rc = -ENOMEM;
@@ -1120,7 +1109,7 @@ decision:
  * @tsid: target security identifier
  * @tclass: target security class
  * @requested: requested permissions, interpreted based on @tclass
- * @flags:  AVC_STRICT, AVC_NONBLOCKING, or 0
+ * @flags:  AVC_STRICT or 0
  * @avd: access vector decisions
  *
  * Check the AVC to determine whether the @requested permissions are granted
@@ -1205,8 +1194,7 @@ int avc_has_perm_flags(struct selinux_state *state,
        struct av_decision avd;
        int rc, rc2;
 
-       rc = avc_has_perm_noaudit(state, ssid, tsid, tclass, requested,
-                                 (flags & MAY_NOT_BLOCK) ? AVC_NONBLOCKING : 0,
+       rc = avc_has_perm_noaudit(state, ssid, tsid, tclass, requested, 0,
                                  &avd);
 
        rc2 = avc_audit(state, ssid, tsid, tclass, requested, &avd, rc,
index fc6a3ab..4e64f68 100644 (file)
@@ -3164,17 +3164,13 @@ static noinline int audit_inode_permission(struct inode *inode,
 {
        struct common_audit_data ad;
        struct inode_security_struct *isec = selinux_inode(inode);
-       int rc;
 
        ad.type = LSM_AUDIT_DATA_INODE;
        ad.u.inode = inode;
 
-       rc = slow_avc_audit(&selinux_state,
+       return slow_avc_audit(&selinux_state,
                            current_sid(), isec->sid, isec->sclass, perms,
                            audited, denied, result, &ad);
-       if (rc)
-               return rc;
-       return 0;
 }
 
 static int selinux_inode_permission(struct inode *inode, int mask)
@@ -3209,8 +3205,7 @@ static int selinux_inode_permission(struct inode *inode, int mask)
                return PTR_ERR(isec);
 
        rc = avc_has_perm_noaudit(&selinux_state,
-                                 sid, isec->sid, isec->sclass, perms,
-                                 no_block ? AVC_NONBLOCKING : 0,
+                                 sid, isec->sid, isec->sclass, perms, 0,
                                  &avd);
        audited = avc_audit_required(perms, &avd, rc,
                                     from_access ? FILE__AUDIT_ACCESS : 0,
@@ -3218,10 +3213,6 @@ static int selinux_inode_permission(struct inode *inode, int mask)
        if (likely(!audited))
                return rc;
 
-       /* fall back to ref-walk if we have to generate audit */
-       if (no_block)
-               return -ECHILD;
-
        rc2 = audit_inode_permission(inode, perms, audited, denied, rc);
        if (rc2)
                return rc2;
index cf4cc3e..c3bbfc8 100644 (file)
@@ -134,9 +134,6 @@ static inline int avc_audit(struct selinux_state *state,
        audited = avc_audit_required(requested, avd, result, 0, &denied);
        if (likely(!audited))
                return 0;
-       /* fall back to ref-walk if we have to generate audit */
-       if (flags & MAY_NOT_BLOCK)
-               return -ECHILD;
        return slow_avc_audit(state, ssid, tsid, tclass,
                              requested, audited, denied, result,
                              a);
@@ -144,7 +141,6 @@ static inline int avc_audit(struct selinux_state *state,
 
 #define AVC_STRICT 1 /* Ignore permissive mode. */
 #define AVC_EXTENDED_PERMS 2   /* update extended permissions */
-#define AVC_NONBLOCKING    4   /* non blocking */
 int avc_has_perm_noaudit(struct selinux_state *state,
                         u32 ssid, u32 tsid,
                         u16 tclass, u32 requested,