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