|
@@ -838,6 +838,7 @@ out:
|
|
|
* @ssid,@tsid,@tclass : identifier of an AVC entry
|
|
* @ssid,@tsid,@tclass : identifier of an AVC entry
|
|
|
* @seqno : sequence number when decision was made
|
|
* @seqno : sequence number when decision was made
|
|
|
* @xpd: extended_perms_decision to be added to the node
|
|
* @xpd: extended_perms_decision to be added to the node
|
|
|
|
|
+ * @flags: the AVC_* flags, e.g. AVC_NONBLOCKING, AVC_EXTENDED_PERMS, or 0.
|
|
|
*
|
|
*
|
|
|
* if a valid AVC entry doesn't exist,this function returns -ENOENT.
|
|
* if a valid AVC entry doesn't exist,this function returns -ENOENT.
|
|
|
* if kmalloc() called internal returns NULL, this function returns -ENOMEM.
|
|
* if kmalloc() called internal returns NULL, this function returns -ENOMEM.
|
|
@@ -856,6 +857,23 @@ static int avc_update_node(struct selinux_avc *avc,
|
|
|
struct hlist_head *head;
|
|
struct hlist_head *head;
|
|
|
spinlock_t *lock;
|
|
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 cannot safely 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 in slow_avc_audit(), and the
|
|
|
|
|
+ * logic in selinux_inode_follow_link and selinux_inode_permission
|
|
|
|
|
+ * for the VFS MAY_NOT_BLOCK flag, which is transliterated into
|
|
|
|
|
+ * AVC_NONBLOCKING for avc_has_perm_noaudit().
|
|
|
|
|
+ */
|
|
|
|
|
+ if (flags & AVC_NONBLOCKING)
|
|
|
|
|
+ return 0;
|
|
|
|
|
+
|
|
|
node = avc_alloc_node(avc);
|
|
node = avc_alloc_node(avc);
|
|
|
if (!node) {
|
|
if (!node) {
|
|
|
rc = -ENOMEM;
|
|
rc = -ENOMEM;
|
|
@@ -1115,7 +1133,7 @@ decision:
|
|
|
* @tsid: target security identifier
|
|
* @tsid: target security identifier
|
|
|
* @tclass: target security class
|
|
* @tclass: target security class
|
|
|
* @requested: requested permissions, interpreted based on @tclass
|
|
* @requested: requested permissions, interpreted based on @tclass
|
|
|
- * @flags: AVC_STRICT or 0
|
|
|
|
|
|
|
+ * @flags: AVC_STRICT, AVC_NONBLOCKING, or 0
|
|
|
* @avd: access vector decisions
|
|
* @avd: access vector decisions
|
|
|
*
|
|
*
|
|
|
* Check the AVC to determine whether the @requested permissions are granted
|
|
* Check the AVC to determine whether the @requested permissions are granted
|
|
@@ -1199,7 +1217,8 @@ int avc_has_perm_flags(struct selinux_state *state,
|
|
|
struct av_decision avd;
|
|
struct av_decision avd;
|
|
|
int rc, rc2;
|
|
int rc, rc2;
|
|
|
|
|
|
|
|
- rc = avc_has_perm_noaudit(state, ssid, tsid, tclass, requested, 0,
|
|
|
|
|
|
|
+ rc = avc_has_perm_noaudit(state, ssid, tsid, tclass, requested,
|
|
|
|
|
+ (flags & MAY_NOT_BLOCK) ? AVC_NONBLOCKING : 0,
|
|
|
&avd);
|
|
&avd);
|
|
|
|
|
|
|
|
rc2 = avc_audit(state, ssid, tsid, tclass, requested, &avd, rc,
|
|
rc2 = avc_audit(state, ssid, tsid, tclass, requested, &avd, rc,
|