blob: 3ce724da3e8f5945d6ad7b234f18086fc86d8195 [file] [log] [blame]
Stephen Smalleyf0740362012-01-04 12:30:47 -05001/*
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
18struct 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
27struct avc_node {
28 struct avc_entry ae;
29 struct avc_node *next;
30};
31
32struct 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
39struct 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
52static void *avc_netlink_thread = NULL;
53static void *avc_lock = NULL;
54static void *avc_log_lock = NULL;
55static struct avc_node *avc_node_freelist = NULL;
56static struct avc_cache avc_cache;
57static char *avc_audit_buf = NULL;
58static struct avc_cache_stats cache_stats;
59static struct avc_callback_node *avc_callbacks = NULL;
60static struct sidtab avc_sidtab;
61
62static 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
69int avc_context_to_sid(const security_context_t 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
78int avc_sid_to_context(security_id_t sid, security_context_t * 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
89int avc_get_initial_sid(const char * name, security_id_t * sid)
90{
91 int rc;
92 security_context_t 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
104int 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
119int 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
202void avc_cache_stats(struct avc_cache_stats *p)
203{
204 memcpy(p, &cache_stats, sizeof(cache_stats));
205}
206
207void 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
217void 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
248hidden_def(avc_av_stats)
249
250static 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
288static inline void avc_clear_avc_entry(struct avc_entry *ae)
289{
290 ae->ssid = ae->tsid = ae->create_sid = NULL;
291 ae->tclass = 0;
292 ae->avd.allowed = ae->avd.decided = 0;
293 ae->avd.auditallow = ae->avd.auditdeny = 0;
294 ae->used = 0;
295}
296
297static inline struct avc_node *avc_claim_node(security_id_t ssid,
298 security_id_t tsid,
299 security_class_t tclass)
300{
301 struct avc_node *new;
302 int hvalue;
303
304 if (!avc_node_freelist)
305 avc_cleanup();
306
307 if (avc_node_freelist) {
308 new = avc_node_freelist;
309 avc_node_freelist = avc_node_freelist->next;
310 avc_cache.active_nodes++;
311 } else {
312 new = avc_reclaim_node();
313 if (!new)
314 goto out;
315 }
316
317 hvalue = avc_hash(ssid, tsid, tclass);
318 avc_clear_avc_entry(&new->ae);
319 new->ae.used = 1;
320 new->ae.ssid = ssid;
321 new->ae.tsid = tsid;
322 new->ae.tclass = tclass;
323 new->next = avc_cache.slots[hvalue];
324 avc_cache.slots[hvalue] = new;
325
326 out:
327 return new;
328}
329
330static inline struct avc_node *avc_search_node(security_id_t ssid,
331 security_id_t tsid,
332 security_class_t tclass,
333 int *probes)
334{
335 struct avc_node *cur;
336 int hvalue;
337 int tprobes = 1;
338
339 hvalue = avc_hash(ssid, tsid, tclass);
340 cur = avc_cache.slots[hvalue];
341 while (cur != NULL &&
342 (ssid != cur->ae.ssid ||
343 tclass != cur->ae.tclass || tsid != cur->ae.tsid)) {
344 tprobes++;
345 cur = cur->next;
346 }
347
348 if (cur == NULL) {
349 /* cache miss */
350 goto out;
351 }
352
353 /* cache hit */
354 if (probes)
355 *probes = tprobes;
356
357 cur->ae.used = 1;
358
359 out:
360 return cur;
361}
362
363/**
364 * avc_lookup - Look up an AVC entry.
365 * @ssid: source security identifier
366 * @tsid: target security identifier
367 * @tclass: target security class
368 * @requested: requested permissions, interpreted based on @tclass
369 * @aeref: AVC entry reference
370 *
371 * Look up an AVC entry that is valid for the
372 * @requested permissions between the SID pair
373 * (@ssid, @tsid), interpreting the permissions
374 * based on @tclass. If a valid AVC entry exists,
375 * then this function updates @aeref to refer to the
376 * entry and returns %0. Otherwise, -1 is returned.
377 */
378static int avc_lookup(security_id_t ssid, security_id_t tsid,
379 security_class_t tclass,
380 access_vector_t requested, struct avc_entry_ref *aeref)
381{
382 struct avc_node *node;
383 int probes, rc = 0;
384
385 avc_cache_stats_incr(cav_lookups);
386 node = avc_search_node(ssid, tsid, tclass, &probes);
387
388 if (node && ((node->ae.avd.decided & requested) == requested)) {
389 avc_cache_stats_incr(cav_hits);
390 avc_cache_stats_add(cav_probes, probes);
391 aeref->ae = &node->ae;
392 goto out;
393 }
394
395 avc_cache_stats_incr(cav_misses);
396 rc = -1;
397 out:
398 return rc;
399}
400
401/**
402 * avc_insert - Insert an AVC entry.
403 * @ssid: source security identifier
404 * @tsid: target security identifier
405 * @tclass: target security class
406 * @ae: AVC entry
407 * @aeref: AVC entry reference
408 *
409 * Insert an AVC entry for the SID pair
410 * (@ssid, @tsid) and class @tclass.
411 * The access vectors and the sequence number are
412 * normally provided by the security server in
413 * response to a security_compute_av() call. If the
414 * sequence number @ae->avd.seqno is not less than the latest
415 * revocation notification, then the function copies
416 * the access vectors into a cache entry, updates
417 * @aeref to refer to the entry, and returns %0.
418 * Otherwise, this function returns -%1 with @errno set to %EAGAIN.
419 */
420static int avc_insert(security_id_t ssid, security_id_t tsid,
421 security_class_t tclass,
422 struct avc_entry *ae, struct avc_entry_ref *aeref)
423{
424 struct avc_node *node;
425 int rc = 0;
426
427 if (ae->avd.seqno < avc_cache.latest_notif) {
428 avc_log(SELINUX_WARNING,
429 "%s: seqno %d < latest_notif %d\n", avc_prefix,
430 ae->avd.seqno, avc_cache.latest_notif);
431 errno = EAGAIN;
432 rc = -1;
433 goto out;
434 }
435
436 node = avc_claim_node(ssid, tsid, tclass);
437 if (!node) {
438 rc = -1;
439 goto out;
440 }
441
442 node->ae.avd.allowed = ae->avd.allowed;
443 node->ae.avd.decided = ae->avd.decided;
444 node->ae.avd.auditallow = ae->avd.auditallow;
445 node->ae.avd.auditdeny = ae->avd.auditdeny;
446 node->ae.avd.seqno = ae->avd.seqno;
447 aeref->ae = &node->ae;
448 out:
449 return rc;
450}
451
452void avc_cleanup(void)
453{
454}
455
456hidden_def(avc_cleanup)
457
458int avc_reset(void)
459{
460 struct avc_callback_node *c;
461 int i, ret, rc = 0, errsave = 0;
462 struct avc_node *node, *tmp;
463 errno = 0;
464
465 if (!avc_running)
466 return 0;
467
468 avc_get_lock(avc_lock);
469
470 for (i = 0; i < AVC_CACHE_SLOTS; i++) {
471 node = avc_cache.slots[i];
472 while (node) {
473 tmp = node;
474 node = node->next;
475 avc_clear_avc_entry(&tmp->ae);
476 tmp->next = avc_node_freelist;
477 avc_node_freelist = tmp;
478 avc_cache.active_nodes--;
479 }
480 avc_cache.slots[i] = 0;
481 }
482 avc_cache.lru_hint = 0;
483
484 avc_release_lock(avc_lock);
485
486 memset(&cache_stats, 0, sizeof(cache_stats));
487
488 for (c = avc_callbacks; c; c = c->next) {
489 if (c->events & AVC_CALLBACK_RESET) {
490 ret = c->callback(AVC_CALLBACK_RESET, 0, 0, 0, 0, 0);
491 if (ret && !rc) {
492 rc = ret;
493 errsave = errno;
494 }
495 }
496 }
497 errno = errsave;
498 return rc;
499}
500
501hidden_def(avc_reset)
502
503void avc_destroy(void)
504{
505 struct avc_callback_node *c;
506 struct avc_node *node, *tmp;
507 int i;
508
509 avc_get_lock(avc_lock);
510
511 if (avc_using_threads)
512 avc_stop_thread(avc_netlink_thread);
513 avc_netlink_close();
514
515 for (i = 0; i < AVC_CACHE_SLOTS; i++) {
516 node = avc_cache.slots[i];
517 while (node) {
518 tmp = node;
519 node = node->next;
520 avc_free(tmp);
521 }
522 }
523 while (avc_node_freelist) {
524 tmp = avc_node_freelist;
525 avc_node_freelist = tmp->next;
526 avc_free(tmp);
527 }
528 avc_release_lock(avc_lock);
529
530 while (avc_callbacks) {
531 c = avc_callbacks;
532 avc_callbacks = c->next;
533 avc_free(c);
534 }
535 sidtab_destroy(&avc_sidtab);
536 avc_free_lock(avc_lock);
537 avc_free_lock(avc_log_lock);
538 avc_free(avc_audit_buf);
539 avc_running = 0;
540}
541
542/* ratelimit stuff put aside for now --EFW */
543#if 0
544/*
545 * Copied from net/core/utils.c:net_ratelimit and modified for
546 * use by the AVC audit facility.
547 */
548#define AVC_MSG_COST 5*HZ
549#define AVC_MSG_BURST 10*5*HZ
550
551/*
552 * This enforces a rate limit: not more than one kernel message
553 * every 5secs to make a denial-of-service attack impossible.
554 */
555static int avc_ratelimit(void)
556{
557 static unsigned long toks = 10 * 5 * HZ;
558 static unsigned long last_msg;
559 static int missed, rc = 0;
560 unsigned long now = jiffies;
561 void *ratelimit_lock = avc_alloc_lock();
562
563 avc_get_lock(ratelimit_lock);
564 toks += now - last_msg;
565 last_msg = now;
566 if (toks > AVC_MSG_BURST)
567 toks = AVC_MSG_BURST;
568 if (toks >= AVC_MSG_COST) {
569 int lost = missed;
570 missed = 0;
571 toks -= AVC_MSG_COST;
572 avc_release_lock(ratelimit_lock);
573 if (lost) {
574 avc_log(SELINUX_WARNING,
575 "%s: %d messages suppressed.\n", avc_prefix,
576 lost);
577 }
578 rc = 1;
579 goto out;
580 }
581 missed++;
582 avc_release_lock(ratelimit_lock);
583 out:
584 avc_free_lock(ratelimit_lock);
585 return rc;
586}
587
588static inline int check_avc_ratelimit(void)
589{
590 if (avc_enforcing)
591 return avc_ratelimit();
592 else {
593 /* If permissive, then never suppress messages. */
594 return 1;
595 }
596}
597#endif /* ratelimit stuff */
598
599/**
600 * avc_dump_av - Display an access vector in human-readable form.
601 * @tclass: target security class
602 * @av: access vector
603 */
604static void avc_dump_av(security_class_t tclass, access_vector_t av)
605{
606 const char *permstr;
607 access_vector_t bit = 1;
608
609 if (av == 0) {
610 log_append(avc_audit_buf, " null");
611 return;
612 }
613
614 log_append(avc_audit_buf, " {");
615
616 while (av) {
617 if (av & bit) {
618 permstr = security_av_perm_to_string(tclass, bit);
619 if (!permstr)
620 break;
621 log_append(avc_audit_buf, " %s", permstr);
622 av &= ~bit;
623 }
624 bit <<= 1;
625 }
626
627 if (av)
628 log_append(avc_audit_buf, " 0x%x", av);
629 log_append(avc_audit_buf, " }");
630}
631
632/**
633 * avc_dump_query - Display a SID pair and a class in human-readable form.
634 * @ssid: source security identifier
635 * @tsid: target security identifier
636 * @tclass: target security class
637 */
638static void avc_dump_query(security_id_t ssid, security_id_t tsid,
639 security_class_t tclass)
640{
641 avc_get_lock(avc_lock);
642
643 log_append(avc_audit_buf, "scontext=%s tcontext=%s",
644 ssid->ctx, tsid->ctx);
645
646 avc_release_lock(avc_lock);
647 log_append(avc_audit_buf, " tclass=%s",
648 security_class_to_string(tclass));
649}
650
651void avc_audit(security_id_t ssid, security_id_t tsid,
652 security_class_t tclass, access_vector_t requested,
653 struct av_decision *avd, int result, void *a)
654{
655 access_vector_t denied, audited;
656
657 denied = requested & ~avd->allowed;
658 if (denied)
659 audited = denied & avd->auditdeny;
660 else if (!requested || result)
661 audited = denied = requested;
662 else
663 audited = requested & avd->auditallow;
664 if (!audited)
665 return;
666#if 0
667 if (!check_avc_ratelimit())
668 return;
669#endif
670 /* prevent overlapping buffer writes */
671 avc_get_lock(avc_log_lock);
672 snprintf(avc_audit_buf, AVC_AUDIT_BUFSIZE,
673 "%s: %s ", avc_prefix, (denied || !requested) ? "denied" : "granted");
674 avc_dump_av(tclass, audited);
675 log_append(avc_audit_buf, " for ");
676
677 /* get any extra information printed by the callback */
678 avc_suppl_audit(a, tclass, avc_audit_buf + strlen(avc_audit_buf),
679 AVC_AUDIT_BUFSIZE - strlen(avc_audit_buf));
680
681 log_append(avc_audit_buf, " ");
682 avc_dump_query(ssid, tsid, tclass);
683 log_append(avc_audit_buf, "\n");
684 avc_log(SELINUX_AVC, "%s", avc_audit_buf);
685
686 avc_release_lock(avc_log_lock);
687}
688
689hidden_def(avc_audit)
690
691int avc_has_perm_noaudit(security_id_t ssid,
692 security_id_t tsid,
693 security_class_t tclass,
694 access_vector_t requested,
695 struct avc_entry_ref *aeref, struct av_decision *avd)
696{
697 struct avc_entry *ae;
698 int rc = 0;
699 struct avc_entry entry;
700 access_vector_t denied;
701 struct avc_entry_ref ref;
702
703 if (!avc_using_threads && !avc_app_main_loop) {
704 (void)avc_netlink_check_nb();
705 }
706
707 if (!aeref) {
708 avc_entry_ref_init(&ref);
709 aeref = &ref;
710 }
711
712 avc_get_lock(avc_lock);
713 avc_cache_stats_incr(entry_lookups);
714 ae = aeref->ae;
715 if (ae) {
716 if (ae->ssid == ssid &&
717 ae->tsid == tsid &&
718 ae->tclass == tclass &&
719 ((ae->avd.decided & requested) == requested)) {
720 avc_cache_stats_incr(entry_hits);
721 ae->used = 1;
722 } else {
723 avc_cache_stats_incr(entry_discards);
724 ae = 0;
725 }
726 }
727
728 if (!ae) {
729 avc_cache_stats_incr(entry_misses);
730 rc = avc_lookup(ssid, tsid, tclass, requested, aeref);
731 if (rc) {
732 rc = security_compute_av(ssid->ctx, tsid->ctx,
733 tclass, requested,
734 &entry.avd);
735 if (rc)
736 goto out;
737 rc = avc_insert(ssid, tsid, tclass, &entry, aeref);
738 if (rc)
739 goto out;
740 }
741 ae = aeref->ae;
742 }
743
744 if (avd)
745 memcpy(avd, &ae->avd, sizeof(*avd));
746
747 denied = requested & ~(ae->avd.allowed);
748
749 if (!requested || denied) {
750 if (!avc_enforcing ||
751 (ae->avd.flags & SELINUX_AVD_FLAGS_PERMISSIVE))
752 ae->avd.allowed |= requested;
753 else {
754 errno = EACCES;
755 rc = -1;
756 }
757 }
758
759 out:
760 avc_release_lock(avc_lock);
761 return rc;
762}
763
764hidden_def(avc_has_perm_noaudit)
765
766int avc_has_perm(security_id_t ssid, security_id_t tsid,
767 security_class_t tclass, access_vector_t requested,
768 struct avc_entry_ref *aeref, void *auditdata)
769{
770 struct av_decision avd;
771 int errsave, rc;
772
773 memset(&avd, 0, sizeof(avd));
774
775 rc = avc_has_perm_noaudit(ssid, tsid, tclass, requested, aeref, &avd);
776 errsave = errno;
777 avc_audit(ssid, tsid, tclass, requested, &avd, rc, auditdata);
778 errno = errsave;
779 return rc;
780}
781
782int avc_compute_create(security_id_t ssid, security_id_t tsid,
783 security_class_t tclass, security_id_t *newsid)
784{
785 int rc;
786 struct avc_entry_ref aeref;
787 struct avc_entry entry;
788 security_context_t ctx;
789
790 *newsid = NULL;
791 avc_entry_ref_init(&aeref);
792
793 avc_get_lock(avc_lock);
794
795 /* check for a cached entry */
796 rc = avc_lookup(ssid, tsid, tclass, 0, &aeref);
797 if (rc) {
798 /* need to make a cache entry for this tuple */
799 rc = security_compute_av(ssid->ctx, tsid->ctx,
800 tclass, 0, &entry.avd);
801 if (rc)
802 goto out;
803 rc = avc_insert(ssid, tsid, tclass, &entry, &aeref);
804 if (rc)
805 goto out;
806 }
807
808 /* check for a saved compute_create value */
809 if (!aeref.ae->create_sid) {
810 /* need to query the kernel policy */
811 rc = security_compute_create(ssid->ctx, tsid->ctx, tclass,
812 &ctx);
813 if (rc)
814 goto out;
815 rc = sidtab_context_to_sid(&avc_sidtab, ctx, newsid);
816 freecon(ctx);
817 if (rc)
818 goto out;
819
820 aeref.ae->create_sid = *newsid;
821 } else {
822 /* found saved value */
823 *newsid = aeref.ae->create_sid;
824 }
825
826 rc = 0;
827out:
828 avc_release_lock(avc_lock);
829 return rc;
830}
831
832int avc_add_callback(int (*callback) (uint32_t event, security_id_t ssid,
833 security_id_t tsid,
834 security_class_t tclass,
835 access_vector_t perms,
836 access_vector_t * out_retained),
837 uint32_t events, security_id_t ssid,
838 security_id_t tsid,
839 security_class_t tclass, access_vector_t perms)
840{
841 struct avc_callback_node *c;
842 int rc = 0;
843
844 c = avc_malloc(sizeof(*c));
845 if (!c) {
846 rc = -1;
847 goto out;
848 }
849
850 c->callback = callback;
851 c->events = events;
852 c->ssid = ssid;
853 c->tsid = tsid;
854 c->tclass = tclass;
855 c->perms = perms;
856 c->next = avc_callbacks;
857 avc_callbacks = c;
858 out:
859 return rc;
860}
861
862static inline int avc_sidcmp(security_id_t x, security_id_t y)
863{
864 return (x == y || x == SECSID_WILD || y == SECSID_WILD);
865}
866
867static inline void avc_update_node(uint32_t event, struct avc_node *node,
868 access_vector_t perms)
869{
870 switch (event) {
871 case AVC_CALLBACK_GRANT:
872 node->ae.avd.allowed |= perms;
873 break;
874 case AVC_CALLBACK_TRY_REVOKE:
875 case AVC_CALLBACK_REVOKE:
876 node->ae.avd.allowed &= ~perms;
877 break;
878 case AVC_CALLBACK_AUDITALLOW_ENABLE:
879 node->ae.avd.auditallow |= perms;
880 break;
881 case AVC_CALLBACK_AUDITALLOW_DISABLE:
882 node->ae.avd.auditallow &= ~perms;
883 break;
884 case AVC_CALLBACK_AUDITDENY_ENABLE:
885 node->ae.avd.auditdeny |= perms;
886 break;
887 case AVC_CALLBACK_AUDITDENY_DISABLE:
888 node->ae.avd.auditdeny &= ~perms;
889 break;
890 }
891}
892
893static int avc_update_cache(uint32_t event, security_id_t ssid,
894 security_id_t tsid, security_class_t tclass,
895 access_vector_t perms)
896{
897 struct avc_node *node;
898 int i;
899
900 avc_get_lock(avc_lock);
901
902 if (ssid == SECSID_WILD || tsid == SECSID_WILD) {
903 /* apply to all matching nodes */
904 for (i = 0; i < AVC_CACHE_SLOTS; i++) {
905 for (node = avc_cache.slots[i]; node; node = node->next) {
906 if (avc_sidcmp(ssid, node->ae.ssid) &&
907 avc_sidcmp(tsid, node->ae.tsid) &&
908 tclass == node->ae.tclass) {
909 avc_update_node(event, node, perms);
910 }
911 }
912 }
913 } else {
914 /* apply to one node */
915 node = avc_search_node(ssid, tsid, tclass, 0);
916 if (node) {
917 avc_update_node(event, node, perms);
918 }
919 }
920
921 avc_release_lock(avc_lock);
922
923 return 0;
924}
925
926/* avc_control - update cache and call callbacks
927 *
928 * This should not be called directly; use the individual event
929 * functions instead.
930 */
931static int avc_control(uint32_t event, security_id_t ssid,
932 security_id_t tsid, security_class_t tclass,
933 access_vector_t perms,
934 uint32_t seqno, access_vector_t * out_retained)
935{
936 struct avc_callback_node *c;
937 access_vector_t tretained = 0, cretained = 0;
938 int ret, rc = 0, errsave = 0;
939 errno = 0;
940
941 /*
942 * try_revoke only removes permissions from the cache
943 * state if they are not retained by the object manager.
944 * Hence, try_revoke must wait until after the callbacks have
945 * been invoked to update the cache state.
946 */
947 if (event != AVC_CALLBACK_TRY_REVOKE)
948 avc_update_cache(event, ssid, tsid, tclass, perms);
949
950 for (c = avc_callbacks; c; c = c->next) {
951 if ((c->events & event) &&
952 avc_sidcmp(c->ssid, ssid) &&
953 avc_sidcmp(c->tsid, tsid) &&
954 c->tclass == tclass && (c->perms & perms)) {
955 cretained = 0;
956 ret = c->callback(event, ssid, tsid, tclass,
957 (c->perms & perms), &cretained);
958 if (ret && !rc) {
959 rc = ret;
960 errsave = errno;
961 }
962 if (!ret)
963 tretained |= cretained;
964 }
965 }
966
967 if (event == AVC_CALLBACK_TRY_REVOKE) {
968 /* revoke any unretained permissions */
969 perms &= ~tretained;
970 avc_update_cache(event, ssid, tsid, tclass, perms);
971 *out_retained = tretained;
972 }
973
974 avc_get_lock(avc_lock);
975 if (seqno > avc_cache.latest_notif)
976 avc_cache.latest_notif = seqno;
977 avc_release_lock(avc_lock);
978
979 errno = errsave;
980 return rc;
981}
982
983/**
984 * avc_ss_grant - Grant previously denied permissions.
985 * @ssid: source security identifier or %SECSID_WILD
986 * @tsid: target security identifier or %SECSID_WILD
987 * @tclass: target security class
988 * @perms: permissions to grant
989 * @seqno: policy sequence number
990 */
991int avc_ss_grant(security_id_t ssid, security_id_t tsid,
992 security_class_t tclass, access_vector_t perms,
993 uint32_t seqno)
994{
995 return avc_control(AVC_CALLBACK_GRANT,
996 ssid, tsid, tclass, perms, seqno, 0);
997}
998
999/**
1000 * avc_ss_try_revoke - Try to revoke previously granted permissions.
1001 * @ssid: source security identifier or %SECSID_WILD
1002 * @tsid: target security identifier or %SECSID_WILD
1003 * @tclass: target security class
1004 * @perms: permissions to grant
1005 * @seqno: policy sequence number
1006 * @out_retained: subset of @perms that are retained
1007 *
1008 * Try to revoke previously granted permissions, but
1009 * only if they are not retained as migrated permissions.
1010 * Return the subset of permissions that are retained via @out_retained.
1011 */
1012int avc_ss_try_revoke(security_id_t ssid, security_id_t tsid,
1013 security_class_t tclass,
1014 access_vector_t perms, uint32_t seqno,
1015 access_vector_t * out_retained)
1016{
1017 return avc_control(AVC_CALLBACK_TRY_REVOKE,
1018 ssid, tsid, tclass, perms, seqno, out_retained);
1019}
1020
1021/**
1022 * avc_ss_revoke - Revoke previously granted permissions.
1023 * @ssid: source security identifier or %SECSID_WILD
1024 * @tsid: target security identifier or %SECSID_WILD
1025 * @tclass: target security class
1026 * @perms: permissions to grant
1027 * @seqno: policy sequence number
1028 *
1029 * Revoke previously granted permissions, even if
1030 * they are retained as migrated permissions.
1031 */
1032int avc_ss_revoke(security_id_t ssid, security_id_t tsid,
1033 security_class_t tclass, access_vector_t perms,
1034 uint32_t seqno)
1035{
1036 return avc_control(AVC_CALLBACK_REVOKE,
1037 ssid, tsid, tclass, perms, seqno, 0);
1038}
1039
1040/**
1041 * avc_ss_reset - Flush the cache and revalidate migrated permissions.
1042 * @seqno: policy sequence number
1043 */
1044int avc_ss_reset(uint32_t seqno)
1045{
1046 int rc;
1047
1048 rc = avc_reset();
1049
1050 avc_get_lock(avc_lock);
1051 if (seqno > avc_cache.latest_notif)
1052 avc_cache.latest_notif = seqno;
1053 avc_release_lock(avc_lock);
1054
1055 return rc;
1056}
1057
1058/**
1059 * avc_ss_set_auditallow - Enable or disable auditing of granted permissions.
1060 * @ssid: source security identifier or %SECSID_WILD
1061 * @tsid: target security identifier or %SECSID_WILD
1062 * @tclass: target security class
1063 * @perms: permissions to grant
1064 * @seqno: policy sequence number
1065 * @enable: enable flag.
1066 */
1067int avc_ss_set_auditallow(security_id_t ssid, security_id_t tsid,
1068 security_class_t tclass, access_vector_t perms,
1069 uint32_t seqno, uint32_t enable)
1070{
1071 if (enable)
1072 return avc_control(AVC_CALLBACK_AUDITALLOW_ENABLE,
1073 ssid, tsid, tclass, perms, seqno, 0);
1074 else
1075 return avc_control(AVC_CALLBACK_AUDITALLOW_DISABLE,
1076 ssid, tsid, tclass, perms, seqno, 0);
1077}
1078
1079/**
1080 * avc_ss_set_auditdeny - Enable or disable auditing of denied permissions.
1081 * @ssid: source security identifier or %SECSID_WILD
1082 * @tsid: target security identifier or %SECSID_WILD
1083 * @tclass: target security class
1084 * @perms: permissions to grant
1085 * @seqno: policy sequence number
1086 * @enable: enable flag.
1087 */
1088int avc_ss_set_auditdeny(security_id_t ssid, security_id_t tsid,
1089 security_class_t tclass, access_vector_t perms,
1090 uint32_t seqno, uint32_t enable)
1091{
1092 if (enable)
1093 return avc_control(AVC_CALLBACK_AUDITDENY_ENABLE,
1094 ssid, tsid, tclass, perms, seqno, 0);
1095 else
1096 return avc_control(AVC_CALLBACK_AUDITDENY_DISABLE,
1097 ssid, tsid, tclass, perms, seqno, 0);
1098}