Commit 6575328c authored by James Morris's avatar James Morris Committed by Linus Torvalds

[PATCH] SELinux scalability: convert AVC to RCU

The following patch improves the scalability of SELinux by replacing the
global avc_lock with an RCU based scheme by Kaigai Kohei.  The size of the
cache is made tunable, to allow administrators to tune systems for different
workloads, while statistics are exported via selinuxfs to allow AVC
performance to be monitored at a low level.

AVC nodes are also allocated now via a slab cache, and AVC references have
been removed from the code.

This code has been extensively tested and benchmarked (see benchmark results
below).  Baseline performance is not improved, although it is clear that
dramatic scalability improvements are achieved.

Baseline performance and networking scalability are areas where work is
ongoing (in particular, we need to add caching of some network security
objects so that we don't fallback to policy database lookups on each
permission call).

Benchmark results:

===============================================================================================

System: 4 node 16-way IA64 NUMA

- 'Stream' is based on http://www.cs.virginia.edu/stream/ , HPC memory bandwidth test,
  higher result is better.
- Hackbench: scheduler scalability benchmark by Rusty, lower is better.

Standard kernel:
  2.6.9-1.648_EL  SELINUX=0 : Stream 6159.987MB/s HackBench 53.144
  2.6.9-1.648_EL  SELINUX=1 : Stream 5872.529MB/s HackBench 1043.132

Kernel with RCU/AVC patches:
  2.6.9-1.689_avcrcu.root SELINUX=0 : Stream 8829.647MB/s HackBench 53.976
  2.6.9-1.689_avcrcu.root SELINUX=1 : Stream 8817.117MB/s HackBench 50.975

===============================================================================================

System: 8-way PIII 900Mhz Xeon with 9GB RAM
Fileystem: ext2 for all testing.

Notes:
    AVC was reset before tests, so avc was flushed.
    System was run in enforcing mode.

Key:
    std-nolsm:      standard kernel with LSM disabled
    std-lsmcap:     standard kernel with LSM enabled, capabilities LSM
    std-sel-strict: standard kernel with SELinux enabled, capabilities secondary LSM
    rcu-sel-strict: as above with RCU & AVC stats patches
parent b0f31274
...@@ -4,6 +4,9 @@ ...@@ -4,6 +4,9 @@
* Authors: Stephen Smalley, <sds@epoch.ncsc.mil> * Authors: Stephen Smalley, <sds@epoch.ncsc.mil>
* James Morris <jmorris@redhat.com> * James Morris <jmorris@redhat.com>
* *
* Update: KaiGai, Kohei <kaigai@ak.jp.nec.com>
* Replaced the avc_lock spinlock by RCU.
*
* Copyright (C) 2003 Red Hat, Inc., James Morris <jmorris@redhat.com> * Copyright (C) 2003 Red Hat, Inc., James Morris <jmorris@redhat.com>
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
...@@ -36,26 +39,29 @@ ...@@ -36,26 +39,29 @@
#include "objsec.h" #include "objsec.h"
#define AVC_CACHE_SLOTS 512 #define AVC_CACHE_SLOTS 512
#define AVC_CACHE_MAXNODES 410 #define AVC_CACHE_THRESHOLD 512
#define AVC_CACHE_RECLAIM 16
struct avc_entry { struct avc_entry {
u32 ssid; u32 ssid;
u32 tsid; u32 tsid;
u16 tclass; u16 tclass;
struct av_decision avd; struct av_decision avd;
int used; /* used recently */ atomic_t used; /* used recently */
}; };
struct avc_node { struct avc_node {
struct avc_entry ae; struct avc_entry ae;
struct avc_node *next; struct list_head list;
struct rcu_head rhead;
}; };
struct avc_cache { struct avc_cache {
struct avc_node *slots[AVC_CACHE_SLOTS]; struct list_head slots[AVC_CACHE_SLOTS];
u32 lru_hint; /* LRU hint for reclaim scan */ spinlock_t slots_lock[AVC_CACHE_SLOTS]; /* lock for writes */
u32 active_nodes; atomic_t lru_hint; /* LRU hint for reclaim scan */
u32 latest_notif; /* latest revocation notification */ atomic_t active_nodes;
u32 latest_notif; /* latest revocation notification */
}; };
struct avc_callback_node { struct avc_callback_node {
...@@ -70,11 +76,10 @@ struct avc_callback_node { ...@@ -70,11 +76,10 @@ struct avc_callback_node {
struct avc_callback_node *next; struct avc_callback_node *next;
}; };
static spinlock_t avc_lock = SPIN_LOCK_UNLOCKED;
static struct avc_node *avc_node_freelist;
static struct avc_cache avc_cache; static struct avc_cache avc_cache;
static unsigned avc_cache_stats[AVC_NSTATS]; static unsigned avc_cache_stats[AVC_NSTATS];
static struct avc_callback_node *avc_callbacks; static struct avc_callback_node *avc_callbacks;
static kmem_cache_t *avc_node_cachep;
static inline int avc_hash(u32 ssid, u32 tsid, u16 tclass) static inline int avc_hash(u32 ssid, u32 tsid, u16 tclass)
{ {
...@@ -188,20 +193,17 @@ void avc_dump_query(struct audit_buffer *ab, u32 ssid, u32 tsid, u16 tclass) ...@@ -188,20 +193,17 @@ void avc_dump_query(struct audit_buffer *ab, u32 ssid, u32 tsid, u16 tclass)
*/ */
void __init avc_init(void) void __init avc_init(void)
{ {
struct avc_node *new;
int i; int i;
for (i = 0; i < AVC_CACHE_MAXNODES; i++) { for (i = 0; i < AVC_CACHE_SLOTS; i++) {
new = kmalloc(sizeof(*new), GFP_ATOMIC); INIT_LIST_HEAD(&avc_cache.slots[i]);
if (!new) { avc_cache.slots_lock[i] = SPIN_LOCK_UNLOCKED;
printk(KERN_WARNING "avc: only able to allocate "
"%d entries\n", i);
break;
}
memset(new, 0, sizeof(*new));
new->next = avc_node_freelist;
avc_node_freelist = new;
} }
atomic_set(&avc_cache.active_nodes, 0);
atomic_set(&avc_cache.lru_hint, 0);
avc_node_cachep = kmem_cache_create("avc_node", sizeof(struct avc_node),
0, SLAB_PANIC, NULL, NULL);
audit_log(current->audit_context, "AVC INITIALIZED\n"); audit_log(current->audit_context, "AVC INITIALIZED\n");
} }
...@@ -211,120 +213,137 @@ static void avc_hash_eval(char *tag) ...@@ -211,120 +213,137 @@ static void avc_hash_eval(char *tag)
{ {
int i, chain_len, max_chain_len, slots_used; int i, chain_len, max_chain_len, slots_used;
struct avc_node *node; struct avc_node *node;
unsigned long flags;
spin_lock_irqsave(&avc_lock,flags); rcu_read_lock();
slots_used = 0; slots_used = 0;
max_chain_len = 0; max_chain_len = 0;
for (i = 0; i < AVC_CACHE_SLOTS; i++) { for (i = 0; i < AVC_CACHE_SLOTS; i++) {
node = avc_cache.slots[i]; if (!list_empty(&avc_cache.slots[i])) {
if (node) {
slots_used++; slots_used++;
chain_len = 0; chain_len = 0;
while (node) { list_for_each_entry_rcu(node, &avc_cache.slots[i], list)
chain_len++; chain_len++;
node = node->next;
}
if (chain_len > max_chain_len) if (chain_len > max_chain_len)
max_chain_len = chain_len; max_chain_len = chain_len;
} }
} }
spin_unlock_irqrestore(&avc_lock,flags); rcu_read_unlock();
printk(KERN_INFO "\n"); printk(KERN_INFO "\n");
printk(KERN_INFO "%s avc: %d entries and %d/%d buckets used, longest " printk(KERN_INFO "%s avc: %d entries and %d/%d buckets used, longest "
"chain length %d\n", tag, avc_cache.active_nodes, slots_used, "chain length %d\n", tag, atomic_read(&avc_cache.active_nodes),
AVC_CACHE_SLOTS, max_chain_len); slots_used, AVC_CACHE_SLOTS, max_chain_len);
} }
#else #else
static inline void avc_hash_eval(char *tag) static inline void avc_hash_eval(char *tag)
{ } { }
#endif #endif
static inline struct avc_node *avc_reclaim_node(void) static void avc_node_free(struct rcu_head *rhead)
{ {
struct avc_node *prev, *cur; struct avc_node *node = container_of(rhead, struct avc_node, rhead);
int hvalue, try; kmem_cache_free(avc_node_cachep, node);
}
hvalue = avc_cache.lru_hint;
for (try = 0; try < 2; try++) {
do {
prev = NULL;
cur = avc_cache.slots[hvalue];
while (cur) {
if (!cur->ae.used)
goto found;
cur->ae.used = 0;
prev = cur;
cur = cur->next;
}
hvalue = (hvalue + 1) & (AVC_CACHE_SLOTS - 1);
} while (hvalue != avc_cache.lru_hint);
}
panic("avc_reclaim_node");
found: static void avc_node_delete(struct avc_node *node)
avc_cache.lru_hint = hvalue; {
list_del_rcu(&node->list);
call_rcu(&node->rhead, avc_node_free);
atomic_dec(&avc_cache.active_nodes);
}
if (prev == NULL) static void avc_node_kill(struct avc_node *node)
avc_cache.slots[hvalue] = cur->next; {
else kmem_cache_free(avc_node_cachep, node);
prev->next = cur->next; avc_cache_stats_incr(frees);
atomic_dec(&avc_cache.active_nodes);
}
return cur; static void avc_node_replace(struct avc_node *new, struct avc_node *old)
{
list_replace_rcu(&old->list, &new->list);
call_rcu(&old->rhead, avc_node_free);
atomic_dec(&avc_cache.active_nodes);
} }
static inline struct avc_node *avc_claim_node(u32 ssid, static inline int avc_reclaim_node(void)
u32 tsid, u16 tclass)
{ {
struct avc_node *new; struct avc_node *node;
int hvalue; int hvalue, try, ecx;
unsigned long flags;
hvalue = avc_hash(ssid, tsid, tclass); for (try = 0, ecx = 0; try < AVC_CACHE_SLOTS; try++ ) {
if (avc_node_freelist) { hvalue = atomic_inc_return(&avc_cache.lru_hint) & (AVC_CACHE_SLOTS - 1);
new = avc_node_freelist;
avc_node_freelist = avc_node_freelist->next; if (!spin_trylock_irqsave(&avc_cache.slots_lock[hvalue], flags))
avc_cache.active_nodes++; continue;
} else {
new = avc_reclaim_node(); list_for_each_entry(node, &avc_cache.slots[hvalue], list) {
if (!new) if (!atomic_dec_and_test(&node->ae.used)) {
goto out; /* Recently Unused */
avc_node_delete(node);
ecx++;
if (ecx >= AVC_CACHE_RECLAIM) {
spin_unlock_irqrestore(&avc_cache.slots_lock[hvalue], flags);
goto out;
}
}
}
spin_unlock_irqrestore(&avc_cache.slots_lock[hvalue], flags);
} }
out:
return ecx;
}
static struct avc_node *avc_alloc_node(void)
{
struct avc_node *node;
node = kmem_cache_alloc(avc_node_cachep, SLAB_ATOMIC);
if (!node)
goto out;
memset(node, 0, sizeof(*node));
INIT_RCU_HEAD(&node->rhead);
INIT_LIST_HEAD(&node->list);
atomic_set(&node->ae.used, 1);
new->ae.used = 1; if (atomic_inc_return(&avc_cache.active_nodes) > AVC_CACHE_THRESHOLD)
new->ae.ssid = ssid; avc_reclaim_node();
new->ae.tsid = tsid;
new->ae.tclass = tclass;
new->next = avc_cache.slots[hvalue];
avc_cache.slots[hvalue] = new;
out: out:
return new; return node;
}
static void avc_node_populate(struct avc_node *node, u32 ssid, u32 tsid, u16 tclass, struct avc_entry *ae)
{
node->ae.ssid = ssid;
node->ae.tsid = tsid;
node->ae.tclass = tclass;
memcpy(&node->ae.avd, &ae->avd, sizeof(node->ae.avd));
} }
static inline struct avc_node *avc_search_node(u32 ssid, u32 tsid, static inline struct avc_node *avc_search_node(u32 ssid, u32 tsid,
u16 tclass, int *probes) u16 tclass, int *probes)
{ {
struct avc_node *cur; struct avc_node *node, *ret = NULL;
int hvalue; int hvalue;
int tprobes = 1; int tprobes = 1;
hvalue = avc_hash(ssid, tsid, tclass); hvalue = avc_hash(ssid, tsid, tclass);
cur = avc_cache.slots[hvalue]; list_for_each_entry_rcu(node, &avc_cache.slots[hvalue], list) {
while (cur != NULL && if (ssid == node->ae.ssid &&
(ssid != cur->ae.ssid || tclass == node->ae.tclass &&
tclass != cur->ae.tclass || tsid == node->ae.tsid) {
tsid != cur->ae.tsid)) { ret = node;
break;
}
tprobes++; tprobes++;
cur = cur->next;
} }
if (cur == NULL) { if (ret == NULL) {
/* cache miss */ /* cache miss */
goto out; goto out;
} }
...@@ -332,11 +351,10 @@ static inline struct avc_node *avc_search_node(u32 ssid, u32 tsid, ...@@ -332,11 +351,10 @@ static inline struct avc_node *avc_search_node(u32 ssid, u32 tsid,
/* cache hit */ /* cache hit */
if (probes) if (probes)
*probes = tprobes; *probes = tprobes;
if (atomic_read(&ret->ae.used) != 1)
cur->ae.used = 1; atomic_set(&ret->ae.used, 1);
out: out:
return cur; return ret;
} }
/** /**
...@@ -345,21 +363,18 @@ static inline struct avc_node *avc_search_node(u32 ssid, u32 tsid, ...@@ -345,21 +363,18 @@ static inline struct avc_node *avc_search_node(u32 ssid, u32 tsid,
* @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
* @aeref: AVC entry reference
* *
* Look up an AVC entry that is valid for the * Look up an AVC entry that is valid for the
* @requested permissions between the SID pair * @requested permissions between the SID pair
* (@ssid, @tsid), interpreting the permissions * (@ssid, @tsid), interpreting the permissions
* based on @tclass. If a valid AVC entry exists, * based on @tclass. If a valid AVC entry exists,
* then this function updates @aeref to refer to the * then this function return the avc_node.
* entry and returns %0. Otherwise, this function * Otherwise, this function returns NULL.
* returns -%ENOENT.
*/ */
int avc_lookup(u32 ssid, u32 tsid, u16 tclass, static struct avc_node *avc_lookup(u32 ssid, u32 tsid, u16 tclass, u32 requested)
u32 requested, struct avc_entry_ref *aeref)
{ {
struct avc_node *node; struct avc_node *node;
int probes, rc = 0; int probes;
avc_cache_stats_incr(AVC_CAV_LOOKUPS); avc_cache_stats_incr(AVC_CAV_LOOKUPS);
node = avc_search_node(ssid, tsid, tclass,&probes); node = avc_search_node(ssid, tsid, tclass,&probes);
...@@ -367,14 +382,35 @@ int avc_lookup(u32 ssid, u32 tsid, u16 tclass, ...@@ -367,14 +382,35 @@ int avc_lookup(u32 ssid, u32 tsid, u16 tclass,
if (node && ((node->ae.avd.decided & requested) == requested)) { if (node && ((node->ae.avd.decided & requested) == requested)) {
avc_cache_stats_incr(AVC_CAV_HITS); avc_cache_stats_incr(AVC_CAV_HITS);
avc_cache_stats_add(AVC_CAV_PROBES,probes); avc_cache_stats_add(AVC_CAV_PROBES,probes);
aeref->ae = &node->ae;
goto out; goto out;
} }
node = NULL;
avc_cache_stats_incr(AVC_CAV_MISSES); avc_cache_stats_incr(AVC_CAV_MISSES);
rc = -ENOENT;
out: out:
return rc; return node;
}
static int avc_latest_notif_update(int seqno, int is_insert)
{
int ret = 0;
static spinlock_t notif_lock = SPIN_LOCK_UNLOCKED;
unsigned long flag;
spin_lock_irqsave(&notif_lock, flag);
if (is_insert) {
if (seqno < avc_cache.latest_notif) {
printk(KERN_WARNING "avc: seqno %d < latest_notif %d\n",
seqno, avc_cache.latest_notif);
ret = -EAGAIN;
}
} else {
if (seqno > avc_cache.latest_notif)
avc_cache.latest_notif = seqno;
}
spin_unlock_irqrestore(&notif_lock, flag);
return ret;
} }
/** /**
...@@ -383,7 +419,6 @@ int avc_lookup(u32 ssid, u32 tsid, u16 tclass, ...@@ -383,7 +419,6 @@ int avc_lookup(u32 ssid, u32 tsid, u16 tclass,
* @tsid: target security identifier * @tsid: target security identifier
* @tclass: target security class * @tclass: target security class
* @ae: AVC entry * @ae: AVC entry
* @aeref: AVC entry reference
* *
* Insert an AVC entry for the SID pair * Insert an AVC entry for the SID pair
* (@ssid, @tsid) and class @tclass. * (@ssid, @tsid) and class @tclass.
...@@ -392,37 +427,38 @@ int avc_lookup(u32 ssid, u32 tsid, u16 tclass, ...@@ -392,37 +427,38 @@ int avc_lookup(u32 ssid, u32 tsid, u16 tclass,
* response to a security_compute_av() call. If the * response to a security_compute_av() call. If the
* sequence number @ae->avd.seqno is not less than the latest * sequence number @ae->avd.seqno is not less than the latest
* revocation notification, then the function copies * revocation notification, then the function copies
* the access vectors into a cache entry, updates * the access vectors into a cache entry, returns
* @aeref to refer to the entry, and returns %0. * avc_node inserted. Otherwise, this function returns NULL.
* Otherwise, this function returns -%EAGAIN.
*/ */
int avc_insert(u32 ssid, u32 tsid, u16 tclass, static struct avc_node *avc_insert(u32 ssid, u32 tsid, u16 tclass, struct avc_entry *ae)
struct avc_entry *ae, struct avc_entry_ref *aeref)
{ {
struct avc_node *node; struct avc_node *pos, *node = NULL;
int rc = 0; int hvalue;
unsigned long flag;
if (ae->avd.seqno < avc_cache.latest_notif) { if (avc_latest_notif_update(ae->avd.seqno, 1))
printk(KERN_WARNING "avc: seqno %d < latest_notif %d\n",
ae->avd.seqno, avc_cache.latest_notif);
rc = -EAGAIN;
goto out; goto out;
}
node = avc_claim_node(ssid, tsid, tclass); node = avc_alloc_node();
if (!node) { if (node) {
rc = -ENOMEM; hvalue = avc_hash(ssid, tsid, tclass);
goto out; avc_node_populate(node, ssid, tsid, tclass, ae);
spin_lock_irqsave(&avc_cache.slots_lock[hvalue], flag);
list_for_each_entry(pos, &avc_cache.slots[hvalue], list) {
if (pos->ae.ssid == ssid &&
pos->ae.tsid == tsid &&
pos->ae.tclass == tclass) {
avc_node_replace(node, pos);
goto found;
}
}
list_add_rcu(&node->list, &avc_cache.slots[hvalue]);
found:
spin_unlock_irqrestore(&avc_cache.slots_lock[hvalue], flag);
} }
node->ae.avd.allowed = ae->avd.allowed;
node->ae.avd.decided = ae->avd.decided;
node->ae.avd.auditallow = ae->avd.auditallow;
node->ae.avd.auditdeny = ae->avd.auditdeny;
node->ae.avd.seqno = ae->avd.seqno;
aeref->ae = &node->ae;
out: out:
return rc; return node;
} }
static inline void avc_print_ipv6_addr(struct audit_buffer *ab, static inline void avc_print_ipv6_addr(struct audit_buffer *ab,
...@@ -686,8 +722,54 @@ static inline int avc_sidcmp(u32 x, u32 y) ...@@ -686,8 +722,54 @@ static inline int avc_sidcmp(u32 x, u32 y)
return (x == y || x == SECSID_WILD || y == SECSID_WILD); return (x == y || x == SECSID_WILD || y == SECSID_WILD);
} }
static inline void avc_update_node(u32 event, struct avc_node *node, u32 perms) /**
* avc_update_node Update an AVC entry
* @event : Updating event
* @perms : Permission mask bits
* @ssid,@tsid,@tclass : identifier of an AVC entry
*
* if a valid AVC entry doesn't exist,this function returns -ENOENT.
* if kmalloc() called internal returns NULL, this function returns -ENOMEM.
* otherwise, this function update the AVC entry. The original AVC-entry object
* will release later by RCU.
*/
static int avc_update_node(u32 event, u32 perms, u32 ssid, u32 tsid, u16 tclass)
{ {
int hvalue, rc = 0;
unsigned long flag;
struct avc_node *pos, *node, *orig = NULL;
node = avc_alloc_node();
if (!node) {
rc = -ENOMEM;
goto out;
}
/* Lock the target slot */
hvalue = avc_hash(ssid, tsid, tclass);
spin_lock_irqsave(&avc_cache.slots_lock[hvalue], flag);
list_for_each_entry(pos, &avc_cache.slots[hvalue], list){
if ( ssid==pos->ae.ssid &&
tsid==pos->ae.tsid &&
tclass==pos->ae.tclass ){
orig = pos;
break;
}
}
if (!orig) {
rc = -ENOENT;
avc_node_kill(node);
goto out_unlock;
}
/*
* Copy and replace original node.
*/
avc_node_populate(node, ssid, tsid, tclass, &orig->ae);
switch (event) { switch (event) {
case AVC_CALLBACK_GRANT: case AVC_CALLBACK_GRANT:
node->ae.avd.allowed |= perms; node->ae.avd.allowed |= perms;
...@@ -709,6 +791,11 @@ static inline void avc_update_node(u32 event, struct avc_node *node, u32 perms) ...@@ -709,6 +791,11 @@ static inline void avc_update_node(u32 event, struct avc_node *node, u32 perms)
node->ae.avd.auditdeny &= ~perms; node->ae.avd.auditdeny &= ~perms;
break; break;
} }
avc_node_replace(node, orig);
out_unlock:
spin_unlock_irqrestore(&avc_cache.slots_lock[hvalue], flag);
out:
return rc;
} }
static int avc_update_cache(u32 event, u32 ssid, u32 tsid, static int avc_update_cache(u32 event, u32 ssid, u32 tsid,
...@@ -716,31 +803,27 @@ static int avc_update_cache(u32 event, u32 ssid, u32 tsid, ...@@ -716,31 +803,27 @@ static int avc_update_cache(u32 event, u32 ssid, u32 tsid,
{ {
struct avc_node *node; struct avc_node *node;
int i; int i;
unsigned long flags;
spin_lock_irqsave(&avc_lock,flags); rcu_read_lock();
if (ssid == SECSID_WILD || tsid == SECSID_WILD) { if (ssid == SECSID_WILD || tsid == SECSID_WILD) {
/* apply to all matching nodes */ /* apply to all matching nodes */
for (i = 0; i < AVC_CACHE_SLOTS; i++) { for (i = 0; i < AVC_CACHE_SLOTS; i++) {
for (node = avc_cache.slots[i]; node; list_for_each_entry_rcu(node, &avc_cache.slots[i], list) {
node = node->next) {
if (avc_sidcmp(ssid, node->ae.ssid) && if (avc_sidcmp(ssid, node->ae.ssid) &&
avc_sidcmp(tsid, node->ae.tsid) && avc_sidcmp(tsid, node->ae.tsid) &&
tclass == node->ae.tclass) { tclass == node->ae.tclass ) {
avc_update_node(event,node,perms); avc_update_node(event, perms, node->ae.ssid,
node->ae.tsid, node->ae.tclass);
} }
} }
} }
} else { } else {
/* apply to one node */ /* apply to one node */
node = avc_search_node(ssid, tsid, tclass, NULL); avc_update_node(event, perms, ssid, tsid, tclass);
if (node) {
avc_update_node(event,node,perms);
}
} }
spin_unlock_irqrestore(&avc_lock,flags); rcu_read_unlock();
return 0; return 0;
} }
...@@ -752,7 +835,6 @@ static int avc_control(u32 event, u32 ssid, u32 tsid, ...@@ -752,7 +835,6 @@ static int avc_control(u32 event, u32 ssid, u32 tsid,
struct avc_callback_node *c; struct avc_callback_node *c;
u32 tretained = 0, cretained = 0; u32 tretained = 0, cretained = 0;
int rc = 0; int rc = 0;
unsigned long flags;
/* /*
* try_revoke only removes permissions from the cache * try_revoke only removes permissions from the cache
...@@ -787,10 +869,7 @@ static int avc_control(u32 event, u32 ssid, u32 tsid, ...@@ -787,10 +869,7 @@ static int avc_control(u32 event, u32 ssid, u32 tsid,
*out_retained = tretained; *out_retained = tretained;
} }
spin_lock_irqsave(&avc_lock,flags); avc_latest_notif_update(seqno, 0);
if (seqno > avc_cache.latest_notif)
avc_cache.latest_notif = seqno;
spin_unlock_irqrestore(&avc_lock,flags);
out: out:
return rc; return rc;
...@@ -857,32 +936,17 @@ int avc_ss_reset(u32 seqno) ...@@ -857,32 +936,17 @@ int avc_ss_reset(u32 seqno)
{ {
struct avc_callback_node *c; struct avc_callback_node *c;
int i, rc = 0; int i, rc = 0;
struct avc_node *node, *tmp; unsigned long flag;
unsigned long flags; struct avc_node *node;
avc_hash_eval("reset"); avc_hash_eval("reset");
spin_lock_irqsave(&avc_lock,flags);
for (i = 0; i < AVC_CACHE_SLOTS; i++) { for (i = 0; i < AVC_CACHE_SLOTS; i++) {
node = avc_cache.slots[i]; spin_lock_irqsave(&avc_cache.slots_lock[i], flag);
while (node) { list_for_each_entry(node, &avc_cache.slots[i], list)
tmp = node; avc_node_delete(node);
node = node->next; spin_unlock_irqrestore(&avc_cache.slots_lock[i], flag);
tmp->ae.ssid = tmp->ae.tsid = SECSID_NULL;
tmp->ae.tclass = SECCLASS_NULL;
tmp->ae.avd.allowed = tmp->ae.avd.decided = 0;
tmp->ae.avd.auditallow = tmp->ae.avd.auditdeny = 0;
tmp->ae.used = 0;
tmp->next = avc_node_freelist;
avc_node_freelist = tmp;
avc_cache.active_nodes--;
}
avc_cache.slots[i] = NULL;
} }
avc_cache.lru_hint = 0;
spin_unlock_irqrestore(&avc_lock,flags);
for (i = 0; i < AVC_NSTATS; i++) for (i = 0; i < AVC_NSTATS; i++)
avc_cache_stats[i] = 0; avc_cache_stats[i] = 0;
...@@ -896,10 +960,7 @@ int avc_ss_reset(u32 seqno) ...@@ -896,10 +960,7 @@ int avc_ss_reset(u32 seqno)
} }
} }
spin_lock_irqsave(&avc_lock,flags); avc_latest_notif_update(seqno, 0);
if (seqno > avc_cache.latest_notif)
avc_cache.latest_notif = seqno;
spin_unlock_irqrestore(&avc_lock,flags);
out: out:
return rc; return rc;
} }
...@@ -950,14 +1011,12 @@ int avc_ss_set_auditdeny(u32 ssid, u32 tsid, u16 tclass, ...@@ -950,14 +1011,12 @@ int avc_ss_set_auditdeny(u32 ssid, u32 tsid, u16 tclass,
* @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
* @aeref: AVC entry reference
* @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
* for the SID pair (@ssid, @tsid), interpreting the permissions * for the SID pair (@ssid, @tsid), interpreting the permissions
* based on @tclass, and call the security server on a cache miss to obtain * based on @tclass, and call the security server on a cache miss to obtain
* a new decision and add it to the cache. Update @aeref to refer to an AVC * a new decision and add it to the cache. Return a copy of the decisions
* entry with the resulting decisions, and return a copy of the decisions
* in @avd. Return %0 if all @requested permissions are granted, * in @avd. Return %0 if all @requested permissions are granted,
* -%EACCES if any permissions are denied, or another -errno upon * -%EACCES if any permissions are denied, or another -errno upon
* other errors. This function is typically called by avc_has_perm(), * other errors. This function is typically called by avc_has_perm(),
...@@ -967,72 +1026,43 @@ int avc_ss_set_auditdeny(u32 ssid, u32 tsid, u16 tclass, ...@@ -967,72 +1026,43 @@ int avc_ss_set_auditdeny(u32 ssid, u32 tsid, u16 tclass,
*/ */
int avc_has_perm_noaudit(u32 ssid, u32 tsid, int avc_has_perm_noaudit(u32 ssid, u32 tsid,
u16 tclass, u32 requested, u16 tclass, u32 requested,
struct avc_entry_ref *aeref, struct av_decision *avd) struct av_decision *avd)
{ {
struct avc_entry *ae; struct avc_node *node;
struct avc_entry entry, *p_ae;
int rc = 0; int rc = 0;
unsigned long flags;
struct avc_entry entry;
u32 denied; u32 denied;
struct avc_entry_ref ref;
if (!aeref) { rcu_read_lock();
avc_entry_ref_init(&ref);
aeref = &ref;
}
spin_lock_irqsave(&avc_lock, flags);
avc_cache_stats_incr(AVC_ENTRY_LOOKUPS); avc_cache_stats_incr(AVC_ENTRY_LOOKUPS);
ae = aeref->ae;
if (ae) {
if (ae->ssid == ssid &&
ae->tsid == tsid &&
ae->tclass == tclass &&
((ae->avd.decided & requested) == requested)) {
avc_cache_stats_incr(AVC_ENTRY_HITS);
ae->used = 1;
} else {
avc_cache_stats_incr(AVC_ENTRY_DISCARDS);
ae = NULL;
}
}
if (!ae) { node = avc_lookup(ssid, tsid, tclass, requested);
avc_cache_stats_incr(AVC_ENTRY_MISSES); if (!node) {
rc = avc_lookup(ssid, tsid, tclass, requested, aeref); rcu_read_unlock();
if (rc) { rc = security_compute_av(ssid,tsid,tclass,requested,&entry.avd);
spin_unlock_irqrestore(&avc_lock,flags); if (rc)
rc = security_compute_av(ssid,tsid,tclass,requested,&entry.avd); goto out;
if (rc) rcu_read_lock();
goto out; node = avc_insert(ssid,tsid,tclass,&entry);
spin_lock_irqsave(&avc_lock, flags);
rc = avc_insert(ssid,tsid,tclass,&entry,aeref);
if (rc) {
spin_unlock_irqrestore(&avc_lock,flags);
goto out;
}
}
ae = aeref->ae;
} }
p_ae = node ? &node->ae : &entry;
if (avd) if (avd)
memcpy(avd, &ae->avd, sizeof(*avd)); memcpy(avd, &p_ae->avd, sizeof(*avd));
denied = requested & ~(ae->avd.allowed); denied = requested & ~(p_ae->avd.allowed);
if (!requested || denied) { if (!requested || denied) {
if (selinux_enforcing) { if (selinux_enforcing)
spin_unlock_irqrestore(&avc_lock,flags);
rc = -EACCES; rc = -EACCES;
goto out; else
} else { if (node)
ae->avd.allowed |= requested; avc_update_node(AVC_CALLBACK_GRANT,requested,
spin_unlock_irqrestore(&avc_lock,flags); ssid,tsid,tclass);
goto out;
}
} }
spin_unlock_irqrestore(&avc_lock,flags); rcu_read_unlock();
out: out:
return rc; return rc;
} }
...@@ -1043,26 +1073,23 @@ int avc_has_perm_noaudit(u32 ssid, u32 tsid, ...@@ -1043,26 +1073,23 @@ int avc_has_perm_noaudit(u32 ssid, u32 tsid,
* @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
* @aeref: AVC entry reference
* @auditdata: auxiliary audit data * @auditdata: auxiliary audit data
* *
* Check the AVC to determine whether the @requested permissions are granted * Check the AVC to determine whether the @requested permissions are granted
* for the SID pair (@ssid, @tsid), interpreting the permissions * for the SID pair (@ssid, @tsid), interpreting the permissions
* based on @tclass, and call the security server on a cache miss to obtain * based on @tclass, and call the security server on a cache miss to obtain
* a new decision and add it to the cache. Update @aeref to refer to an AVC * a new decision and add it to the cache. Audit the granting or denial of
* entry with the resulting decisions. Audit the granting or denial of
* permissions in accordance with the policy. Return %0 if all @requested * permissions in accordance with the policy. Return %0 if all @requested
* permissions are granted, -%EACCES if any permissions are denied, or * permissions are granted, -%EACCES if any permissions are denied, or
* another -errno upon other errors. * another -errno upon other errors.
*/ */
int avc_has_perm(u32 ssid, u32 tsid, u16 tclass, int avc_has_perm(u32 ssid, u32 tsid, u16 tclass,
u32 requested, struct avc_entry_ref *aeref, u32 requested, struct avc_audit_data *auditdata)
struct avc_audit_data *auditdata)
{ {
struct av_decision avd; struct av_decision avd;
int rc; int rc;
rc = avc_has_perm_noaudit(ssid, tsid, tclass, requested, aeref, &avd); rc = avc_has_perm_noaudit(ssid, tsid, tclass, requested, &avd);
avc_audit(ssid, tsid, tclass, requested, &avd, rc, auditdata); avc_audit(ssid, tsid, tclass, requested, &avd, rc, auditdata);
return rc; return rc;
} }
...@@ -448,12 +448,12 @@ static int try_context_mount(struct super_block *sb, void *data) ...@@ -448,12 +448,12 @@ static int try_context_mount(struct super_block *sb, void *data)
} }
rc = avc_has_perm(tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM, rc = avc_has_perm(tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM,
FILESYSTEM__RELABELFROM, NULL, NULL); FILESYSTEM__RELABELFROM, NULL);
if (rc) if (rc)
goto out_free; goto out_free;
rc = avc_has_perm(tsec->sid, sid, SECCLASS_FILESYSTEM, rc = avc_has_perm(tsec->sid, sid, SECCLASS_FILESYSTEM,
FILESYSTEM__RELABELTO, NULL, NULL); FILESYSTEM__RELABELTO, NULL);
if (rc) if (rc)
goto out_free; goto out_free;
...@@ -476,12 +476,12 @@ static int try_context_mount(struct super_block *sb, void *data) ...@@ -476,12 +476,12 @@ static int try_context_mount(struct super_block *sb, void *data)
goto out_free; goto out_free;
rc = avc_has_perm(tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM, rc = avc_has_perm(tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM,
FILESYSTEM__RELABELFROM, NULL, NULL); FILESYSTEM__RELABELFROM, NULL);
if (rc) if (rc)
goto out_free; goto out_free;
rc = avc_has_perm(sid, sbsec->sid, SECCLASS_FILESYSTEM, rc = avc_has_perm(sid, sbsec->sid, SECCLASS_FILESYSTEM,
FILESYSTEM__ASSOCIATE, NULL, NULL); FILESYSTEM__ASSOCIATE, NULL);
if (rc) if (rc)
goto out_free; goto out_free;
...@@ -927,7 +927,7 @@ int task_has_perm(struct task_struct *tsk1, ...@@ -927,7 +927,7 @@ int task_has_perm(struct task_struct *tsk1,
tsec1 = tsk1->security; tsec1 = tsk1->security;
tsec2 = tsk2->security; tsec2 = tsk2->security;
return avc_has_perm(tsec1->sid, tsec2->sid, return avc_has_perm(tsec1->sid, tsec2->sid,
SECCLASS_PROCESS, perms, &tsec2->avcr, NULL); SECCLASS_PROCESS, perms, NULL);
} }
/* Check whether a task is allowed to use a capability. */ /* Check whether a task is allowed to use a capability. */
...@@ -944,7 +944,7 @@ int task_has_capability(struct task_struct *tsk, ...@@ -944,7 +944,7 @@ int task_has_capability(struct task_struct *tsk,
ad.u.cap = cap; ad.u.cap = cap;
return avc_has_perm(tsec->sid, tsec->sid, return avc_has_perm(tsec->sid, tsec->sid,
SECCLASS_CAPABILITY, CAP_TO_MASK(cap), NULL, &ad); SECCLASS_CAPABILITY, CAP_TO_MASK(cap), &ad);
} }
/* Check whether a task is allowed to use a system operation. */ /* Check whether a task is allowed to use a system operation. */
...@@ -956,18 +956,15 @@ int task_has_system(struct task_struct *tsk, ...@@ -956,18 +956,15 @@ int task_has_system(struct task_struct *tsk,
tsec = tsk->security; tsec = tsk->security;
return avc_has_perm(tsec->sid, SECINITSID_KERNEL, return avc_has_perm(tsec->sid, SECINITSID_KERNEL,
SECCLASS_SYSTEM, perms, NULL, NULL); SECCLASS_SYSTEM, perms, NULL);
} }
/* Check whether a task has a particular permission to an inode. /* Check whether a task has a particular permission to an inode.
The 'aeref' parameter is optional and allows other AVC
entry references to be passed (e.g. the one in the struct file).
The 'adp' parameter is optional and allows other audit The 'adp' parameter is optional and allows other audit
data to be passed (e.g. the dentry). */ data to be passed (e.g. the dentry). */
int inode_has_perm(struct task_struct *tsk, int inode_has_perm(struct task_struct *tsk,
struct inode *inode, struct inode *inode,
u32 perms, u32 perms,
struct avc_entry_ref *aeref,
struct avc_audit_data *adp) struct avc_audit_data *adp)
{ {
struct task_security_struct *tsec; struct task_security_struct *tsec;
...@@ -983,8 +980,7 @@ int inode_has_perm(struct task_struct *tsk, ...@@ -983,8 +980,7 @@ int inode_has_perm(struct task_struct *tsk,
ad.u.fs.inode = inode; ad.u.fs.inode = inode;
} }
return avc_has_perm(tsec->sid, isec->sid, isec->sclass, return avc_has_perm(tsec->sid, isec->sid, isec->sclass, perms, adp);
perms, aeref ? aeref : &isec->avcr, adp);
} }
/* Same as inode_has_perm, but pass explicit audit data containing /* Same as inode_has_perm, but pass explicit audit data containing
...@@ -1000,7 +996,7 @@ static inline int dentry_has_perm(struct task_struct *tsk, ...@@ -1000,7 +996,7 @@ static inline int dentry_has_perm(struct task_struct *tsk,
AVC_AUDIT_DATA_INIT(&ad,FS); AVC_AUDIT_DATA_INIT(&ad,FS);
ad.u.fs.mnt = mnt; ad.u.fs.mnt = mnt;
ad.u.fs.dentry = dentry; ad.u.fs.dentry = dentry;
return inode_has_perm(tsk, inode, av, NULL, &ad); return inode_has_perm(tsk, inode, av, &ad);
} }
/* Check whether a task can use an open file descriptor to /* Check whether a task can use an open file descriptor to
...@@ -1031,14 +1027,14 @@ static inline int file_has_perm(struct task_struct *tsk, ...@@ -1031,14 +1027,14 @@ static inline int file_has_perm(struct task_struct *tsk,
rc = avc_has_perm(tsec->sid, fsec->sid, rc = avc_has_perm(tsec->sid, fsec->sid,
SECCLASS_FD, SECCLASS_FD,
FD__USE, FD__USE,
&fsec->avcr, &ad); &ad);
if (rc) if (rc)
return rc; return rc;
} }
/* av is zero if only checking access to the descriptor. */ /* av is zero if only checking access to the descriptor. */
if (av) if (av)
return inode_has_perm(tsk, inode, av, &fsec->inode_avcr, &ad); return inode_has_perm(tsk, inode, av, &ad);
return 0; return 0;
} }
...@@ -1064,7 +1060,7 @@ static int may_create(struct inode *dir, ...@@ -1064,7 +1060,7 @@ static int may_create(struct inode *dir,
rc = avc_has_perm(tsec->sid, dsec->sid, SECCLASS_DIR, rc = avc_has_perm(tsec->sid, dsec->sid, SECCLASS_DIR,
DIR__ADD_NAME | DIR__SEARCH, DIR__ADD_NAME | DIR__SEARCH,
&dsec->avcr, &ad); &ad);
if (rc) if (rc)
return rc; return rc;
...@@ -1077,13 +1073,13 @@ static int may_create(struct inode *dir, ...@@ -1077,13 +1073,13 @@ static int may_create(struct inode *dir,
return rc; return rc;
} }
rc = avc_has_perm(tsec->sid, newsid, tclass, FILE__CREATE, NULL, &ad); rc = avc_has_perm(tsec->sid, newsid, tclass, FILE__CREATE, &ad);
if (rc) if (rc)
return rc; return rc;
return avc_has_perm(newsid, sbsec->sid, return avc_has_perm(newsid, sbsec->sid,
SECCLASS_FILESYSTEM, SECCLASS_FILESYSTEM,
FILESYSTEM__ASSOCIATE, NULL, &ad); FILESYSTEM__ASSOCIATE, &ad);
} }
#define MAY_LINK 0 #define MAY_LINK 0
...@@ -1111,8 +1107,7 @@ static int may_link(struct inode *dir, ...@@ -1111,8 +1107,7 @@ static int may_link(struct inode *dir,
av = DIR__SEARCH; av = DIR__SEARCH;
av |= (kind ? DIR__REMOVE_NAME : DIR__ADD_NAME); av |= (kind ? DIR__REMOVE_NAME : DIR__ADD_NAME);
rc = avc_has_perm(tsec->sid, dsec->sid, SECCLASS_DIR, rc = avc_has_perm(tsec->sid, dsec->sid, SECCLASS_DIR, av, &ad);
av, &dsec->avcr, &ad);
if (rc) if (rc)
return rc; return rc;
...@@ -1131,8 +1126,7 @@ static int may_link(struct inode *dir, ...@@ -1131,8 +1126,7 @@ static int may_link(struct inode *dir,
return 0; return 0;
} }
rc = avc_has_perm(tsec->sid, isec->sid, isec->sclass, rc = avc_has_perm(tsec->sid, isec->sid, isec->sclass, av, &ad);
av, &isec->avcr, &ad);
return rc; return rc;
} }
...@@ -1158,21 +1152,16 @@ static inline int may_rename(struct inode *old_dir, ...@@ -1158,21 +1152,16 @@ static inline int may_rename(struct inode *old_dir,
ad.u.fs.dentry = old_dentry; ad.u.fs.dentry = old_dentry;
rc = avc_has_perm(tsec->sid, old_dsec->sid, SECCLASS_DIR, rc = avc_has_perm(tsec->sid, old_dsec->sid, SECCLASS_DIR,
DIR__REMOVE_NAME | DIR__SEARCH, DIR__REMOVE_NAME | DIR__SEARCH, &ad);
&old_dsec->avcr, &ad);
if (rc) if (rc)
return rc; return rc;
rc = avc_has_perm(tsec->sid, old_isec->sid, rc = avc_has_perm(tsec->sid, old_isec->sid,
old_isec->sclass, old_isec->sclass, FILE__RENAME, &ad);
FILE__RENAME,
&old_isec->avcr, &ad);
if (rc) if (rc)
return rc; return rc;
if (old_is_dir && new_dir != old_dir) { if (old_is_dir && new_dir != old_dir) {
rc = avc_has_perm(tsec->sid, old_isec->sid, rc = avc_has_perm(tsec->sid, old_isec->sid,
old_isec->sclass, old_isec->sclass, DIR__REPARENT, &ad);
DIR__REPARENT,
&old_isec->avcr, &ad);
if (rc) if (rc)
return rc; return rc;
} }
...@@ -1181,8 +1170,7 @@ static inline int may_rename(struct inode *old_dir, ...@@ -1181,8 +1170,7 @@ static inline int may_rename(struct inode *old_dir,
av = DIR__ADD_NAME | DIR__SEARCH; av = DIR__ADD_NAME | DIR__SEARCH;
if (new_dentry->d_inode) if (new_dentry->d_inode)
av |= DIR__REMOVE_NAME; av |= DIR__REMOVE_NAME;
rc = avc_has_perm(tsec->sid, new_dsec->sid, SECCLASS_DIR, rc = avc_has_perm(tsec->sid, new_dsec->sid, SECCLASS_DIR, av, &ad);
av,&new_dsec->avcr, &ad);
if (rc) if (rc)
return rc; return rc;
if (new_dentry->d_inode) { if (new_dentry->d_inode) {
...@@ -1190,8 +1178,7 @@ static inline int may_rename(struct inode *old_dir, ...@@ -1190,8 +1178,7 @@ static inline int may_rename(struct inode *old_dir,
new_is_dir = S_ISDIR(new_dentry->d_inode->i_mode); new_is_dir = S_ISDIR(new_dentry->d_inode->i_mode);
rc = avc_has_perm(tsec->sid, new_isec->sid, rc = avc_has_perm(tsec->sid, new_isec->sid,
new_isec->sclass, new_isec->sclass,
(new_is_dir ? DIR__RMDIR : FILE__UNLINK), (new_is_dir ? DIR__RMDIR : FILE__UNLINK), &ad);
&new_isec->avcr, &ad);
if (rc) if (rc)
return rc; return rc;
} }
...@@ -1211,7 +1198,7 @@ int superblock_has_perm(struct task_struct *tsk, ...@@ -1211,7 +1198,7 @@ int superblock_has_perm(struct task_struct *tsk,
tsec = tsk->security; tsec = tsk->security;
sbsec = sb->s_security; sbsec = sb->s_security;
return avc_has_perm(tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM, return avc_has_perm(tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM,
perms, NULL, ad); perms, ad);
} }
/* Convert a Linux mode and permission mask to an access vector. */ /* Convert a Linux mode and permission mask to an access vector. */
...@@ -1442,7 +1429,7 @@ static int selinux_sysctl(ctl_table *table, int op) ...@@ -1442,7 +1429,7 @@ static int selinux_sysctl(ctl_table *table, int op)
* a bad coupling between this module and sysctl.c */ * a bad coupling between this module and sysctl.c */
if(op == 001) { if(op == 001) {
error = avc_has_perm(tsec->sid, tsid, error = avc_has_perm(tsec->sid, tsid,
SECCLASS_DIR, DIR__SEARCH, NULL, NULL); SECCLASS_DIR, DIR__SEARCH, NULL);
} else { } else {
av = 0; av = 0;
if (op & 004) if (op & 004)
...@@ -1451,7 +1438,7 @@ static int selinux_sysctl(ctl_table *table, int op) ...@@ -1451,7 +1438,7 @@ static int selinux_sysctl(ctl_table *table, int op)
av |= FILE__WRITE; av |= FILE__WRITE;
if (av) if (av)
error = avc_has_perm(tsec->sid, tsid, error = avc_has_perm(tsec->sid, tsid,
SECCLASS_FILE, av, NULL, NULL); SECCLASS_FILE, av, NULL);
} }
return error; return error;
...@@ -1570,8 +1557,7 @@ static int selinux_vm_enough_memory(long pages) ...@@ -1570,8 +1557,7 @@ static int selinux_vm_enough_memory(long pages)
if (!rc) { if (!rc) {
rc = avc_has_perm_noaudit(tsec->sid, tsec->sid, rc = avc_has_perm_noaudit(tsec->sid, tsec->sid,
SECCLASS_CAPABILITY, SECCLASS_CAPABILITY,
CAP_TO_MASK(CAP_SYS_ADMIN), CAP_TO_MASK(CAP_SYS_ADMIN), NULL);
NULL, NULL);
} }
if (rc) if (rc)
free -= free / 32; free -= free / 32;
...@@ -1663,22 +1649,18 @@ static int selinux_bprm_set_security(struct linux_binprm *bprm) ...@@ -1663,22 +1649,18 @@ static int selinux_bprm_set_security(struct linux_binprm *bprm)
if (tsec->sid == newsid) { if (tsec->sid == newsid) {
rc = avc_has_perm(tsec->sid, isec->sid, rc = avc_has_perm(tsec->sid, isec->sid,
SECCLASS_FILE, FILE__EXECUTE_NO_TRANS, SECCLASS_FILE, FILE__EXECUTE_NO_TRANS, &ad);
&isec->avcr, &ad);
if (rc) if (rc)
return rc; return rc;
} else { } else {
/* Check permissions for the transition. */ /* Check permissions for the transition. */
rc = avc_has_perm(tsec->sid, newsid, rc = avc_has_perm(tsec->sid, newsid,
SECCLASS_PROCESS, PROCESS__TRANSITION, SECCLASS_PROCESS, PROCESS__TRANSITION, &ad);
NULL,
&ad);
if (rc) if (rc)
return rc; return rc;
rc = avc_has_perm(newsid, isec->sid, rc = avc_has_perm(newsid, isec->sid,
SECCLASS_FILE, FILE__ENTRYPOINT, SECCLASS_FILE, FILE__ENTRYPOINT, &ad);
&isec->avcr, &ad);
if (rc) if (rc)
return rc; return rc;
...@@ -1710,7 +1692,7 @@ static int selinux_bprm_secureexec (struct linux_binprm *bprm) ...@@ -1710,7 +1692,7 @@ static int selinux_bprm_secureexec (struct linux_binprm *bprm)
the two SIDs, i.e. ahp returns 0. */ the two SIDs, i.e. ahp returns 0. */
atsecure = avc_has_perm(tsec->osid, tsec->sid, atsecure = avc_has_perm(tsec->osid, tsec->sid,
SECCLASS_PROCESS, SECCLASS_PROCESS,
PROCESS__NOATSECURE, NULL, NULL); PROCESS__NOATSECURE, NULL);
} }
return (atsecure || secondary_ops->bprm_secureexec(bprm)); return (atsecure || secondary_ops->bprm_secureexec(bprm));
...@@ -1745,8 +1727,7 @@ static inline void flush_unauthorized_files(struct files_struct * files) ...@@ -1745,8 +1727,7 @@ static inline void flush_unauthorized_files(struct files_struct * files)
interested in the inode-based check here. */ interested in the inode-based check here. */
struct inode *inode = file->f_dentry->d_inode; struct inode *inode = file->f_dentry->d_inode;
if (inode_has_perm(current, inode, if (inode_has_perm(current, inode,
FILE__READ | FILE__WRITE, FILE__READ | FILE__WRITE, NULL)) {
NULL, NULL)) {
/* Reset controlling tty. */ /* Reset controlling tty. */
current->signal->tty = NULL; current->signal->tty = NULL;
current->signal->tty_old_pgrp = 0; current->signal->tty_old_pgrp = 0;
...@@ -1832,8 +1813,7 @@ static void selinux_bprm_apply_creds(struct linux_binprm *bprm, int unsafe) ...@@ -1832,8 +1813,7 @@ static void selinux_bprm_apply_creds(struct linux_binprm *bprm, int unsafe)
unchanged and kill. */ unchanged and kill. */
if (unsafe & LSM_UNSAFE_SHARE) { if (unsafe & LSM_UNSAFE_SHARE) {
rc = avc_has_perm_noaudit(tsec->sid, sid, rc = avc_has_perm_noaudit(tsec->sid, sid,
SECCLASS_PROCESS, PROCESS__SHARE, SECCLASS_PROCESS, PROCESS__SHARE, &avd);
NULL, &avd);
if (rc) { if (rc) {
task_unlock(current); task_unlock(current);
avc_audit(tsec->sid, sid, SECCLASS_PROCESS, avc_audit(tsec->sid, sid, SECCLASS_PROCESS,
...@@ -1847,8 +1827,7 @@ static void selinux_bprm_apply_creds(struct linux_binprm *bprm, int unsafe) ...@@ -1847,8 +1827,7 @@ static void selinux_bprm_apply_creds(struct linux_binprm *bprm, int unsafe)
Otherwise, leave SID unchanged and kill. */ Otherwise, leave SID unchanged and kill. */
if (unsafe & (LSM_UNSAFE_PTRACE | LSM_UNSAFE_PTRACE_CAP)) { if (unsafe & (LSM_UNSAFE_PTRACE | LSM_UNSAFE_PTRACE_CAP)) {
rc = avc_has_perm_noaudit(tsec->ptrace_sid, sid, rc = avc_has_perm_noaudit(tsec->ptrace_sid, sid,
SECCLASS_PROCESS, PROCESS__PTRACE, SECCLASS_PROCESS, PROCESS__PTRACE, &avd);
NULL, &avd);
if (!rc) if (!rc)
tsec->sid = sid; tsec->sid = sid;
task_unlock(current); task_unlock(current);
...@@ -1873,7 +1852,7 @@ static void selinux_bprm_apply_creds(struct linux_binprm *bprm, int unsafe) ...@@ -1873,7 +1852,7 @@ static void selinux_bprm_apply_creds(struct linux_binprm *bprm, int unsafe)
been updated so that any kill done after the flush been updated so that any kill done after the flush
will be checked against the new SID. */ will be checked against the new SID. */
rc = avc_has_perm(tsec->osid, tsec->sid, SECCLASS_PROCESS, rc = avc_has_perm(tsec->osid, tsec->sid, SECCLASS_PROCESS,
PROCESS__SIGINH, NULL, NULL); PROCESS__SIGINH, NULL);
if (rc) { if (rc) {
memset(&itimer, 0, sizeof itimer); memset(&itimer, 0, sizeof itimer);
for (i = 0; i < 3; i++) for (i = 0; i < 3; i++)
...@@ -1897,7 +1876,7 @@ static void selinux_bprm_apply_creds(struct linux_binprm *bprm, int unsafe) ...@@ -1897,7 +1876,7 @@ static void selinux_bprm_apply_creds(struct linux_binprm *bprm, int unsafe)
is lower than the hard limit, e.g. RLIMIT_CORE or is lower than the hard limit, e.g. RLIMIT_CORE or
RLIMIT_STACK.*/ RLIMIT_STACK.*/
rc = avc_has_perm(tsec->osid, tsec->sid, SECCLASS_PROCESS, rc = avc_has_perm(tsec->osid, tsec->sid, SECCLASS_PROCESS,
PROCESS__RLIMITINH, NULL, NULL); PROCESS__RLIMITINH, NULL);
if (rc) { if (rc) {
for (i = 0; i < RLIM_NLIMITS; i++) { for (i = 0; i < RLIM_NLIMITS; i++) {
rlim = current->signal->rlim + i; rlim = current->signal->rlim + i;
...@@ -2183,7 +2162,7 @@ static int selinux_inode_permission(struct inode *inode, int mask, ...@@ -2183,7 +2162,7 @@ static int selinux_inode_permission(struct inode *inode, int mask,
} }
return inode_has_perm(current, inode, return inode_has_perm(current, inode,
file_mask_to_av(inode->i_mode, mask), NULL, NULL); file_mask_to_av(inode->i_mode, mask), NULL);
} }
static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr) static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr)
...@@ -2241,8 +2220,7 @@ static int selinux_inode_setxattr(struct dentry *dentry, char *name, void *value ...@@ -2241,8 +2220,7 @@ static int selinux_inode_setxattr(struct dentry *dentry, char *name, void *value
ad.u.fs.dentry = dentry; ad.u.fs.dentry = dentry;
rc = avc_has_perm(tsec->sid, isec->sid, isec->sclass, rc = avc_has_perm(tsec->sid, isec->sid, isec->sclass,
FILE__RELABELFROM, FILE__RELABELFROM, &ad);
&isec->avcr, &ad);
if (rc) if (rc)
return rc; return rc;
...@@ -2251,7 +2229,7 @@ static int selinux_inode_setxattr(struct dentry *dentry, char *name, void *value ...@@ -2251,7 +2229,7 @@ static int selinux_inode_setxattr(struct dentry *dentry, char *name, void *value
return rc; return rc;
rc = avc_has_perm(tsec->sid, newsid, isec->sclass, rc = avc_has_perm(tsec->sid, newsid, isec->sclass,
FILE__RELABELTO, NULL, &ad); FILE__RELABELTO, &ad);
if (rc) if (rc)
return rc; return rc;
...@@ -2259,7 +2237,6 @@ static int selinux_inode_setxattr(struct dentry *dentry, char *name, void *value ...@@ -2259,7 +2237,6 @@ static int selinux_inode_setxattr(struct dentry *dentry, char *name, void *value
sbsec->sid, sbsec->sid,
SECCLASS_FILESYSTEM, SECCLASS_FILESYSTEM,
FILESYSTEM__ASSOCIATE, FILESYSTEM__ASSOCIATE,
NULL,
&ad); &ad);
} }
...@@ -2581,7 +2558,7 @@ static int selinux_file_send_sigiotask(struct task_struct *tsk, ...@@ -2581,7 +2558,7 @@ static int selinux_file_send_sigiotask(struct task_struct *tsk,
perm = signal_to_av(signum); perm = signal_to_av(signum);
return avc_has_perm(fsec->fown_sid, tsec->sid, return avc_has_perm(fsec->fown_sid, tsec->sid,
SECCLASS_PROCESS, perm, NULL, NULL); SECCLASS_PROCESS, perm, NULL);
} }
static int selinux_file_receive(struct file *file) static int selinux_file_receive(struct file *file)
...@@ -2718,8 +2695,7 @@ static int selinux_task_setscheduler(struct task_struct *p, int policy, struct s ...@@ -2718,8 +2695,7 @@ static int selinux_task_setscheduler(struct task_struct *p, int policy, struct s
is held and the system will deadlock if we try to log an audit is held and the system will deadlock if we try to log an audit
message. */ message. */
return avc_has_perm_noaudit(tsec1->sid, tsec2->sid, return avc_has_perm_noaudit(tsec1->sid, tsec2->sid,
SECCLASS_PROCESS, PROCESS__SETSCHED, SECCLASS_PROCESS, PROCESS__SETSCHED, NULL);
&tsec2->avcr, NULL);
} }
static int selinux_task_getscheduler(struct task_struct *p) static int selinux_task_getscheduler(struct task_struct *p)
...@@ -2962,8 +2938,7 @@ static int socket_has_perm(struct task_struct *task, struct socket *sock, ...@@ -2962,8 +2938,7 @@ static int socket_has_perm(struct task_struct *task, struct socket *sock,
AVC_AUDIT_DATA_INIT(&ad,NET); AVC_AUDIT_DATA_INIT(&ad,NET);
ad.u.net.sk = sock->sk; ad.u.net.sk = sock->sk;
err = avc_has_perm(tsec->sid, isec->sid, isec->sclass, err = avc_has_perm(tsec->sid, isec->sid, isec->sclass, perms, &ad);
perms, &isec->avcr, &ad);
out: out:
return err; return err;
...@@ -2981,7 +2956,7 @@ static int selinux_socket_create(int family, int type, ...@@ -2981,7 +2956,7 @@ static int selinux_socket_create(int family, int type,
tsec = current->security; tsec = current->security;
err = avc_has_perm(tsec->sid, tsec->sid, err = avc_has_perm(tsec->sid, tsec->sid,
socket_type_to_security_class(family, type, socket_type_to_security_class(family, type,
protocol), SOCKET__CREATE, NULL, NULL); protocol), SOCKET__CREATE, NULL);
out: out:
return err; return err;
...@@ -3062,7 +3037,7 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in ...@@ -3062,7 +3037,7 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in
ad.u.net.family = family; ad.u.net.family = family;
err = avc_has_perm(isec->sid, sid, err = avc_has_perm(isec->sid, sid,
isec->sclass, isec->sclass,
SOCKET__NAME_BIND, NULL, &ad); SOCKET__NAME_BIND, &ad);
if (err) if (err)
goto out; goto out;
} }
...@@ -3095,7 +3070,7 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in ...@@ -3095,7 +3070,7 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in
ipv6_addr_copy(&ad.u.net.v6info.saddr, &addr6->sin6_addr); ipv6_addr_copy(&ad.u.net.v6info.saddr, &addr6->sin6_addr);
err = avc_has_perm(isec->sid, sid, err = avc_has_perm(isec->sid, sid,
isec->sclass, node_perm, NULL, &ad); isec->sclass, node_perm, &ad);
if (err) if (err)
goto out; goto out;
} }
...@@ -3195,8 +3170,7 @@ static int selinux_socket_unix_stream_connect(struct socket *sock, ...@@ -3195,8 +3170,7 @@ static int selinux_socket_unix_stream_connect(struct socket *sock,
err = avc_has_perm(isec->sid, other_isec->sid, err = avc_has_perm(isec->sid, other_isec->sid,
isec->sclass, isec->sclass,
UNIX_STREAM_SOCKET__CONNECTTO, UNIX_STREAM_SOCKET__CONNECTTO, &ad);
&other_isec->avcr, &ad);
if (err) if (err)
return err; return err;
...@@ -3226,9 +3200,7 @@ static int selinux_socket_unix_may_send(struct socket *sock, ...@@ -3226,9 +3200,7 @@ static int selinux_socket_unix_may_send(struct socket *sock,
ad.u.net.sk = other->sk; ad.u.net.sk = other->sk;
err = avc_has_perm(isec->sid, other_isec->sid, err = avc_has_perm(isec->sid, other_isec->sid,
isec->sclass, isec->sclass, SOCKET__SENDTO, &ad);
SOCKET__SENDTO,
&other_isec->avcr, &ad);
if (err) if (err)
return err; return err;
...@@ -3306,8 +3278,7 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) ...@@ -3306,8 +3278,7 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
if (err) if (err)
goto out; goto out;
err = avc_has_perm(sock_sid, if_sid, SECCLASS_NETIF, err = avc_has_perm(sock_sid, if_sid, SECCLASS_NETIF, netif_perm, &ad);
netif_perm, NULL, &ad);
if (err) if (err)
goto out; goto out;
...@@ -3316,7 +3287,7 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) ...@@ -3316,7 +3287,7 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
if (err) if (err)
goto out; goto out;
err = avc_has_perm(sock_sid, node_sid, SECCLASS_NODE, node_perm, NULL, &ad); err = avc_has_perm(sock_sid, node_sid, SECCLASS_NODE, node_perm, &ad);
if (err) if (err)
goto out; goto out;
...@@ -3330,8 +3301,8 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) ...@@ -3330,8 +3301,8 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
if (err) if (err)
goto out; goto out;
err = avc_has_perm(sock_sid, port_sid, sock_class, err = avc_has_perm(sock_sid, port_sid,
recv_perm, NULL, &ad); sock_class, recv_perm, &ad);
} }
out: out:
return err; return err;
...@@ -3480,7 +3451,7 @@ static unsigned int selinux_ip_postroute_last(unsigned int hooknum, ...@@ -3480,7 +3451,7 @@ static unsigned int selinux_ip_postroute_last(unsigned int hooknum,
goto out; goto out;
err = avc_has_perm(isec->sid, if_sid, SECCLASS_NETIF, err = avc_has_perm(isec->sid, if_sid, SECCLASS_NETIF,
netif_perm, NULL, &ad) ? NF_DROP : NF_ACCEPT; netif_perm, &ad) ? NF_DROP : NF_ACCEPT;
if (err != NF_ACCEPT) if (err != NF_ACCEPT)
goto out; goto out;
...@@ -3491,7 +3462,7 @@ static unsigned int selinux_ip_postroute_last(unsigned int hooknum, ...@@ -3491,7 +3462,7 @@ static unsigned int selinux_ip_postroute_last(unsigned int hooknum,
goto out; goto out;
err = avc_has_perm(isec->sid, node_sid, SECCLASS_NODE, err = avc_has_perm(isec->sid, node_sid, SECCLASS_NODE,
node_perm, NULL, &ad) ? NF_DROP : NF_ACCEPT; node_perm, &ad) ? NF_DROP : NF_ACCEPT;
if (err != NF_ACCEPT) if (err != NF_ACCEPT)
goto out; goto out;
...@@ -3508,7 +3479,7 @@ static unsigned int selinux_ip_postroute_last(unsigned int hooknum, ...@@ -3508,7 +3479,7 @@ static unsigned int selinux_ip_postroute_last(unsigned int hooknum,
goto out; goto out;
err = avc_has_perm(isec->sid, port_sid, isec->sclass, err = avc_has_perm(isec->sid, port_sid, isec->sclass,
send_perm, NULL, &ad) ? NF_DROP : NF_ACCEPT; send_perm, &ad) ? NF_DROP : NF_ACCEPT;
} }
out: out:
...@@ -3645,8 +3616,7 @@ static int ipc_has_perm(struct kern_ipc_perm *ipc_perms, ...@@ -3645,8 +3616,7 @@ static int ipc_has_perm(struct kern_ipc_perm *ipc_perms,
AVC_AUDIT_DATA_INIT(&ad, IPC); AVC_AUDIT_DATA_INIT(&ad, IPC);
ad.u.ipc_id = ipc_perms->key; ad.u.ipc_id = ipc_perms->key;
return avc_has_perm(tsec->sid, isec->sid, sclass, return avc_has_perm(tsec->sid, isec->sid, sclass, perms, &ad);
perms, &isec->avcr, &ad);
} }
static int selinux_msg_msg_alloc_security(struct msg_msg *msg) static int selinux_msg_msg_alloc_security(struct msg_msg *msg)
...@@ -3678,7 +3648,7 @@ static int selinux_msg_queue_alloc_security(struct msg_queue *msq) ...@@ -3678,7 +3648,7 @@ static int selinux_msg_queue_alloc_security(struct msg_queue *msq)
ad.u.ipc_id = msq->q_perm.key; ad.u.ipc_id = msq->q_perm.key;
rc = avc_has_perm(tsec->sid, isec->sid, SECCLASS_MSGQ, rc = avc_has_perm(tsec->sid, isec->sid, SECCLASS_MSGQ,
MSGQ__CREATE, &isec->avcr, &ad); MSGQ__CREATE, &ad);
if (rc) { if (rc) {
ipc_free_security(&msq->q_perm); ipc_free_security(&msq->q_perm);
return rc; return rc;
...@@ -3704,7 +3674,7 @@ static int selinux_msg_queue_associate(struct msg_queue *msq, int msqflg) ...@@ -3704,7 +3674,7 @@ static int selinux_msg_queue_associate(struct msg_queue *msq, int msqflg)
ad.u.ipc_id = msq->q_perm.key; ad.u.ipc_id = msq->q_perm.key;
return avc_has_perm(tsec->sid, isec->sid, SECCLASS_MSGQ, return avc_has_perm(tsec->sid, isec->sid, SECCLASS_MSGQ,
MSGQ__ASSOCIATE, &isec->avcr, &ad); MSGQ__ASSOCIATE, &ad);
} }
static int selinux_msg_queue_msgctl(struct msg_queue *msq, int cmd) static int selinux_msg_queue_msgctl(struct msg_queue *msq, int cmd)
...@@ -3768,17 +3738,15 @@ static int selinux_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg, ...@@ -3768,17 +3738,15 @@ static int selinux_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg,
/* Can this process write to the queue? */ /* Can this process write to the queue? */
rc = avc_has_perm(tsec->sid, isec->sid, SECCLASS_MSGQ, rc = avc_has_perm(tsec->sid, isec->sid, SECCLASS_MSGQ,
MSGQ__WRITE, &isec->avcr, &ad); MSGQ__WRITE, &ad);
if (!rc) if (!rc)
/* Can this process send the message */ /* Can this process send the message */
rc = avc_has_perm(tsec->sid, msec->sid, rc = avc_has_perm(tsec->sid, msec->sid,
SECCLASS_MSG, MSG__SEND, SECCLASS_MSG, MSG__SEND, &ad);
&msec->avcr, &ad);
if (!rc) if (!rc)
/* Can the message be put in the queue? */ /* Can the message be put in the queue? */
rc = avc_has_perm(msec->sid, isec->sid, rc = avc_has_perm(msec->sid, isec->sid,
SECCLASS_MSGQ, MSGQ__ENQUEUE, SECCLASS_MSGQ, MSGQ__ENQUEUE, &ad);
&isec->avcr, &ad);
return rc; return rc;
} }
...@@ -3801,12 +3769,10 @@ static int selinux_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg, ...@@ -3801,12 +3769,10 @@ static int selinux_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg,
ad.u.ipc_id = msq->q_perm.key; ad.u.ipc_id = msq->q_perm.key;
rc = avc_has_perm(tsec->sid, isec->sid, rc = avc_has_perm(tsec->sid, isec->sid,
SECCLASS_MSGQ, MSGQ__READ, SECCLASS_MSGQ, MSGQ__READ, &ad);
&isec->avcr, &ad);
if (!rc) if (!rc)
rc = avc_has_perm(tsec->sid, msec->sid, rc = avc_has_perm(tsec->sid, msec->sid,
SECCLASS_MSG, MSG__RECEIVE, SECCLASS_MSG, MSG__RECEIVE, &ad);
&msec->avcr, &ad);
return rc; return rc;
} }
...@@ -3829,7 +3795,7 @@ static int selinux_shm_alloc_security(struct shmid_kernel *shp) ...@@ -3829,7 +3795,7 @@ static int selinux_shm_alloc_security(struct shmid_kernel *shp)
ad.u.ipc_id = shp->shm_perm.key; ad.u.ipc_id = shp->shm_perm.key;
rc = avc_has_perm(tsec->sid, isec->sid, SECCLASS_SHM, rc = avc_has_perm(tsec->sid, isec->sid, SECCLASS_SHM,
SHM__CREATE, &isec->avcr, &ad); SHM__CREATE, &ad);
if (rc) { if (rc) {
ipc_free_security(&shp->shm_perm); ipc_free_security(&shp->shm_perm);
return rc; return rc;
...@@ -3855,7 +3821,7 @@ static int selinux_shm_associate(struct shmid_kernel *shp, int shmflg) ...@@ -3855,7 +3821,7 @@ static int selinux_shm_associate(struct shmid_kernel *shp, int shmflg)
ad.u.ipc_id = shp->shm_perm.key; ad.u.ipc_id = shp->shm_perm.key;
return avc_has_perm(tsec->sid, isec->sid, SECCLASS_SHM, return avc_has_perm(tsec->sid, isec->sid, SECCLASS_SHM,
SHM__ASSOCIATE, &isec->avcr, &ad); SHM__ASSOCIATE, &ad);
} }
/* Note, at this point, shp is locked down */ /* Note, at this point, shp is locked down */
...@@ -3928,7 +3894,7 @@ static int selinux_sem_alloc_security(struct sem_array *sma) ...@@ -3928,7 +3894,7 @@ static int selinux_sem_alloc_security(struct sem_array *sma)
ad.u.ipc_id = sma->sem_perm.key; ad.u.ipc_id = sma->sem_perm.key;
rc = avc_has_perm(tsec->sid, isec->sid, SECCLASS_SEM, rc = avc_has_perm(tsec->sid, isec->sid, SECCLASS_SEM,
SEM__CREATE, &isec->avcr, &ad); SEM__CREATE, &ad);
if (rc) { if (rc) {
ipc_free_security(&sma->sem_perm); ipc_free_security(&sma->sem_perm);
return rc; return rc;
...@@ -3954,7 +3920,7 @@ static int selinux_sem_associate(struct sem_array *sma, int semflg) ...@@ -3954,7 +3920,7 @@ static int selinux_sem_associate(struct sem_array *sma, int semflg)
ad.u.ipc_id = sma->sem_perm.key; ad.u.ipc_id = sma->sem_perm.key;
return avc_has_perm(tsec->sid, isec->sid, SECCLASS_SEM, return avc_has_perm(tsec->sid, isec->sid, SECCLASS_SEM,
SEM__ASSOCIATE, &isec->avcr, &ad); SEM__ASSOCIATE, &ad);
} }
/* Note, at this point, sma is locked down */ /* Note, at this point, sma is locked down */
......
...@@ -29,19 +29,6 @@ extern int selinux_enforcing; ...@@ -29,19 +29,6 @@ extern int selinux_enforcing;
*/ */
struct avc_entry; struct avc_entry;
/*
* A reference to an AVC entry.
*/
struct avc_entry_ref {
struct avc_entry *ae;
};
/* Initialize an AVC entry reference before first use. */
static inline void avc_entry_ref_init(struct avc_entry_ref *h)
{
h->ae = NULL;
}
struct task_struct; struct task_struct;
struct vfsmount; struct vfsmount;
struct dentry; struct dentry;
...@@ -118,23 +105,17 @@ void avc_dump_query(struct audit_buffer *ab, u32 ssid, u32 tsid, u16 tclass); ...@@ -118,23 +105,17 @@ void avc_dump_query(struct audit_buffer *ab, u32 ssid, u32 tsid, u16 tclass);
void __init avc_init(void); void __init avc_init(void);
int avc_lookup(u32 ssid, u32 tsid, u16 tclass,
u32 requested, struct avc_entry_ref *aeref);
int avc_insert(u32 ssid, u32 tsid, u16 tclass,
struct avc_entry *ae, struct avc_entry_ref *out_aeref);
void avc_audit(u32 ssid, u32 tsid, void avc_audit(u32 ssid, u32 tsid,
u16 tclass, u32 requested, u16 tclass, u32 requested,
struct av_decision *avd, int result, struct avc_audit_data *auditdata); struct av_decision *avd, int result, struct avc_audit_data *auditdata);
int avc_has_perm_noaudit(u32 ssid, u32 tsid, int avc_has_perm_noaudit(u32 ssid, u32 tsid,
u16 tclass, u32 requested, u16 tclass, u32 requested,
struct avc_entry_ref *aeref, struct av_decision *avd); struct av_decision *avd);
int avc_has_perm(u32 ssid, u32 tsid, int avc_has_perm(u32 ssid, u32 tsid,
u16 tclass, u32 requested, u16 tclass, u32 requested,
struct avc_entry_ref *aeref, struct avc_audit_data *auditdata); struct avc_audit_data *auditdata);
#define AVC_CALLBACK_GRANT 1 #define AVC_CALLBACK_GRANT 1
#define AVC_CALLBACK_TRY_REVOKE 2 #define AVC_CALLBACK_TRY_REVOKE 2
......
...@@ -33,7 +33,6 @@ struct task_security_struct { ...@@ -33,7 +33,6 @@ struct task_security_struct {
u32 sid; /* current SID */ u32 sid; /* current SID */
u32 exec_sid; /* exec SID */ u32 exec_sid; /* exec SID */
u32 create_sid; /* fscreate SID */ u32 create_sid; /* fscreate SID */
struct avc_entry_ref avcr; /* reference to process permissions */
u32 ptrace_sid; /* SID of ptrace parent */ u32 ptrace_sid; /* SID of ptrace parent */
}; };
...@@ -44,7 +43,6 @@ struct inode_security_struct { ...@@ -44,7 +43,6 @@ struct inode_security_struct {
u32 task_sid; /* SID of creating task */ u32 task_sid; /* SID of creating task */
u32 sid; /* SID of this object */ u32 sid; /* SID of this object */
u16 sclass; /* security class of this object */ u16 sclass; /* security class of this object */
struct avc_entry_ref avcr; /* reference to object permissions */
unsigned char initialized; /* initialization flag */ unsigned char initialized; /* initialization flag */
struct semaphore sem; struct semaphore sem;
unsigned char inherit; /* inherit SID from parent entry */ unsigned char inherit; /* inherit SID from parent entry */
...@@ -55,8 +53,6 @@ struct file_security_struct { ...@@ -55,8 +53,6 @@ struct file_security_struct {
struct file *file; /* back pointer to file object */ struct file *file; /* back pointer to file object */
u32 sid; /* SID of open file description */ u32 sid; /* SID of open file description */
u32 fown_sid; /* SID of file owner (for SIGIO) */ u32 fown_sid; /* SID of file owner (for SIGIO) */
struct avc_entry_ref avcr; /* reference to fd permissions */
struct avc_entry_ref inode_avcr; /* reference to object permissions */
}; };
struct superblock_security_struct { struct superblock_security_struct {
...@@ -77,7 +73,6 @@ struct msg_security_struct { ...@@ -77,7 +73,6 @@ struct msg_security_struct {
unsigned long magic; /* magic number for this module */ unsigned long magic; /* magic number for this module */
struct msg_msg *msg; /* back pointer */ struct msg_msg *msg; /* back pointer */
u32 sid; /* SID of message */ u32 sid; /* SID of message */
struct avc_entry_ref avcr; /* reference to permissions */
}; };
struct ipc_security_struct { struct ipc_security_struct {
...@@ -85,7 +80,6 @@ struct ipc_security_struct { ...@@ -85,7 +80,6 @@ struct ipc_security_struct {
struct kern_ipc_perm *ipc_perm; /* back pointer */ struct kern_ipc_perm *ipc_perm; /* back pointer */
u16 sclass; /* security class of this object */ u16 sclass; /* security class of this object */
u32 sid; /* SID of IPC resource */ u32 sid; /* SID of IPC resource */
struct avc_entry_ref avcr; /* reference to permissions */
}; };
struct bprm_security_struct { struct bprm_security_struct {
......
...@@ -51,7 +51,7 @@ int task_has_security(struct task_struct *tsk, ...@@ -51,7 +51,7 @@ int task_has_security(struct task_struct *tsk,
return -EACCES; return -EACCES;
return avc_has_perm(tsec->sid, SECINITSID_SECURITY, return avc_has_perm(tsec->sid, SECINITSID_SECURITY,
SECCLASS_SECURITY, perms, NULL, NULL); SECCLASS_SECURITY, perms, NULL);
} }
enum sel_inos { enum sel_inos {
......
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