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