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