• 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@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 
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_netlink_thread = NULL;
54 static void *avc_lock = NULL;
55 static void *avc_log_lock = NULL;
56 static struct avc_node *avc_node_freelist = NULL;
57 static struct avc_cache avc_cache;
58 static char *avc_audit_buf = NULL;
59 static struct avc_cache_stats cache_stats;
60 static struct avc_callback_node *avc_callbacks = NULL;
61 static struct sidtab avc_sidtab;
62 
avc_hash(security_id_t ssid,security_id_t tsid,security_class_t tclass)63 static 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 
avc_context_to_sid_raw(const char * ctx,security_id_t * sid)70 int 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 
avc_context_to_sid(const char * ctx,security_id_t * sid)82 int 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 
avc_sid_to_context_raw(security_id_t sid,char ** ctx)97 int 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 
avc_sid_to_context(security_id_t sid,char ** ctx)108 int 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 
sidget(security_id_t sid)123 int sidget(security_id_t sid __attribute__((unused)))
124 {
125 	return 1;
126 }
127 
sidput(security_id_t sid)128 int sidput(security_id_t sid __attribute__((unused)))
129 {
130 	return 1;
131 }
132 
avc_get_initial_sid(const char * name,security_id_t * sid)133 int 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 
avc_open(struct selinux_opt * opts,unsigned nopts)148 int 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 
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)163 int 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 
avc_cache_stats(struct avc_cache_stats * p)249 void avc_cache_stats(struct avc_cache_stats *p)
250 {
251 	memcpy(p, &cache_stats, sizeof(cache_stats));
252 }
253 
avc_sid_stats(void)254 void 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 
avc_av_stats(void)266 void 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 
hidden_def(avc_av_stats)297 hidden_def(avc_av_stats)
298 
299 static 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 
avc_clear_avc_entry(struct avc_entry * ae)337 static inline void avc_clear_avc_entry(struct avc_entry *ae)
338 {
339 	memset(ae, 0, sizeof(*ae));
340 }
341 
avc_claim_node(security_id_t ssid,security_id_t tsid,security_class_t tclass)342 static 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 
avc_search_node(security_id_t ssid,security_id_t tsid,security_class_t tclass,int * probes)375 static 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  */
avc_lookup(security_id_t ssid,security_id_t tsid,security_class_t tclass,access_vector_t requested,struct avc_entry_ref * aeref)423 static 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  */
avc_insert(security_id_t ssid,security_id_t tsid,security_class_t tclass,struct avc_entry * ae,struct avc_entry_ref * aeref)465 static 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 
avc_cleanup(void)493 void avc_cleanup(void)
494 {
495 }
496 
hidden_def(avc_cleanup)497 hidden_def(avc_cleanup)
498 
499 int 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 
hidden_def(avc_reset)542 hidden_def(avc_reset)
543 
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 	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  */
598 static 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 
631 static 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  */
avc_dump_av(security_class_t tclass,access_vector_t av)647 static 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  */
avc_dump_query(security_id_t ssid,security_id_t tsid,security_class_t tclass)681 static 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 
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)694 void 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 
727 	if (denied)
728 		log_append(avc_audit_buf, " permissive=%u", result ? 0 : 1);
729 
730 	log_append(avc_audit_buf, "\n");
731 	avc_log(SELINUX_AVC, "%s", avc_audit_buf);
732 
733 	avc_release_lock(avc_log_lock);
734 }
735 
hidden_def(avc_audit)736 hidden_def(avc_audit)
737 
738 
739 static void avd_init(struct av_decision *avd)
740 {
741 	avd->allowed = 0;
742 	avd->auditallow = 0;
743 	avd->auditdeny = 0xffffffff;
744 	avd->seqno = avc_cache.latest_notif;
745 	avd->flags = 0;
746 }
747 
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)748 int avc_has_perm_noaudit(security_id_t ssid,
749 			 security_id_t tsid,
750 			 security_class_t tclass,
751 			 access_vector_t requested,
752 			 struct avc_entry_ref *aeref, struct av_decision *avd)
753 {
754 	struct avc_entry *ae;
755 	int rc = 0;
756 	struct avc_entry entry;
757 	access_vector_t denied;
758 	struct avc_entry_ref ref;
759 
760 	if (avd)
761 		avd_init(avd);
762 
763 	if (!avc_using_threads && !avc_app_main_loop) {
764 		(void)avc_netlink_check_nb();
765 	}
766 
767 	if (!aeref) {
768 		avc_entry_ref_init(&ref);
769 		aeref = &ref;
770 	}
771 
772 	avc_get_lock(avc_lock);
773 	avc_cache_stats_incr(entry_lookups);
774 	ae = aeref->ae;
775 	if (ae) {
776 		if (ae->ssid == ssid &&
777 		    ae->tsid == tsid &&
778 		    ae->tclass == tclass &&
779 		    ((ae->avd.decided & requested) == requested)) {
780 			avc_cache_stats_incr(entry_hits);
781 			ae->used = 1;
782 		} else {
783 			avc_cache_stats_incr(entry_discards);
784 			ae = 0;
785 		}
786 	}
787 
788 	if (!ae) {
789 		avc_cache_stats_incr(entry_misses);
790 		rc = avc_lookup(ssid, tsid, tclass, requested, aeref);
791 		if (rc) {
792 			rc = security_compute_av_flags_raw(ssid->ctx, tsid->ctx,
793 							   tclass, requested,
794 							   &entry.avd);
795 			if (rc && errno == EINVAL && !avc_enforcing) {
796 				rc = errno = 0;
797 				goto out;
798 			}
799 			if (rc)
800 				goto out;
801 			rc = avc_insert(ssid, tsid, tclass, &entry, aeref);
802 			if (rc)
803 				goto out;
804 		}
805 		ae = aeref->ae;
806 	}
807 
808 	if (avd)
809 		memcpy(avd, &ae->avd, sizeof(*avd));
810 
811 	denied = requested & ~(ae->avd.allowed);
812 
813 	if (!requested || denied) {
814 		if (!avc_enforcing ||
815 		    (ae->avd.flags & SELINUX_AVD_FLAGS_PERMISSIVE))
816 			ae->avd.allowed |= requested;
817 		else {
818 			errno = EACCES;
819 			rc = -1;
820 		}
821 	}
822 
823       out:
824 	avc_release_lock(avc_lock);
825 	return rc;
826 }
827 
hidden_def(avc_has_perm_noaudit)828 hidden_def(avc_has_perm_noaudit)
829 
830 int avc_has_perm(security_id_t ssid, security_id_t tsid,
831 		 security_class_t tclass, access_vector_t requested,
832 		 struct avc_entry_ref *aeref, void *auditdata)
833 {
834 	struct av_decision avd;
835 	int errsave, rc;
836 
837 	rc = avc_has_perm_noaudit(ssid, tsid, tclass, requested, aeref, &avd);
838 	errsave = errno;
839 	avc_audit(ssid, tsid, tclass, requested, &avd, rc, auditdata);
840 	errno = errsave;
841 	return rc;
842 }
843 
avc_compute_create(security_id_t ssid,security_id_t tsid,security_class_t tclass,security_id_t * newsid)844 int avc_compute_create(security_id_t ssid,  security_id_t tsid,
845 		       security_class_t tclass, security_id_t *newsid)
846 {
847 	int rc;
848 	struct avc_entry_ref aeref;
849 	struct avc_entry entry;
850 	char * ctx;
851 
852 	*newsid = NULL;
853 	avc_entry_ref_init(&aeref);
854 
855 	avc_get_lock(avc_lock);
856 
857 	/* check for a cached entry */
858 	rc = avc_lookup(ssid, tsid, tclass, 0, &aeref);
859 	if (rc) {
860 		/* need to make a cache entry for this tuple */
861 		rc = security_compute_av_flags_raw(ssid->ctx, tsid->ctx,
862 						   tclass, 0, &entry.avd);
863 		if (rc)
864 			goto out;
865 		rc = avc_insert(ssid, tsid, tclass, &entry, &aeref);
866 		if (rc)
867 			goto out;
868 	}
869 
870 	/* check for a saved compute_create value */
871 	if (!aeref.ae->create_sid) {
872 		/* need to query the kernel policy */
873 		rc = security_compute_create_raw(ssid->ctx, tsid->ctx, tclass,
874 						 &ctx);
875 		if (rc)
876 			goto out;
877 		rc = sidtab_context_to_sid(&avc_sidtab, ctx, newsid);
878 		freecon(ctx);
879 		if (rc)
880 			goto out;
881 
882 		aeref.ae->create_sid = *newsid;
883 	} else {
884 		/* found saved value */
885 		*newsid = aeref.ae->create_sid;
886 	}
887 
888 	rc = 0;
889 out:
890 	avc_release_lock(avc_lock);
891 	return rc;
892 }
893 
avc_compute_member(security_id_t ssid,security_id_t tsid,security_class_t tclass,security_id_t * newsid)894 int avc_compute_member(security_id_t ssid,  security_id_t tsid,
895 		       security_class_t tclass, security_id_t *newsid)
896 {
897 	int rc;
898 	char * ctx = NULL;
899 	*newsid = NULL;
900 	/* avc_init needs to be called before this function */
901 	assert(avc_running);
902 	avc_get_lock(avc_lock);
903 
904 	rc = security_compute_member_raw(ssid->ctx, tsid->ctx, tclass, &ctx);
905 	if (rc)
906 		goto out;
907 	rc = sidtab_context_to_sid(&avc_sidtab, ctx, newsid);
908 	freecon(ctx);
909 out:
910 	avc_release_lock(avc_lock);
911 	return rc;
912 }
913 
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)914 int avc_add_callback(int (*callback) (uint32_t event, security_id_t ssid,
915 				      security_id_t tsid,
916 				      security_class_t tclass,
917 				      access_vector_t perms,
918 				      access_vector_t * out_retained),
919 		     uint32_t events, security_id_t ssid,
920 		     security_id_t tsid,
921 		     security_class_t tclass, access_vector_t perms)
922 {
923 	struct avc_callback_node *c;
924 	int rc = 0;
925 
926 	c = avc_malloc(sizeof(*c));
927 	if (!c) {
928 		rc = -1;
929 		goto out;
930 	}
931 
932 	c->callback = callback;
933 	c->events = events;
934 	c->ssid = ssid;
935 	c->tsid = tsid;
936 	c->tclass = tclass;
937 	c->perms = perms;
938 	c->next = avc_callbacks;
939 	avc_callbacks = c;
940       out:
941 	return rc;
942 }
943 
avc_sidcmp(security_id_t x,security_id_t y)944 static inline int avc_sidcmp(security_id_t x, security_id_t y)
945 {
946 	return (x == y || x == SECSID_WILD || y == SECSID_WILD);
947 }
948 
avc_update_node(uint32_t event,struct avc_node * node,access_vector_t perms)949 static inline void avc_update_node(uint32_t event, struct avc_node *node,
950 				   access_vector_t perms)
951 {
952 	switch (event) {
953 	case AVC_CALLBACK_GRANT:
954 		node->ae.avd.allowed |= perms;
955 		break;
956 	case AVC_CALLBACK_TRY_REVOKE:
957 	case AVC_CALLBACK_REVOKE:
958 		node->ae.avd.allowed &= ~perms;
959 		break;
960 	case AVC_CALLBACK_AUDITALLOW_ENABLE:
961 		node->ae.avd.auditallow |= perms;
962 		break;
963 	case AVC_CALLBACK_AUDITALLOW_DISABLE:
964 		node->ae.avd.auditallow &= ~perms;
965 		break;
966 	case AVC_CALLBACK_AUDITDENY_ENABLE:
967 		node->ae.avd.auditdeny |= perms;
968 		break;
969 	case AVC_CALLBACK_AUDITDENY_DISABLE:
970 		node->ae.avd.auditdeny &= ~perms;
971 		break;
972 	}
973 }
974 
avc_update_cache(uint32_t event,security_id_t ssid,security_id_t tsid,security_class_t tclass,access_vector_t perms)975 static int avc_update_cache(uint32_t event, security_id_t ssid,
976 			    security_id_t tsid, security_class_t tclass,
977 			    access_vector_t perms)
978 {
979 	struct avc_node *node;
980 	int i;
981 
982 	avc_get_lock(avc_lock);
983 
984 	if (ssid == SECSID_WILD || tsid == SECSID_WILD) {
985 		/* apply to all matching nodes */
986 		for (i = 0; i < AVC_CACHE_SLOTS; i++) {
987 			for (node = avc_cache.slots[i]; node; node = node->next) {
988 				if (avc_sidcmp(ssid, node->ae.ssid) &&
989 				    avc_sidcmp(tsid, node->ae.tsid) &&
990 				    tclass == node->ae.tclass) {
991 					avc_update_node(event, node, perms);
992 				}
993 			}
994 		}
995 	} else {
996 		/* apply to one node */
997 		node = avc_search_node(ssid, tsid, tclass, 0);
998 		if (node) {
999 			avc_update_node(event, node, perms);
1000 		}
1001 	}
1002 
1003 	avc_release_lock(avc_lock);
1004 
1005 	return 0;
1006 }
1007 
1008 /* avc_control - update cache and call callbacks
1009  *
1010  * This should not be called directly; use the individual event
1011  * functions instead.
1012  */
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)1013 static int avc_control(uint32_t event, security_id_t ssid,
1014 		       security_id_t tsid, security_class_t tclass,
1015 		       access_vector_t perms,
1016 		       uint32_t seqno, access_vector_t * out_retained)
1017 {
1018 	struct avc_callback_node *c;
1019 	access_vector_t tretained = 0, cretained = 0;
1020 	int ret, rc = 0, errsave = 0;
1021 	errno = 0;
1022 
1023 	/*
1024 	 * try_revoke only removes permissions from the cache
1025 	 * state if they are not retained by the object manager.
1026 	 * Hence, try_revoke must wait until after the callbacks have
1027 	 * been invoked to update the cache state.
1028 	 */
1029 	if (event != AVC_CALLBACK_TRY_REVOKE)
1030 		avc_update_cache(event, ssid, tsid, tclass, perms);
1031 
1032 	for (c = avc_callbacks; c; c = c->next) {
1033 		if ((c->events & event) &&
1034 		    avc_sidcmp(c->ssid, ssid) &&
1035 		    avc_sidcmp(c->tsid, tsid) &&
1036 		    c->tclass == tclass && (c->perms & perms)) {
1037 			cretained = 0;
1038 			ret = c->callback(event, ssid, tsid, tclass,
1039 					  (c->perms & perms), &cretained);
1040 			if (ret && !rc) {
1041 				rc = ret;
1042 				errsave = errno;
1043 			}
1044 			if (!ret)
1045 				tretained |= cretained;
1046 		}
1047 	}
1048 
1049 	if (event == AVC_CALLBACK_TRY_REVOKE) {
1050 		/* revoke any unretained permissions */
1051 		perms &= ~tretained;
1052 		avc_update_cache(event, ssid, tsid, tclass, perms);
1053 		*out_retained = tretained;
1054 	}
1055 
1056 	avc_get_lock(avc_lock);
1057 	if (seqno > avc_cache.latest_notif)
1058 		avc_cache.latest_notif = seqno;
1059 	avc_release_lock(avc_lock);
1060 
1061 	errno = errsave;
1062 	return rc;
1063 }
1064 
1065 /**
1066  * avc_ss_grant - Grant previously denied permissions.
1067  * @ssid: source security identifier or %SECSID_WILD
1068  * @tsid: target security identifier or %SECSID_WILD
1069  * @tclass: target security class
1070  * @perms: permissions to grant
1071  * @seqno: policy sequence number
1072  */
avc_ss_grant(security_id_t ssid,security_id_t tsid,security_class_t tclass,access_vector_t perms,uint32_t seqno)1073 int avc_ss_grant(security_id_t ssid, security_id_t tsid,
1074 		 security_class_t tclass, access_vector_t perms,
1075 		 uint32_t seqno)
1076 {
1077 	return avc_control(AVC_CALLBACK_GRANT,
1078 			   ssid, tsid, tclass, perms, seqno, 0);
1079 }
1080 
1081 /**
1082  * avc_ss_try_revoke - Try to revoke previously granted permissions.
1083  * @ssid: source security identifier or %SECSID_WILD
1084  * @tsid: target security identifier or %SECSID_WILD
1085  * @tclass: target security class
1086  * @perms: permissions to grant
1087  * @seqno: policy sequence number
1088  * @out_retained: subset of @perms that are retained
1089  *
1090  * Try to revoke previously granted permissions, but
1091  * only if they are not retained as migrated permissions.
1092  * Return the subset of permissions that are retained via @out_retained.
1093  */
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)1094 int avc_ss_try_revoke(security_id_t ssid, security_id_t tsid,
1095 		      security_class_t tclass,
1096 		      access_vector_t perms, uint32_t seqno,
1097 		      access_vector_t * out_retained)
1098 {
1099 	return avc_control(AVC_CALLBACK_TRY_REVOKE,
1100 			   ssid, tsid, tclass, perms, seqno, out_retained);
1101 }
1102 
1103 /**
1104  * avc_ss_revoke - Revoke previously granted permissions.
1105  * @ssid: source security identifier or %SECSID_WILD
1106  * @tsid: target security identifier or %SECSID_WILD
1107  * @tclass: target security class
1108  * @perms: permissions to grant
1109  * @seqno: policy sequence number
1110  *
1111  * Revoke previously granted permissions, even if
1112  * they are retained as migrated permissions.
1113  */
avc_ss_revoke(security_id_t ssid,security_id_t tsid,security_class_t tclass,access_vector_t perms,uint32_t seqno)1114 int avc_ss_revoke(security_id_t ssid, security_id_t tsid,
1115 		  security_class_t tclass, access_vector_t perms,
1116 		  uint32_t seqno)
1117 {
1118 	return avc_control(AVC_CALLBACK_REVOKE,
1119 			   ssid, tsid, tclass, perms, seqno, 0);
1120 }
1121 
1122 /**
1123  * avc_ss_reset - Flush the cache and revalidate migrated permissions.
1124  * @seqno: policy sequence number
1125  */
avc_ss_reset(uint32_t seqno)1126 int avc_ss_reset(uint32_t seqno)
1127 {
1128 	int rc;
1129 
1130 	rc = avc_reset();
1131 
1132 	avc_get_lock(avc_lock);
1133 	if (seqno > avc_cache.latest_notif)
1134 		avc_cache.latest_notif = seqno;
1135 	avc_release_lock(avc_lock);
1136 
1137 	return rc;
1138 }
1139 
1140 /**
1141  * avc_ss_set_auditallow - Enable or disable auditing of granted permissions.
1142  * @ssid: source security identifier or %SECSID_WILD
1143  * @tsid: target security identifier or %SECSID_WILD
1144  * @tclass: target security class
1145  * @perms: permissions to grant
1146  * @seqno: policy sequence number
1147  * @enable: enable flag.
1148  */
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)1149 int avc_ss_set_auditallow(security_id_t ssid, security_id_t tsid,
1150 			  security_class_t tclass, access_vector_t perms,
1151 			  uint32_t seqno, uint32_t enable)
1152 {
1153 	if (enable)
1154 		return avc_control(AVC_CALLBACK_AUDITALLOW_ENABLE,
1155 				   ssid, tsid, tclass, perms, seqno, 0);
1156 	else
1157 		return avc_control(AVC_CALLBACK_AUDITALLOW_DISABLE,
1158 				   ssid, tsid, tclass, perms, seqno, 0);
1159 }
1160 
1161 /**
1162  * avc_ss_set_auditdeny - Enable or disable auditing of denied permissions.
1163  * @ssid: source security identifier or %SECSID_WILD
1164  * @tsid: target security identifier or %SECSID_WILD
1165  * @tclass: target security class
1166  * @perms: permissions to grant
1167  * @seqno: policy sequence number
1168  * @enable: enable flag.
1169  */
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)1170 int avc_ss_set_auditdeny(security_id_t ssid, security_id_t tsid,
1171 			 security_class_t tclass, access_vector_t perms,
1172 			 uint32_t seqno, uint32_t enable)
1173 {
1174 	if (enable)
1175 		return avc_control(AVC_CALLBACK_AUDITDENY_ENABLE,
1176 				   ssid, tsid, tclass, perms, seqno, 0);
1177 	else
1178 		return avc_control(AVC_CALLBACK_AUDITDENY_DISABLE,
1179 				   ssid, tsid, tclass, perms, seqno, 0);
1180 }
1181