diff options
Diffstat (limited to 'security/selinux/avc.c')
-rw-r--r-- | security/selinux/avc.c | 61 |
1 files changed, 16 insertions, 45 deletions
diff --git a/security/selinux/avc.c b/security/selinux/avc.c index ad451cf9375e..97f4c944a20f 100644 --- a/security/selinux/avc.c +++ b/security/selinux/avc.c @@ -297,26 +297,27 @@ static struct avc_xperms_decision_node struct avc_xperms_decision_node *xpd_node; struct extended_perms_decision *xpd; - xpd_node = kmem_cache_zalloc(avc_xperms_decision_cachep, GFP_NOWAIT); + xpd_node = kmem_cache_zalloc(avc_xperms_decision_cachep, + GFP_NOWAIT | __GFP_NOWARN); if (!xpd_node) return NULL; xpd = &xpd_node->xpd; if (which & XPERMS_ALLOWED) { xpd->allowed = kmem_cache_zalloc(avc_xperms_data_cachep, - GFP_NOWAIT); + GFP_NOWAIT | __GFP_NOWARN); if (!xpd->allowed) goto error; } if (which & XPERMS_AUDITALLOW) { xpd->auditallow = kmem_cache_zalloc(avc_xperms_data_cachep, - GFP_NOWAIT); + GFP_NOWAIT | __GFP_NOWARN); if (!xpd->auditallow) goto error; } if (which & XPERMS_DONTAUDIT) { xpd->dontaudit = kmem_cache_zalloc(avc_xperms_data_cachep, - GFP_NOWAIT); + GFP_NOWAIT | __GFP_NOWARN); if (!xpd->dontaudit) goto error; } @@ -344,7 +345,7 @@ static struct avc_xperms_node *avc_xperms_alloc(void) { struct avc_xperms_node *xp_node; - xp_node = kmem_cache_zalloc(avc_xperms_cachep, GFP_NOWAIT); + xp_node = kmem_cache_zalloc(avc_xperms_cachep, GFP_NOWAIT | __GFP_NOWARN); if (!xp_node) return xp_node; INIT_LIST_HEAD(&xp_node->xpd_head); @@ -500,7 +501,7 @@ static struct avc_node *avc_alloc_node(struct selinux_avc *avc) { struct avc_node *node; - node = kmem_cache_zalloc(avc_node_cachep, GFP_NOWAIT); + node = kmem_cache_zalloc(avc_node_cachep, GFP_NOWAIT | __GFP_NOWARN); if (!node) goto out; @@ -758,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, @@ -819,13 +824,13 @@ out: } /** - * avc_update_node Update an AVC entry + * avc_update_node - Update an AVC entry * @event : Updating event * @perms : Permission mask bits * @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. @@ -844,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; @@ -1119,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 @@ -1190,26 +1180,7 @@ int avc_has_perm(struct selinux_state *state, u32 ssid, u32 tsid, u16 tclass, &avd); rc2 = avc_audit(state, ssid, tsid, tclass, requested, &avd, rc, - auditdata, 0); - if (rc2) - return rc2; - return rc; -} - -int avc_has_perm_flags(struct selinux_state *state, - u32 ssid, u32 tsid, u16 tclass, u32 requested, - struct common_audit_data *auditdata, - int flags) -{ - struct av_decision avd; - int rc, rc2; - - rc = avc_has_perm_noaudit(state, ssid, tsid, tclass, requested, - (flags & MAY_NOT_BLOCK) ? AVC_NONBLOCKING : 0, - &avd); - - rc2 = avc_audit(state, ssid, tsid, tclass, requested, &avd, rc, - auditdata, flags); + auditdata); if (rc2) return rc2; return rc; |