Skip to content

Commit 3a28cff

Browse files
stephensmalleypcmoore
authored andcommitted
selinux: avoid silent denials in permissive mode under RCU walk
commit 0dc1ba2 ("SELINUX: Make selinux cache VFS RCU walks safe") results in no audit messages at all if in permissive mode because the cache is updated during the rcu walk and thus no denial occurs on the subsequent ref walk. Fix this by not updating the cache when performing a non-blocking permission check. This only affects search and symlink read checks during rcu walk. Fixes: 0dc1ba2 ("SELINUX: Make selinux cache VFS RCU walks safe") Reported-by: BMK <[email protected]> Signed-off-by: Stephen Smalley <[email protected]> Signed-off-by: Paul Moore <[email protected]>
1 parent bfeffd1 commit 3a28cff

3 files changed

Lines changed: 25 additions & 3 deletions

File tree

security/selinux/avc.c

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -838,6 +838,7 @@ int __init avc_add_callback(int (*callback)(u32 event), u32 events)
838838
* @ssid,@tsid,@tclass : identifier of an AVC entry
839839
* @seqno : sequence number when decision was made
840840
* @xpd: extended_perms_decision to be added to the node
841+
* @flags: the AVC_* flags, e.g. AVC_NONBLOCKING, AVC_EXTENDED_PERMS, or 0.
841842
*
842843
* if a valid AVC entry doesn't exist,this function returns -ENOENT.
843844
* if kmalloc() called internal returns NULL, this function returns -ENOMEM.
@@ -856,6 +857,23 @@ static int avc_update_node(struct selinux_avc *avc,
856857
struct hlist_head *head;
857858
spinlock_t *lock;
858859

860+
/*
861+
* If we are in a non-blocking code path, e.g. VFS RCU walk,
862+
* then we must not add permissions to a cache entry
863+
* because we cannot safely audit the denial. Otherwise,
864+
* during the subsequent blocking retry (e.g. VFS ref walk), we
865+
* will find the permissions already granted in the cache entry
866+
* and won't audit anything at all, leading to silent denials in
867+
* permissive mode that only appear when in enforcing mode.
868+
*
869+
* See the corresponding handling in slow_avc_audit(), and the
870+
* logic in selinux_inode_follow_link and selinux_inode_permission
871+
* for the VFS MAY_NOT_BLOCK flag, which is transliterated into
872+
* AVC_NONBLOCKING for avc_has_perm_noaudit().
873+
*/
874+
if (flags & AVC_NONBLOCKING)
875+
return 0;
876+
859877
node = avc_alloc_node(avc);
860878
if (!node) {
861879
rc = -ENOMEM;
@@ -1115,7 +1133,7 @@ int avc_has_extended_perms(struct selinux_state *state,
11151133
* @tsid: target security identifier
11161134
* @tclass: target security class
11171135
* @requested: requested permissions, interpreted based on @tclass
1118-
* @flags: AVC_STRICT or 0
1136+
* @flags: AVC_STRICT, AVC_NONBLOCKING, or 0
11191137
* @avd: access vector decisions
11201138
*
11211139
* Check the AVC to determine whether the @requested permissions are granted
@@ -1199,7 +1217,8 @@ int avc_has_perm_flags(struct selinux_state *state,
11991217
struct av_decision avd;
12001218
int rc, rc2;
12011219

1202-
rc = avc_has_perm_noaudit(state, ssid, tsid, tclass, requested, 0,
1220+
rc = avc_has_perm_noaudit(state, ssid, tsid, tclass, requested,
1221+
(flags & MAY_NOT_BLOCK) ? AVC_NONBLOCKING : 0,
12031222
&avd);
12041223

12051224
rc2 = avc_audit(state, ssid, tsid, tclass, requested, &avd, rc,

security/selinux/hooks.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2982,7 +2982,9 @@ static int selinux_inode_permission(struct inode *inode, int mask)
29822982
return PTR_ERR(isec);
29832983

29842984
rc = avc_has_perm_noaudit(&selinux_state,
2985-
sid, isec->sid, isec->sclass, perms, 0, &avd);
2985+
sid, isec->sid, isec->sclass, perms,
2986+
(flags & MAY_NOT_BLOCK) ? AVC_NONBLOCKING : 0,
2987+
&avd);
29862988
audited = avc_audit_required(perms, &avd, rc,
29872989
from_access ? FILE__AUDIT_ACCESS : 0,
29882990
&denied);

security/selinux/include/avc.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,7 @@ static inline int avc_audit(struct selinux_state *state,
142142

143143
#define AVC_STRICT 1 /* Ignore permissive mode. */
144144
#define AVC_EXTENDED_PERMS 2 /* update extended permissions */
145+
#define AVC_NONBLOCKING 4 /* non blocking */
145146
int avc_has_perm_noaudit(struct selinux_state *state,
146147
u32 ssid, u32 tsid,
147148
u16 tclass, u32 requested,

0 commit comments

Comments
 (0)