Commit b17ec22f authored by Al Viro's avatar Al Viro Committed by Paul Moore

selinux: slow_avc_audit has become non-blocking

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: default avatarAl Viro <viro@zeniv.linux.org.uk>
Signed-off-by: default avatarPaul Moore <paul@paul-moore.com>
parent d0a83314
...@@ -759,7 +759,11 @@ static void avc_audit_post_callback(struct audit_buffer *ab, void *a) ...@@ -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, noinline int slow_avc_audit(struct selinux_state *state,
u32 ssid, u32 tsid, u16 tclass, u32 ssid, u32 tsid, u16 tclass,
u32 requested, u32 audited, u32 denied, int result, u32 requested, u32 audited, u32 denied, int result,
...@@ -826,7 +830,7 @@ int __init avc_add_callback(int (*callback)(u32 event), u32 events) ...@@ -826,7 +830,7 @@ int __init avc_add_callback(int (*callback)(u32 event), u32 events)
* @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. * @flags: the AVC_* flags, e.g. 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.
...@@ -845,21 +849,6 @@ static int avc_update_node(struct selinux_avc *avc, ...@@ -845,21 +849,6 @@ 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 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); node = avc_alloc_node(avc);
if (!node) { if (!node) {
rc = -ENOMEM; rc = -ENOMEM;
...@@ -1120,7 +1109,7 @@ int avc_has_extended_perms(struct selinux_state *state, ...@@ -1120,7 +1109,7 @@ int avc_has_extended_perms(struct selinux_state *state,
* @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, AVC_NONBLOCKING, or 0 * @flags: AVC_STRICT 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
...@@ -1205,8 +1194,7 @@ int avc_has_perm_flags(struct selinux_state *state, ...@@ -1205,8 +1194,7 @@ 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, rc = avc_has_perm_noaudit(state, ssid, tsid, tclass, requested, 0,
(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,
......
...@@ -3164,17 +3164,13 @@ static noinline int audit_inode_permission(struct inode *inode, ...@@ -3164,17 +3164,13 @@ static noinline int audit_inode_permission(struct inode *inode,
{ {
struct common_audit_data ad; struct common_audit_data ad;
struct inode_security_struct *isec = selinux_inode(inode); struct inode_security_struct *isec = selinux_inode(inode);
int rc;
ad.type = LSM_AUDIT_DATA_INODE; ad.type = LSM_AUDIT_DATA_INODE;
ad.u.inode = inode; ad.u.inode = inode;
rc = slow_avc_audit(&selinux_state, return slow_avc_audit(&selinux_state,
current_sid(), isec->sid, isec->sclass, perms, current_sid(), isec->sid, isec->sclass, perms,
audited, denied, result, &ad); audited, denied, result, &ad);
if (rc)
return rc;
return 0;
} }
static int selinux_inode_permission(struct inode *inode, int mask) static int selinux_inode_permission(struct inode *inode, int mask)
...@@ -3209,8 +3205,7 @@ 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); return PTR_ERR(isec);
rc = avc_has_perm_noaudit(&selinux_state, rc = avc_has_perm_noaudit(&selinux_state,
sid, isec->sid, isec->sclass, perms, sid, isec->sid, isec->sclass, perms, 0,
no_block ? AVC_NONBLOCKING : 0,
&avd); &avd);
audited = avc_audit_required(perms, &avd, rc, audited = avc_audit_required(perms, &avd, rc,
from_access ? FILE__AUDIT_ACCESS : 0, from_access ? FILE__AUDIT_ACCESS : 0,
...@@ -3218,10 +3213,6 @@ static int selinux_inode_permission(struct inode *inode, int mask) ...@@ -3218,10 +3213,6 @@ static int selinux_inode_permission(struct inode *inode, int mask)
if (likely(!audited)) if (likely(!audited))
return rc; 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); rc2 = audit_inode_permission(inode, perms, audited, denied, rc);
if (rc2) if (rc2)
return rc2; return rc2;
......
...@@ -134,9 +134,6 @@ static inline int avc_audit(struct selinux_state *state, ...@@ -134,9 +134,6 @@ static inline int avc_audit(struct selinux_state *state,
audited = avc_audit_required(requested, avd, result, 0, &denied); audited = avc_audit_required(requested, avd, result, 0, &denied);
if (likely(!audited)) if (likely(!audited))
return 0; 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, return slow_avc_audit(state, ssid, tsid, tclass,
requested, audited, denied, result, requested, audited, denied, result,
a); a);
...@@ -144,7 +141,6 @@ static inline int avc_audit(struct selinux_state *state, ...@@ -144,7 +141,6 @@ static inline int avc_audit(struct selinux_state *state,
#define AVC_STRICT 1 /* Ignore permissive mode. */ #define AVC_STRICT 1 /* Ignore permissive mode. */
#define AVC_EXTENDED_PERMS 2 /* update extended permissions */ #define AVC_EXTENDED_PERMS 2 /* update extended permissions */
#define AVC_NONBLOCKING 4 /* non blocking */
int avc_has_perm_noaudit(struct selinux_state *state, int avc_has_perm_noaudit(struct selinux_state *state,
u32 ssid, u32 tsid, u32 ssid, u32 tsid,
u16 tclass, u32 requested, u16 tclass, u32 requested,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment