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