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