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 "avc_sidtab.h"
13#include "avc_internal.h"
14
15#define AVC_CACHE_SLOTS		512
16#define AVC_CACHE_MAXNODES	410
17
18struct 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
27struct avc_node {
28	struct avc_entry ae;
29	struct avc_node *next;
30};
31
32struct 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
39struct 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
52static void *avc_netlink_thread = NULL;
53static void *avc_lock = NULL;
54static void *avc_log_lock = NULL;
55static struct avc_node *avc_node_freelist = NULL;
56static struct avc_cache avc_cache;
57static char *avc_audit_buf = NULL;
58static struct avc_cache_stats cache_stats;
59static struct avc_callback_node *avc_callbacks = NULL;
60static struct sidtab avc_sidtab;
61
62static 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
69int 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
78int 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
89int 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
104int 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
119int 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
202void avc_cache_stats(struct avc_cache_stats *p)
203{
204	memcpy(p, &cache_stats, sizeof(cache_stats));
205}
206
207void 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
217void 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
248hidden_def(avc_av_stats)
249
250static 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
288static 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
297static 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
330static 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 */
378static 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 */
420static 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
452void avc_cleanup(void)
453{
454}
455
456hidden_def(avc_cleanup)
457
458int 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
501hidden_def(avc_reset)
502
503void 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 */
555static 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
588static 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 */
604static 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 */
638static 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
651void 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
689hidden_def(avc_audit)
690
691int 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
764hidden_def(avc_has_perm_noaudit)
765
766int 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
782int 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;
827out:
828	avc_release_lock(avc_lock);
829	return rc;
830}
831
832int 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
862static 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
867static 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
893static 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 */
931static 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 */
991int 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 */
1012int 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 */
1032int 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 */
1044int 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 */
1067int 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 */
1088int 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