summaryrefslogtreecommitdiff
path: root/security/selinux/avc.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/selinux/avc.c')
-rw-r--r--security/selinux/avc.c276
1 files changed, 139 insertions, 137 deletions
diff --git a/security/selinux/avc.c b/security/selinux/avc.c
index 9a43af0ebd7d..eaed5c2da02b 100644
--- a/security/selinux/avc.c
+++ b/security/selinux/avc.c
@@ -93,7 +93,7 @@ struct selinux_avc {
static struct selinux_avc selinux_avc;
-void selinux_avc_init(struct selinux_avc **avc)
+void selinux_avc_init(void)
{
int i;
@@ -104,18 +104,16 @@ void selinux_avc_init(struct selinux_avc **avc)
}
atomic_set(&selinux_avc.avc_cache.active_nodes, 0);
atomic_set(&selinux_avc.avc_cache.lru_hint, 0);
- *avc = &selinux_avc;
}
-unsigned int avc_get_cache_threshold(struct selinux_avc *avc)
+unsigned int avc_get_cache_threshold(void)
{
- return avc->avc_cache_threshold;
+ return selinux_avc.avc_cache_threshold;
}
-void avc_set_cache_threshold(struct selinux_avc *avc,
- unsigned int cache_threshold)
+void avc_set_cache_threshold(unsigned int cache_threshold)
{
- avc->avc_cache_threshold = cache_threshold;
+ selinux_avc.avc_cache_threshold = cache_threshold;
}
static struct avc_callback_node *avc_callbacks __ro_after_init;
@@ -150,7 +148,7 @@ void __init avc_init(void)
0, SLAB_PANIC, NULL);
}
-int avc_get_hash_stats(struct selinux_avc *avc, char *page)
+int avc_get_hash_stats(char *page)
{
int i, chain_len, max_chain_len, slots_used;
struct avc_node *node;
@@ -161,7 +159,7 @@ int avc_get_hash_stats(struct selinux_avc *avc, char *page)
slots_used = 0;
max_chain_len = 0;
for (i = 0; i < AVC_CACHE_SLOTS; i++) {
- head = &avc->avc_cache.slots[i];
+ head = &selinux_avc.avc_cache.slots[i];
if (!hlist_empty(head)) {
slots_used++;
chain_len = 0;
@@ -176,7 +174,7 @@ int avc_get_hash_stats(struct selinux_avc *avc, char *page)
return scnprintf(page, PAGE_SIZE, "entries: %d\nbuckets used: %d/%d\n"
"longest chain: %d\n",
- atomic_read(&avc->avc_cache.active_nodes),
+ atomic_read(&selinux_avc.avc_cache.active_nodes),
slots_used, AVC_CACHE_SLOTS, max_chain_len);
}
@@ -414,8 +412,7 @@ static inline u32 avc_xperms_audit_required(u32 requested,
return audited;
}
-static inline int avc_xperms_audit(struct selinux_state *state,
- u32 ssid, u32 tsid, u16 tclass,
+static inline int avc_xperms_audit(u32 ssid, u32 tsid, u16 tclass,
u32 requested, struct av_decision *avd,
struct extended_perms_decision *xpd,
u8 perm, int result,
@@ -427,7 +424,7 @@ static inline int avc_xperms_audit(struct selinux_state *state,
requested, avd, xpd, perm, result, &denied);
if (likely(!audited))
return 0;
- return slow_avc_audit(state, ssid, tsid, tclass, requested,
+ return slow_avc_audit(ssid, tsid, tclass, requested,
audited, denied, result, ad);
}
@@ -439,30 +436,29 @@ static void avc_node_free(struct rcu_head *rhead)
avc_cache_stats_incr(frees);
}
-static void avc_node_delete(struct selinux_avc *avc, struct avc_node *node)
+static void avc_node_delete(struct avc_node *node)
{
hlist_del_rcu(&node->list);
call_rcu(&node->rhead, avc_node_free);
- atomic_dec(&avc->avc_cache.active_nodes);
+ atomic_dec(&selinux_avc.avc_cache.active_nodes);
}
-static void avc_node_kill(struct selinux_avc *avc, struct avc_node *node)
+static void avc_node_kill(struct avc_node *node)
{
avc_xperms_free(node->ae.xp_node);
kmem_cache_free(avc_node_cachep, node);
avc_cache_stats_incr(frees);
- atomic_dec(&avc->avc_cache.active_nodes);
+ atomic_dec(&selinux_avc.avc_cache.active_nodes);
}
-static void avc_node_replace(struct selinux_avc *avc,
- struct avc_node *new, struct avc_node *old)
+static void avc_node_replace(struct avc_node *new, struct avc_node *old)
{
hlist_replace_rcu(&old->list, &new->list);
call_rcu(&old->rhead, avc_node_free);
- atomic_dec(&avc->avc_cache.active_nodes);
+ atomic_dec(&selinux_avc.avc_cache.active_nodes);
}
-static inline int avc_reclaim_node(struct selinux_avc *avc)
+static inline int avc_reclaim_node(void)
{
struct avc_node *node;
int hvalue, try, ecx;
@@ -471,17 +467,17 @@ static inline int avc_reclaim_node(struct selinux_avc *avc)
spinlock_t *lock;
for (try = 0, ecx = 0; try < AVC_CACHE_SLOTS; try++) {
- hvalue = atomic_inc_return(&avc->avc_cache.lru_hint) &
+ hvalue = atomic_inc_return(&selinux_avc.avc_cache.lru_hint) &
(AVC_CACHE_SLOTS - 1);
- head = &avc->avc_cache.slots[hvalue];
- lock = &avc->avc_cache.slots_lock[hvalue];
+ head = &selinux_avc.avc_cache.slots[hvalue];
+ lock = &selinux_avc.avc_cache.slots_lock[hvalue];
if (!spin_trylock_irqsave(lock, flags))
continue;
rcu_read_lock();
hlist_for_each_entry(node, head, list) {
- avc_node_delete(avc, node);
+ avc_node_delete(node);
avc_cache_stats_incr(reclaims);
ecx++;
if (ecx >= AVC_CACHE_RECLAIM) {
@@ -497,7 +493,7 @@ out:
return ecx;
}
-static struct avc_node *avc_alloc_node(struct selinux_avc *avc)
+static struct avc_node *avc_alloc_node(void)
{
struct avc_node *node;
@@ -508,9 +504,9 @@ static struct avc_node *avc_alloc_node(struct selinux_avc *avc)
INIT_HLIST_NODE(&node->list);
avc_cache_stats_incr(allocations);
- if (atomic_inc_return(&avc->avc_cache.active_nodes) >
- avc->avc_cache_threshold)
- avc_reclaim_node(avc);
+ if (atomic_inc_return(&selinux_avc.avc_cache.active_nodes) >
+ selinux_avc.avc_cache_threshold)
+ avc_reclaim_node();
out:
return node;
@@ -524,15 +520,14 @@ static void avc_node_populate(struct avc_node *node, u32 ssid, u32 tsid, u16 tcl
memcpy(&node->ae.avd, avd, sizeof(node->ae.avd));
}
-static inline struct avc_node *avc_search_node(struct selinux_avc *avc,
- u32 ssid, u32 tsid, u16 tclass)
+static inline struct avc_node *avc_search_node(u32 ssid, u32 tsid, u16 tclass)
{
struct avc_node *node, *ret = NULL;
int hvalue;
struct hlist_head *head;
hvalue = avc_hash(ssid, tsid, tclass);
- head = &avc->avc_cache.slots[hvalue];
+ head = &selinux_avc.avc_cache.slots[hvalue];
hlist_for_each_entry_rcu(node, head, list) {
if (ssid == node->ae.ssid &&
tclass == node->ae.tclass &&
@@ -547,7 +542,6 @@ static inline struct avc_node *avc_search_node(struct selinux_avc *avc,
/**
* avc_lookup - Look up an AVC entry.
- * @avc: the access vector cache
* @ssid: source security identifier
* @tsid: target security identifier
* @tclass: target security class
@@ -558,13 +552,12 @@ static inline struct avc_node *avc_search_node(struct selinux_avc *avc,
* then this function returns the avc_node.
* Otherwise, this function returns NULL.
*/
-static struct avc_node *avc_lookup(struct selinux_avc *avc,
- u32 ssid, u32 tsid, u16 tclass)
+static struct avc_node *avc_lookup(u32 ssid, u32 tsid, u16 tclass)
{
struct avc_node *node;
avc_cache_stats_incr(lookups);
- node = avc_search_node(avc, ssid, tsid, tclass);
+ node = avc_search_node(ssid, tsid, tclass);
if (node)
return node;
@@ -573,8 +566,7 @@ static struct avc_node *avc_lookup(struct selinux_avc *avc,
return NULL;
}
-static int avc_latest_notif_update(struct selinux_avc *avc,
- int seqno, int is_insert)
+static int avc_latest_notif_update(int seqno, int is_insert)
{
int ret = 0;
static DEFINE_SPINLOCK(notif_lock);
@@ -582,14 +574,14 @@ static int avc_latest_notif_update(struct selinux_avc *avc,
spin_lock_irqsave(&notif_lock, flag);
if (is_insert) {
- if (seqno < avc->avc_cache.latest_notif) {
+ if (seqno < selinux_avc.avc_cache.latest_notif) {
pr_warn("SELinux: avc: seqno %d < latest_notif %d\n",
- seqno, avc->avc_cache.latest_notif);
+ seqno, selinux_avc.avc_cache.latest_notif);
ret = -EAGAIN;
}
} else {
- if (seqno > avc->avc_cache.latest_notif)
- avc->avc_cache.latest_notif = seqno;
+ if (seqno > selinux_avc.avc_cache.latest_notif)
+ selinux_avc.avc_cache.latest_notif = seqno;
}
spin_unlock_irqrestore(&notif_lock, flag);
@@ -598,7 +590,6 @@ static int avc_latest_notif_update(struct selinux_avc *avc,
/**
* avc_insert - Insert an AVC entry.
- * @avc: the access vector cache
* @ssid: source security identifier
* @tsid: target security identifier
* @tclass: target security class
@@ -612,13 +603,10 @@ static int avc_latest_notif_update(struct selinux_avc *avc,
* response to a security_compute_av() call. If the
* sequence number @avd->seqno is not less than the latest
* revocation notification, then the function copies
- * the access vectors into a cache entry, returns
- * avc_node inserted. Otherwise, this function returns NULL.
+ * the access vectors into a cache entry.
*/
-static struct avc_node *avc_insert(struct selinux_avc *avc,
- u32 ssid, u32 tsid, u16 tclass,
- struct av_decision *avd,
- struct avc_xperms_node *xp_node)
+static void avc_insert(u32 ssid, u32 tsid, u16 tclass,
+ struct av_decision *avd, struct avc_xperms_node *xp_node)
{
struct avc_node *pos, *node = NULL;
int hvalue;
@@ -626,35 +614,35 @@ static struct avc_node *avc_insert(struct selinux_avc *avc,
spinlock_t *lock;
struct hlist_head *head;
- if (avc_latest_notif_update(avc, avd->seqno, 1))
- return NULL;
+ if (avc_latest_notif_update(avd->seqno, 1))
+ return;
- node = avc_alloc_node(avc);
+ node = avc_alloc_node();
if (!node)
- return NULL;
+ return;
avc_node_populate(node, ssid, tsid, tclass, avd);
if (avc_xperms_populate(node, xp_node)) {
- avc_node_kill(avc, node);
- return NULL;
+ avc_node_kill(node);
+ return;
}
hvalue = avc_hash(ssid, tsid, tclass);
- head = &avc->avc_cache.slots[hvalue];
- lock = &avc->avc_cache.slots_lock[hvalue];
+ head = &selinux_avc.avc_cache.slots[hvalue];
+ lock = &selinux_avc.avc_cache.slots_lock[hvalue];
spin_lock_irqsave(lock, flag);
hlist_for_each_entry(pos, head, list) {
if (pos->ae.ssid == ssid &&
pos->ae.tsid == tsid &&
pos->ae.tclass == tclass) {
- avc_node_replace(avc, node, pos);
+ avc_node_replace(node, pos);
goto found;
}
}
hlist_add_head_rcu(&node->list, head);
found:
spin_unlock_irqrestore(lock, flag);
- return node;
+ return;
}
/**
@@ -715,14 +703,14 @@ static void avc_audit_post_callback(struct audit_buffer *ab, void *a)
u32 tcontext_len;
int rc;
- rc = security_sid_to_context(sad->state, sad->ssid, &scontext,
+ rc = security_sid_to_context(sad->ssid, &scontext,
&scontext_len);
if (rc)
audit_log_format(ab, " ssid=%d", sad->ssid);
else
audit_log_format(ab, " scontext=%s", scontext);
- rc = security_sid_to_context(sad->state, sad->tsid, &tcontext,
+ rc = security_sid_to_context(sad->tsid, &tcontext,
&tcontext_len);
if (rc)
audit_log_format(ab, " tsid=%d", sad->tsid);
@@ -740,7 +728,7 @@ static void avc_audit_post_callback(struct audit_buffer *ab, void *a)
kfree(scontext);
/* in case of invalid context report also the actual context string */
- rc = security_sid_to_context_inval(sad->state, sad->ssid, &scontext,
+ rc = security_sid_to_context_inval(sad->ssid, &scontext,
&scontext_len);
if (!rc && scontext) {
if (scontext_len && scontext[scontext_len - 1] == '\0')
@@ -750,7 +738,7 @@ static void avc_audit_post_callback(struct audit_buffer *ab, void *a)
kfree(scontext);
}
- rc = security_sid_to_context_inval(sad->state, sad->tsid, &scontext,
+ rc = security_sid_to_context_inval(sad->tsid, &scontext,
&scontext_len);
if (!rc && scontext) {
if (scontext_len && scontext[scontext_len - 1] == '\0')
@@ -766,8 +754,7 @@ static void avc_audit_post_callback(struct audit_buffer *ab, void *a)
* 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,
+noinline int slow_avc_audit(u32 ssid, u32 tsid, u16 tclass,
u32 requested, u32 audited, u32 denied, int result,
struct common_audit_data *a)
{
@@ -789,7 +776,6 @@ noinline int slow_avc_audit(struct selinux_state *state,
sad.audited = audited;
sad.denied = denied;
sad.result = result;
- sad.state = state;
a->selinux_audit_data = &sad;
@@ -827,7 +813,6 @@ out:
/**
* avc_update_node - Update an AVC entry
- * @avc: the access vector cache
* @event : Updating event
* @perms : Permission mask bits
* @driver: xperm driver information
@@ -844,8 +829,7 @@ out:
* otherwise, this function updates the AVC entry. The original AVC-entry object
* will release later by RCU.
*/
-static int avc_update_node(struct selinux_avc *avc,
- u32 event, u32 perms, u8 driver, u8 xperm, u32 ssid,
+static int avc_update_node(u32 event, u32 perms, u8 driver, u8 xperm, u32 ssid,
u32 tsid, u16 tclass, u32 seqno,
struct extended_perms_decision *xpd,
u32 flags)
@@ -856,7 +840,7 @@ static int avc_update_node(struct selinux_avc *avc,
struct hlist_head *head;
spinlock_t *lock;
- node = avc_alloc_node(avc);
+ node = avc_alloc_node();
if (!node) {
rc = -ENOMEM;
goto out;
@@ -865,8 +849,8 @@ static int avc_update_node(struct selinux_avc *avc,
/* Lock the target slot */
hvalue = avc_hash(ssid, tsid, tclass);
- head = &avc->avc_cache.slots[hvalue];
- lock = &avc->avc_cache.slots_lock[hvalue];
+ head = &selinux_avc.avc_cache.slots[hvalue];
+ lock = &selinux_avc.avc_cache.slots_lock[hvalue];
spin_lock_irqsave(lock, flag);
@@ -882,7 +866,7 @@ static int avc_update_node(struct selinux_avc *avc,
if (!orig) {
rc = -ENOENT;
- avc_node_kill(avc, node);
+ avc_node_kill(node);
goto out_unlock;
}
@@ -895,7 +879,7 @@ static int avc_update_node(struct selinux_avc *avc,
if (orig->ae.xp_node) {
rc = avc_xperms_populate(node, orig->ae.xp_node);
if (rc) {
- avc_node_kill(avc, node);
+ avc_node_kill(node);
goto out_unlock;
}
}
@@ -926,7 +910,7 @@ static int avc_update_node(struct selinux_avc *avc,
avc_add_xperms_decision(node, xpd);
break;
}
- avc_node_replace(avc, node, orig);
+ avc_node_replace(node, orig);
out_unlock:
spin_unlock_irqrestore(lock, flag);
out:
@@ -935,9 +919,8 @@ out:
/**
* avc_flush - Flush the cache
- * @avc: the access vector cache
*/
-static void avc_flush(struct selinux_avc *avc)
+static void avc_flush(void)
{
struct hlist_head *head;
struct avc_node *node;
@@ -946,8 +929,8 @@ static void avc_flush(struct selinux_avc *avc)
int i;
for (i = 0; i < AVC_CACHE_SLOTS; i++) {
- head = &avc->avc_cache.slots[i];
- lock = &avc->avc_cache.slots_lock[i];
+ head = &selinux_avc.avc_cache.slots[i];
+ lock = &selinux_avc.avc_cache.slots_lock[i];
spin_lock_irqsave(lock, flag);
/*
@@ -956,7 +939,7 @@ static void avc_flush(struct selinux_avc *avc)
*/
rcu_read_lock();
hlist_for_each_entry(node, head, list)
- avc_node_delete(avc, node);
+ avc_node_delete(node);
rcu_read_unlock();
spin_unlock_irqrestore(lock, flag);
}
@@ -964,15 +947,14 @@ static void avc_flush(struct selinux_avc *avc)
/**
* avc_ss_reset - Flush the cache and revalidate migrated permissions.
- * @avc: the access vector cache
* @seqno: policy sequence number
*/
-int avc_ss_reset(struct selinux_avc *avc, u32 seqno)
+int avc_ss_reset(u32 seqno)
{
struct avc_callback_node *c;
int rc = 0, tmprc;
- avc_flush(avc);
+ avc_flush();
for (c = avc_callbacks; c; c = c->next) {
if (c->events & AVC_CALLBACK_RESET) {
@@ -984,34 +966,32 @@ int avc_ss_reset(struct selinux_avc *avc, u32 seqno)
}
}
- avc_latest_notif_update(avc, seqno, 0);
+ avc_latest_notif_update(seqno, 0);
return rc;
}
-/*
- * Slow-path helper function for avc_has_perm_noaudit,
- * when the avc_node lookup fails. We get called with
- * the RCU read lock held, and need to return with it
- * still held, but drop if for the security compute.
+/**
+ * avc_compute_av - Add an entry to the AVC based on the security policy
+ * @ssid: subject
+ * @tsid: object/target
+ * @tclass: object class
+ * @avd: access vector decision
+ * @xp_node: AVC extended permissions node
*
- * Don't inline this, since it's the slow-path and just
- * results in a bigger stack frame.
+ * Slow-path helper function for avc_has_perm_noaudit, when the avc_node lookup
+ * fails. Don't inline this, since it's the slow-path and just results in a
+ * bigger stack frame.
*/
-static noinline
-struct avc_node *avc_compute_av(struct selinux_state *state,
- u32 ssid, u32 tsid,
- u16 tclass, struct av_decision *avd,
- struct avc_xperms_node *xp_node)
+static noinline void avc_compute_av(u32 ssid, u32 tsid, u16 tclass,
+ struct av_decision *avd,
+ struct avc_xperms_node *xp_node)
{
- rcu_read_unlock();
INIT_LIST_HEAD(&xp_node->xpd_head);
- security_compute_av(state, ssid, tsid, tclass, avd, &xp_node->xp);
- rcu_read_lock();
- return avc_insert(state->avc, ssid, tsid, tclass, avd, xp_node);
+ security_compute_av(ssid, tsid, tclass, avd, &xp_node->xp);
+ avc_insert(ssid, tsid, tclass, avd, xp_node);
}
-static noinline int avc_denied(struct selinux_state *state,
- u32 ssid, u32 tsid,
+static noinline int avc_denied(u32 ssid, u32 tsid,
u16 tclass, u32 requested,
u8 driver, u8 xperm, unsigned int flags,
struct av_decision *avd)
@@ -1019,11 +999,11 @@ static noinline int avc_denied(struct selinux_state *state,
if (flags & AVC_STRICT)
return -EACCES;
- if (enforcing_enabled(state) &&
+ if (enforcing_enabled() &&
!(avd->flags & AVD_FLAGS_PERMISSIVE))
return -EACCES;
- avc_update_node(state->avc, AVC_CALLBACK_GRANT, requested, driver,
+ avc_update_node(AVC_CALLBACK_GRANT, requested, driver,
xperm, ssid, tsid, tclass, avd->seqno, NULL, flags);
return 0;
}
@@ -1035,8 +1015,7 @@ static noinline int avc_denied(struct selinux_state *state,
* as-is the case with ioctls, then multiple may be chained together and the
* driver field is used to specify which set contains the permission.
*/
-int avc_has_extended_perms(struct selinux_state *state,
- u32 ssid, u32 tsid, u16 tclass, u32 requested,
+int avc_has_extended_perms(u32 ssid, u32 tsid, u16 tclass, u32 requested,
u8 driver, u8 xperm, struct common_audit_data *ad)
{
struct avc_node *node;
@@ -1057,9 +1036,9 @@ int avc_has_extended_perms(struct selinux_state *state,
rcu_read_lock();
- node = avc_lookup(state->avc, ssid, tsid, tclass);
+ node = avc_lookup(ssid, tsid, tclass);
if (unlikely(!node)) {
- avc_compute_av(state, ssid, tsid, tclass, &avd, xp_node);
+ avc_compute_av(ssid, tsid, tclass, &avd, xp_node);
} else {
memcpy(&avd, &node->ae.avd, sizeof(avd));
xp_node = node->ae.xp_node;
@@ -1083,10 +1062,10 @@ int avc_has_extended_perms(struct selinux_state *state,
goto decision;
}
rcu_read_unlock();
- security_compute_xperms_decision(state, ssid, tsid, tclass,
+ security_compute_xperms_decision(ssid, tsid, tclass,
driver, &local_xpd);
rcu_read_lock();
- avc_update_node(state->avc, AVC_CALLBACK_ADD_XPERMS, requested,
+ avc_update_node(AVC_CALLBACK_ADD_XPERMS, requested,
driver, xperm, ssid, tsid, tclass, avd.seqno,
&local_xpd, 0);
} else {
@@ -1100,12 +1079,12 @@ int avc_has_extended_perms(struct selinux_state *state,
decision:
denied = requested & ~(avd.allowed);
if (unlikely(denied))
- rc = avc_denied(state, ssid, tsid, tclass, requested,
+ rc = avc_denied(ssid, tsid, tclass, requested,
driver, xperm, AVC_EXTENDED_PERMS, &avd);
rcu_read_unlock();
- rc2 = avc_xperms_audit(state, ssid, tsid, tclass, requested,
+ rc2 = avc_xperms_audit(ssid, tsid, tclass, requested,
&avd, xpd, xperm, rc, ad);
if (rc2)
return rc2;
@@ -1113,8 +1092,35 @@ decision:
}
/**
+ * avc_perm_nonode - Add an entry to the AVC
+ * @ssid: subject
+ * @tsid: object/target
+ * @tclass: object class
+ * @requested: requested permissions
+ * @flags: AVC flags
+ * @avd: access vector decision
+ *
+ * This is the "we have no node" part of avc_has_perm_noaudit(), which is
+ * unlikely and needs extra stack space for the new node that we generate, so
+ * don't inline it.
+ */
+static noinline int avc_perm_nonode(u32 ssid, u32 tsid, u16 tclass,
+ u32 requested, unsigned int flags,
+ struct av_decision *avd)
+{
+ u32 denied;
+ struct avc_xperms_node xp_node;
+
+ avc_compute_av(ssid, tsid, tclass, avd, &xp_node);
+ denied = requested & ~(avd->allowed);
+ if (unlikely(denied))
+ return avc_denied(ssid, tsid, tclass, requested, 0, 0,
+ flags, avd);
+ return 0;
+}
+
+/**
* avc_has_perm_noaudit - Check permissions but perform no auditing.
- * @state: SELinux state
* @ssid: source security identifier
* @tsid: target security identifier
* @tclass: target security class
@@ -1133,40 +1139,36 @@ decision:
* auditing, e.g. in cases where a lock must be held for the check but
* should be released for the auditing.
*/
-inline int avc_has_perm_noaudit(struct selinux_state *state,
- u32 ssid, u32 tsid,
+inline int avc_has_perm_noaudit(u32 ssid, u32 tsid,
u16 tclass, u32 requested,
unsigned int flags,
struct av_decision *avd)
{
- struct avc_node *node;
- struct avc_xperms_node xp_node;
- int rc = 0;
u32 denied;
+ struct avc_node *node;
if (WARN_ON(!requested))
return -EACCES;
rcu_read_lock();
+ node = avc_lookup(ssid, tsid, tclass);
+ if (unlikely(!node)) {
+ rcu_read_unlock();
+ return avc_perm_nonode(ssid, tsid, tclass, requested,
+ flags, avd);
+ }
+ denied = requested & ~node->ae.avd.allowed;
+ memcpy(avd, &node->ae.avd, sizeof(*avd));
+ rcu_read_unlock();
- node = avc_lookup(state->avc, ssid, tsid, tclass);
- if (unlikely(!node))
- avc_compute_av(state, ssid, tsid, tclass, avd, &xp_node);
- else
- memcpy(avd, &node->ae.avd, sizeof(*avd));
-
- denied = requested & ~(avd->allowed);
if (unlikely(denied))
- rc = avc_denied(state, ssid, tsid, tclass, requested, 0, 0,
- flags, avd);
-
- rcu_read_unlock();
- return rc;
+ return avc_denied(ssid, tsid, tclass, requested, 0, 0,
+ flags, avd);
+ return 0;
}
/**
* avc_has_perm - Check permissions and perform any appropriate auditing.
- * @state: SELinux state
* @ssid: source security identifier
* @tsid: target security identifier
* @tclass: target security class
@@ -1181,25 +1183,25 @@ inline int avc_has_perm_noaudit(struct selinux_state *state,
* permissions are granted, -%EACCES if any permissions are denied, or
* another -errno upon other errors.
*/
-int avc_has_perm(struct selinux_state *state, u32 ssid, u32 tsid, u16 tclass,
+int avc_has_perm(u32 ssid, u32 tsid, u16 tclass,
u32 requested, struct common_audit_data *auditdata)
{
struct av_decision avd;
int rc, rc2;
- rc = avc_has_perm_noaudit(state, ssid, tsid, tclass, requested, 0,
+ rc = avc_has_perm_noaudit(ssid, tsid, tclass, requested, 0,
&avd);
- rc2 = avc_audit(state, ssid, tsid, tclass, requested, &avd, rc,
+ rc2 = avc_audit(ssid, tsid, tclass, requested, &avd, rc,
auditdata);
if (rc2)
return rc2;
return rc;
}
-u32 avc_policy_seqno(struct selinux_state *state)
+u32 avc_policy_seqno(void)
{
- return state->avc->avc_cache.latest_notif;
+ return selinux_avc.avc_cache.latest_notif;
}
void avc_disable(void)
@@ -1216,7 +1218,7 @@ void avc_disable(void)
* the cache and get that memory back.
*/
if (avc_node_cachep) {
- avc_flush(selinux_state.avc);
+ avc_flush();
/* kmem_cache_destroy(avc_node_cachep); */
}
}