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