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