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: Al Viro <viro@zeniv.linux.org.uk> Signed-off-by: Paul Moore <paul@paul-moore.com>
This commit is contained in:
parent
d0a83314db
commit
b17ec22fb3
3 changed files with 10 additions and 35 deletions
|
@ -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 @@ 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.
|
* @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,
|
||||||
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 @@ 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, 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,
|
||||||
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,
|
||||||
{
|
{
|
||||||
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)
|
||||||
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)
|
||||||
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,
|
||||||
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,
|
||||||
|
|
||||||
#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,
|
||||||
|
|
Loading…
Add table
Reference in a new issue