xref: /aosp_15_r20/external/selinux/libselinux/src/avc.c (revision 2d543d20722ada2425b5bdab9d0d1d29470e7bba)
1 /*
2  * Implementation of the userspace access vector cache (AVC).
3  *
4  * Author : Eamon Walsh <[email protected]>
5  *
6  * Derived from the kernel AVC implementation by
7  * Stephen Smalley <[email protected]> and
8  * James Morris <[email protected]>.
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(const struct selinux_opt * opts,unsigned nopts)228 int avc_open(const struct selinux_opt *opts, unsigned nopts)
229 {
230 	avc_setenforce = 0;
231 
232 	while (nopts) {
233 		nopts--;
234 		switch(opts[nopts].type) {
235 		case AVC_OPT_SETENFORCE:
236 			avc_setenforce = 1;
237 			avc_enforcing = !!opts[nopts].value;
238 			break;
239 		}
240 	}
241 
242 	return avc_init_internal("avc", NULL, NULL, NULL, NULL);
243 }
244 
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)245 int avc_init(const char *prefix,
246 	     const struct avc_memory_callback *mem_cb,
247 	     const struct avc_log_callback *log_cb,
248 	     const struct avc_thread_callback *thread_cb,
249 	     const struct avc_lock_callback *lock_cb)
250 {
251 	return avc_init_internal(prefix, mem_cb, log_cb, thread_cb, lock_cb);
252 }
253 
avc_cache_stats(struct avc_cache_stats * p)254 void avc_cache_stats(struct avc_cache_stats *p)
255 {
256 	memcpy(p, &cache_stats, sizeof(cache_stats));
257 }
258 
avc_sid_stats(void)259 void avc_sid_stats(void)
260 {
261 	/* avc_init needs to be called before this function */
262 	assert(avc_running);
263 	avc_get_lock(avc_log_lock);
264 	avc_get_lock(avc_lock);
265 	sidtab_sid_stats(&avc_sidtab, avc_audit_buf, AVC_AUDIT_BUFSIZE);
266 	avc_release_lock(avc_lock);
267 	avc_log(SELINUX_INFO, "%s", avc_audit_buf);
268 	avc_release_lock(avc_log_lock);
269 }
270 
avc_av_stats(void)271 void avc_av_stats(void)
272 {
273 	int i, chain_len, max_chain_len, slots_used;
274 	struct avc_node *node;
275 
276 	avc_get_lock(avc_lock);
277 
278 	slots_used = 0;
279 	max_chain_len = 0;
280 	for (i = 0; i < AVC_CACHE_SLOTS; i++) {
281 		node = avc_cache.slots[i];
282 		if (node) {
283 			slots_used++;
284 			chain_len = 0;
285 			while (node) {
286 				chain_len++;
287 				node = node->next;
288 			}
289 			if (chain_len > max_chain_len)
290 				max_chain_len = chain_len;
291 		}
292 	}
293 
294 	avc_release_lock(avc_lock);
295 
296 	avc_log(SELINUX_INFO, "%s:  %u AV entries and %d/%d buckets used, "
297 		"longest chain length %d\n", avc_prefix,
298 		avc_cache.active_nodes,
299 		slots_used, AVC_CACHE_SLOTS, max_chain_len);
300 }
301 
302 
avc_reclaim_node(void)303 static inline struct avc_node *avc_reclaim_node(void)
304 {
305 	struct avc_node *prev, *cur;
306 	int try;
307 	uint32_t hvalue;
308 
309 	hvalue = avc_cache.lru_hint;
310 	for (try = 0; try < 2; try++) {
311 		do {
312 			prev = NULL;
313 			cur = avc_cache.slots[hvalue];
314 			while (cur) {
315 				if (!cur->ae.used)
316 					goto found;
317 
318 				cur->ae.used = 0;
319 
320 				prev = cur;
321 				cur = cur->next;
322 			}
323 			hvalue = (hvalue + 1) & (AVC_CACHE_SLOTS - 1);
324 		} while (hvalue != avc_cache.lru_hint);
325 	}
326 
327 	errno = ENOMEM;		/* this was a panic in the kernel... */
328 	return NULL;
329 
330       found:
331 	avc_cache.lru_hint = hvalue;
332 
333 	if (prev == NULL)
334 		avc_cache.slots[hvalue] = cur->next;
335 	else
336 		prev->next = cur->next;
337 
338 	return cur;
339 }
340 
avc_clear_avc_entry(struct avc_entry * ae)341 static inline void avc_clear_avc_entry(struct avc_entry *ae)
342 {
343 	memset(ae, 0, sizeof(*ae));
344 }
345 
avc_claim_node(security_id_t ssid,security_id_t tsid,security_class_t tclass)346 static inline struct avc_node *avc_claim_node(security_id_t ssid,
347 					      security_id_t tsid,
348 					      security_class_t tclass)
349 {
350 	struct avc_node *new;
351 	int hvalue;
352 
353 	if (!avc_node_freelist)
354 		avc_cleanup();
355 
356 	if (avc_node_freelist) {
357 		new = avc_node_freelist;
358 		avc_node_freelist = avc_node_freelist->next;
359 		avc_cache.active_nodes++;
360 	} else {
361 		new = avc_reclaim_node();
362 		if (!new)
363 			goto out;
364 	}
365 
366 	hvalue = avc_hash(ssid, tsid, tclass);
367 	avc_clear_avc_entry(&new->ae);
368 	new->ae.used = 1;
369 	new->ae.ssid = ssid;
370 	new->ae.tsid = tsid;
371 	new->ae.tclass = tclass;
372 	new->next = avc_cache.slots[hvalue];
373 	avc_cache.slots[hvalue] = new;
374 
375       out:
376 	return new;
377 }
378 
avc_search_node(security_id_t ssid,security_id_t tsid,security_class_t tclass,int * probes)379 static inline struct avc_node *avc_search_node(security_id_t ssid,
380 					       security_id_t tsid,
381 					       security_class_t tclass,
382 					       int *probes)
383 {
384 	struct avc_node *cur;
385 	int hvalue;
386 	int tprobes = 1;
387 
388 	hvalue = avc_hash(ssid, tsid, tclass);
389 	cur = avc_cache.slots[hvalue];
390 	while (cur != NULL &&
391 	       (ssid != cur->ae.ssid ||
392 		tclass != cur->ae.tclass || tsid != cur->ae.tsid)) {
393 		tprobes++;
394 		cur = cur->next;
395 	}
396 
397 	if (cur == NULL) {
398 		/* cache miss */
399 		goto out;
400 	}
401 
402 	/* cache hit */
403 	if (probes)
404 		*probes = tprobes;
405 
406 	cur->ae.used = 1;
407 
408       out:
409 	return cur;
410 }
411 
412 /**
413  * avc_lookup - Look up an AVC entry.
414  * @ssid: source security identifier
415  * @tsid: target security identifier
416  * @tclass: target security class
417  * @requested: requested permissions, interpreted based on @tclass
418  * @aeref:  AVC entry reference
419  *
420  * Look up an AVC entry that is valid for the
421  * @requested permissions between the SID pair
422  * (@ssid, @tsid), interpreting the permissions
423  * based on @tclass.  If a valid AVC entry exists,
424  * then this function updates @aeref to refer to the
425  * entry and returns %0.  Otherwise, -1 is returned.
426  */
avc_lookup(security_id_t ssid,security_id_t tsid,security_class_t tclass,access_vector_t requested,struct avc_entry_ref * aeref)427 static int avc_lookup(security_id_t ssid, security_id_t tsid,
428 		      security_class_t tclass,
429 		      access_vector_t requested, struct avc_entry_ref *aeref)
430 {
431 	struct avc_node *node;
432 	int probes, rc = 0;
433 
434 	avc_cache_stats_incr(cav_lookups);
435 	node = avc_search_node(ssid, tsid, tclass, &probes);
436 
437 	if (node && ((node->ae.avd.decided & requested) == requested)) {
438 		avc_cache_stats_incr(cav_hits);
439 		avc_cache_stats_add(cav_probes, probes);
440 		aeref->ae = &node->ae;
441 		goto out;
442 	}
443 
444 	avc_cache_stats_incr(cav_misses);
445 	rc = -1;
446       out:
447 	return rc;
448 }
449 
450 /**
451  * avc_insert - Insert an AVC entry.
452  * @ssid: source security identifier
453  * @tsid: target security identifier
454  * @tclass: target security class
455  * @ae: AVC entry
456  * @aeref:  AVC entry reference
457  *
458  * Insert an AVC entry for the SID pair
459  * (@ssid, @tsid) and class @tclass.
460  * The access vectors and the sequence number are
461  * normally provided by the security server in
462  * response to a security_compute_av() call.  If the
463  * sequence number @ae->avd.seqno is not less than the latest
464  * revocation notification, then the function copies
465  * the access vectors into a cache entry, updates
466  * @aeref to refer to the entry, and returns %0.
467  * Otherwise, this function returns -%1 with @errno set to %EAGAIN.
468  */
avc_insert(security_id_t ssid,security_id_t tsid,security_class_t tclass,struct avc_entry * ae,struct avc_entry_ref * aeref)469 static int avc_insert(security_id_t ssid, security_id_t tsid,
470 		      security_class_t tclass,
471 		      struct avc_entry *ae, struct avc_entry_ref *aeref)
472 {
473 	struct avc_node *node;
474 	int rc = 0;
475 
476 	if (ae->avd.seqno < avc_cache.latest_notif) {
477 		avc_log(SELINUX_WARNING,
478 			"%s:  seqno %u < latest_notif %u\n", avc_prefix,
479 			ae->avd.seqno, avc_cache.latest_notif);
480 		errno = EAGAIN;
481 		rc = -1;
482 		goto out;
483 	}
484 
485 	node = avc_claim_node(ssid, tsid, tclass);
486 	if (!node) {
487 		rc = -1;
488 		goto out;
489 	}
490 
491 	memcpy(&node->ae.avd, &ae->avd, sizeof(ae->avd));
492 	aeref->ae = &node->ae;
493       out:
494 	return rc;
495 }
496 
avc_cleanup(void)497 void avc_cleanup(void)
498 {
499 }
500 
501 
avc_reset(void)502 int avc_reset(void)
503 {
504 	struct avc_callback_node *c;
505 	int i, ret, rc = 0, errsave = 0;
506 	struct avc_node *node, *tmp;
507 	errno = 0;
508 
509 	if (!avc_running)
510 		return 0;
511 
512 	avc_get_lock(avc_lock);
513 
514 	for (i = 0; i < AVC_CACHE_SLOTS; i++) {
515 		node = avc_cache.slots[i];
516 		while (node) {
517 			tmp = node;
518 			node = node->next;
519 			avc_clear_avc_entry(&tmp->ae);
520 			tmp->next = avc_node_freelist;
521 			avc_node_freelist = tmp;
522 			avc_cache.active_nodes--;
523 		}
524 		avc_cache.slots[i] = 0;
525 	}
526 	avc_cache.lru_hint = 0;
527 
528 	avc_release_lock(avc_lock);
529 
530 	memset(&cache_stats, 0, sizeof(cache_stats));
531 
532 	for (c = avc_callbacks; c; c = c->next) {
533 		if (c->events & AVC_CALLBACK_RESET) {
534 			ret = c->callback(AVC_CALLBACK_RESET, 0, 0, 0, 0, 0);
535 			if (ret && !rc) {
536 				rc = ret;
537 				errsave = errno;
538 			}
539 		}
540 	}
541 	errno = errsave;
542 	return rc;
543 }
544 
545 
avc_destroy(void)546 void avc_destroy(void)
547 {
548 	struct avc_callback_node *c;
549 	struct avc_node *node, *tmp;
550 	int i;
551 	/* avc_init needs to be called before this function */
552 	assert(avc_running);
553 
554 	avc_get_lock(avc_lock);
555 
556 	selinux_status_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 	avc_log(SELINUX_AVC, "%s", avc_audit_buf);
731 
732 	avc_release_lock(avc_log_lock);
733 }
734 
735 
736 
avd_init(struct av_decision * avd)737 static void avd_init(struct av_decision *avd)
738 {
739 	avd->allowed = 0;
740 	avd->auditallow = 0;
741 	avd->auditdeny = 0xffffffff;
742 	avd->seqno = avc_cache.latest_notif;
743 	avd->flags = 0;
744 }
745 
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)746 int avc_has_perm_noaudit(security_id_t ssid,
747 			 security_id_t tsid,
748 			 security_class_t tclass,
749 			 access_vector_t requested,
750 			 struct avc_entry_ref *aeref, struct av_decision *avd)
751 {
752 	struct avc_entry *ae;
753 	int rc = 0;
754 	struct avc_entry entry;
755 	access_vector_t denied;
756 	struct avc_entry_ref ref;
757 
758 	if (avd)
759 		avd_init(avd);
760 
761 	if (!avc_using_threads && !avc_app_main_loop) {
762 		(void) selinux_status_updated();
763 	}
764 
765 	if (!aeref) {
766 		avc_entry_ref_init(&ref);
767 		aeref = &ref;
768 	}
769 
770 	avc_get_lock(avc_lock);
771 	avc_cache_stats_incr(entry_lookups);
772 	ae = aeref->ae;
773 	if (ae) {
774 		if (ae->ssid == ssid &&
775 		    ae->tsid == tsid &&
776 		    ae->tclass == tclass &&
777 		    ((ae->avd.decided & requested) == requested)) {
778 			avc_cache_stats_incr(entry_hits);
779 			ae->used = 1;
780 		} else {
781 			avc_cache_stats_incr(entry_discards);
782 			ae = 0;
783 		}
784 	}
785 
786 	if (!ae) {
787 		avc_cache_stats_incr(entry_misses);
788 		rc = avc_lookup(ssid, tsid, tclass, requested, aeref);
789 		if (rc) {
790 			rc = security_compute_av_flags_raw(ssid->ctx, tsid->ctx,
791 							   tclass, requested,
792 							   &entry.avd);
793 			if (rc && errno == EINVAL && !avc_enforcing) {
794 				rc = errno = 0;
795 				goto out;
796 			}
797 			if (rc)
798 				goto out;
799 			rc = avc_insert(ssid, tsid, tclass, &entry, aeref);
800 			if (rc)
801 				goto out;
802 		}
803 		ae = aeref->ae;
804 	}
805 
806 	if (avd)
807 		memcpy(avd, &ae->avd, sizeof(*avd));
808 
809 	denied = requested & ~(ae->avd.allowed);
810 
811 	if (!requested || denied) {
812 		if (!avc_enforcing ||
813 		    (ae->avd.flags & SELINUX_AVD_FLAGS_PERMISSIVE))
814 			ae->avd.allowed |= requested;
815 		else {
816 			errno = EACCES;
817 			rc = -1;
818 		}
819 	}
820 
821       out:
822 	avc_release_lock(avc_lock);
823 	return rc;
824 }
825 
826 
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)827 int avc_has_perm(security_id_t ssid, security_id_t tsid,
828 		 security_class_t tclass, access_vector_t requested,
829 		 struct avc_entry_ref *aeref, void *auditdata)
830 {
831 	struct av_decision avd;
832 	int errsave, rc;
833 
834 	rc = avc_has_perm_noaudit(ssid, tsid, tclass, requested, aeref, &avd);
835 	errsave = errno;
836 	avc_audit(ssid, tsid, tclass, requested, &avd, rc, auditdata);
837 	errno = errsave;
838 	return rc;
839 }
840 
avc_compute_create(security_id_t ssid,security_id_t tsid,security_class_t tclass,security_id_t * newsid)841 int avc_compute_create(security_id_t ssid,  security_id_t tsid,
842 		       security_class_t tclass, security_id_t *newsid)
843 {
844 	int rc;
845 	struct avc_entry_ref aeref;
846 	struct avc_entry entry;
847 	char * ctx;
848 
849 	*newsid = NULL;
850 	avc_entry_ref_init(&aeref);
851 
852 	avc_get_lock(avc_lock);
853 
854 	/* check for a cached entry */
855 	rc = avc_lookup(ssid, tsid, tclass, 0, &aeref);
856 	if (rc) {
857 		/* need to make a cache entry for this tuple */
858 		rc = security_compute_av_flags_raw(ssid->ctx, tsid->ctx,
859 						   tclass, 0, &entry.avd);
860 		if (rc)
861 			goto out;
862 		rc = avc_insert(ssid, tsid, tclass, &entry, &aeref);
863 		if (rc)
864 			goto out;
865 	}
866 
867 	/* check for a saved compute_create value */
868 	if (!aeref.ae->create_sid) {
869 		/* need to query the kernel policy */
870 		rc = security_compute_create_raw(ssid->ctx, tsid->ctx, tclass,
871 						 &ctx);
872 		if (rc)
873 			goto out;
874 		rc = sidtab_context_to_sid(&avc_sidtab, ctx, newsid);
875 		freecon(ctx);
876 		if (rc)
877 			goto out;
878 
879 		aeref.ae->create_sid = *newsid;
880 	} else {
881 		/* found saved value */
882 		*newsid = aeref.ae->create_sid;
883 	}
884 
885 	rc = 0;
886 out:
887 	avc_release_lock(avc_lock);
888 	return rc;
889 }
890 
avc_compute_member(security_id_t ssid,security_id_t tsid,security_class_t tclass,security_id_t * newsid)891 int avc_compute_member(security_id_t ssid,  security_id_t tsid,
892 		       security_class_t tclass, security_id_t *newsid)
893 {
894 	int rc;
895 	char * ctx = NULL;
896 	*newsid = NULL;
897 	/* avc_init needs to be called before this function */
898 	assert(avc_running);
899 	avc_get_lock(avc_lock);
900 
901 	rc = security_compute_member_raw(ssid->ctx, tsid->ctx, tclass, &ctx);
902 	if (rc)
903 		goto out;
904 	rc = sidtab_context_to_sid(&avc_sidtab, ctx, newsid);
905 	freecon(ctx);
906 out:
907 	avc_release_lock(avc_lock);
908 	return rc;
909 }
910 
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)911 int avc_add_callback(int (*callback) (uint32_t event, security_id_t ssid,
912 				      security_id_t tsid,
913 				      security_class_t tclass,
914 				      access_vector_t perms,
915 				      access_vector_t * out_retained),
916 		     uint32_t events, security_id_t ssid,
917 		     security_id_t tsid,
918 		     security_class_t tclass, access_vector_t perms)
919 {
920 	struct avc_callback_node *c;
921 	int rc = 0;
922 
923 	c = avc_malloc(sizeof(*c));
924 	if (!c) {
925 		rc = -1;
926 		goto out;
927 	}
928 
929 	c->callback = callback;
930 	c->events = events;
931 	c->ssid = ssid;
932 	c->tsid = tsid;
933 	c->tclass = tclass;
934 	c->perms = perms;
935 	c->next = avc_callbacks;
936 	avc_callbacks = c;
937       out:
938 	return rc;
939 }
940 
avc_sidcmp(security_id_t x,security_id_t y)941 static inline int avc_sidcmp(security_id_t x, security_id_t y)
942 {
943 	return (x == y || x == SECSID_WILD || y == SECSID_WILD);
944 }
945 
avc_update_node(uint32_t event,struct avc_node * node,access_vector_t perms)946 static inline void avc_update_node(uint32_t event, struct avc_node *node,
947 				   access_vector_t perms)
948 {
949 	switch (event) {
950 	case AVC_CALLBACK_GRANT:
951 		node->ae.avd.allowed |= perms;
952 		break;
953 	case AVC_CALLBACK_TRY_REVOKE:
954 	case AVC_CALLBACK_REVOKE:
955 		node->ae.avd.allowed &= ~perms;
956 		break;
957 	case AVC_CALLBACK_AUDITALLOW_ENABLE:
958 		node->ae.avd.auditallow |= perms;
959 		break;
960 	case AVC_CALLBACK_AUDITALLOW_DISABLE:
961 		node->ae.avd.auditallow &= ~perms;
962 		break;
963 	case AVC_CALLBACK_AUDITDENY_ENABLE:
964 		node->ae.avd.auditdeny |= perms;
965 		break;
966 	case AVC_CALLBACK_AUDITDENY_DISABLE:
967 		node->ae.avd.auditdeny &= ~perms;
968 		break;
969 	}
970 }
971 
avc_update_cache(uint32_t event,security_id_t ssid,security_id_t tsid,security_class_t tclass,access_vector_t perms)972 static int avc_update_cache(uint32_t event, security_id_t ssid,
973 			    security_id_t tsid, security_class_t tclass,
974 			    access_vector_t perms)
975 {
976 	struct avc_node *node;
977 	int i;
978 
979 	avc_get_lock(avc_lock);
980 
981 	if (ssid == SECSID_WILD || tsid == SECSID_WILD) {
982 		/* apply to all matching nodes */
983 		for (i = 0; i < AVC_CACHE_SLOTS; i++) {
984 			for (node = avc_cache.slots[i]; node; node = node->next) {
985 				if (avc_sidcmp(ssid, node->ae.ssid) &&
986 				    avc_sidcmp(tsid, node->ae.tsid) &&
987 				    tclass == node->ae.tclass) {
988 					avc_update_node(event, node, perms);
989 				}
990 			}
991 		}
992 	} else {
993 		/* apply to one node */
994 		node = avc_search_node(ssid, tsid, tclass, 0);
995 		if (node) {
996 			avc_update_node(event, node, perms);
997 		}
998 	}
999 
1000 	avc_release_lock(avc_lock);
1001 
1002 	return 0;
1003 }
1004 
1005 /* avc_control - update cache and call callbacks
1006  *
1007  * This should not be called directly; use the individual event
1008  * functions instead.
1009  */
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)1010 static int avc_control(uint32_t event, security_id_t ssid,
1011 		       security_id_t tsid, security_class_t tclass,
1012 		       access_vector_t perms,
1013 		       uint32_t seqno, access_vector_t * out_retained)
1014 {
1015 	struct avc_callback_node *c;
1016 	access_vector_t tretained = 0, cretained = 0;
1017 	int ret, rc = 0, errsave = 0;
1018 	errno = 0;
1019 
1020 	/*
1021 	 * try_revoke only removes permissions from the cache
1022 	 * state if they are not retained by the object manager.
1023 	 * Hence, try_revoke must wait until after the callbacks have
1024 	 * been invoked to update the cache state.
1025 	 */
1026 	if (event != AVC_CALLBACK_TRY_REVOKE)
1027 		avc_update_cache(event, ssid, tsid, tclass, perms);
1028 
1029 	for (c = avc_callbacks; c; c = c->next) {
1030 		if ((c->events & event) &&
1031 		    avc_sidcmp(c->ssid, ssid) &&
1032 		    avc_sidcmp(c->tsid, tsid) &&
1033 		    c->tclass == tclass && (c->perms & perms)) {
1034 			cretained = 0;
1035 			ret = c->callback(event, ssid, tsid, tclass,
1036 					  (c->perms & perms), &cretained);
1037 			if (ret && !rc) {
1038 				rc = ret;
1039 				errsave = errno;
1040 			}
1041 			if (!ret)
1042 				tretained |= cretained;
1043 		}
1044 	}
1045 
1046 	if (event == AVC_CALLBACK_TRY_REVOKE) {
1047 		/* revoke any unretained permissions */
1048 		perms &= ~tretained;
1049 		avc_update_cache(event, ssid, tsid, tclass, perms);
1050 		*out_retained = tretained;
1051 	}
1052 
1053 	avc_get_lock(avc_lock);
1054 	if (seqno > avc_cache.latest_notif)
1055 		avc_cache.latest_notif = seqno;
1056 	avc_release_lock(avc_lock);
1057 
1058 	errno = errsave;
1059 	return rc;
1060 }
1061 
1062 /**
1063  * avc_ss_grant - Grant previously denied permissions.
1064  * @ssid: source security identifier or %SECSID_WILD
1065  * @tsid: target security identifier or %SECSID_WILD
1066  * @tclass: target security class
1067  * @perms: permissions to grant
1068  * @seqno: policy sequence number
1069  */
avc_ss_grant(security_id_t ssid,security_id_t tsid,security_class_t tclass,access_vector_t perms,uint32_t seqno)1070 int avc_ss_grant(security_id_t ssid, security_id_t tsid,
1071 		 security_class_t tclass, access_vector_t perms,
1072 		 uint32_t seqno)
1073 {
1074 	return avc_control(AVC_CALLBACK_GRANT,
1075 			   ssid, tsid, tclass, perms, seqno, 0);
1076 }
1077 
1078 /**
1079  * avc_ss_try_revoke - Try to revoke previously granted permissions.
1080  * @ssid: source security identifier or %SECSID_WILD
1081  * @tsid: target security identifier or %SECSID_WILD
1082  * @tclass: target security class
1083  * @perms: permissions to grant
1084  * @seqno: policy sequence number
1085  * @out_retained: subset of @perms that are retained
1086  *
1087  * Try to revoke previously granted permissions, but
1088  * only if they are not retained as migrated permissions.
1089  * Return the subset of permissions that are retained via @out_retained.
1090  */
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)1091 int avc_ss_try_revoke(security_id_t ssid, security_id_t tsid,
1092 		      security_class_t tclass,
1093 		      access_vector_t perms, uint32_t seqno,
1094 		      access_vector_t * out_retained)
1095 {
1096 	return avc_control(AVC_CALLBACK_TRY_REVOKE,
1097 			   ssid, tsid, tclass, perms, seqno, out_retained);
1098 }
1099 
1100 /**
1101  * avc_ss_revoke - Revoke previously granted permissions.
1102  * @ssid: source security identifier or %SECSID_WILD
1103  * @tsid: target security identifier or %SECSID_WILD
1104  * @tclass: target security class
1105  * @perms: permissions to grant
1106  * @seqno: policy sequence number
1107  *
1108  * Revoke previously granted permissions, even if
1109  * they are retained as migrated permissions.
1110  */
avc_ss_revoke(security_id_t ssid,security_id_t tsid,security_class_t tclass,access_vector_t perms,uint32_t seqno)1111 int avc_ss_revoke(security_id_t ssid, security_id_t tsid,
1112 		  security_class_t tclass, access_vector_t perms,
1113 		  uint32_t seqno)
1114 {
1115 	return avc_control(AVC_CALLBACK_REVOKE,
1116 			   ssid, tsid, tclass, perms, seqno, 0);
1117 }
1118 
1119 /**
1120  * avc_ss_reset - Flush the cache and revalidate migrated permissions.
1121  * @seqno: policy sequence number
1122  */
avc_ss_reset(uint32_t seqno)1123 int avc_ss_reset(uint32_t seqno)
1124 {
1125 	int rc;
1126 
1127 	rc = avc_reset();
1128 
1129 	avc_get_lock(avc_lock);
1130 	if (seqno > avc_cache.latest_notif)
1131 		avc_cache.latest_notif = seqno;
1132 	avc_release_lock(avc_lock);
1133 
1134 	return rc;
1135 }
1136 
1137 /**
1138  * avc_ss_set_auditallow - Enable or disable auditing of granted permissions.
1139  * @ssid: source security identifier or %SECSID_WILD
1140  * @tsid: target security identifier or %SECSID_WILD
1141  * @tclass: target security class
1142  * @perms: permissions to grant
1143  * @seqno: policy sequence number
1144  * @enable: enable flag.
1145  */
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)1146 int avc_ss_set_auditallow(security_id_t ssid, security_id_t tsid,
1147 			  security_class_t tclass, access_vector_t perms,
1148 			  uint32_t seqno, uint32_t enable)
1149 {
1150 	if (enable)
1151 		return avc_control(AVC_CALLBACK_AUDITALLOW_ENABLE,
1152 				   ssid, tsid, tclass, perms, seqno, 0);
1153 	else
1154 		return avc_control(AVC_CALLBACK_AUDITALLOW_DISABLE,
1155 				   ssid, tsid, tclass, perms, seqno, 0);
1156 }
1157 
1158 /**
1159  * avc_ss_set_auditdeny - Enable or disable auditing of denied permissions.
1160  * @ssid: source security identifier or %SECSID_WILD
1161  * @tsid: target security identifier or %SECSID_WILD
1162  * @tclass: target security class
1163  * @perms: permissions to grant
1164  * @seqno: policy sequence number
1165  * @enable: enable flag.
1166  */
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)1167 int avc_ss_set_auditdeny(security_id_t ssid, security_id_t tsid,
1168 			 security_class_t tclass, access_vector_t perms,
1169 			 uint32_t seqno, uint32_t enable)
1170 {
1171 	if (enable)
1172 		return avc_control(AVC_CALLBACK_AUDITDENY_ENABLE,
1173 				   ssid, tsid, tclass, perms, seqno, 0);
1174 	else
1175 		return avc_control(AVC_CALLBACK_AUDITDENY_DISABLE,
1176 				   ssid, tsid, tclass, perms, seqno, 0);
1177 }
1178