1f074036424618c130dacb3464465a8b40bffef5Stephen Smalley/* 2f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * Implementation of the userspace access vector cache (AVC). 3f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * 4f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * Author : Eamon Walsh <ewalsh@epoch.ncsc.mil> 5f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * 6f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * Derived from the kernel AVC implementation by 7f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * Stephen Smalley <sds@epoch.ncsc.mil> and 8f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * James Morris <jmorris@redhat.com>. 9f074036424618c130dacb3464465a8b40bffef5Stephen Smalley */ 10f074036424618c130dacb3464465a8b40bffef5Stephen Smalley#include <selinux/avc.h> 11f074036424618c130dacb3464465a8b40bffef5Stephen Smalley#include "selinux_internal.h" 12f074036424618c130dacb3464465a8b40bffef5Stephen Smalley#include "avc_sidtab.h" 13f074036424618c130dacb3464465a8b40bffef5Stephen Smalley#include "avc_internal.h" 14f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 15f074036424618c130dacb3464465a8b40bffef5Stephen Smalley#define AVC_CACHE_SLOTS 512 16f074036424618c130dacb3464465a8b40bffef5Stephen Smalley#define AVC_CACHE_MAXNODES 410 17f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 18f074036424618c130dacb3464465a8b40bffef5Stephen Smalleystruct avc_entry { 19f074036424618c130dacb3464465a8b40bffef5Stephen Smalley security_id_t ssid; 20f074036424618c130dacb3464465a8b40bffef5Stephen Smalley security_id_t tsid; 21f074036424618c130dacb3464465a8b40bffef5Stephen Smalley security_class_t tclass; 22f074036424618c130dacb3464465a8b40bffef5Stephen Smalley struct av_decision avd; 23f074036424618c130dacb3464465a8b40bffef5Stephen Smalley security_id_t create_sid; 24f074036424618c130dacb3464465a8b40bffef5Stephen Smalley int used; /* used recently */ 25f074036424618c130dacb3464465a8b40bffef5Stephen Smalley}; 26f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 27f074036424618c130dacb3464465a8b40bffef5Stephen Smalleystruct avc_node { 28f074036424618c130dacb3464465a8b40bffef5Stephen Smalley struct avc_entry ae; 29f074036424618c130dacb3464465a8b40bffef5Stephen Smalley struct avc_node *next; 30f074036424618c130dacb3464465a8b40bffef5Stephen Smalley}; 31f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 32f074036424618c130dacb3464465a8b40bffef5Stephen Smalleystruct avc_cache { 33f074036424618c130dacb3464465a8b40bffef5Stephen Smalley struct avc_node *slots[AVC_CACHE_SLOTS]; 34f074036424618c130dacb3464465a8b40bffef5Stephen Smalley uint32_t lru_hint; /* LRU hint for reclaim scan */ 35f074036424618c130dacb3464465a8b40bffef5Stephen Smalley uint32_t active_nodes; 36f074036424618c130dacb3464465a8b40bffef5Stephen Smalley uint32_t latest_notif; /* latest revocation notification */ 37f074036424618c130dacb3464465a8b40bffef5Stephen Smalley}; 38f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 39f074036424618c130dacb3464465a8b40bffef5Stephen Smalleystruct avc_callback_node { 40f074036424618c130dacb3464465a8b40bffef5Stephen Smalley int (*callback) (uint32_t event, security_id_t ssid, 41f074036424618c130dacb3464465a8b40bffef5Stephen Smalley security_id_t tsid, 42f074036424618c130dacb3464465a8b40bffef5Stephen Smalley security_class_t tclass, access_vector_t perms, 43f074036424618c130dacb3464465a8b40bffef5Stephen Smalley access_vector_t * out_retained); 44f074036424618c130dacb3464465a8b40bffef5Stephen Smalley uint32_t events; 45f074036424618c130dacb3464465a8b40bffef5Stephen Smalley security_id_t ssid; 46f074036424618c130dacb3464465a8b40bffef5Stephen Smalley security_id_t tsid; 47f074036424618c130dacb3464465a8b40bffef5Stephen Smalley security_class_t tclass; 48f074036424618c130dacb3464465a8b40bffef5Stephen Smalley access_vector_t perms; 49f074036424618c130dacb3464465a8b40bffef5Stephen Smalley struct avc_callback_node *next; 50f074036424618c130dacb3464465a8b40bffef5Stephen Smalley}; 51f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 52f074036424618c130dacb3464465a8b40bffef5Stephen Smalleystatic void *avc_netlink_thread = NULL; 53f074036424618c130dacb3464465a8b40bffef5Stephen Smalleystatic void *avc_lock = NULL; 54f074036424618c130dacb3464465a8b40bffef5Stephen Smalleystatic void *avc_log_lock = NULL; 55f074036424618c130dacb3464465a8b40bffef5Stephen Smalleystatic struct avc_node *avc_node_freelist = NULL; 56f074036424618c130dacb3464465a8b40bffef5Stephen Smalleystatic struct avc_cache avc_cache; 57f074036424618c130dacb3464465a8b40bffef5Stephen Smalleystatic char *avc_audit_buf = NULL; 58f074036424618c130dacb3464465a8b40bffef5Stephen Smalleystatic struct avc_cache_stats cache_stats; 59f074036424618c130dacb3464465a8b40bffef5Stephen Smalleystatic struct avc_callback_node *avc_callbacks = NULL; 60f074036424618c130dacb3464465a8b40bffef5Stephen Smalleystatic struct sidtab avc_sidtab; 61f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 62f074036424618c130dacb3464465a8b40bffef5Stephen Smalleystatic inline int avc_hash(security_id_t ssid, 63f074036424618c130dacb3464465a8b40bffef5Stephen Smalley security_id_t tsid, security_class_t tclass) 64f074036424618c130dacb3464465a8b40bffef5Stephen Smalley{ 65f074036424618c130dacb3464465a8b40bffef5Stephen Smalley return ((uintptr_t) ssid ^ ((uintptr_t) tsid << 2) ^ tclass) 66f074036424618c130dacb3464465a8b40bffef5Stephen Smalley & (AVC_CACHE_SLOTS - 1); 67f074036424618c130dacb3464465a8b40bffef5Stephen Smalley} 68f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 69ab40ea9bfd71b50138f1482c4764a65ac17d8cafStephen Smalleyint avc_context_to_sid(const char * ctx, security_id_t * sid) 70f074036424618c130dacb3464465a8b40bffef5Stephen Smalley{ 71f074036424618c130dacb3464465a8b40bffef5Stephen Smalley int rc; 72f074036424618c130dacb3464465a8b40bffef5Stephen Smalley avc_get_lock(avc_lock); 73f074036424618c130dacb3464465a8b40bffef5Stephen Smalley rc = sidtab_context_to_sid(&avc_sidtab, ctx, sid); 74f074036424618c130dacb3464465a8b40bffef5Stephen Smalley avc_release_lock(avc_lock); 75f074036424618c130dacb3464465a8b40bffef5Stephen Smalley return rc; 76f074036424618c130dacb3464465a8b40bffef5Stephen Smalley} 77f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 78ab40ea9bfd71b50138f1482c4764a65ac17d8cafStephen Smalleyint avc_sid_to_context(security_id_t sid, char ** ctx) 79f074036424618c130dacb3464465a8b40bffef5Stephen Smalley{ 80f074036424618c130dacb3464465a8b40bffef5Stephen Smalley int rc; 81f074036424618c130dacb3464465a8b40bffef5Stephen Smalley *ctx = NULL; 82f074036424618c130dacb3464465a8b40bffef5Stephen Smalley avc_get_lock(avc_lock); 83f074036424618c130dacb3464465a8b40bffef5Stephen Smalley *ctx = strdup(sid->ctx); /* caller must free via freecon */ 84f074036424618c130dacb3464465a8b40bffef5Stephen Smalley rc = *ctx ? 0 : -1; 85f074036424618c130dacb3464465a8b40bffef5Stephen Smalley avc_release_lock(avc_lock); 86f074036424618c130dacb3464465a8b40bffef5Stephen Smalley return rc; 87f074036424618c130dacb3464465a8b40bffef5Stephen Smalley} 88f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 89f074036424618c130dacb3464465a8b40bffef5Stephen Smalleyint avc_get_initial_sid(const char * name, security_id_t * sid) 90f074036424618c130dacb3464465a8b40bffef5Stephen Smalley{ 91f074036424618c130dacb3464465a8b40bffef5Stephen Smalley int rc; 92ab40ea9bfd71b50138f1482c4764a65ac17d8cafStephen Smalley char * con; 93f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 94f074036424618c130dacb3464465a8b40bffef5Stephen Smalley rc = security_get_initial_context(name, &con); 95f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (rc < 0) 96f074036424618c130dacb3464465a8b40bffef5Stephen Smalley return rc; 97f074036424618c130dacb3464465a8b40bffef5Stephen Smalley rc = avc_context_to_sid(con, sid); 98f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 99f074036424618c130dacb3464465a8b40bffef5Stephen Smalley freecon(con); 100f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 101f074036424618c130dacb3464465a8b40bffef5Stephen Smalley return rc; 102f074036424618c130dacb3464465a8b40bffef5Stephen Smalley} 103f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 104f074036424618c130dacb3464465a8b40bffef5Stephen Smalleyint avc_open(struct selinux_opt *opts, unsigned nopts) 105f074036424618c130dacb3464465a8b40bffef5Stephen Smalley{ 106f074036424618c130dacb3464465a8b40bffef5Stephen Smalley avc_setenforce = 0; 107f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 108f074036424618c130dacb3464465a8b40bffef5Stephen Smalley while (nopts--) 109f074036424618c130dacb3464465a8b40bffef5Stephen Smalley switch(opts[nopts].type) { 110f074036424618c130dacb3464465a8b40bffef5Stephen Smalley case AVC_OPT_SETENFORCE: 111f074036424618c130dacb3464465a8b40bffef5Stephen Smalley avc_setenforce = 1; 112f074036424618c130dacb3464465a8b40bffef5Stephen Smalley avc_enforcing = !!opts[nopts].value; 113f074036424618c130dacb3464465a8b40bffef5Stephen Smalley break; 114f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 115f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 116f074036424618c130dacb3464465a8b40bffef5Stephen Smalley return avc_init("avc", NULL, NULL, NULL, NULL); 117f074036424618c130dacb3464465a8b40bffef5Stephen Smalley} 118f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 119f074036424618c130dacb3464465a8b40bffef5Stephen Smalleyint avc_init(const char *prefix, 120f074036424618c130dacb3464465a8b40bffef5Stephen Smalley const struct avc_memory_callback *mem_cb, 121f074036424618c130dacb3464465a8b40bffef5Stephen Smalley const struct avc_log_callback *log_cb, 122f074036424618c130dacb3464465a8b40bffef5Stephen Smalley const struct avc_thread_callback *thread_cb, 123f074036424618c130dacb3464465a8b40bffef5Stephen Smalley const struct avc_lock_callback *lock_cb) 124f074036424618c130dacb3464465a8b40bffef5Stephen Smalley{ 125f074036424618c130dacb3464465a8b40bffef5Stephen Smalley struct avc_node *new; 126f074036424618c130dacb3464465a8b40bffef5Stephen Smalley int i, rc = 0; 127f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 128f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (prefix) 129f074036424618c130dacb3464465a8b40bffef5Stephen Smalley strncpy(avc_prefix, prefix, AVC_PREFIX_SIZE - 1); 130f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 131f074036424618c130dacb3464465a8b40bffef5Stephen Smalley set_callbacks(mem_cb, log_cb, thread_cb, lock_cb); 132f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 133f074036424618c130dacb3464465a8b40bffef5Stephen Smalley avc_lock = avc_alloc_lock(); 134f074036424618c130dacb3464465a8b40bffef5Stephen Smalley avc_log_lock = avc_alloc_lock(); 135f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 136f074036424618c130dacb3464465a8b40bffef5Stephen Smalley memset(&cache_stats, 0, sizeof(cache_stats)); 137f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 138f074036424618c130dacb3464465a8b40bffef5Stephen Smalley for (i = 0; i < AVC_CACHE_SLOTS; i++) 139f074036424618c130dacb3464465a8b40bffef5Stephen Smalley avc_cache.slots[i] = 0; 140f074036424618c130dacb3464465a8b40bffef5Stephen Smalley avc_cache.lru_hint = 0; 141f074036424618c130dacb3464465a8b40bffef5Stephen Smalley avc_cache.active_nodes = 0; 142f074036424618c130dacb3464465a8b40bffef5Stephen Smalley avc_cache.latest_notif = 0; 143f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 144f074036424618c130dacb3464465a8b40bffef5Stephen Smalley rc = sidtab_init(&avc_sidtab); 145f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (rc) { 146f074036424618c130dacb3464465a8b40bffef5Stephen Smalley avc_log(SELINUX_ERROR, 147f074036424618c130dacb3464465a8b40bffef5Stephen Smalley "%s: unable to initialize SID table\n", 148f074036424618c130dacb3464465a8b40bffef5Stephen Smalley avc_prefix); 149f074036424618c130dacb3464465a8b40bffef5Stephen Smalley goto out; 150f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 151f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 152f074036424618c130dacb3464465a8b40bffef5Stephen Smalley avc_audit_buf = (char *)avc_malloc(AVC_AUDIT_BUFSIZE); 153f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (!avc_audit_buf) { 154f074036424618c130dacb3464465a8b40bffef5Stephen Smalley avc_log(SELINUX_ERROR, 155f074036424618c130dacb3464465a8b40bffef5Stephen Smalley "%s: unable to allocate audit buffer\n", 156f074036424618c130dacb3464465a8b40bffef5Stephen Smalley avc_prefix); 157f074036424618c130dacb3464465a8b40bffef5Stephen Smalley rc = -1; 158f074036424618c130dacb3464465a8b40bffef5Stephen Smalley goto out; 159f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 160f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 161f074036424618c130dacb3464465a8b40bffef5Stephen Smalley for (i = 0; i < AVC_CACHE_MAXNODES; i++) { 162f074036424618c130dacb3464465a8b40bffef5Stephen Smalley new = avc_malloc(sizeof(*new)); 163f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (!new) { 164f074036424618c130dacb3464465a8b40bffef5Stephen Smalley avc_log(SELINUX_WARNING, 165f074036424618c130dacb3464465a8b40bffef5Stephen Smalley "%s: warning: only got %d av entries\n", 166f074036424618c130dacb3464465a8b40bffef5Stephen Smalley avc_prefix, i); 167f074036424618c130dacb3464465a8b40bffef5Stephen Smalley break; 168f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 169f074036424618c130dacb3464465a8b40bffef5Stephen Smalley memset(new, 0, sizeof(*new)); 170f074036424618c130dacb3464465a8b40bffef5Stephen Smalley new->next = avc_node_freelist; 171f074036424618c130dacb3464465a8b40bffef5Stephen Smalley avc_node_freelist = new; 172f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 173f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 174f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (!avc_setenforce) { 175f074036424618c130dacb3464465a8b40bffef5Stephen Smalley rc = security_getenforce(); 176f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (rc < 0) { 177f074036424618c130dacb3464465a8b40bffef5Stephen Smalley avc_log(SELINUX_ERROR, 178f074036424618c130dacb3464465a8b40bffef5Stephen Smalley "%s: could not determine enforcing mode: %s\n", 179f074036424618c130dacb3464465a8b40bffef5Stephen Smalley avc_prefix, 180f074036424618c130dacb3464465a8b40bffef5Stephen Smalley strerror(errno)); 181f074036424618c130dacb3464465a8b40bffef5Stephen Smalley goto out; 182f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 183f074036424618c130dacb3464465a8b40bffef5Stephen Smalley avc_enforcing = rc; 184f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 185f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 186f074036424618c130dacb3464465a8b40bffef5Stephen Smalley rc = avc_netlink_open(0); 187f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (rc < 0) { 188f074036424618c130dacb3464465a8b40bffef5Stephen Smalley avc_log(SELINUX_ERROR, 189f074036424618c130dacb3464465a8b40bffef5Stephen Smalley "%s: can't open netlink socket: %d (%s)\n", 190f074036424618c130dacb3464465a8b40bffef5Stephen Smalley avc_prefix, errno, strerror(errno)); 191f074036424618c130dacb3464465a8b40bffef5Stephen Smalley goto out; 192f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 193f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (avc_using_threads) { 194f074036424618c130dacb3464465a8b40bffef5Stephen Smalley avc_netlink_thread = avc_create_thread(&avc_netlink_loop); 195f074036424618c130dacb3464465a8b40bffef5Stephen Smalley avc_netlink_trouble = 0; 196f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 197f074036424618c130dacb3464465a8b40bffef5Stephen Smalley avc_running = 1; 198f074036424618c130dacb3464465a8b40bffef5Stephen Smalley out: 199f074036424618c130dacb3464465a8b40bffef5Stephen Smalley return rc; 200f074036424618c130dacb3464465a8b40bffef5Stephen Smalley} 201f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 202f074036424618c130dacb3464465a8b40bffef5Stephen Smalleyvoid avc_cache_stats(struct avc_cache_stats *p) 203f074036424618c130dacb3464465a8b40bffef5Stephen Smalley{ 204f074036424618c130dacb3464465a8b40bffef5Stephen Smalley memcpy(p, &cache_stats, sizeof(cache_stats)); 205f074036424618c130dacb3464465a8b40bffef5Stephen Smalley} 206f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 207f074036424618c130dacb3464465a8b40bffef5Stephen Smalleyvoid avc_sid_stats(void) 208f074036424618c130dacb3464465a8b40bffef5Stephen Smalley{ 209f074036424618c130dacb3464465a8b40bffef5Stephen Smalley avc_get_lock(avc_log_lock); 210f074036424618c130dacb3464465a8b40bffef5Stephen Smalley avc_get_lock(avc_lock); 211f074036424618c130dacb3464465a8b40bffef5Stephen Smalley sidtab_sid_stats(&avc_sidtab, avc_audit_buf, AVC_AUDIT_BUFSIZE); 212f074036424618c130dacb3464465a8b40bffef5Stephen Smalley avc_release_lock(avc_lock); 213f074036424618c130dacb3464465a8b40bffef5Stephen Smalley avc_log(SELINUX_INFO, "%s", avc_audit_buf); 214f074036424618c130dacb3464465a8b40bffef5Stephen Smalley avc_release_lock(avc_log_lock); 215f074036424618c130dacb3464465a8b40bffef5Stephen Smalley} 216f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 217f074036424618c130dacb3464465a8b40bffef5Stephen Smalleyvoid avc_av_stats(void) 218f074036424618c130dacb3464465a8b40bffef5Stephen Smalley{ 219f074036424618c130dacb3464465a8b40bffef5Stephen Smalley int i, chain_len, max_chain_len, slots_used; 220f074036424618c130dacb3464465a8b40bffef5Stephen Smalley struct avc_node *node; 221f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 222f074036424618c130dacb3464465a8b40bffef5Stephen Smalley avc_get_lock(avc_lock); 223f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 224f074036424618c130dacb3464465a8b40bffef5Stephen Smalley slots_used = 0; 225f074036424618c130dacb3464465a8b40bffef5Stephen Smalley max_chain_len = 0; 226f074036424618c130dacb3464465a8b40bffef5Stephen Smalley for (i = 0; i < AVC_CACHE_SLOTS; i++) { 227f074036424618c130dacb3464465a8b40bffef5Stephen Smalley node = avc_cache.slots[i]; 228f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (node) { 229f074036424618c130dacb3464465a8b40bffef5Stephen Smalley slots_used++; 230f074036424618c130dacb3464465a8b40bffef5Stephen Smalley chain_len = 0; 231f074036424618c130dacb3464465a8b40bffef5Stephen Smalley while (node) { 232f074036424618c130dacb3464465a8b40bffef5Stephen Smalley chain_len++; 233f074036424618c130dacb3464465a8b40bffef5Stephen Smalley node = node->next; 234f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 235f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (chain_len > max_chain_len) 236f074036424618c130dacb3464465a8b40bffef5Stephen Smalley max_chain_len = chain_len; 237f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 238f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 239f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 240f074036424618c130dacb3464465a8b40bffef5Stephen Smalley avc_release_lock(avc_lock); 241f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 242f074036424618c130dacb3464465a8b40bffef5Stephen Smalley avc_log(SELINUX_INFO, "%s: %d AV entries and %d/%d buckets used, " 243f074036424618c130dacb3464465a8b40bffef5Stephen Smalley "longest chain length %d\n", avc_prefix, 244f074036424618c130dacb3464465a8b40bffef5Stephen Smalley avc_cache.active_nodes, 245f074036424618c130dacb3464465a8b40bffef5Stephen Smalley slots_used, AVC_CACHE_SLOTS, max_chain_len); 246f074036424618c130dacb3464465a8b40bffef5Stephen Smalley} 247f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 248f074036424618c130dacb3464465a8b40bffef5Stephen Smalleyhidden_def(avc_av_stats) 249f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 250f074036424618c130dacb3464465a8b40bffef5Stephen Smalleystatic inline struct avc_node *avc_reclaim_node(void) 251f074036424618c130dacb3464465a8b40bffef5Stephen Smalley{ 252f074036424618c130dacb3464465a8b40bffef5Stephen Smalley struct avc_node *prev, *cur; 253f074036424618c130dacb3464465a8b40bffef5Stephen Smalley int try; 254f074036424618c130dacb3464465a8b40bffef5Stephen Smalley uint32_t hvalue; 255f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 256f074036424618c130dacb3464465a8b40bffef5Stephen Smalley hvalue = avc_cache.lru_hint; 257f074036424618c130dacb3464465a8b40bffef5Stephen Smalley for (try = 0; try < 2; try++) { 258f074036424618c130dacb3464465a8b40bffef5Stephen Smalley do { 259f074036424618c130dacb3464465a8b40bffef5Stephen Smalley prev = NULL; 260f074036424618c130dacb3464465a8b40bffef5Stephen Smalley cur = avc_cache.slots[hvalue]; 261f074036424618c130dacb3464465a8b40bffef5Stephen Smalley while (cur) { 262f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (!cur->ae.used) 263f074036424618c130dacb3464465a8b40bffef5Stephen Smalley goto found; 264f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 265f074036424618c130dacb3464465a8b40bffef5Stephen Smalley cur->ae.used = 0; 266f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 267f074036424618c130dacb3464465a8b40bffef5Stephen Smalley prev = cur; 268f074036424618c130dacb3464465a8b40bffef5Stephen Smalley cur = cur->next; 269f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 270f074036424618c130dacb3464465a8b40bffef5Stephen Smalley hvalue = (hvalue + 1) & (AVC_CACHE_SLOTS - 1); 271f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } while (hvalue != avc_cache.lru_hint); 272f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 273f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 274f074036424618c130dacb3464465a8b40bffef5Stephen Smalley errno = ENOMEM; /* this was a panic in the kernel... */ 275f074036424618c130dacb3464465a8b40bffef5Stephen Smalley return NULL; 276f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 277f074036424618c130dacb3464465a8b40bffef5Stephen Smalley found: 278f074036424618c130dacb3464465a8b40bffef5Stephen Smalley avc_cache.lru_hint = hvalue; 279f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 280f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (prev == NULL) 281f074036424618c130dacb3464465a8b40bffef5Stephen Smalley avc_cache.slots[hvalue] = cur->next; 282f074036424618c130dacb3464465a8b40bffef5Stephen Smalley else 283f074036424618c130dacb3464465a8b40bffef5Stephen Smalley prev->next = cur->next; 284f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 285f074036424618c130dacb3464465a8b40bffef5Stephen Smalley return cur; 286f074036424618c130dacb3464465a8b40bffef5Stephen Smalley} 287f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 288f074036424618c130dacb3464465a8b40bffef5Stephen Smalleystatic inline void avc_clear_avc_entry(struct avc_entry *ae) 289f074036424618c130dacb3464465a8b40bffef5Stephen Smalley{ 2900dbac4eafd82ba0d9d9fa4ecf9bfdd34b6db2b52Stephen Smalley memset(ae, 0, sizeof *ae); 291f074036424618c130dacb3464465a8b40bffef5Stephen Smalley} 292f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 293f074036424618c130dacb3464465a8b40bffef5Stephen Smalleystatic inline struct avc_node *avc_claim_node(security_id_t ssid, 294f074036424618c130dacb3464465a8b40bffef5Stephen Smalley security_id_t tsid, 295f074036424618c130dacb3464465a8b40bffef5Stephen Smalley security_class_t tclass) 296f074036424618c130dacb3464465a8b40bffef5Stephen Smalley{ 297f074036424618c130dacb3464465a8b40bffef5Stephen Smalley struct avc_node *new; 298f074036424618c130dacb3464465a8b40bffef5Stephen Smalley int hvalue; 299f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 300f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (!avc_node_freelist) 301f074036424618c130dacb3464465a8b40bffef5Stephen Smalley avc_cleanup(); 302f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 303f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (avc_node_freelist) { 304f074036424618c130dacb3464465a8b40bffef5Stephen Smalley new = avc_node_freelist; 305f074036424618c130dacb3464465a8b40bffef5Stephen Smalley avc_node_freelist = avc_node_freelist->next; 306f074036424618c130dacb3464465a8b40bffef5Stephen Smalley avc_cache.active_nodes++; 307f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } else { 308f074036424618c130dacb3464465a8b40bffef5Stephen Smalley new = avc_reclaim_node(); 309f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (!new) 310f074036424618c130dacb3464465a8b40bffef5Stephen Smalley goto out; 311f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 312f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 313f074036424618c130dacb3464465a8b40bffef5Stephen Smalley hvalue = avc_hash(ssid, tsid, tclass); 314f074036424618c130dacb3464465a8b40bffef5Stephen Smalley avc_clear_avc_entry(&new->ae); 315f074036424618c130dacb3464465a8b40bffef5Stephen Smalley new->ae.used = 1; 316f074036424618c130dacb3464465a8b40bffef5Stephen Smalley new->ae.ssid = ssid; 317f074036424618c130dacb3464465a8b40bffef5Stephen Smalley new->ae.tsid = tsid; 318f074036424618c130dacb3464465a8b40bffef5Stephen Smalley new->ae.tclass = tclass; 319f074036424618c130dacb3464465a8b40bffef5Stephen Smalley new->next = avc_cache.slots[hvalue]; 320f074036424618c130dacb3464465a8b40bffef5Stephen Smalley avc_cache.slots[hvalue] = new; 321f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 322f074036424618c130dacb3464465a8b40bffef5Stephen Smalley out: 323f074036424618c130dacb3464465a8b40bffef5Stephen Smalley return new; 324f074036424618c130dacb3464465a8b40bffef5Stephen Smalley} 325f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 326f074036424618c130dacb3464465a8b40bffef5Stephen Smalleystatic inline struct avc_node *avc_search_node(security_id_t ssid, 327f074036424618c130dacb3464465a8b40bffef5Stephen Smalley security_id_t tsid, 328f074036424618c130dacb3464465a8b40bffef5Stephen Smalley security_class_t tclass, 329f074036424618c130dacb3464465a8b40bffef5Stephen Smalley int *probes) 330f074036424618c130dacb3464465a8b40bffef5Stephen Smalley{ 331f074036424618c130dacb3464465a8b40bffef5Stephen Smalley struct avc_node *cur; 332f074036424618c130dacb3464465a8b40bffef5Stephen Smalley int hvalue; 333f074036424618c130dacb3464465a8b40bffef5Stephen Smalley int tprobes = 1; 334f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 335f074036424618c130dacb3464465a8b40bffef5Stephen Smalley hvalue = avc_hash(ssid, tsid, tclass); 336f074036424618c130dacb3464465a8b40bffef5Stephen Smalley cur = avc_cache.slots[hvalue]; 337f074036424618c130dacb3464465a8b40bffef5Stephen Smalley while (cur != NULL && 338f074036424618c130dacb3464465a8b40bffef5Stephen Smalley (ssid != cur->ae.ssid || 339f074036424618c130dacb3464465a8b40bffef5Stephen Smalley tclass != cur->ae.tclass || tsid != cur->ae.tsid)) { 340f074036424618c130dacb3464465a8b40bffef5Stephen Smalley tprobes++; 341f074036424618c130dacb3464465a8b40bffef5Stephen Smalley cur = cur->next; 342f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 343f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 344f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (cur == NULL) { 345f074036424618c130dacb3464465a8b40bffef5Stephen Smalley /* cache miss */ 346f074036424618c130dacb3464465a8b40bffef5Stephen Smalley goto out; 347f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 348f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 349f074036424618c130dacb3464465a8b40bffef5Stephen Smalley /* cache hit */ 350f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (probes) 351f074036424618c130dacb3464465a8b40bffef5Stephen Smalley *probes = tprobes; 352f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 353f074036424618c130dacb3464465a8b40bffef5Stephen Smalley cur->ae.used = 1; 354f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 355f074036424618c130dacb3464465a8b40bffef5Stephen Smalley out: 356f074036424618c130dacb3464465a8b40bffef5Stephen Smalley return cur; 357f074036424618c130dacb3464465a8b40bffef5Stephen Smalley} 358f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 359f074036424618c130dacb3464465a8b40bffef5Stephen Smalley/** 360f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * avc_lookup - Look up an AVC entry. 361f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * @ssid: source security identifier 362f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * @tsid: target security identifier 363f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * @tclass: target security class 364f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * @requested: requested permissions, interpreted based on @tclass 365f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * @aeref: AVC entry reference 366f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * 367f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * Look up an AVC entry that is valid for the 368f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * @requested permissions between the SID pair 369f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * (@ssid, @tsid), interpreting the permissions 370f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * based on @tclass. If a valid AVC entry exists, 371f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * then this function updates @aeref to refer to the 372f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * entry and returns %0. Otherwise, -1 is returned. 373f074036424618c130dacb3464465a8b40bffef5Stephen Smalley */ 374f074036424618c130dacb3464465a8b40bffef5Stephen Smalleystatic int avc_lookup(security_id_t ssid, security_id_t tsid, 375f074036424618c130dacb3464465a8b40bffef5Stephen Smalley security_class_t tclass, 376f074036424618c130dacb3464465a8b40bffef5Stephen Smalley access_vector_t requested, struct avc_entry_ref *aeref) 377f074036424618c130dacb3464465a8b40bffef5Stephen Smalley{ 378f074036424618c130dacb3464465a8b40bffef5Stephen Smalley struct avc_node *node; 379f074036424618c130dacb3464465a8b40bffef5Stephen Smalley int probes, rc = 0; 380f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 381f074036424618c130dacb3464465a8b40bffef5Stephen Smalley avc_cache_stats_incr(cav_lookups); 382f074036424618c130dacb3464465a8b40bffef5Stephen Smalley node = avc_search_node(ssid, tsid, tclass, &probes); 383f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 384f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (node && ((node->ae.avd.decided & requested) == requested)) { 385f074036424618c130dacb3464465a8b40bffef5Stephen Smalley avc_cache_stats_incr(cav_hits); 386f074036424618c130dacb3464465a8b40bffef5Stephen Smalley avc_cache_stats_add(cav_probes, probes); 387f074036424618c130dacb3464465a8b40bffef5Stephen Smalley aeref->ae = &node->ae; 388f074036424618c130dacb3464465a8b40bffef5Stephen Smalley goto out; 389f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 390f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 391f074036424618c130dacb3464465a8b40bffef5Stephen Smalley avc_cache_stats_incr(cav_misses); 392f074036424618c130dacb3464465a8b40bffef5Stephen Smalley rc = -1; 393f074036424618c130dacb3464465a8b40bffef5Stephen Smalley out: 394f074036424618c130dacb3464465a8b40bffef5Stephen Smalley return rc; 395f074036424618c130dacb3464465a8b40bffef5Stephen Smalley} 396f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 397f074036424618c130dacb3464465a8b40bffef5Stephen Smalley/** 398f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * avc_insert - Insert an AVC entry. 399f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * @ssid: source security identifier 400f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * @tsid: target security identifier 401f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * @tclass: target security class 402f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * @ae: AVC entry 403f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * @aeref: AVC entry reference 404f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * 405f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * Insert an AVC entry for the SID pair 406f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * (@ssid, @tsid) and class @tclass. 407f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * The access vectors and the sequence number are 408f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * normally provided by the security server in 409f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * response to a security_compute_av() call. If the 410f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * sequence number @ae->avd.seqno is not less than the latest 411f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * revocation notification, then the function copies 412f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * the access vectors into a cache entry, updates 413f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * @aeref to refer to the entry, and returns %0. 414f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * Otherwise, this function returns -%1 with @errno set to %EAGAIN. 415f074036424618c130dacb3464465a8b40bffef5Stephen Smalley */ 416f074036424618c130dacb3464465a8b40bffef5Stephen Smalleystatic int avc_insert(security_id_t ssid, security_id_t tsid, 417f074036424618c130dacb3464465a8b40bffef5Stephen Smalley security_class_t tclass, 418f074036424618c130dacb3464465a8b40bffef5Stephen Smalley struct avc_entry *ae, struct avc_entry_ref *aeref) 419f074036424618c130dacb3464465a8b40bffef5Stephen Smalley{ 420f074036424618c130dacb3464465a8b40bffef5Stephen Smalley struct avc_node *node; 421f074036424618c130dacb3464465a8b40bffef5Stephen Smalley int rc = 0; 422f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 423f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (ae->avd.seqno < avc_cache.latest_notif) { 424f074036424618c130dacb3464465a8b40bffef5Stephen Smalley avc_log(SELINUX_WARNING, 425f074036424618c130dacb3464465a8b40bffef5Stephen Smalley "%s: seqno %d < latest_notif %d\n", avc_prefix, 426f074036424618c130dacb3464465a8b40bffef5Stephen Smalley ae->avd.seqno, avc_cache.latest_notif); 427f074036424618c130dacb3464465a8b40bffef5Stephen Smalley errno = EAGAIN; 428f074036424618c130dacb3464465a8b40bffef5Stephen Smalley rc = -1; 429f074036424618c130dacb3464465a8b40bffef5Stephen Smalley goto out; 430f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 431f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 432f074036424618c130dacb3464465a8b40bffef5Stephen Smalley node = avc_claim_node(ssid, tsid, tclass); 433f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (!node) { 434f074036424618c130dacb3464465a8b40bffef5Stephen Smalley rc = -1; 435f074036424618c130dacb3464465a8b40bffef5Stephen Smalley goto out; 436f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 437f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 4380dbac4eafd82ba0d9d9fa4ecf9bfdd34b6db2b52Stephen Smalley memcpy(&node->ae.avd, &ae->avd, sizeof ae->avd); 439f074036424618c130dacb3464465a8b40bffef5Stephen Smalley aeref->ae = &node->ae; 440f074036424618c130dacb3464465a8b40bffef5Stephen Smalley out: 441f074036424618c130dacb3464465a8b40bffef5Stephen Smalley return rc; 442f074036424618c130dacb3464465a8b40bffef5Stephen Smalley} 443f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 444f074036424618c130dacb3464465a8b40bffef5Stephen Smalleyvoid avc_cleanup(void) 445f074036424618c130dacb3464465a8b40bffef5Stephen Smalley{ 446f074036424618c130dacb3464465a8b40bffef5Stephen Smalley} 447f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 448f074036424618c130dacb3464465a8b40bffef5Stephen Smalleyhidden_def(avc_cleanup) 449f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 450f074036424618c130dacb3464465a8b40bffef5Stephen Smalleyint avc_reset(void) 451f074036424618c130dacb3464465a8b40bffef5Stephen Smalley{ 452f074036424618c130dacb3464465a8b40bffef5Stephen Smalley struct avc_callback_node *c; 453f074036424618c130dacb3464465a8b40bffef5Stephen Smalley int i, ret, rc = 0, errsave = 0; 454f074036424618c130dacb3464465a8b40bffef5Stephen Smalley struct avc_node *node, *tmp; 455f074036424618c130dacb3464465a8b40bffef5Stephen Smalley errno = 0; 456f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 457f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (!avc_running) 458f074036424618c130dacb3464465a8b40bffef5Stephen Smalley return 0; 459f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 460f074036424618c130dacb3464465a8b40bffef5Stephen Smalley avc_get_lock(avc_lock); 461f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 462f074036424618c130dacb3464465a8b40bffef5Stephen Smalley for (i = 0; i < AVC_CACHE_SLOTS; i++) { 463f074036424618c130dacb3464465a8b40bffef5Stephen Smalley node = avc_cache.slots[i]; 464f074036424618c130dacb3464465a8b40bffef5Stephen Smalley while (node) { 465f074036424618c130dacb3464465a8b40bffef5Stephen Smalley tmp = node; 466f074036424618c130dacb3464465a8b40bffef5Stephen Smalley node = node->next; 467f074036424618c130dacb3464465a8b40bffef5Stephen Smalley avc_clear_avc_entry(&tmp->ae); 468f074036424618c130dacb3464465a8b40bffef5Stephen Smalley tmp->next = avc_node_freelist; 469f074036424618c130dacb3464465a8b40bffef5Stephen Smalley avc_node_freelist = tmp; 470f074036424618c130dacb3464465a8b40bffef5Stephen Smalley avc_cache.active_nodes--; 471f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 472f074036424618c130dacb3464465a8b40bffef5Stephen Smalley avc_cache.slots[i] = 0; 473f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 474f074036424618c130dacb3464465a8b40bffef5Stephen Smalley avc_cache.lru_hint = 0; 475f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 476f074036424618c130dacb3464465a8b40bffef5Stephen Smalley avc_release_lock(avc_lock); 477f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 478f074036424618c130dacb3464465a8b40bffef5Stephen Smalley memset(&cache_stats, 0, sizeof(cache_stats)); 479f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 480f074036424618c130dacb3464465a8b40bffef5Stephen Smalley for (c = avc_callbacks; c; c = c->next) { 481f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (c->events & AVC_CALLBACK_RESET) { 482f074036424618c130dacb3464465a8b40bffef5Stephen Smalley ret = c->callback(AVC_CALLBACK_RESET, 0, 0, 0, 0, 0); 483f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (ret && !rc) { 484f074036424618c130dacb3464465a8b40bffef5Stephen Smalley rc = ret; 485f074036424618c130dacb3464465a8b40bffef5Stephen Smalley errsave = errno; 486f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 487f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 488f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 489f074036424618c130dacb3464465a8b40bffef5Stephen Smalley errno = errsave; 490f074036424618c130dacb3464465a8b40bffef5Stephen Smalley return rc; 491f074036424618c130dacb3464465a8b40bffef5Stephen Smalley} 492f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 493f074036424618c130dacb3464465a8b40bffef5Stephen Smalleyhidden_def(avc_reset) 494f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 495f074036424618c130dacb3464465a8b40bffef5Stephen Smalleyvoid avc_destroy(void) 496f074036424618c130dacb3464465a8b40bffef5Stephen Smalley{ 497f074036424618c130dacb3464465a8b40bffef5Stephen Smalley struct avc_callback_node *c; 498f074036424618c130dacb3464465a8b40bffef5Stephen Smalley struct avc_node *node, *tmp; 499f074036424618c130dacb3464465a8b40bffef5Stephen Smalley int i; 500f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 501f074036424618c130dacb3464465a8b40bffef5Stephen Smalley avc_get_lock(avc_lock); 502f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 503f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (avc_using_threads) 504f074036424618c130dacb3464465a8b40bffef5Stephen Smalley avc_stop_thread(avc_netlink_thread); 505f074036424618c130dacb3464465a8b40bffef5Stephen Smalley avc_netlink_close(); 506f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 507f074036424618c130dacb3464465a8b40bffef5Stephen Smalley for (i = 0; i < AVC_CACHE_SLOTS; i++) { 508f074036424618c130dacb3464465a8b40bffef5Stephen Smalley node = avc_cache.slots[i]; 509f074036424618c130dacb3464465a8b40bffef5Stephen Smalley while (node) { 510f074036424618c130dacb3464465a8b40bffef5Stephen Smalley tmp = node; 511f074036424618c130dacb3464465a8b40bffef5Stephen Smalley node = node->next; 512f074036424618c130dacb3464465a8b40bffef5Stephen Smalley avc_free(tmp); 513f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 514f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 515f074036424618c130dacb3464465a8b40bffef5Stephen Smalley while (avc_node_freelist) { 516f074036424618c130dacb3464465a8b40bffef5Stephen Smalley tmp = avc_node_freelist; 517f074036424618c130dacb3464465a8b40bffef5Stephen Smalley avc_node_freelist = tmp->next; 518f074036424618c130dacb3464465a8b40bffef5Stephen Smalley avc_free(tmp); 519f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 520f074036424618c130dacb3464465a8b40bffef5Stephen Smalley avc_release_lock(avc_lock); 521f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 522f074036424618c130dacb3464465a8b40bffef5Stephen Smalley while (avc_callbacks) { 523f074036424618c130dacb3464465a8b40bffef5Stephen Smalley c = avc_callbacks; 524f074036424618c130dacb3464465a8b40bffef5Stephen Smalley avc_callbacks = c->next; 525f074036424618c130dacb3464465a8b40bffef5Stephen Smalley avc_free(c); 526f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 527f074036424618c130dacb3464465a8b40bffef5Stephen Smalley sidtab_destroy(&avc_sidtab); 528f074036424618c130dacb3464465a8b40bffef5Stephen Smalley avc_free_lock(avc_lock); 529f074036424618c130dacb3464465a8b40bffef5Stephen Smalley avc_free_lock(avc_log_lock); 530f074036424618c130dacb3464465a8b40bffef5Stephen Smalley avc_free(avc_audit_buf); 531f074036424618c130dacb3464465a8b40bffef5Stephen Smalley avc_running = 0; 532f074036424618c130dacb3464465a8b40bffef5Stephen Smalley} 533f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 534f074036424618c130dacb3464465a8b40bffef5Stephen Smalley/* ratelimit stuff put aside for now --EFW */ 535f074036424618c130dacb3464465a8b40bffef5Stephen Smalley#if 0 536f074036424618c130dacb3464465a8b40bffef5Stephen Smalley/* 537f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * Copied from net/core/utils.c:net_ratelimit and modified for 538f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * use by the AVC audit facility. 539f074036424618c130dacb3464465a8b40bffef5Stephen Smalley */ 540f074036424618c130dacb3464465a8b40bffef5Stephen Smalley#define AVC_MSG_COST 5*HZ 541f074036424618c130dacb3464465a8b40bffef5Stephen Smalley#define AVC_MSG_BURST 10*5*HZ 542f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 543f074036424618c130dacb3464465a8b40bffef5Stephen Smalley/* 544f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * This enforces a rate limit: not more than one kernel message 545f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * every 5secs to make a denial-of-service attack impossible. 546f074036424618c130dacb3464465a8b40bffef5Stephen Smalley */ 547f074036424618c130dacb3464465a8b40bffef5Stephen Smalleystatic int avc_ratelimit(void) 548f074036424618c130dacb3464465a8b40bffef5Stephen Smalley{ 549f074036424618c130dacb3464465a8b40bffef5Stephen Smalley static unsigned long toks = 10 * 5 * HZ; 550f074036424618c130dacb3464465a8b40bffef5Stephen Smalley static unsigned long last_msg; 551f074036424618c130dacb3464465a8b40bffef5Stephen Smalley static int missed, rc = 0; 552f074036424618c130dacb3464465a8b40bffef5Stephen Smalley unsigned long now = jiffies; 553f074036424618c130dacb3464465a8b40bffef5Stephen Smalley void *ratelimit_lock = avc_alloc_lock(); 554f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 555f074036424618c130dacb3464465a8b40bffef5Stephen Smalley avc_get_lock(ratelimit_lock); 556f074036424618c130dacb3464465a8b40bffef5Stephen Smalley toks += now - last_msg; 557f074036424618c130dacb3464465a8b40bffef5Stephen Smalley last_msg = now; 558f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (toks > AVC_MSG_BURST) 559f074036424618c130dacb3464465a8b40bffef5Stephen Smalley toks = AVC_MSG_BURST; 560f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (toks >= AVC_MSG_COST) { 561f074036424618c130dacb3464465a8b40bffef5Stephen Smalley int lost = missed; 562f074036424618c130dacb3464465a8b40bffef5Stephen Smalley missed = 0; 563f074036424618c130dacb3464465a8b40bffef5Stephen Smalley toks -= AVC_MSG_COST; 564f074036424618c130dacb3464465a8b40bffef5Stephen Smalley avc_release_lock(ratelimit_lock); 565f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (lost) { 566f074036424618c130dacb3464465a8b40bffef5Stephen Smalley avc_log(SELINUX_WARNING, 567f074036424618c130dacb3464465a8b40bffef5Stephen Smalley "%s: %d messages suppressed.\n", avc_prefix, 568f074036424618c130dacb3464465a8b40bffef5Stephen Smalley lost); 569f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 570f074036424618c130dacb3464465a8b40bffef5Stephen Smalley rc = 1; 571f074036424618c130dacb3464465a8b40bffef5Stephen Smalley goto out; 572f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 573f074036424618c130dacb3464465a8b40bffef5Stephen Smalley missed++; 574f074036424618c130dacb3464465a8b40bffef5Stephen Smalley avc_release_lock(ratelimit_lock); 575f074036424618c130dacb3464465a8b40bffef5Stephen Smalley out: 576f074036424618c130dacb3464465a8b40bffef5Stephen Smalley avc_free_lock(ratelimit_lock); 577f074036424618c130dacb3464465a8b40bffef5Stephen Smalley return rc; 578f074036424618c130dacb3464465a8b40bffef5Stephen Smalley} 579f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 580f074036424618c130dacb3464465a8b40bffef5Stephen Smalleystatic inline int check_avc_ratelimit(void) 581f074036424618c130dacb3464465a8b40bffef5Stephen Smalley{ 582f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (avc_enforcing) 583f074036424618c130dacb3464465a8b40bffef5Stephen Smalley return avc_ratelimit(); 584f074036424618c130dacb3464465a8b40bffef5Stephen Smalley else { 585f074036424618c130dacb3464465a8b40bffef5Stephen Smalley /* If permissive, then never suppress messages. */ 586f074036424618c130dacb3464465a8b40bffef5Stephen Smalley return 1; 587f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 588f074036424618c130dacb3464465a8b40bffef5Stephen Smalley} 589f074036424618c130dacb3464465a8b40bffef5Stephen Smalley#endif /* ratelimit stuff */ 590f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 591f074036424618c130dacb3464465a8b40bffef5Stephen Smalley/** 592f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * avc_dump_av - Display an access vector in human-readable form. 593f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * @tclass: target security class 594f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * @av: access vector 595f074036424618c130dacb3464465a8b40bffef5Stephen Smalley */ 596f074036424618c130dacb3464465a8b40bffef5Stephen Smalleystatic void avc_dump_av(security_class_t tclass, access_vector_t av) 597f074036424618c130dacb3464465a8b40bffef5Stephen Smalley{ 598f074036424618c130dacb3464465a8b40bffef5Stephen Smalley const char *permstr; 599f074036424618c130dacb3464465a8b40bffef5Stephen Smalley access_vector_t bit = 1; 600f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 601f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (av == 0) { 602f074036424618c130dacb3464465a8b40bffef5Stephen Smalley log_append(avc_audit_buf, " null"); 603f074036424618c130dacb3464465a8b40bffef5Stephen Smalley return; 604f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 605f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 606f074036424618c130dacb3464465a8b40bffef5Stephen Smalley log_append(avc_audit_buf, " {"); 607f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 608f074036424618c130dacb3464465a8b40bffef5Stephen Smalley while (av) { 609f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (av & bit) { 610f074036424618c130dacb3464465a8b40bffef5Stephen Smalley permstr = security_av_perm_to_string(tclass, bit); 611f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (!permstr) 612f074036424618c130dacb3464465a8b40bffef5Stephen Smalley break; 613f074036424618c130dacb3464465a8b40bffef5Stephen Smalley log_append(avc_audit_buf, " %s", permstr); 614f074036424618c130dacb3464465a8b40bffef5Stephen Smalley av &= ~bit; 615f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 616f074036424618c130dacb3464465a8b40bffef5Stephen Smalley bit <<= 1; 617f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 618f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 619f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (av) 620f074036424618c130dacb3464465a8b40bffef5Stephen Smalley log_append(avc_audit_buf, " 0x%x", av); 621f074036424618c130dacb3464465a8b40bffef5Stephen Smalley log_append(avc_audit_buf, " }"); 622f074036424618c130dacb3464465a8b40bffef5Stephen Smalley} 623f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 624f074036424618c130dacb3464465a8b40bffef5Stephen Smalley/** 625f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * avc_dump_query - Display a SID pair and a class in human-readable form. 626f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * @ssid: source security identifier 627f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * @tsid: target security identifier 628f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * @tclass: target security class 629f074036424618c130dacb3464465a8b40bffef5Stephen Smalley */ 630f074036424618c130dacb3464465a8b40bffef5Stephen Smalleystatic void avc_dump_query(security_id_t ssid, security_id_t tsid, 631f074036424618c130dacb3464465a8b40bffef5Stephen Smalley security_class_t tclass) 632f074036424618c130dacb3464465a8b40bffef5Stephen Smalley{ 633f074036424618c130dacb3464465a8b40bffef5Stephen Smalley avc_get_lock(avc_lock); 634f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 635f074036424618c130dacb3464465a8b40bffef5Stephen Smalley log_append(avc_audit_buf, "scontext=%s tcontext=%s", 636f074036424618c130dacb3464465a8b40bffef5Stephen Smalley ssid->ctx, tsid->ctx); 637f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 638f074036424618c130dacb3464465a8b40bffef5Stephen Smalley avc_release_lock(avc_lock); 639f074036424618c130dacb3464465a8b40bffef5Stephen Smalley log_append(avc_audit_buf, " tclass=%s", 640f074036424618c130dacb3464465a8b40bffef5Stephen Smalley security_class_to_string(tclass)); 641f074036424618c130dacb3464465a8b40bffef5Stephen Smalley} 642f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 643f074036424618c130dacb3464465a8b40bffef5Stephen Smalleyvoid avc_audit(security_id_t ssid, security_id_t tsid, 644f074036424618c130dacb3464465a8b40bffef5Stephen Smalley security_class_t tclass, access_vector_t requested, 645f074036424618c130dacb3464465a8b40bffef5Stephen Smalley struct av_decision *avd, int result, void *a) 646f074036424618c130dacb3464465a8b40bffef5Stephen Smalley{ 647f074036424618c130dacb3464465a8b40bffef5Stephen Smalley access_vector_t denied, audited; 648f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 649f074036424618c130dacb3464465a8b40bffef5Stephen Smalley denied = requested & ~avd->allowed; 650f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (denied) 651f074036424618c130dacb3464465a8b40bffef5Stephen Smalley audited = denied & avd->auditdeny; 652f074036424618c130dacb3464465a8b40bffef5Stephen Smalley else if (!requested || result) 653f074036424618c130dacb3464465a8b40bffef5Stephen Smalley audited = denied = requested; 654f074036424618c130dacb3464465a8b40bffef5Stephen Smalley else 655f074036424618c130dacb3464465a8b40bffef5Stephen Smalley audited = requested & avd->auditallow; 656f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (!audited) 657f074036424618c130dacb3464465a8b40bffef5Stephen Smalley return; 658f074036424618c130dacb3464465a8b40bffef5Stephen Smalley#if 0 659f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (!check_avc_ratelimit()) 660f074036424618c130dacb3464465a8b40bffef5Stephen Smalley return; 661f074036424618c130dacb3464465a8b40bffef5Stephen Smalley#endif 662f074036424618c130dacb3464465a8b40bffef5Stephen Smalley /* prevent overlapping buffer writes */ 663f074036424618c130dacb3464465a8b40bffef5Stephen Smalley avc_get_lock(avc_log_lock); 664f074036424618c130dacb3464465a8b40bffef5Stephen Smalley snprintf(avc_audit_buf, AVC_AUDIT_BUFSIZE, 665f074036424618c130dacb3464465a8b40bffef5Stephen Smalley "%s: %s ", avc_prefix, (denied || !requested) ? "denied" : "granted"); 666f074036424618c130dacb3464465a8b40bffef5Stephen Smalley avc_dump_av(tclass, audited); 667f074036424618c130dacb3464465a8b40bffef5Stephen Smalley log_append(avc_audit_buf, " for "); 668f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 669f074036424618c130dacb3464465a8b40bffef5Stephen Smalley /* get any extra information printed by the callback */ 670f074036424618c130dacb3464465a8b40bffef5Stephen Smalley avc_suppl_audit(a, tclass, avc_audit_buf + strlen(avc_audit_buf), 671f074036424618c130dacb3464465a8b40bffef5Stephen Smalley AVC_AUDIT_BUFSIZE - strlen(avc_audit_buf)); 672f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 673f074036424618c130dacb3464465a8b40bffef5Stephen Smalley log_append(avc_audit_buf, " "); 674f074036424618c130dacb3464465a8b40bffef5Stephen Smalley avc_dump_query(ssid, tsid, tclass); 675f074036424618c130dacb3464465a8b40bffef5Stephen Smalley log_append(avc_audit_buf, "\n"); 676f074036424618c130dacb3464465a8b40bffef5Stephen Smalley avc_log(SELINUX_AVC, "%s", avc_audit_buf); 677f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 678f074036424618c130dacb3464465a8b40bffef5Stephen Smalley avc_release_lock(avc_log_lock); 679f074036424618c130dacb3464465a8b40bffef5Stephen Smalley} 680f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 681f074036424618c130dacb3464465a8b40bffef5Stephen Smalleyhidden_def(avc_audit) 682f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 683f074036424618c130dacb3464465a8b40bffef5Stephen Smalleyint avc_has_perm_noaudit(security_id_t ssid, 684f074036424618c130dacb3464465a8b40bffef5Stephen Smalley security_id_t tsid, 685f074036424618c130dacb3464465a8b40bffef5Stephen Smalley security_class_t tclass, 686f074036424618c130dacb3464465a8b40bffef5Stephen Smalley access_vector_t requested, 687f074036424618c130dacb3464465a8b40bffef5Stephen Smalley struct avc_entry_ref *aeref, struct av_decision *avd) 688f074036424618c130dacb3464465a8b40bffef5Stephen Smalley{ 689f074036424618c130dacb3464465a8b40bffef5Stephen Smalley struct avc_entry *ae; 690f074036424618c130dacb3464465a8b40bffef5Stephen Smalley int rc = 0; 691f074036424618c130dacb3464465a8b40bffef5Stephen Smalley struct avc_entry entry; 692f074036424618c130dacb3464465a8b40bffef5Stephen Smalley access_vector_t denied; 693f074036424618c130dacb3464465a8b40bffef5Stephen Smalley struct avc_entry_ref ref; 694f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 695f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (!avc_using_threads && !avc_app_main_loop) { 696f074036424618c130dacb3464465a8b40bffef5Stephen Smalley (void)avc_netlink_check_nb(); 697f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 698f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 699f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (!aeref) { 700f074036424618c130dacb3464465a8b40bffef5Stephen Smalley avc_entry_ref_init(&ref); 701f074036424618c130dacb3464465a8b40bffef5Stephen Smalley aeref = &ref; 702f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 703f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 704f074036424618c130dacb3464465a8b40bffef5Stephen Smalley avc_get_lock(avc_lock); 705f074036424618c130dacb3464465a8b40bffef5Stephen Smalley avc_cache_stats_incr(entry_lookups); 706f074036424618c130dacb3464465a8b40bffef5Stephen Smalley ae = aeref->ae; 707f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (ae) { 708f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (ae->ssid == ssid && 709f074036424618c130dacb3464465a8b40bffef5Stephen Smalley ae->tsid == tsid && 710f074036424618c130dacb3464465a8b40bffef5Stephen Smalley ae->tclass == tclass && 711f074036424618c130dacb3464465a8b40bffef5Stephen Smalley ((ae->avd.decided & requested) == requested)) { 712f074036424618c130dacb3464465a8b40bffef5Stephen Smalley avc_cache_stats_incr(entry_hits); 713f074036424618c130dacb3464465a8b40bffef5Stephen Smalley ae->used = 1; 714f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } else { 715f074036424618c130dacb3464465a8b40bffef5Stephen Smalley avc_cache_stats_incr(entry_discards); 716f074036424618c130dacb3464465a8b40bffef5Stephen Smalley ae = 0; 717f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 718f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 719f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 720f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (!ae) { 721f074036424618c130dacb3464465a8b40bffef5Stephen Smalley avc_cache_stats_incr(entry_misses); 722f074036424618c130dacb3464465a8b40bffef5Stephen Smalley rc = avc_lookup(ssid, tsid, tclass, requested, aeref); 723f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (rc) { 724f074036424618c130dacb3464465a8b40bffef5Stephen Smalley rc = security_compute_av(ssid->ctx, tsid->ctx, 725f074036424618c130dacb3464465a8b40bffef5Stephen Smalley tclass, requested, 726f074036424618c130dacb3464465a8b40bffef5Stephen Smalley &entry.avd); 727f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (rc) 728f074036424618c130dacb3464465a8b40bffef5Stephen Smalley goto out; 729f074036424618c130dacb3464465a8b40bffef5Stephen Smalley rc = avc_insert(ssid, tsid, tclass, &entry, aeref); 730f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (rc) 731f074036424618c130dacb3464465a8b40bffef5Stephen Smalley goto out; 732f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 733f074036424618c130dacb3464465a8b40bffef5Stephen Smalley ae = aeref->ae; 734f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 735f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 736f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (avd) 737f074036424618c130dacb3464465a8b40bffef5Stephen Smalley memcpy(avd, &ae->avd, sizeof(*avd)); 738f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 739f074036424618c130dacb3464465a8b40bffef5Stephen Smalley denied = requested & ~(ae->avd.allowed); 740f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 741f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (!requested || denied) { 742f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (!avc_enforcing || 743f074036424618c130dacb3464465a8b40bffef5Stephen Smalley (ae->avd.flags & SELINUX_AVD_FLAGS_PERMISSIVE)) 744f074036424618c130dacb3464465a8b40bffef5Stephen Smalley ae->avd.allowed |= requested; 745f074036424618c130dacb3464465a8b40bffef5Stephen Smalley else { 746f074036424618c130dacb3464465a8b40bffef5Stephen Smalley errno = EACCES; 747f074036424618c130dacb3464465a8b40bffef5Stephen Smalley rc = -1; 748f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 749f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 750f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 751f074036424618c130dacb3464465a8b40bffef5Stephen Smalley out: 752f074036424618c130dacb3464465a8b40bffef5Stephen Smalley avc_release_lock(avc_lock); 753f074036424618c130dacb3464465a8b40bffef5Stephen Smalley return rc; 754f074036424618c130dacb3464465a8b40bffef5Stephen Smalley} 755f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 756f074036424618c130dacb3464465a8b40bffef5Stephen Smalleyhidden_def(avc_has_perm_noaudit) 757f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 758f074036424618c130dacb3464465a8b40bffef5Stephen Smalleyint avc_has_perm(security_id_t ssid, security_id_t tsid, 759f074036424618c130dacb3464465a8b40bffef5Stephen Smalley security_class_t tclass, access_vector_t requested, 760f074036424618c130dacb3464465a8b40bffef5Stephen Smalley struct avc_entry_ref *aeref, void *auditdata) 761f074036424618c130dacb3464465a8b40bffef5Stephen Smalley{ 762f074036424618c130dacb3464465a8b40bffef5Stephen Smalley struct av_decision avd; 763f074036424618c130dacb3464465a8b40bffef5Stephen Smalley int errsave, rc; 764f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 765f074036424618c130dacb3464465a8b40bffef5Stephen Smalley memset(&avd, 0, sizeof(avd)); 766f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 767f074036424618c130dacb3464465a8b40bffef5Stephen Smalley rc = avc_has_perm_noaudit(ssid, tsid, tclass, requested, aeref, &avd); 768f074036424618c130dacb3464465a8b40bffef5Stephen Smalley errsave = errno; 769f074036424618c130dacb3464465a8b40bffef5Stephen Smalley avc_audit(ssid, tsid, tclass, requested, &avd, rc, auditdata); 770f074036424618c130dacb3464465a8b40bffef5Stephen Smalley errno = errsave; 771f074036424618c130dacb3464465a8b40bffef5Stephen Smalley return rc; 772f074036424618c130dacb3464465a8b40bffef5Stephen Smalley} 773f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 774f074036424618c130dacb3464465a8b40bffef5Stephen Smalleyint avc_compute_create(security_id_t ssid, security_id_t tsid, 775f074036424618c130dacb3464465a8b40bffef5Stephen Smalley security_class_t tclass, security_id_t *newsid) 776f074036424618c130dacb3464465a8b40bffef5Stephen Smalley{ 777f074036424618c130dacb3464465a8b40bffef5Stephen Smalley int rc; 778f074036424618c130dacb3464465a8b40bffef5Stephen Smalley struct avc_entry_ref aeref; 779f074036424618c130dacb3464465a8b40bffef5Stephen Smalley struct avc_entry entry; 780ab40ea9bfd71b50138f1482c4764a65ac17d8cafStephen Smalley char * ctx; 781f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 782f074036424618c130dacb3464465a8b40bffef5Stephen Smalley *newsid = NULL; 783f074036424618c130dacb3464465a8b40bffef5Stephen Smalley avc_entry_ref_init(&aeref); 784f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 785f074036424618c130dacb3464465a8b40bffef5Stephen Smalley avc_get_lock(avc_lock); 786f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 787f074036424618c130dacb3464465a8b40bffef5Stephen Smalley /* check for a cached entry */ 788f074036424618c130dacb3464465a8b40bffef5Stephen Smalley rc = avc_lookup(ssid, tsid, tclass, 0, &aeref); 789f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (rc) { 790f074036424618c130dacb3464465a8b40bffef5Stephen Smalley /* need to make a cache entry for this tuple */ 791f074036424618c130dacb3464465a8b40bffef5Stephen Smalley rc = security_compute_av(ssid->ctx, tsid->ctx, 792f074036424618c130dacb3464465a8b40bffef5Stephen Smalley tclass, 0, &entry.avd); 793f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (rc) 794f074036424618c130dacb3464465a8b40bffef5Stephen Smalley goto out; 795f074036424618c130dacb3464465a8b40bffef5Stephen Smalley rc = avc_insert(ssid, tsid, tclass, &entry, &aeref); 796f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (rc) 797f074036424618c130dacb3464465a8b40bffef5Stephen Smalley goto out; 798f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 799f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 800f074036424618c130dacb3464465a8b40bffef5Stephen Smalley /* check for a saved compute_create value */ 801f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (!aeref.ae->create_sid) { 802f074036424618c130dacb3464465a8b40bffef5Stephen Smalley /* need to query the kernel policy */ 803f074036424618c130dacb3464465a8b40bffef5Stephen Smalley rc = security_compute_create(ssid->ctx, tsid->ctx, tclass, 804f074036424618c130dacb3464465a8b40bffef5Stephen Smalley &ctx); 805f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (rc) 806f074036424618c130dacb3464465a8b40bffef5Stephen Smalley goto out; 807f074036424618c130dacb3464465a8b40bffef5Stephen Smalley rc = sidtab_context_to_sid(&avc_sidtab, ctx, newsid); 808f074036424618c130dacb3464465a8b40bffef5Stephen Smalley freecon(ctx); 809f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (rc) 810f074036424618c130dacb3464465a8b40bffef5Stephen Smalley goto out; 811f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 812f074036424618c130dacb3464465a8b40bffef5Stephen Smalley aeref.ae->create_sid = *newsid; 813f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } else { 814f074036424618c130dacb3464465a8b40bffef5Stephen Smalley /* found saved value */ 815f074036424618c130dacb3464465a8b40bffef5Stephen Smalley *newsid = aeref.ae->create_sid; 816f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 817f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 818f074036424618c130dacb3464465a8b40bffef5Stephen Smalley rc = 0; 819f074036424618c130dacb3464465a8b40bffef5Stephen Smalleyout: 820f074036424618c130dacb3464465a8b40bffef5Stephen Smalley avc_release_lock(avc_lock); 821f074036424618c130dacb3464465a8b40bffef5Stephen Smalley return rc; 822f074036424618c130dacb3464465a8b40bffef5Stephen Smalley} 823f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 824f074036424618c130dacb3464465a8b40bffef5Stephen Smalleyint avc_add_callback(int (*callback) (uint32_t event, security_id_t ssid, 825f074036424618c130dacb3464465a8b40bffef5Stephen Smalley security_id_t tsid, 826f074036424618c130dacb3464465a8b40bffef5Stephen Smalley security_class_t tclass, 827f074036424618c130dacb3464465a8b40bffef5Stephen Smalley access_vector_t perms, 828f074036424618c130dacb3464465a8b40bffef5Stephen Smalley access_vector_t * out_retained), 829f074036424618c130dacb3464465a8b40bffef5Stephen Smalley uint32_t events, security_id_t ssid, 830f074036424618c130dacb3464465a8b40bffef5Stephen Smalley security_id_t tsid, 831f074036424618c130dacb3464465a8b40bffef5Stephen Smalley security_class_t tclass, access_vector_t perms) 832f074036424618c130dacb3464465a8b40bffef5Stephen Smalley{ 833f074036424618c130dacb3464465a8b40bffef5Stephen Smalley struct avc_callback_node *c; 834f074036424618c130dacb3464465a8b40bffef5Stephen Smalley int rc = 0; 835f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 836f074036424618c130dacb3464465a8b40bffef5Stephen Smalley c = avc_malloc(sizeof(*c)); 837f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (!c) { 838f074036424618c130dacb3464465a8b40bffef5Stephen Smalley rc = -1; 839f074036424618c130dacb3464465a8b40bffef5Stephen Smalley goto out; 840f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 841f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 842f074036424618c130dacb3464465a8b40bffef5Stephen Smalley c->callback = callback; 843f074036424618c130dacb3464465a8b40bffef5Stephen Smalley c->events = events; 844f074036424618c130dacb3464465a8b40bffef5Stephen Smalley c->ssid = ssid; 845f074036424618c130dacb3464465a8b40bffef5Stephen Smalley c->tsid = tsid; 846f074036424618c130dacb3464465a8b40bffef5Stephen Smalley c->tclass = tclass; 847f074036424618c130dacb3464465a8b40bffef5Stephen Smalley c->perms = perms; 848f074036424618c130dacb3464465a8b40bffef5Stephen Smalley c->next = avc_callbacks; 849f074036424618c130dacb3464465a8b40bffef5Stephen Smalley avc_callbacks = c; 850f074036424618c130dacb3464465a8b40bffef5Stephen Smalley out: 851f074036424618c130dacb3464465a8b40bffef5Stephen Smalley return rc; 852f074036424618c130dacb3464465a8b40bffef5Stephen Smalley} 853f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 854f074036424618c130dacb3464465a8b40bffef5Stephen Smalleystatic inline int avc_sidcmp(security_id_t x, security_id_t y) 855f074036424618c130dacb3464465a8b40bffef5Stephen Smalley{ 856f074036424618c130dacb3464465a8b40bffef5Stephen Smalley return (x == y || x == SECSID_WILD || y == SECSID_WILD); 857f074036424618c130dacb3464465a8b40bffef5Stephen Smalley} 858f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 859f074036424618c130dacb3464465a8b40bffef5Stephen Smalleystatic inline void avc_update_node(uint32_t event, struct avc_node *node, 860f074036424618c130dacb3464465a8b40bffef5Stephen Smalley access_vector_t perms) 861f074036424618c130dacb3464465a8b40bffef5Stephen Smalley{ 862f074036424618c130dacb3464465a8b40bffef5Stephen Smalley switch (event) { 863f074036424618c130dacb3464465a8b40bffef5Stephen Smalley case AVC_CALLBACK_GRANT: 864f074036424618c130dacb3464465a8b40bffef5Stephen Smalley node->ae.avd.allowed |= perms; 865f074036424618c130dacb3464465a8b40bffef5Stephen Smalley break; 866f074036424618c130dacb3464465a8b40bffef5Stephen Smalley case AVC_CALLBACK_TRY_REVOKE: 867f074036424618c130dacb3464465a8b40bffef5Stephen Smalley case AVC_CALLBACK_REVOKE: 868f074036424618c130dacb3464465a8b40bffef5Stephen Smalley node->ae.avd.allowed &= ~perms; 869f074036424618c130dacb3464465a8b40bffef5Stephen Smalley break; 870f074036424618c130dacb3464465a8b40bffef5Stephen Smalley case AVC_CALLBACK_AUDITALLOW_ENABLE: 871f074036424618c130dacb3464465a8b40bffef5Stephen Smalley node->ae.avd.auditallow |= perms; 872f074036424618c130dacb3464465a8b40bffef5Stephen Smalley break; 873f074036424618c130dacb3464465a8b40bffef5Stephen Smalley case AVC_CALLBACK_AUDITALLOW_DISABLE: 874f074036424618c130dacb3464465a8b40bffef5Stephen Smalley node->ae.avd.auditallow &= ~perms; 875f074036424618c130dacb3464465a8b40bffef5Stephen Smalley break; 876f074036424618c130dacb3464465a8b40bffef5Stephen Smalley case AVC_CALLBACK_AUDITDENY_ENABLE: 877f074036424618c130dacb3464465a8b40bffef5Stephen Smalley node->ae.avd.auditdeny |= perms; 878f074036424618c130dacb3464465a8b40bffef5Stephen Smalley break; 879f074036424618c130dacb3464465a8b40bffef5Stephen Smalley case AVC_CALLBACK_AUDITDENY_DISABLE: 880f074036424618c130dacb3464465a8b40bffef5Stephen Smalley node->ae.avd.auditdeny &= ~perms; 881f074036424618c130dacb3464465a8b40bffef5Stephen Smalley break; 882f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 883f074036424618c130dacb3464465a8b40bffef5Stephen Smalley} 884f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 885f074036424618c130dacb3464465a8b40bffef5Stephen Smalleystatic int avc_update_cache(uint32_t event, security_id_t ssid, 886f074036424618c130dacb3464465a8b40bffef5Stephen Smalley security_id_t tsid, security_class_t tclass, 887f074036424618c130dacb3464465a8b40bffef5Stephen Smalley access_vector_t perms) 888f074036424618c130dacb3464465a8b40bffef5Stephen Smalley{ 889f074036424618c130dacb3464465a8b40bffef5Stephen Smalley struct avc_node *node; 890f074036424618c130dacb3464465a8b40bffef5Stephen Smalley int i; 891f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 892f074036424618c130dacb3464465a8b40bffef5Stephen Smalley avc_get_lock(avc_lock); 893f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 894f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (ssid == SECSID_WILD || tsid == SECSID_WILD) { 895f074036424618c130dacb3464465a8b40bffef5Stephen Smalley /* apply to all matching nodes */ 896f074036424618c130dacb3464465a8b40bffef5Stephen Smalley for (i = 0; i < AVC_CACHE_SLOTS; i++) { 897f074036424618c130dacb3464465a8b40bffef5Stephen Smalley for (node = avc_cache.slots[i]; node; node = node->next) { 898f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (avc_sidcmp(ssid, node->ae.ssid) && 899f074036424618c130dacb3464465a8b40bffef5Stephen Smalley avc_sidcmp(tsid, node->ae.tsid) && 900f074036424618c130dacb3464465a8b40bffef5Stephen Smalley tclass == node->ae.tclass) { 901f074036424618c130dacb3464465a8b40bffef5Stephen Smalley avc_update_node(event, node, perms); 902f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 903f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 904f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 905f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } else { 906f074036424618c130dacb3464465a8b40bffef5Stephen Smalley /* apply to one node */ 907f074036424618c130dacb3464465a8b40bffef5Stephen Smalley node = avc_search_node(ssid, tsid, tclass, 0); 908f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (node) { 909f074036424618c130dacb3464465a8b40bffef5Stephen Smalley avc_update_node(event, node, perms); 910f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 911f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 912f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 913f074036424618c130dacb3464465a8b40bffef5Stephen Smalley avc_release_lock(avc_lock); 914f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 915f074036424618c130dacb3464465a8b40bffef5Stephen Smalley return 0; 916f074036424618c130dacb3464465a8b40bffef5Stephen Smalley} 917f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 918f074036424618c130dacb3464465a8b40bffef5Stephen Smalley/* avc_control - update cache and call callbacks 919f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * 920f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * This should not be called directly; use the individual event 921f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * functions instead. 922f074036424618c130dacb3464465a8b40bffef5Stephen Smalley */ 923f074036424618c130dacb3464465a8b40bffef5Stephen Smalleystatic int avc_control(uint32_t event, security_id_t ssid, 924f074036424618c130dacb3464465a8b40bffef5Stephen Smalley security_id_t tsid, security_class_t tclass, 925f074036424618c130dacb3464465a8b40bffef5Stephen Smalley access_vector_t perms, 926f074036424618c130dacb3464465a8b40bffef5Stephen Smalley uint32_t seqno, access_vector_t * out_retained) 927f074036424618c130dacb3464465a8b40bffef5Stephen Smalley{ 928f074036424618c130dacb3464465a8b40bffef5Stephen Smalley struct avc_callback_node *c; 929f074036424618c130dacb3464465a8b40bffef5Stephen Smalley access_vector_t tretained = 0, cretained = 0; 930f074036424618c130dacb3464465a8b40bffef5Stephen Smalley int ret, rc = 0, errsave = 0; 931f074036424618c130dacb3464465a8b40bffef5Stephen Smalley errno = 0; 932f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 933f074036424618c130dacb3464465a8b40bffef5Stephen Smalley /* 934f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * try_revoke only removes permissions from the cache 935f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * state if they are not retained by the object manager. 936f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * Hence, try_revoke must wait until after the callbacks have 937f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * been invoked to update the cache state. 938f074036424618c130dacb3464465a8b40bffef5Stephen Smalley */ 939f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (event != AVC_CALLBACK_TRY_REVOKE) 940f074036424618c130dacb3464465a8b40bffef5Stephen Smalley avc_update_cache(event, ssid, tsid, tclass, perms); 941f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 942f074036424618c130dacb3464465a8b40bffef5Stephen Smalley for (c = avc_callbacks; c; c = c->next) { 943f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if ((c->events & event) && 944f074036424618c130dacb3464465a8b40bffef5Stephen Smalley avc_sidcmp(c->ssid, ssid) && 945f074036424618c130dacb3464465a8b40bffef5Stephen Smalley avc_sidcmp(c->tsid, tsid) && 946f074036424618c130dacb3464465a8b40bffef5Stephen Smalley c->tclass == tclass && (c->perms & perms)) { 947f074036424618c130dacb3464465a8b40bffef5Stephen Smalley cretained = 0; 948f074036424618c130dacb3464465a8b40bffef5Stephen Smalley ret = c->callback(event, ssid, tsid, tclass, 949f074036424618c130dacb3464465a8b40bffef5Stephen Smalley (c->perms & perms), &cretained); 950f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (ret && !rc) { 951f074036424618c130dacb3464465a8b40bffef5Stephen Smalley rc = ret; 952f074036424618c130dacb3464465a8b40bffef5Stephen Smalley errsave = errno; 953f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 954f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (!ret) 955f074036424618c130dacb3464465a8b40bffef5Stephen Smalley tretained |= cretained; 956f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 957f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 958f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 959f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (event == AVC_CALLBACK_TRY_REVOKE) { 960f074036424618c130dacb3464465a8b40bffef5Stephen Smalley /* revoke any unretained permissions */ 961f074036424618c130dacb3464465a8b40bffef5Stephen Smalley perms &= ~tretained; 962f074036424618c130dacb3464465a8b40bffef5Stephen Smalley avc_update_cache(event, ssid, tsid, tclass, perms); 963f074036424618c130dacb3464465a8b40bffef5Stephen Smalley *out_retained = tretained; 964f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 965f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 966f074036424618c130dacb3464465a8b40bffef5Stephen Smalley avc_get_lock(avc_lock); 967f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (seqno > avc_cache.latest_notif) 968f074036424618c130dacb3464465a8b40bffef5Stephen Smalley avc_cache.latest_notif = seqno; 969f074036424618c130dacb3464465a8b40bffef5Stephen Smalley avc_release_lock(avc_lock); 970f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 971f074036424618c130dacb3464465a8b40bffef5Stephen Smalley errno = errsave; 972f074036424618c130dacb3464465a8b40bffef5Stephen Smalley return rc; 973f074036424618c130dacb3464465a8b40bffef5Stephen Smalley} 974f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 975f074036424618c130dacb3464465a8b40bffef5Stephen Smalley/** 976f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * avc_ss_grant - Grant previously denied permissions. 977f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * @ssid: source security identifier or %SECSID_WILD 978f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * @tsid: target security identifier or %SECSID_WILD 979f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * @tclass: target security class 980f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * @perms: permissions to grant 981f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * @seqno: policy sequence number 982f074036424618c130dacb3464465a8b40bffef5Stephen Smalley */ 983f074036424618c130dacb3464465a8b40bffef5Stephen Smalleyint avc_ss_grant(security_id_t ssid, security_id_t tsid, 984f074036424618c130dacb3464465a8b40bffef5Stephen Smalley security_class_t tclass, access_vector_t perms, 985f074036424618c130dacb3464465a8b40bffef5Stephen Smalley uint32_t seqno) 986f074036424618c130dacb3464465a8b40bffef5Stephen Smalley{ 987f074036424618c130dacb3464465a8b40bffef5Stephen Smalley return avc_control(AVC_CALLBACK_GRANT, 988f074036424618c130dacb3464465a8b40bffef5Stephen Smalley ssid, tsid, tclass, perms, seqno, 0); 989f074036424618c130dacb3464465a8b40bffef5Stephen Smalley} 990f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 991f074036424618c130dacb3464465a8b40bffef5Stephen Smalley/** 992f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * avc_ss_try_revoke - Try to revoke previously granted permissions. 993f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * @ssid: source security identifier or %SECSID_WILD 994f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * @tsid: target security identifier or %SECSID_WILD 995f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * @tclass: target security class 996f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * @perms: permissions to grant 997f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * @seqno: policy sequence number 998f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * @out_retained: subset of @perms that are retained 999f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * 1000f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * Try to revoke previously granted permissions, but 1001f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * only if they are not retained as migrated permissions. 1002f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * Return the subset of permissions that are retained via @out_retained. 1003f074036424618c130dacb3464465a8b40bffef5Stephen Smalley */ 1004f074036424618c130dacb3464465a8b40bffef5Stephen Smalleyint avc_ss_try_revoke(security_id_t ssid, security_id_t tsid, 1005f074036424618c130dacb3464465a8b40bffef5Stephen Smalley security_class_t tclass, 1006f074036424618c130dacb3464465a8b40bffef5Stephen Smalley access_vector_t perms, uint32_t seqno, 1007f074036424618c130dacb3464465a8b40bffef5Stephen Smalley access_vector_t * out_retained) 1008f074036424618c130dacb3464465a8b40bffef5Stephen Smalley{ 1009f074036424618c130dacb3464465a8b40bffef5Stephen Smalley return avc_control(AVC_CALLBACK_TRY_REVOKE, 1010f074036424618c130dacb3464465a8b40bffef5Stephen Smalley ssid, tsid, tclass, perms, seqno, out_retained); 1011f074036424618c130dacb3464465a8b40bffef5Stephen Smalley} 1012f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 1013f074036424618c130dacb3464465a8b40bffef5Stephen Smalley/** 1014f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * avc_ss_revoke - Revoke previously granted permissions. 1015f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * @ssid: source security identifier or %SECSID_WILD 1016f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * @tsid: target security identifier or %SECSID_WILD 1017f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * @tclass: target security class 1018f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * @perms: permissions to grant 1019f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * @seqno: policy sequence number 1020f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * 1021f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * Revoke previously granted permissions, even if 1022f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * they are retained as migrated permissions. 1023f074036424618c130dacb3464465a8b40bffef5Stephen Smalley */ 1024f074036424618c130dacb3464465a8b40bffef5Stephen Smalleyint avc_ss_revoke(security_id_t ssid, security_id_t tsid, 1025f074036424618c130dacb3464465a8b40bffef5Stephen Smalley security_class_t tclass, access_vector_t perms, 1026f074036424618c130dacb3464465a8b40bffef5Stephen Smalley uint32_t seqno) 1027f074036424618c130dacb3464465a8b40bffef5Stephen Smalley{ 1028f074036424618c130dacb3464465a8b40bffef5Stephen Smalley return avc_control(AVC_CALLBACK_REVOKE, 1029f074036424618c130dacb3464465a8b40bffef5Stephen Smalley ssid, tsid, tclass, perms, seqno, 0); 1030f074036424618c130dacb3464465a8b40bffef5Stephen Smalley} 1031f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 1032f074036424618c130dacb3464465a8b40bffef5Stephen Smalley/** 1033f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * avc_ss_reset - Flush the cache and revalidate migrated permissions. 1034f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * @seqno: policy sequence number 1035f074036424618c130dacb3464465a8b40bffef5Stephen Smalley */ 1036f074036424618c130dacb3464465a8b40bffef5Stephen Smalleyint avc_ss_reset(uint32_t seqno) 1037f074036424618c130dacb3464465a8b40bffef5Stephen Smalley{ 1038f074036424618c130dacb3464465a8b40bffef5Stephen Smalley int rc; 1039f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 1040f074036424618c130dacb3464465a8b40bffef5Stephen Smalley rc = avc_reset(); 1041f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 1042f074036424618c130dacb3464465a8b40bffef5Stephen Smalley avc_get_lock(avc_lock); 1043f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (seqno > avc_cache.latest_notif) 1044f074036424618c130dacb3464465a8b40bffef5Stephen Smalley avc_cache.latest_notif = seqno; 1045f074036424618c130dacb3464465a8b40bffef5Stephen Smalley avc_release_lock(avc_lock); 1046f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 1047f074036424618c130dacb3464465a8b40bffef5Stephen Smalley return rc; 1048f074036424618c130dacb3464465a8b40bffef5Stephen Smalley} 1049f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 1050f074036424618c130dacb3464465a8b40bffef5Stephen Smalley/** 1051f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * avc_ss_set_auditallow - Enable or disable auditing of granted permissions. 1052f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * @ssid: source security identifier or %SECSID_WILD 1053f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * @tsid: target security identifier or %SECSID_WILD 1054f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * @tclass: target security class 1055f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * @perms: permissions to grant 1056f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * @seqno: policy sequence number 1057f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * @enable: enable flag. 1058f074036424618c130dacb3464465a8b40bffef5Stephen Smalley */ 1059f074036424618c130dacb3464465a8b40bffef5Stephen Smalleyint avc_ss_set_auditallow(security_id_t ssid, security_id_t tsid, 1060f074036424618c130dacb3464465a8b40bffef5Stephen Smalley security_class_t tclass, access_vector_t perms, 1061f074036424618c130dacb3464465a8b40bffef5Stephen Smalley uint32_t seqno, uint32_t enable) 1062f074036424618c130dacb3464465a8b40bffef5Stephen Smalley{ 1063f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (enable) 1064f074036424618c130dacb3464465a8b40bffef5Stephen Smalley return avc_control(AVC_CALLBACK_AUDITALLOW_ENABLE, 1065f074036424618c130dacb3464465a8b40bffef5Stephen Smalley ssid, tsid, tclass, perms, seqno, 0); 1066f074036424618c130dacb3464465a8b40bffef5Stephen Smalley else 1067f074036424618c130dacb3464465a8b40bffef5Stephen Smalley return avc_control(AVC_CALLBACK_AUDITALLOW_DISABLE, 1068f074036424618c130dacb3464465a8b40bffef5Stephen Smalley ssid, tsid, tclass, perms, seqno, 0); 1069f074036424618c130dacb3464465a8b40bffef5Stephen Smalley} 1070f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 1071f074036424618c130dacb3464465a8b40bffef5Stephen Smalley/** 1072f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * avc_ss_set_auditdeny - Enable or disable auditing of denied permissions. 1073f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * @ssid: source security identifier or %SECSID_WILD 1074f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * @tsid: target security identifier or %SECSID_WILD 1075f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * @tclass: target security class 1076f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * @perms: permissions to grant 1077f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * @seqno: policy sequence number 1078f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * @enable: enable flag. 1079f074036424618c130dacb3464465a8b40bffef5Stephen Smalley */ 1080f074036424618c130dacb3464465a8b40bffef5Stephen Smalleyint avc_ss_set_auditdeny(security_id_t ssid, security_id_t tsid, 1081f074036424618c130dacb3464465a8b40bffef5Stephen Smalley security_class_t tclass, access_vector_t perms, 1082f074036424618c130dacb3464465a8b40bffef5Stephen Smalley uint32_t seqno, uint32_t enable) 1083f074036424618c130dacb3464465a8b40bffef5Stephen Smalley{ 1084f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (enable) 1085f074036424618c130dacb3464465a8b40bffef5Stephen Smalley return avc_control(AVC_CALLBACK_AUDITDENY_ENABLE, 1086f074036424618c130dacb3464465a8b40bffef5Stephen Smalley ssid, tsid, tclass, perms, seqno, 0); 1087f074036424618c130dacb3464465a8b40bffef5Stephen Smalley else 1088f074036424618c130dacb3464465a8b40bffef5Stephen Smalley return avc_control(AVC_CALLBACK_AUDITDENY_DISABLE, 1089f074036424618c130dacb3464465a8b40bffef5Stephen Smalley ssid, tsid, tclass, perms, seqno, 0); 1090f074036424618c130dacb3464465a8b40bffef5Stephen Smalley} 1091