Branch data Line data Source code
1 : : // SPDX-License-Identifier: GPL-2.0-only
2 : : /*
3 : : * Implementation of the security services.
4 : : *
5 : : * Authors : Stephen Smalley, <sds@tycho.nsa.gov>
6 : : * James Morris <jmorris@redhat.com>
7 : : *
8 : : * Updated: Trusted Computer Solutions, Inc. <dgoeddel@trustedcs.com>
9 : : *
10 : : * Support for enhanced MLS infrastructure.
11 : : * Support for context based audit filters.
12 : : *
13 : : * Updated: Frank Mayer <mayerf@tresys.com> and Karl MacMillan <kmacmillan@tresys.com>
14 : : *
15 : : * Added conditional policy language extensions
16 : : *
17 : : * Updated: Hewlett-Packard <paul@paul-moore.com>
18 : : *
19 : : * Added support for NetLabel
20 : : * Added support for the policy capability bitmap
21 : : *
22 : : * Updated: Chad Sellers <csellers@tresys.com>
23 : : *
24 : : * Added validation of kernel classes and permissions
25 : : *
26 : : * Updated: KaiGai Kohei <kaigai@ak.jp.nec.com>
27 : : *
28 : : * Added support for bounds domain and audit messaged on masked permissions
29 : : *
30 : : * Updated: Guido Trentalancia <guido@trentalancia.com>
31 : : *
32 : : * Added support for runtime switching of the policy type
33 : : *
34 : : * Copyright (C) 2008, 2009 NEC Corporation
35 : : * Copyright (C) 2006, 2007 Hewlett-Packard Development Company, L.P.
36 : : * Copyright (C) 2004-2006 Trusted Computer Solutions, Inc.
37 : : * Copyright (C) 2003 - 2004, 2006 Tresys Technology, LLC
38 : : * Copyright (C) 2003 Red Hat, Inc., James Morris <jmorris@redhat.com>
39 : : */
40 : : #include <linux/kernel.h>
41 : : #include <linux/slab.h>
42 : : #include <linux/string.h>
43 : : #include <linux/spinlock.h>
44 : : #include <linux/rcupdate.h>
45 : : #include <linux/errno.h>
46 : : #include <linux/in.h>
47 : : #include <linux/sched.h>
48 : : #include <linux/audit.h>
49 : : #include <linux/mutex.h>
50 : : #include <linux/vmalloc.h>
51 : : #include <net/netlabel.h>
52 : :
53 : : #include "flask.h"
54 : : #include "avc.h"
55 : : #include "avc_ss.h"
56 : : #include "security.h"
57 : : #include "context.h"
58 : : #include "policydb.h"
59 : : #include "sidtab.h"
60 : : #include "services.h"
61 : : #include "conditional.h"
62 : : #include "mls.h"
63 : : #include "objsec.h"
64 : : #include "netlabel.h"
65 : : #include "xfrm.h"
66 : : #include "ebitmap.h"
67 : : #include "audit.h"
68 : :
69 : : /* Policy capability names */
70 : : const char *selinux_policycap_names[__POLICYDB_CAPABILITY_MAX] = {
71 : : "network_peer_controls",
72 : : "open_perms",
73 : : "extended_socket_class",
74 : : "always_check_network",
75 : : "cgroup_seclabel",
76 : : "nnp_nosuid_transition"
77 : : };
78 : :
79 : : static struct selinux_ss selinux_ss;
80 : :
81 : 28 : void selinux_ss_init(struct selinux_ss **ss)
82 : : {
83 : 28 : rwlock_init(&selinux_ss.policy_rwlock);
84 : 28 : mutex_init(&selinux_ss.status_lock);
85 : 28 : *ss = &selinux_ss;
86 : 28 : }
87 : :
88 : : /* Forward declaration. */
89 : : static int context_struct_to_string(struct policydb *policydb,
90 : : struct context *context,
91 : : char **scontext,
92 : : u32 *scontext_len);
93 : :
94 : : static int sidtab_entry_to_string(struct policydb *policydb,
95 : : struct sidtab *sidtab,
96 : : struct sidtab_entry *entry,
97 : : char **scontext,
98 : : u32 *scontext_len);
99 : :
100 : : static void context_struct_compute_av(struct policydb *policydb,
101 : : struct context *scontext,
102 : : struct context *tcontext,
103 : : u16 tclass,
104 : : struct av_decision *avd,
105 : : struct extended_perms *xperms);
106 : :
107 : : static int selinux_set_mapping(struct policydb *pol,
108 : : struct security_class_mapping *map,
109 : : struct selinux_map *out_map)
110 : : {
111 : : u16 i, j;
112 : : unsigned k;
113 : : bool print_unknown_handle = false;
114 : :
115 : : /* Find number of classes in the input mapping */
116 : : if (!map)
117 : : return -EINVAL;
118 : : i = 0;
119 : : while (map[i].name)
120 : : i++;
121 : :
122 : : /* Allocate space for the class records, plus one for class zero */
123 : : out_map->mapping = kcalloc(++i, sizeof(*out_map->mapping), GFP_ATOMIC);
124 : : if (!out_map->mapping)
125 : : return -ENOMEM;
126 : :
127 : : /* Store the raw class and permission values */
128 : : j = 0;
129 : : while (map[j].name) {
130 : : struct security_class_mapping *p_in = map + (j++);
131 : : struct selinux_mapping *p_out = out_map->mapping + j;
132 : :
133 : : /* An empty class string skips ahead */
134 : : if (!strcmp(p_in->name, "")) {
135 : : p_out->num_perms = 0;
136 : : continue;
137 : : }
138 : :
139 : : p_out->value = string_to_security_class(pol, p_in->name);
140 : : if (!p_out->value) {
141 : : pr_info("SELinux: Class %s not defined in policy.\n",
142 : : p_in->name);
143 : : if (pol->reject_unknown)
144 : : goto err;
145 : : p_out->num_perms = 0;
146 : : print_unknown_handle = true;
147 : : continue;
148 : : }
149 : :
150 : : k = 0;
151 : : while (p_in->perms[k]) {
152 : : /* An empty permission string skips ahead */
153 : : if (!*p_in->perms[k]) {
154 : : k++;
155 : : continue;
156 : : }
157 : : p_out->perms[k] = string_to_av_perm(pol, p_out->value,
158 : : p_in->perms[k]);
159 : : if (!p_out->perms[k]) {
160 : : pr_info("SELinux: Permission %s in class %s not defined in policy.\n",
161 : : p_in->perms[k], p_in->name);
162 : : if (pol->reject_unknown)
163 : : goto err;
164 : : print_unknown_handle = true;
165 : : }
166 : :
167 : : k++;
168 : : }
169 : : p_out->num_perms = k;
170 : : }
171 : :
172 : : if (print_unknown_handle)
173 : : pr_info("SELinux: the above unknown classes and permissions will be %s\n",
174 : : pol->allow_unknown ? "allowed" : "denied");
175 : :
176 : : out_map->size = i;
177 : : return 0;
178 : : err:
179 : : kfree(out_map->mapping);
180 : : out_map->mapping = NULL;
181 : : return -EINVAL;
182 : : }
183 : :
184 : : /*
185 : : * Get real, policy values from mapped values
186 : : */
187 : :
188 : 0 : static u16 unmap_class(struct selinux_map *map, u16 tclass)
189 : : {
190 : 0 : if (tclass < map->size)
191 : 0 : return map->mapping[tclass].value;
192 : :
193 : : return tclass;
194 : : }
195 : :
196 : : /*
197 : : * Get kernel value for class from its policy value
198 : : */
199 : 0 : static u16 map_class(struct selinux_map *map, u16 pol_value)
200 : : {
201 : 0 : u16 i;
202 : :
203 [ # # ]: 0 : for (i = 1; i < map->size; i++) {
204 [ # # ]: 0 : if (map->mapping[i].value == pol_value)
205 : : return i;
206 : : }
207 : :
208 : : return SECCLASS_NULL;
209 : : }
210 : :
211 : 0 : static void map_decision(struct selinux_map *map,
212 : : u16 tclass, struct av_decision *avd,
213 : : int allow_unknown)
214 : : {
215 [ # # ]: 0 : if (tclass < map->size) {
216 : 0 : struct selinux_mapping *mapping = &map->mapping[tclass];
217 : 0 : unsigned int i, n = mapping->num_perms;
218 : 0 : u32 result;
219 : :
220 [ # # ]: 0 : for (i = 0, result = 0; i < n; i++) {
221 [ # # ]: 0 : if (avd->allowed & mapping->perms[i])
222 : 0 : result |= 1<<i;
223 [ # # # # ]: 0 : if (allow_unknown && !mapping->perms[i])
224 : 0 : result |= 1<<i;
225 : : }
226 : 0 : avd->allowed = result;
227 : :
228 [ # # ]: 0 : for (i = 0, result = 0; i < n; i++)
229 [ # # ]: 0 : if (avd->auditallow & mapping->perms[i])
230 : 0 : result |= 1<<i;
231 : 0 : avd->auditallow = result;
232 : :
233 [ # # ]: 0 : for (i = 0, result = 0; i < n; i++) {
234 [ # # ]: 0 : if (avd->auditdeny & mapping->perms[i])
235 : 0 : result |= 1<<i;
236 [ # # # # ]: 0 : if (!allow_unknown && !mapping->perms[i])
237 : 0 : result |= 1<<i;
238 : : }
239 : : /*
240 : : * In case the kernel has a bug and requests a permission
241 : : * between num_perms and the maximum permission number, we
242 : : * should audit that denial
243 : : */
244 [ # # ]: 0 : for (; i < (sizeof(u32)*8); i++)
245 : 0 : result |= 1<<i;
246 : 0 : avd->auditdeny = result;
247 : : }
248 : 0 : }
249 : :
250 : 0 : int security_mls_enabled(struct selinux_state *state)
251 : : {
252 : 0 : struct policydb *p = &state->ss->policydb;
253 : :
254 : 0 : return p->mls_enabled;
255 : : }
256 : :
257 : : /*
258 : : * Return the boolean value of a constraint expression
259 : : * when it is applied to the specified source and target
260 : : * security contexts.
261 : : *
262 : : * xcontext is a special beast... It is used by the validatetrans rules
263 : : * only. For these rules, scontext is the context before the transition,
264 : : * tcontext is the context after the transition, and xcontext is the context
265 : : * of the process performing the transition. All other callers of
266 : : * constraint_expr_eval should pass in NULL for xcontext.
267 : : */
268 : : static int constraint_expr_eval(struct policydb *policydb,
269 : : struct context *scontext,
270 : : struct context *tcontext,
271 : : struct context *xcontext,
272 : : struct constraint_expr *cexpr)
273 : : {
274 : : u32 val1, val2;
275 : : struct context *c;
276 : : struct role_datum *r1, *r2;
277 : : struct mls_level *l1, *l2;
278 : : struct constraint_expr *e;
279 : : int s[CEXPR_MAXDEPTH];
280 : : int sp = -1;
281 : :
282 : : for (e = cexpr; e; e = e->next) {
283 : : switch (e->expr_type) {
284 : : case CEXPR_NOT:
285 : : BUG_ON(sp < 0);
286 : : s[sp] = !s[sp];
287 : : break;
288 : : case CEXPR_AND:
289 : : BUG_ON(sp < 1);
290 : : sp--;
291 : : s[sp] &= s[sp + 1];
292 : : break;
293 : : case CEXPR_OR:
294 : : BUG_ON(sp < 1);
295 : : sp--;
296 : : s[sp] |= s[sp + 1];
297 : : break;
298 : : case CEXPR_ATTR:
299 : : if (sp == (CEXPR_MAXDEPTH - 1))
300 : : return 0;
301 : : switch (e->attr) {
302 : : case CEXPR_USER:
303 : : val1 = scontext->user;
304 : : val2 = tcontext->user;
305 : : break;
306 : : case CEXPR_TYPE:
307 : : val1 = scontext->type;
308 : : val2 = tcontext->type;
309 : : break;
310 : : case CEXPR_ROLE:
311 : : val1 = scontext->role;
312 : : val2 = tcontext->role;
313 : : r1 = policydb->role_val_to_struct[val1 - 1];
314 : : r2 = policydb->role_val_to_struct[val2 - 1];
315 : : switch (e->op) {
316 : : case CEXPR_DOM:
317 : : s[++sp] = ebitmap_get_bit(&r1->dominates,
318 : : val2 - 1);
319 : : continue;
320 : : case CEXPR_DOMBY:
321 : : s[++sp] = ebitmap_get_bit(&r2->dominates,
322 : : val1 - 1);
323 : : continue;
324 : : case CEXPR_INCOMP:
325 : : s[++sp] = (!ebitmap_get_bit(&r1->dominates,
326 : : val2 - 1) &&
327 : : !ebitmap_get_bit(&r2->dominates,
328 : : val1 - 1));
329 : : continue;
330 : : default:
331 : : break;
332 : : }
333 : : break;
334 : : case CEXPR_L1L2:
335 : : l1 = &(scontext->range.level[0]);
336 : : l2 = &(tcontext->range.level[0]);
337 : : goto mls_ops;
338 : : case CEXPR_L1H2:
339 : : l1 = &(scontext->range.level[0]);
340 : : l2 = &(tcontext->range.level[1]);
341 : : goto mls_ops;
342 : : case CEXPR_H1L2:
343 : : l1 = &(scontext->range.level[1]);
344 : : l2 = &(tcontext->range.level[0]);
345 : : goto mls_ops;
346 : : case CEXPR_H1H2:
347 : : l1 = &(scontext->range.level[1]);
348 : : l2 = &(tcontext->range.level[1]);
349 : : goto mls_ops;
350 : : case CEXPR_L1H1:
351 : : l1 = &(scontext->range.level[0]);
352 : : l2 = &(scontext->range.level[1]);
353 : : goto mls_ops;
354 : : case CEXPR_L2H2:
355 : : l1 = &(tcontext->range.level[0]);
356 : : l2 = &(tcontext->range.level[1]);
357 : : goto mls_ops;
358 : : mls_ops:
359 : : switch (e->op) {
360 : : case CEXPR_EQ:
361 : : s[++sp] = mls_level_eq(l1, l2);
362 : : continue;
363 : : case CEXPR_NEQ:
364 : : s[++sp] = !mls_level_eq(l1, l2);
365 : : continue;
366 : : case CEXPR_DOM:
367 : : s[++sp] = mls_level_dom(l1, l2);
368 : : continue;
369 : : case CEXPR_DOMBY:
370 : : s[++sp] = mls_level_dom(l2, l1);
371 : : continue;
372 : : case CEXPR_INCOMP:
373 : : s[++sp] = mls_level_incomp(l2, l1);
374 : : continue;
375 : : default:
376 : : BUG();
377 : : return 0;
378 : : }
379 : : break;
380 : : default:
381 : : BUG();
382 : : return 0;
383 : : }
384 : :
385 : : switch (e->op) {
386 : : case CEXPR_EQ:
387 : : s[++sp] = (val1 == val2);
388 : : break;
389 : : case CEXPR_NEQ:
390 : : s[++sp] = (val1 != val2);
391 : : break;
392 : : default:
393 : : BUG();
394 : : return 0;
395 : : }
396 : : break;
397 : : case CEXPR_NAMES:
398 : : if (sp == (CEXPR_MAXDEPTH-1))
399 : : return 0;
400 : : c = scontext;
401 : : if (e->attr & CEXPR_TARGET)
402 : : c = tcontext;
403 : : else if (e->attr & CEXPR_XTARGET) {
404 : : c = xcontext;
405 : : if (!c) {
406 : : BUG();
407 : : return 0;
408 : : }
409 : : }
410 : : if (e->attr & CEXPR_USER)
411 : : val1 = c->user;
412 : : else if (e->attr & CEXPR_ROLE)
413 : : val1 = c->role;
414 : : else if (e->attr & CEXPR_TYPE)
415 : : val1 = c->type;
416 : : else {
417 : : BUG();
418 : : return 0;
419 : : }
420 : :
421 : : switch (e->op) {
422 : : case CEXPR_EQ:
423 : : s[++sp] = ebitmap_get_bit(&e->names, val1 - 1);
424 : : break;
425 : : case CEXPR_NEQ:
426 : : s[++sp] = !ebitmap_get_bit(&e->names, val1 - 1);
427 : : break;
428 : : default:
429 : : BUG();
430 : : return 0;
431 : : }
432 : : break;
433 : : default:
434 : : BUG();
435 : : return 0;
436 : : }
437 : : }
438 : :
439 : : BUG_ON(sp != 0);
440 : : return s[0];
441 : : }
442 : :
443 : : /*
444 : : * security_dump_masked_av - dumps masked permissions during
445 : : * security_compute_av due to RBAC, MLS/Constraint and Type bounds.
446 : : */
447 : 0 : static int dump_masked_av_helper(void *k, void *d, void *args)
448 : : {
449 : 0 : struct perm_datum *pdatum = d;
450 : 0 : char **permission_names = args;
451 : :
452 [ # # ]: 0 : BUG_ON(pdatum->value < 1 || pdatum->value > 32);
453 : :
454 : 0 : permission_names[pdatum->value - 1] = (char *)k;
455 : :
456 : 0 : return 0;
457 : : }
458 : :
459 : 0 : static void security_dump_masked_av(struct policydb *policydb,
460 : : struct context *scontext,
461 : : struct context *tcontext,
462 : : u16 tclass,
463 : : u32 permissions,
464 : : const char *reason)
465 : : {
466 : 0 : struct common_datum *common_dat;
467 : 0 : struct class_datum *tclass_dat;
468 : 0 : struct audit_buffer *ab;
469 : 0 : char *tclass_name;
470 : 0 : char *scontext_name = NULL;
471 : 0 : char *tcontext_name = NULL;
472 : 0 : char *permission_names[32];
473 : 0 : int index;
474 : 0 : u32 length;
475 : 0 : bool need_comma = false;
476 : :
477 [ # # ]: 0 : if (!permissions)
478 : : return;
479 : :
480 [ # # ]: 0 : tclass_name = sym_name(policydb, SYM_CLASSES, tclass - 1);
481 : 0 : tclass_dat = policydb->class_val_to_struct[tclass - 1];
482 : 0 : common_dat = tclass_dat->comdatum;
483 : :
484 : : /* init permission_names */
485 [ # # # # ]: 0 : if (common_dat &&
486 : 0 : hashtab_map(common_dat->permissions.table,
487 : : dump_masked_av_helper, permission_names) < 0)
488 : 0 : goto out;
489 : :
490 [ # # ]: 0 : if (hashtab_map(tclass_dat->permissions.table,
491 : : dump_masked_av_helper, permission_names) < 0)
492 : 0 : goto out;
493 : :
494 : : /* get scontext/tcontext in text form */
495 [ # # ]: 0 : if (context_struct_to_string(policydb, scontext,
496 : : &scontext_name, &length) < 0)
497 : 0 : goto out;
498 : :
499 [ # # ]: 0 : if (context_struct_to_string(policydb, tcontext,
500 : : &tcontext_name, &length) < 0)
501 : 0 : goto out;
502 : :
503 : : /* audit a message */
504 : 0 : ab = audit_log_start(audit_context(),
505 : : GFP_ATOMIC, AUDIT_SELINUX_ERR);
506 [ # # ]: 0 : if (!ab)
507 : 0 : goto out;
508 : :
509 : 0 : audit_log_format(ab, "op=security_compute_av reason=%s "
510 : : "scontext=%s tcontext=%s tclass=%s perms=",
511 : : reason, scontext_name, tcontext_name, tclass_name);
512 : :
513 [ # # ]: 0 : for (index = 0; index < 32; index++) {
514 : 0 : u32 mask = (1 << index);
515 : :
516 [ # # ]: 0 : if ((mask & permissions) == 0)
517 : 0 : continue;
518 : :
519 [ # # ]: 0 : audit_log_format(ab, "%s%s",
520 : : need_comma ? "," : "",
521 [ # # ]: 0 : permission_names[index]
522 : : ? permission_names[index] : "????");
523 : 0 : need_comma = true;
524 : : }
525 : 0 : audit_log_end(ab);
526 : 0 : out:
527 : : /* release scontext/tcontext */
528 : 0 : kfree(tcontext_name);
529 : 0 : kfree(scontext_name);
530 : :
531 : 0 : return;
532 : : }
533 : :
534 : : /*
535 : : * security_boundary_permission - drops violated permissions
536 : : * on boundary constraint.
537 : : */
538 : 0 : static void type_attribute_bounds_av(struct policydb *policydb,
539 : : struct context *scontext,
540 : : struct context *tcontext,
541 : : u16 tclass,
542 : : struct av_decision *avd)
543 : : {
544 : 0 : struct context lo_scontext;
545 : 0 : struct context lo_tcontext, *tcontextp = tcontext;
546 : 0 : struct av_decision lo_avd;
547 : 0 : struct type_datum *source;
548 : 0 : struct type_datum *target;
549 : 0 : u32 masked = 0;
550 : :
551 : 0 : source = policydb->type_val_to_struct[scontext->type - 1];
552 [ # # ]: 0 : BUG_ON(!source);
553 : :
554 [ # # ]: 0 : if (!source->bounds)
555 : 0 : return;
556 : :
557 : 0 : target = policydb->type_val_to_struct[tcontext->type - 1];
558 [ # # ]: 0 : BUG_ON(!target);
559 : :
560 : 0 : memset(&lo_avd, 0, sizeof(lo_avd));
561 : :
562 : 0 : memcpy(&lo_scontext, scontext, sizeof(lo_scontext));
563 : 0 : lo_scontext.type = source->bounds;
564 : :
565 [ # # ]: 0 : if (target->bounds) {
566 : 0 : memcpy(&lo_tcontext, tcontext, sizeof(lo_tcontext));
567 : 0 : lo_tcontext.type = target->bounds;
568 : 0 : tcontextp = &lo_tcontext;
569 : : }
570 : :
571 : 0 : context_struct_compute_av(policydb, &lo_scontext,
572 : : tcontextp,
573 : : tclass,
574 : : &lo_avd,
575 : : NULL);
576 : :
577 : 0 : masked = ~lo_avd.allowed & avd->allowed;
578 : :
579 [ # # ]: 0 : if (likely(!masked))
580 : : return; /* no masked permission */
581 : :
582 : : /* mask violated permissions */
583 : 0 : avd->allowed &= ~masked;
584 : :
585 : : /* audit masked permissions */
586 : 0 : security_dump_masked_av(policydb, scontext, tcontext,
587 : : tclass, masked, "bounds");
588 : : }
589 : :
590 : : /*
591 : : * flag which drivers have permissions
592 : : * only looking for ioctl based extended permssions
593 : : */
594 : 0 : void services_compute_xperms_drivers(
595 : : struct extended_perms *xperms,
596 : : struct avtab_node *node)
597 : : {
598 : 0 : unsigned int i;
599 : :
600 [ # # ]: 0 : if (node->datum.u.xperms->specified == AVTAB_XPERMS_IOCTLDRIVER) {
601 : : /* if one or more driver has all permissions allowed */
602 [ # # ]: 0 : for (i = 0; i < ARRAY_SIZE(xperms->drivers.p); i++)
603 : 0 : xperms->drivers.p[i] |= node->datum.u.xperms->perms.p[i];
604 [ # # ]: 0 : } else if (node->datum.u.xperms->specified == AVTAB_XPERMS_IOCTLFUNCTION) {
605 : : /* if allowing permissions within a driver */
606 : 0 : security_xperm_set(xperms->drivers.p,
607 : : node->datum.u.xperms->driver);
608 : : }
609 : :
610 : : /* If no ioctl commands are allowed, ignore auditallow and auditdeny */
611 [ # # ]: 0 : if (node->key.specified & AVTAB_XPERMS_ALLOWED)
612 : 0 : xperms->len = 1;
613 : 0 : }
614 : :
615 : : /*
616 : : * Compute access vectors and extended permissions based on a context
617 : : * structure pair for the permissions in a particular class.
618 : : */
619 : 0 : static void context_struct_compute_av(struct policydb *policydb,
620 : : struct context *scontext,
621 : : struct context *tcontext,
622 : : u16 tclass,
623 : : struct av_decision *avd,
624 : : struct extended_perms *xperms)
625 : : {
626 : 0 : struct constraint_node *constraint;
627 : 0 : struct role_allow *ra;
628 : 0 : struct avtab_key avkey;
629 : 0 : struct avtab_node *node;
630 : 0 : struct class_datum *tclass_datum;
631 : 0 : struct ebitmap *sattr, *tattr;
632 : 0 : struct ebitmap_node *snode, *tnode;
633 : 0 : unsigned int i, j;
634 : :
635 : 0 : avd->allowed = 0;
636 : 0 : avd->auditallow = 0;
637 : 0 : avd->auditdeny = 0xffffffff;
638 [ # # ]: 0 : if (xperms) {
639 : 0 : memset(&xperms->drivers, 0, sizeof(xperms->drivers));
640 : 0 : xperms->len = 0;
641 : : }
642 : :
643 [ # # # # ]: 0 : if (unlikely(!tclass || tclass > policydb->p_classes.nprim)) {
644 [ # # ]: 0 : if (printk_ratelimit())
645 : 0 : pr_warn("SELinux: Invalid class %hu\n", tclass);
646 : 0 : return;
647 : : }
648 : :
649 : 0 : tclass_datum = policydb->class_val_to_struct[tclass - 1];
650 : :
651 : : /*
652 : : * If a specific type enforcement rule was defined for
653 : : * this permission check, then use it.
654 : : */
655 : 0 : avkey.target_class = tclass;
656 : 0 : avkey.specified = AVTAB_AV | AVTAB_XPERMS;
657 : 0 : sattr = &policydb->type_attr_map_array[scontext->type - 1];
658 : 0 : tattr = &policydb->type_attr_map_array[tcontext->type - 1];
659 [ # # ]: 0 : ebitmap_for_each_positive_bit(sattr, snode, i) {
660 [ # # ]: 0 : ebitmap_for_each_positive_bit(tattr, tnode, j) {
661 : 0 : avkey.source_type = i + 1;
662 : 0 : avkey.target_type = j + 1;
663 : 0 : for (node = avtab_search_node(&policydb->te_avtab,
664 : : &avkey);
665 [ # # ]: 0 : node;
666 : 0 : node = avtab_search_node_next(node, avkey.specified)) {
667 [ # # ]: 0 : if (node->key.specified == AVTAB_ALLOWED)
668 : 0 : avd->allowed |= node->datum.u.data;
669 [ # # ]: 0 : else if (node->key.specified == AVTAB_AUDITALLOW)
670 : 0 : avd->auditallow |= node->datum.u.data;
671 [ # # ]: 0 : else if (node->key.specified == AVTAB_AUDITDENY)
672 : 0 : avd->auditdeny &= node->datum.u.data;
673 [ # # # # ]: 0 : else if (xperms && (node->key.specified & AVTAB_XPERMS))
674 : 0 : services_compute_xperms_drivers(xperms, node);
675 : : }
676 : :
677 : : /* Check conditional av table for additional permissions */
678 : 0 : cond_compute_av(&policydb->te_cond_avtab, &avkey,
679 : : avd, xperms);
680 : :
681 : : }
682 : : }
683 : :
684 : : /*
685 : : * Remove any permissions prohibited by a constraint (this includes
686 : : * the MLS policy).
687 : : */
688 : 0 : constraint = tclass_datum->constraints;
689 [ # # ]: 0 : while (constraint) {
690 [ # # # # ]: 0 : if ((constraint->permissions & (avd->allowed)) &&
691 : 0 : !constraint_expr_eval(policydb, scontext, tcontext, NULL,
692 : : constraint->expr)) {
693 : 0 : avd->allowed &= ~(constraint->permissions);
694 : : }
695 : 0 : constraint = constraint->next;
696 : : }
697 : :
698 : : /*
699 : : * If checking process transition permission and the
700 : : * role is changing, then check the (current_role, new_role)
701 : : * pair.
702 : : */
703 [ # # ]: 0 : if (tclass == policydb->process_class &&
704 [ # # ]: 0 : (avd->allowed & policydb->process_trans_perms) &&
705 [ # # ]: 0 : scontext->role != tcontext->role) {
706 [ # # ]: 0 : for (ra = policydb->role_allow; ra; ra = ra->next) {
707 [ # # ]: 0 : if (scontext->role == ra->role &&
708 [ # # ]: 0 : tcontext->role == ra->new_role)
709 : : break;
710 : : }
711 [ # # ]: 0 : if (!ra)
712 : 0 : avd->allowed &= ~policydb->process_trans_perms;
713 : : }
714 : :
715 : : /*
716 : : * If the given source and target types have boundary
717 : : * constraint, lazy checks have to mask any violated
718 : : * permission and notice it to userspace via audit.
719 : : */
720 : 0 : type_attribute_bounds_av(policydb, scontext, tcontext,
721 : : tclass, avd);
722 : : }
723 : :
724 : 0 : static int security_validtrans_handle_fail(struct selinux_state *state,
725 : : struct sidtab_entry *oentry,
726 : : struct sidtab_entry *nentry,
727 : : struct sidtab_entry *tentry,
728 : : u16 tclass)
729 : : {
730 : 0 : struct policydb *p = &state->ss->policydb;
731 : 0 : struct sidtab *sidtab = state->ss->sidtab;
732 : 0 : char *o = NULL, *n = NULL, *t = NULL;
733 : 0 : u32 olen, nlen, tlen;
734 : :
735 [ # # ]: 0 : if (sidtab_entry_to_string(p, sidtab, oentry, &o, &olen))
736 : 0 : goto out;
737 [ # # ]: 0 : if (sidtab_entry_to_string(p, sidtab, nentry, &n, &nlen))
738 : 0 : goto out;
739 [ # # ]: 0 : if (sidtab_entry_to_string(p, sidtab, tentry, &t, &tlen))
740 : 0 : goto out;
741 : 0 : audit_log(audit_context(), GFP_ATOMIC, AUDIT_SELINUX_ERR,
742 : : "op=security_validate_transition seresult=denied"
743 : : " oldcontext=%s newcontext=%s taskcontext=%s tclass=%s",
744 : 0 : o, n, t, sym_name(p, SYM_CLASSES, tclass-1));
745 : 0 : out:
746 : 0 : kfree(o);
747 : 0 : kfree(n);
748 : 0 : kfree(t);
749 : :
750 [ # # ]: 0 : if (!enforcing_enabled(state))
751 : 0 : return 0;
752 : : return -EPERM;
753 : : }
754 : :
755 : 0 : static int security_compute_validatetrans(struct selinux_state *state,
756 : : u32 oldsid, u32 newsid, u32 tasksid,
757 : : u16 orig_tclass, bool user)
758 : : {
759 : 0 : struct policydb *policydb;
760 : 0 : struct sidtab *sidtab;
761 : 0 : struct sidtab_entry *oentry;
762 : 0 : struct sidtab_entry *nentry;
763 : 0 : struct sidtab_entry *tentry;
764 : 0 : struct class_datum *tclass_datum;
765 : 0 : struct constraint_node *constraint;
766 : 0 : u16 tclass;
767 : 0 : int rc = 0;
768 : :
769 : :
770 [ # # ]: 0 : if (!selinux_initialized(state))
771 : : return 0;
772 : :
773 : 0 : read_lock(&state->ss->policy_rwlock);
774 : :
775 : 0 : policydb = &state->ss->policydb;
776 : 0 : sidtab = state->ss->sidtab;
777 : :
778 [ # # ]: 0 : if (!user)
779 [ # # ]: 0 : tclass = unmap_class(&state->ss->map, orig_tclass);
780 : : else
781 : : tclass = orig_tclass;
782 : :
783 [ # # # # ]: 0 : if (!tclass || tclass > policydb->p_classes.nprim) {
784 : 0 : rc = -EINVAL;
785 : 0 : goto out;
786 : : }
787 : 0 : tclass_datum = policydb->class_val_to_struct[tclass - 1];
788 : :
789 : 0 : oentry = sidtab_search_entry(sidtab, oldsid);
790 [ # # ]: 0 : if (!oentry) {
791 : 0 : pr_err("SELinux: %s: unrecognized SID %d\n",
792 : : __func__, oldsid);
793 : 0 : rc = -EINVAL;
794 : 0 : goto out;
795 : : }
796 : :
797 : 0 : nentry = sidtab_search_entry(sidtab, newsid);
798 [ # # ]: 0 : if (!nentry) {
799 : 0 : pr_err("SELinux: %s: unrecognized SID %d\n",
800 : : __func__, newsid);
801 : 0 : rc = -EINVAL;
802 : 0 : goto out;
803 : : }
804 : :
805 : 0 : tentry = sidtab_search_entry(sidtab, tasksid);
806 [ # # ]: 0 : if (!tentry) {
807 : 0 : pr_err("SELinux: %s: unrecognized SID %d\n",
808 : : __func__, tasksid);
809 : 0 : rc = -EINVAL;
810 : 0 : goto out;
811 : : }
812 : :
813 : 0 : constraint = tclass_datum->validatetrans;
814 [ # # ]: 0 : while (constraint) {
815 [ # # ]: 0 : if (!constraint_expr_eval(policydb, &oentry->context,
816 : : &nentry->context, &tentry->context,
817 : : constraint->expr)) {
818 [ # # ]: 0 : if (user)
819 : : rc = -EPERM;
820 : : else
821 : 0 : rc = security_validtrans_handle_fail(state,
822 : : oentry,
823 : : nentry,
824 : : tentry,
825 : : tclass);
826 : 0 : goto out;
827 : : }
828 : 0 : constraint = constraint->next;
829 : : }
830 : :
831 : 0 : out:
832 : 0 : read_unlock(&state->ss->policy_rwlock);
833 : 0 : return rc;
834 : : }
835 : :
836 : 0 : int security_validate_transition_user(struct selinux_state *state,
837 : : u32 oldsid, u32 newsid, u32 tasksid,
838 : : u16 tclass)
839 : : {
840 : 0 : return security_compute_validatetrans(state, oldsid, newsid, tasksid,
841 : : tclass, true);
842 : : }
843 : :
844 : 0 : int security_validate_transition(struct selinux_state *state,
845 : : u32 oldsid, u32 newsid, u32 tasksid,
846 : : u16 orig_tclass)
847 : : {
848 : 0 : return security_compute_validatetrans(state, oldsid, newsid, tasksid,
849 : : orig_tclass, false);
850 : : }
851 : :
852 : : /*
853 : : * security_bounded_transition - check whether the given
854 : : * transition is directed to bounded, or not.
855 : : * It returns 0, if @newsid is bounded by @oldsid.
856 : : * Otherwise, it returns error code.
857 : : *
858 : : * @oldsid : current security identifier
859 : : * @newsid : destinated security identifier
860 : : */
861 : 0 : int security_bounded_transition(struct selinux_state *state,
862 : : u32 old_sid, u32 new_sid)
863 : : {
864 : 0 : struct policydb *policydb;
865 : 0 : struct sidtab *sidtab;
866 : 0 : struct sidtab_entry *old_entry, *new_entry;
867 : 0 : struct type_datum *type;
868 : 0 : int index;
869 : 0 : int rc;
870 : :
871 [ # # ]: 0 : if (!selinux_initialized(state))
872 : : return 0;
873 : :
874 : 0 : read_lock(&state->ss->policy_rwlock);
875 : :
876 : 0 : policydb = &state->ss->policydb;
877 : 0 : sidtab = state->ss->sidtab;
878 : :
879 : 0 : rc = -EINVAL;
880 : 0 : old_entry = sidtab_search_entry(sidtab, old_sid);
881 [ # # ]: 0 : if (!old_entry) {
882 : 0 : pr_err("SELinux: %s: unrecognized SID %u\n",
883 : : __func__, old_sid);
884 : 0 : goto out;
885 : : }
886 : :
887 : 0 : rc = -EINVAL;
888 : 0 : new_entry = sidtab_search_entry(sidtab, new_sid);
889 [ # # ]: 0 : if (!new_entry) {
890 : 0 : pr_err("SELinux: %s: unrecognized SID %u\n",
891 : : __func__, new_sid);
892 : 0 : goto out;
893 : : }
894 : :
895 : 0 : rc = 0;
896 : : /* type/domain unchanged */
897 [ # # ]: 0 : if (old_entry->context.type == new_entry->context.type)
898 : 0 : goto out;
899 : :
900 : 0 : index = new_entry->context.type;
901 : 0 : while (true) {
902 : 0 : type = policydb->type_val_to_struct[index - 1];
903 [ # # ]: 0 : BUG_ON(!type);
904 : :
905 : : /* not bounded anymore */
906 : 0 : rc = -EPERM;
907 [ # # ]: 0 : if (!type->bounds)
908 : : break;
909 : :
910 : : /* @newsid is bounded by @oldsid */
911 : 0 : rc = 0;
912 [ # # ]: 0 : if (type->bounds == old_entry->context.type)
913 : : break;
914 : :
915 : 0 : index = type->bounds;
916 : : }
917 : :
918 [ # # ]: 0 : if (rc) {
919 : 0 : char *old_name = NULL;
920 : 0 : char *new_name = NULL;
921 : 0 : u32 length;
922 : :
923 [ # # ]: 0 : if (!sidtab_entry_to_string(policydb, sidtab, old_entry,
924 [ # # ]: 0 : &old_name, &length) &&
925 : 0 : !sidtab_entry_to_string(policydb, sidtab, new_entry,
926 : : &new_name, &length)) {
927 : 0 : audit_log(audit_context(),
928 : : GFP_ATOMIC, AUDIT_SELINUX_ERR,
929 : : "op=security_bounded_transition "
930 : : "seresult=denied "
931 : : "oldcontext=%s newcontext=%s",
932 : : old_name, new_name);
933 : : }
934 : 0 : kfree(new_name);
935 : 0 : kfree(old_name);
936 : : }
937 : 0 : out:
938 : 0 : read_unlock(&state->ss->policy_rwlock);
939 : :
940 : 0 : return rc;
941 : : }
942 : :
943 : 784 : static void avd_init(struct selinux_state *state, struct av_decision *avd)
944 : : {
945 : 784 : avd->allowed = 0;
946 : 784 : avd->auditallow = 0;
947 : 784 : avd->auditdeny = 0xffffffff;
948 : 784 : avd->seqno = state->ss->latest_granting;
949 : 784 : avd->flags = 0;
950 : : }
951 : :
952 : 0 : void services_compute_xperms_decision(struct extended_perms_decision *xpermd,
953 : : struct avtab_node *node)
954 : : {
955 : 0 : unsigned int i;
956 : :
957 [ # # ]: 0 : if (node->datum.u.xperms->specified == AVTAB_XPERMS_IOCTLFUNCTION) {
958 [ # # ]: 0 : if (xpermd->driver != node->datum.u.xperms->driver)
959 : : return;
960 [ # # ]: 0 : } else if (node->datum.u.xperms->specified == AVTAB_XPERMS_IOCTLDRIVER) {
961 [ # # ]: 0 : if (!security_xperm_test(node->datum.u.xperms->perms.p,
962 : : xpermd->driver))
963 : : return;
964 : : } else {
965 : 0 : BUG();
966 : : }
967 : :
968 [ # # ]: 0 : if (node->key.specified == AVTAB_XPERMS_ALLOWED) {
969 : 0 : xpermd->used |= XPERMS_ALLOWED;
970 [ # # ]: 0 : if (node->datum.u.xperms->specified == AVTAB_XPERMS_IOCTLDRIVER) {
971 : 0 : memset(xpermd->allowed->p, 0xff,
972 : : sizeof(xpermd->allowed->p));
973 : : }
974 [ # # ]: 0 : if (node->datum.u.xperms->specified == AVTAB_XPERMS_IOCTLFUNCTION) {
975 [ # # ]: 0 : for (i = 0; i < ARRAY_SIZE(xpermd->allowed->p); i++)
976 : 0 : xpermd->allowed->p[i] |=
977 : 0 : node->datum.u.xperms->perms.p[i];
978 : : }
979 [ # # ]: 0 : } else if (node->key.specified == AVTAB_XPERMS_AUDITALLOW) {
980 : 0 : xpermd->used |= XPERMS_AUDITALLOW;
981 [ # # ]: 0 : if (node->datum.u.xperms->specified == AVTAB_XPERMS_IOCTLDRIVER) {
982 : 0 : memset(xpermd->auditallow->p, 0xff,
983 : : sizeof(xpermd->auditallow->p));
984 : : }
985 [ # # ]: 0 : if (node->datum.u.xperms->specified == AVTAB_XPERMS_IOCTLFUNCTION) {
986 [ # # ]: 0 : for (i = 0; i < ARRAY_SIZE(xpermd->auditallow->p); i++)
987 : 0 : xpermd->auditallow->p[i] |=
988 : 0 : node->datum.u.xperms->perms.p[i];
989 : : }
990 [ # # ]: 0 : } else if (node->key.specified == AVTAB_XPERMS_DONTAUDIT) {
991 : 0 : xpermd->used |= XPERMS_DONTAUDIT;
992 [ # # ]: 0 : if (node->datum.u.xperms->specified == AVTAB_XPERMS_IOCTLDRIVER) {
993 : 0 : memset(xpermd->dontaudit->p, 0xff,
994 : : sizeof(xpermd->dontaudit->p));
995 : : }
996 [ # # ]: 0 : if (node->datum.u.xperms->specified == AVTAB_XPERMS_IOCTLFUNCTION) {
997 [ # # ]: 0 : for (i = 0; i < ARRAY_SIZE(xpermd->dontaudit->p); i++)
998 : 0 : xpermd->dontaudit->p[i] |=
999 : 0 : node->datum.u.xperms->perms.p[i];
1000 : : }
1001 : : } else {
1002 : 0 : BUG();
1003 : : }
1004 : : }
1005 : :
1006 : 0 : void security_compute_xperms_decision(struct selinux_state *state,
1007 : : u32 ssid,
1008 : : u32 tsid,
1009 : : u16 orig_tclass,
1010 : : u8 driver,
1011 : : struct extended_perms_decision *xpermd)
1012 : : {
1013 : 0 : struct policydb *policydb;
1014 : 0 : struct sidtab *sidtab;
1015 : 0 : u16 tclass;
1016 : 0 : struct context *scontext, *tcontext;
1017 : 0 : struct avtab_key avkey;
1018 : 0 : struct avtab_node *node;
1019 : 0 : struct ebitmap *sattr, *tattr;
1020 : 0 : struct ebitmap_node *snode, *tnode;
1021 : 0 : unsigned int i, j;
1022 : :
1023 : 0 : xpermd->driver = driver;
1024 : 0 : xpermd->used = 0;
1025 : 0 : memset(xpermd->allowed->p, 0, sizeof(xpermd->allowed->p));
1026 : 0 : memset(xpermd->auditallow->p, 0, sizeof(xpermd->auditallow->p));
1027 : 0 : memset(xpermd->dontaudit->p, 0, sizeof(xpermd->dontaudit->p));
1028 : :
1029 : 0 : read_lock(&state->ss->policy_rwlock);
1030 [ # # ]: 0 : if (!selinux_initialized(state))
1031 : 0 : goto allow;
1032 : :
1033 : 0 : policydb = &state->ss->policydb;
1034 : 0 : sidtab = state->ss->sidtab;
1035 : :
1036 : 0 : scontext = sidtab_search(sidtab, ssid);
1037 [ # # ]: 0 : if (!scontext) {
1038 : 0 : pr_err("SELinux: %s: unrecognized SID %d\n",
1039 : : __func__, ssid);
1040 : 0 : goto out;
1041 : : }
1042 : :
1043 : 0 : tcontext = sidtab_search(sidtab, tsid);
1044 [ # # ]: 0 : if (!tcontext) {
1045 : 0 : pr_err("SELinux: %s: unrecognized SID %d\n",
1046 : : __func__, tsid);
1047 : 0 : goto out;
1048 : : }
1049 : :
1050 [ # # ]: 0 : tclass = unmap_class(&state->ss->map, orig_tclass);
1051 [ # # ]: 0 : if (unlikely(orig_tclass && !tclass)) {
1052 [ # # ]: 0 : if (policydb->allow_unknown)
1053 : 0 : goto allow;
1054 : 0 : goto out;
1055 : : }
1056 : :
1057 : :
1058 [ # # # # ]: 0 : if (unlikely(!tclass || tclass > policydb->p_classes.nprim)) {
1059 [ # # ]: 0 : pr_warn_ratelimited("SELinux: Invalid class %hu\n", tclass);
1060 : 0 : goto out;
1061 : : }
1062 : :
1063 : 0 : avkey.target_class = tclass;
1064 : 0 : avkey.specified = AVTAB_XPERMS;
1065 : 0 : sattr = &policydb->type_attr_map_array[scontext->type - 1];
1066 : 0 : tattr = &policydb->type_attr_map_array[tcontext->type - 1];
1067 [ # # ]: 0 : ebitmap_for_each_positive_bit(sattr, snode, i) {
1068 [ # # ]: 0 : ebitmap_for_each_positive_bit(tattr, tnode, j) {
1069 : 0 : avkey.source_type = i + 1;
1070 : 0 : avkey.target_type = j + 1;
1071 : 0 : for (node = avtab_search_node(&policydb->te_avtab,
1072 : : &avkey);
1073 [ # # ]: 0 : node;
1074 : 0 : node = avtab_search_node_next(node, avkey.specified))
1075 : 0 : services_compute_xperms_decision(xpermd, node);
1076 : :
1077 : 0 : cond_compute_xperms(&policydb->te_cond_avtab,
1078 : : &avkey, xpermd);
1079 : : }
1080 : : }
1081 : 0 : out:
1082 : 0 : read_unlock(&state->ss->policy_rwlock);
1083 : 0 : return;
1084 : 0 : allow:
1085 : 0 : memset(xpermd->allowed->p, 0xff, sizeof(xpermd->allowed->p));
1086 : 0 : goto out;
1087 : : }
1088 : :
1089 : : /**
1090 : : * security_compute_av - Compute access vector decisions.
1091 : : * @ssid: source security identifier
1092 : : * @tsid: target security identifier
1093 : : * @tclass: target security class
1094 : : * @avd: access vector decisions
1095 : : * @xperms: extended permissions
1096 : : *
1097 : : * Compute a set of access vector decisions based on the
1098 : : * SID pair (@ssid, @tsid) for the permissions in @tclass.
1099 : : */
1100 : 784 : void security_compute_av(struct selinux_state *state,
1101 : : u32 ssid,
1102 : : u32 tsid,
1103 : : u16 orig_tclass,
1104 : : struct av_decision *avd,
1105 : : struct extended_perms *xperms)
1106 : : {
1107 : 784 : struct policydb *policydb;
1108 : 784 : struct sidtab *sidtab;
1109 : 784 : u16 tclass;
1110 : 784 : struct context *scontext = NULL, *tcontext = NULL;
1111 : :
1112 : 784 : read_lock(&state->ss->policy_rwlock);
1113 : 784 : avd_init(state, avd);
1114 : 784 : xperms->len = 0;
1115 [ + - ]: 784 : if (!selinux_initialized(state))
1116 : 784 : goto allow;
1117 : :
1118 : 0 : policydb = &state->ss->policydb;
1119 : 0 : sidtab = state->ss->sidtab;
1120 : :
1121 : 0 : scontext = sidtab_search(sidtab, ssid);
1122 [ # # ]: 0 : if (!scontext) {
1123 : 0 : pr_err("SELinux: %s: unrecognized SID %d\n",
1124 : : __func__, ssid);
1125 : 0 : goto out;
1126 : : }
1127 : :
1128 : : /* permissive domain? */
1129 [ # # ]: 0 : if (ebitmap_get_bit(&policydb->permissive_map, scontext->type))
1130 : 0 : avd->flags |= AVD_FLAGS_PERMISSIVE;
1131 : :
1132 : 0 : tcontext = sidtab_search(sidtab, tsid);
1133 [ # # ]: 0 : if (!tcontext) {
1134 : 0 : pr_err("SELinux: %s: unrecognized SID %d\n",
1135 : : __func__, tsid);
1136 : 0 : goto out;
1137 : : }
1138 : :
1139 [ # # ]: 0 : tclass = unmap_class(&state->ss->map, orig_tclass);
1140 [ # # ]: 0 : if (unlikely(orig_tclass && !tclass)) {
1141 [ # # ]: 0 : if (policydb->allow_unknown)
1142 : 0 : goto allow;
1143 : 0 : goto out;
1144 : : }
1145 : 0 : context_struct_compute_av(policydb, scontext, tcontext, tclass, avd,
1146 : : xperms);
1147 : 0 : map_decision(&state->ss->map, orig_tclass, avd,
1148 : 0 : policydb->allow_unknown);
1149 : 784 : out:
1150 : 784 : read_unlock(&state->ss->policy_rwlock);
1151 : 784 : return;
1152 : 784 : allow:
1153 : 784 : avd->allowed = 0xffffffff;
1154 : 784 : goto out;
1155 : : }
1156 : :
1157 : 0 : void security_compute_av_user(struct selinux_state *state,
1158 : : u32 ssid,
1159 : : u32 tsid,
1160 : : u16 tclass,
1161 : : struct av_decision *avd)
1162 : : {
1163 : 0 : struct policydb *policydb;
1164 : 0 : struct sidtab *sidtab;
1165 : 0 : struct context *scontext = NULL, *tcontext = NULL;
1166 : :
1167 : 0 : read_lock(&state->ss->policy_rwlock);
1168 : 0 : avd_init(state, avd);
1169 [ # # ]: 0 : if (!selinux_initialized(state))
1170 : 0 : goto allow;
1171 : :
1172 : 0 : policydb = &state->ss->policydb;
1173 : 0 : sidtab = state->ss->sidtab;
1174 : :
1175 : 0 : scontext = sidtab_search(sidtab, ssid);
1176 [ # # ]: 0 : if (!scontext) {
1177 : 0 : pr_err("SELinux: %s: unrecognized SID %d\n",
1178 : : __func__, ssid);
1179 : 0 : goto out;
1180 : : }
1181 : :
1182 : : /* permissive domain? */
1183 [ # # ]: 0 : if (ebitmap_get_bit(&policydb->permissive_map, scontext->type))
1184 : 0 : avd->flags |= AVD_FLAGS_PERMISSIVE;
1185 : :
1186 : 0 : tcontext = sidtab_search(sidtab, tsid);
1187 [ # # ]: 0 : if (!tcontext) {
1188 : 0 : pr_err("SELinux: %s: unrecognized SID %d\n",
1189 : : __func__, tsid);
1190 : 0 : goto out;
1191 : : }
1192 : :
1193 [ # # ]: 0 : if (unlikely(!tclass)) {
1194 [ # # ]: 0 : if (policydb->allow_unknown)
1195 : 0 : goto allow;
1196 : 0 : goto out;
1197 : : }
1198 : :
1199 : 0 : context_struct_compute_av(policydb, scontext, tcontext, tclass, avd,
1200 : : NULL);
1201 : 0 : out:
1202 : 0 : read_unlock(&state->ss->policy_rwlock);
1203 : 0 : return;
1204 : 0 : allow:
1205 : 0 : avd->allowed = 0xffffffff;
1206 : 0 : goto out;
1207 : : }
1208 : :
1209 : : /*
1210 : : * Write the security context string representation of
1211 : : * the context structure `context' into a dynamically
1212 : : * allocated string of the correct size. Set `*scontext'
1213 : : * to point to this string and set `*scontext_len' to
1214 : : * the length of the string.
1215 : : */
1216 : 0 : static int context_struct_to_string(struct policydb *p,
1217 : : struct context *context,
1218 : : char **scontext, u32 *scontext_len)
1219 : : {
1220 : 0 : char *scontextp;
1221 : :
1222 [ # # ]: 0 : if (scontext)
1223 : 0 : *scontext = NULL;
1224 : 0 : *scontext_len = 0;
1225 : :
1226 [ # # ]: 0 : if (context->len) {
1227 : 0 : *scontext_len = context->len;
1228 [ # # ]: 0 : if (scontext) {
1229 : 0 : *scontext = kstrdup(context->str, GFP_ATOMIC);
1230 [ # # ]: 0 : if (!(*scontext))
1231 : : return -ENOMEM;
1232 : : }
1233 : 0 : return 0;
1234 : : }
1235 : :
1236 : : /* Compute the size of the context. */
1237 : 0 : *scontext_len += strlen(sym_name(p, SYM_USERS, context->user - 1)) + 1;
1238 : 0 : *scontext_len += strlen(sym_name(p, SYM_ROLES, context->role - 1)) + 1;
1239 : 0 : *scontext_len += strlen(sym_name(p, SYM_TYPES, context->type - 1)) + 1;
1240 : 0 : *scontext_len += mls_compute_context_len(p, context);
1241 : :
1242 [ # # ]: 0 : if (!scontext)
1243 : : return 0;
1244 : :
1245 : : /* Allocate space for the context; caller must free this space. */
1246 [ # # ]: 0 : scontextp = kmalloc(*scontext_len, GFP_ATOMIC);
1247 [ # # ]: 0 : if (!scontextp)
1248 : : return -ENOMEM;
1249 : 0 : *scontext = scontextp;
1250 : :
1251 : : /*
1252 : : * Copy the user name, role name and type name into the context.
1253 : : */
1254 : 0 : scontextp += sprintf(scontextp, "%s:%s:%s",
1255 : 0 : sym_name(p, SYM_USERS, context->user - 1),
1256 : 0 : sym_name(p, SYM_ROLES, context->role - 1),
1257 : 0 : sym_name(p, SYM_TYPES, context->type - 1));
1258 : :
1259 : 0 : mls_sid_to_context(p, context, &scontextp);
1260 : :
1261 : 0 : *scontextp = 0;
1262 : :
1263 : 0 : return 0;
1264 : : }
1265 : :
1266 : 0 : static int sidtab_entry_to_string(struct policydb *p,
1267 : : struct sidtab *sidtab,
1268 : : struct sidtab_entry *entry,
1269 : : char **scontext, u32 *scontext_len)
1270 : : {
1271 : 0 : int rc = sidtab_sid2str_get(sidtab, entry, scontext, scontext_len);
1272 : :
1273 [ # # ]: 0 : if (rc != -ENOENT)
1274 : : return rc;
1275 : :
1276 : 0 : rc = context_struct_to_string(p, &entry->context, scontext,
1277 : : scontext_len);
1278 [ # # ]: 0 : if (!rc && scontext)
1279 : 0 : sidtab_sid2str_put(sidtab, entry, *scontext, *scontext_len);
1280 : : return rc;
1281 : : }
1282 : :
1283 : : #include "initial_sid_to_string.h"
1284 : :
1285 : 0 : int security_sidtab_hash_stats(struct selinux_state *state, char *page)
1286 : : {
1287 : 0 : int rc;
1288 : :
1289 [ # # ]: 0 : if (!selinux_initialized(state)) {
1290 : 0 : pr_err("SELinux: %s: called before initial load_policy\n",
1291 : : __func__);
1292 : 0 : return -EINVAL;
1293 : : }
1294 : :
1295 : 0 : read_lock(&state->ss->policy_rwlock);
1296 : 0 : rc = sidtab_hash_stats(state->ss->sidtab, page);
1297 : 0 : read_unlock(&state->ss->policy_rwlock);
1298 : :
1299 : 0 : return rc;
1300 : : }
1301 : :
1302 : 756 : const char *security_get_initial_sid_context(u32 sid)
1303 : : {
1304 [ + - ]: 756 : if (unlikely(sid > SECINITSID_NUM))
1305 : : return NULL;
1306 : 756 : return initial_sid_to_string[sid];
1307 : : }
1308 : :
1309 : 5414 : static int security_sid_to_context_core(struct selinux_state *state,
1310 : : u32 sid, char **scontext,
1311 : : u32 *scontext_len, int force,
1312 : : int only_invalid)
1313 : : {
1314 : 5414 : struct policydb *policydb;
1315 : 5414 : struct sidtab *sidtab;
1316 : 5414 : struct sidtab_entry *entry;
1317 : 5414 : int rc = 0;
1318 : :
1319 [ + - ]: 5414 : if (scontext)
1320 : 5414 : *scontext = NULL;
1321 : 5414 : *scontext_len = 0;
1322 : :
1323 [ + - ]: 5414 : if (!selinux_initialized(state)) {
1324 [ + - ]: 5414 : if (sid <= SECINITSID_NUM) {
1325 : 5414 : char *scontextp;
1326 : :
1327 : 5414 : *scontext_len = strlen(initial_sid_to_string[sid]) + 1;
1328 [ - + ]: 5414 : if (!scontext)
1329 : 0 : goto out;
1330 : 5414 : scontextp = kmemdup(initial_sid_to_string[sid],
1331 : : *scontext_len, GFP_ATOMIC);
1332 [ - + ]: 5414 : if (!scontextp) {
1333 : 0 : rc = -ENOMEM;
1334 : 0 : goto out;
1335 : : }
1336 : 5414 : *scontext = scontextp;
1337 : 5414 : goto out;
1338 : : }
1339 : 0 : pr_err("SELinux: %s: called before initial "
1340 : : "load_policy on unknown SID %d\n", __func__, sid);
1341 : 0 : rc = -EINVAL;
1342 : 0 : goto out;
1343 : : }
1344 : 0 : read_lock(&state->ss->policy_rwlock);
1345 : 0 : policydb = &state->ss->policydb;
1346 : 0 : sidtab = state->ss->sidtab;
1347 : :
1348 [ # # ]: 0 : if (force)
1349 : 0 : entry = sidtab_search_entry_force(sidtab, sid);
1350 : : else
1351 : 0 : entry = sidtab_search_entry(sidtab, sid);
1352 [ # # ]: 0 : if (!entry) {
1353 : 0 : pr_err("SELinux: %s: unrecognized SID %d\n",
1354 : : __func__, sid);
1355 : 0 : rc = -EINVAL;
1356 : 0 : goto out_unlock;
1357 : : }
1358 [ # # # # ]: 0 : if (only_invalid && !entry->context.len)
1359 : 0 : goto out_unlock;
1360 : :
1361 : 0 : rc = sidtab_entry_to_string(policydb, sidtab, entry, scontext,
1362 : : scontext_len);
1363 : :
1364 : 0 : out_unlock:
1365 : 0 : read_unlock(&state->ss->policy_rwlock);
1366 : 5414 : out:
1367 : 5414 : return rc;
1368 : :
1369 : : }
1370 : :
1371 : : /**
1372 : : * security_sid_to_context - Obtain a context for a given SID.
1373 : : * @sid: security identifier, SID
1374 : : * @scontext: security context
1375 : : * @scontext_len: length in bytes
1376 : : *
1377 : : * Write the string representation of the context associated with @sid
1378 : : * into a dynamically allocated string of the correct size. Set @scontext
1379 : : * to point to this string and set @scontext_len to the length of the string.
1380 : : */
1381 : 5414 : int security_sid_to_context(struct selinux_state *state,
1382 : : u32 sid, char **scontext, u32 *scontext_len)
1383 : : {
1384 : 5414 : return security_sid_to_context_core(state, sid, scontext,
1385 : : scontext_len, 0, 0);
1386 : : }
1387 : :
1388 : 0 : int security_sid_to_context_force(struct selinux_state *state, u32 sid,
1389 : : char **scontext, u32 *scontext_len)
1390 : : {
1391 : 0 : return security_sid_to_context_core(state, sid, scontext,
1392 : : scontext_len, 1, 0);
1393 : : }
1394 : :
1395 : : /**
1396 : : * security_sid_to_context_inval - Obtain a context for a given SID if it
1397 : : * is invalid.
1398 : : * @sid: security identifier, SID
1399 : : * @scontext: security context
1400 : : * @scontext_len: length in bytes
1401 : : *
1402 : : * Write the string representation of the context associated with @sid
1403 : : * into a dynamically allocated string of the correct size, but only if the
1404 : : * context is invalid in the current policy. Set @scontext to point to
1405 : : * this string (or NULL if the context is valid) and set @scontext_len to
1406 : : * the length of the string (or 0 if the context is valid).
1407 : : */
1408 : 0 : int security_sid_to_context_inval(struct selinux_state *state, u32 sid,
1409 : : char **scontext, u32 *scontext_len)
1410 : : {
1411 : 0 : return security_sid_to_context_core(state, sid, scontext,
1412 : : scontext_len, 1, 1);
1413 : : }
1414 : :
1415 : : /*
1416 : : * Caveat: Mutates scontext.
1417 : : */
1418 : 0 : static int string_to_context_struct(struct policydb *pol,
1419 : : struct sidtab *sidtabp,
1420 : : char *scontext,
1421 : : struct context *ctx,
1422 : : u32 def_sid)
1423 : : {
1424 : 0 : struct role_datum *role;
1425 : 0 : struct type_datum *typdatum;
1426 : 0 : struct user_datum *usrdatum;
1427 : 0 : char *scontextp, *p, oldc;
1428 : 0 : int rc = 0;
1429 : :
1430 : 0 : context_init(ctx);
1431 : :
1432 : : /* Parse the security context. */
1433 : :
1434 : 0 : rc = -EINVAL;
1435 : 0 : scontextp = (char *) scontext;
1436 : :
1437 : : /* Extract the user. */
1438 : 0 : p = scontextp;
1439 [ # # ]: 0 : while (*p && *p != ':')
1440 : 0 : p++;
1441 : :
1442 [ # # ]: 0 : if (*p == 0)
1443 : 0 : goto out;
1444 : :
1445 : 0 : *p++ = 0;
1446 : :
1447 : 0 : usrdatum = hashtab_search(pol->p_users.table, scontextp);
1448 [ # # ]: 0 : if (!usrdatum)
1449 : 0 : goto out;
1450 : :
1451 : 0 : ctx->user = usrdatum->value;
1452 : :
1453 : : /* Extract role. */
1454 : 0 : scontextp = p;
1455 [ # # ]: 0 : while (*p && *p != ':')
1456 : 0 : p++;
1457 : :
1458 [ # # ]: 0 : if (*p == 0)
1459 : 0 : goto out;
1460 : :
1461 : 0 : *p++ = 0;
1462 : :
1463 : 0 : role = hashtab_search(pol->p_roles.table, scontextp);
1464 [ # # ]: 0 : if (!role)
1465 : 0 : goto out;
1466 : 0 : ctx->role = role->value;
1467 : :
1468 : : /* Extract type. */
1469 : 0 : scontextp = p;
1470 [ # # ]: 0 : while (*p && *p != ':')
1471 : 0 : p++;
1472 : 0 : oldc = *p;
1473 : 0 : *p++ = 0;
1474 : :
1475 : 0 : typdatum = hashtab_search(pol->p_types.table, scontextp);
1476 [ # # # # ]: 0 : if (!typdatum || typdatum->attribute)
1477 : 0 : goto out;
1478 : :
1479 : 0 : ctx->type = typdatum->value;
1480 : :
1481 : 0 : rc = mls_context_to_sid(pol, oldc, p, ctx, sidtabp, def_sid);
1482 [ # # ]: 0 : if (rc)
1483 : 0 : goto out;
1484 : :
1485 : : /* Check the validity of the new context. */
1486 : 0 : rc = -EINVAL;
1487 [ # # ]: 0 : if (!policydb_context_isvalid(pol, ctx))
1488 : 0 : goto out;
1489 : : rc = 0;
1490 : : out:
1491 : 0 : if (rc)
1492 : 0 : context_destroy(ctx);
1493 : 0 : return rc;
1494 : : }
1495 : :
1496 : 0 : int context_add_hash(struct policydb *policydb,
1497 : : struct context *context)
1498 : : {
1499 : 0 : int rc;
1500 : 0 : char *str;
1501 : 0 : int len;
1502 : :
1503 [ # # ]: 0 : if (context->str) {
1504 : 0 : context->hash = context_compute_hash(context->str);
1505 : : } else {
1506 : 0 : rc = context_struct_to_string(policydb, context,
1507 : : &str, &len);
1508 [ # # ]: 0 : if (rc)
1509 : : return rc;
1510 : 0 : context->hash = context_compute_hash(str);
1511 : 0 : kfree(str);
1512 : : }
1513 : : return 0;
1514 : : }
1515 : :
1516 : : static int context_struct_to_sid(struct selinux_state *state,
1517 : : struct context *context, u32 *sid)
1518 : : {
1519 : : int rc;
1520 : : struct sidtab *sidtab = state->ss->sidtab;
1521 : : struct policydb *policydb = &state->ss->policydb;
1522 : :
1523 : : if (!context->hash) {
1524 : : rc = context_add_hash(policydb, context);
1525 : : if (rc)
1526 : : return rc;
1527 : : }
1528 : :
1529 : : return sidtab_context_to_sid(sidtab, context, sid);
1530 : : }
1531 : :
1532 : 0 : static int security_context_to_sid_core(struct selinux_state *state,
1533 : : const char *scontext, u32 scontext_len,
1534 : : u32 *sid, u32 def_sid, gfp_t gfp_flags,
1535 : : int force)
1536 : : {
1537 : 0 : struct policydb *policydb;
1538 : 0 : struct sidtab *sidtab;
1539 : 0 : char *scontext2, *str = NULL;
1540 : 0 : struct context context;
1541 : 0 : int rc = 0;
1542 : :
1543 : : /* An empty security context is never valid. */
1544 [ # # ]: 0 : if (!scontext_len)
1545 : : return -EINVAL;
1546 : :
1547 : : /* Copy the string to allow changes and ensure a NUL terminator */
1548 : 0 : scontext2 = kmemdup_nul(scontext, scontext_len, gfp_flags);
1549 [ # # ]: 0 : if (!scontext2)
1550 : : return -ENOMEM;
1551 : :
1552 [ # # ]: 0 : if (!selinux_initialized(state)) {
1553 : : int i;
1554 : :
1555 [ # # ]: 0 : for (i = 1; i < SECINITSID_NUM; i++) {
1556 [ # # ]: 0 : if (!strcmp(initial_sid_to_string[i], scontext2)) {
1557 : 0 : *sid = i;
1558 : 0 : goto out;
1559 : : }
1560 : : }
1561 : 0 : *sid = SECINITSID_KERNEL;
1562 : 0 : goto out;
1563 : : }
1564 : 0 : *sid = SECSID_NULL;
1565 : :
1566 [ # # ]: 0 : if (force) {
1567 : : /* Save another copy for storing in uninterpreted form */
1568 : 0 : rc = -ENOMEM;
1569 : 0 : str = kstrdup(scontext2, gfp_flags);
1570 [ # # ]: 0 : if (!str)
1571 : 0 : goto out;
1572 : : }
1573 : 0 : read_lock(&state->ss->policy_rwlock);
1574 : 0 : policydb = &state->ss->policydb;
1575 : 0 : sidtab = state->ss->sidtab;
1576 : 0 : rc = string_to_context_struct(policydb, sidtab, scontext2,
1577 : : &context, def_sid);
1578 [ # # ]: 0 : if (rc == -EINVAL && force) {
1579 : 0 : context.str = str;
1580 : 0 : context.len = strlen(str) + 1;
1581 : 0 : str = NULL;
1582 [ # # ]: 0 : } else if (rc)
1583 : 0 : goto out_unlock;
1584 : 0 : rc = context_struct_to_sid(state, &context, sid);
1585 : 0 : context_destroy(&context);
1586 : 0 : out_unlock:
1587 : 0 : read_unlock(&state->ss->policy_rwlock);
1588 : 0 : out:
1589 : 0 : kfree(scontext2);
1590 : 0 : kfree(str);
1591 : 0 : return rc;
1592 : : }
1593 : :
1594 : : /**
1595 : : * security_context_to_sid - Obtain a SID for a given security context.
1596 : : * @scontext: security context
1597 : : * @scontext_len: length in bytes
1598 : : * @sid: security identifier, SID
1599 : : * @gfp: context for the allocation
1600 : : *
1601 : : * Obtains a SID associated with the security context that
1602 : : * has the string representation specified by @scontext.
1603 : : * Returns -%EINVAL if the context is invalid, -%ENOMEM if insufficient
1604 : : * memory is available, or 0 on success.
1605 : : */
1606 : 0 : int security_context_to_sid(struct selinux_state *state,
1607 : : const char *scontext, u32 scontext_len, u32 *sid,
1608 : : gfp_t gfp)
1609 : : {
1610 : 0 : return security_context_to_sid_core(state, scontext, scontext_len,
1611 : : sid, SECSID_NULL, gfp, 0);
1612 : : }
1613 : :
1614 : 0 : int security_context_str_to_sid(struct selinux_state *state,
1615 : : const char *scontext, u32 *sid, gfp_t gfp)
1616 : : {
1617 : 0 : return security_context_to_sid(state, scontext, strlen(scontext),
1618 : : sid, gfp);
1619 : : }
1620 : :
1621 : : /**
1622 : : * security_context_to_sid_default - Obtain a SID for a given security context,
1623 : : * falling back to specified default if needed.
1624 : : *
1625 : : * @scontext: security context
1626 : : * @scontext_len: length in bytes
1627 : : * @sid: security identifier, SID
1628 : : * @def_sid: default SID to assign on error
1629 : : *
1630 : : * Obtains a SID associated with the security context that
1631 : : * has the string representation specified by @scontext.
1632 : : * The default SID is passed to the MLS layer to be used to allow
1633 : : * kernel labeling of the MLS field if the MLS field is not present
1634 : : * (for upgrading to MLS without full relabel).
1635 : : * Implicitly forces adding of the context even if it cannot be mapped yet.
1636 : : * Returns -%EINVAL if the context is invalid, -%ENOMEM if insufficient
1637 : : * memory is available, or 0 on success.
1638 : : */
1639 : 0 : int security_context_to_sid_default(struct selinux_state *state,
1640 : : const char *scontext, u32 scontext_len,
1641 : : u32 *sid, u32 def_sid, gfp_t gfp_flags)
1642 : : {
1643 : 0 : return security_context_to_sid_core(state, scontext, scontext_len,
1644 : : sid, def_sid, gfp_flags, 1);
1645 : : }
1646 : :
1647 : 0 : int security_context_to_sid_force(struct selinux_state *state,
1648 : : const char *scontext, u32 scontext_len,
1649 : : u32 *sid)
1650 : : {
1651 : 0 : return security_context_to_sid_core(state, scontext, scontext_len,
1652 : : sid, SECSID_NULL, GFP_KERNEL, 1);
1653 : : }
1654 : :
1655 : 0 : static int compute_sid_handle_invalid_context(
1656 : : struct selinux_state *state,
1657 : : struct sidtab_entry *sentry,
1658 : : struct sidtab_entry *tentry,
1659 : : u16 tclass,
1660 : : struct context *newcontext)
1661 : : {
1662 : 0 : struct policydb *policydb = &state->ss->policydb;
1663 : 0 : struct sidtab *sidtab = state->ss->sidtab;
1664 : 0 : char *s = NULL, *t = NULL, *n = NULL;
1665 : 0 : u32 slen, tlen, nlen;
1666 : 0 : struct audit_buffer *ab;
1667 : :
1668 [ # # ]: 0 : if (sidtab_entry_to_string(policydb, sidtab, sentry, &s, &slen))
1669 : 0 : goto out;
1670 [ # # ]: 0 : if (sidtab_entry_to_string(policydb, sidtab, tentry, &t, &tlen))
1671 : 0 : goto out;
1672 [ # # ]: 0 : if (context_struct_to_string(policydb, newcontext, &n, &nlen))
1673 : 0 : goto out;
1674 : 0 : ab = audit_log_start(audit_context(), GFP_ATOMIC, AUDIT_SELINUX_ERR);
1675 : 0 : audit_log_format(ab,
1676 : : "op=security_compute_sid invalid_context=");
1677 : : /* no need to record the NUL with untrusted strings */
1678 : 0 : audit_log_n_untrustedstring(ab, n, nlen - 1);
1679 : 0 : audit_log_format(ab, " scontext=%s tcontext=%s tclass=%s",
1680 : 0 : s, t, sym_name(policydb, SYM_CLASSES, tclass-1));
1681 : 0 : audit_log_end(ab);
1682 : 0 : out:
1683 : 0 : kfree(s);
1684 : 0 : kfree(t);
1685 : 0 : kfree(n);
1686 [ # # ]: 0 : if (!enforcing_enabled(state))
1687 : 0 : return 0;
1688 : : return -EACCES;
1689 : : }
1690 : :
1691 : 0 : static void filename_compute_type(struct policydb *policydb,
1692 : : struct context *newcontext,
1693 : : u32 stype, u32 ttype, u16 tclass,
1694 : : const char *objname)
1695 : : {
1696 : 0 : struct filename_trans ft;
1697 : 0 : struct filename_trans_datum *otype;
1698 : :
1699 : : /*
1700 : : * Most filename trans rules are going to live in specific directories
1701 : : * like /dev or /var/run. This bitmap will quickly skip rule searches
1702 : : * if the ttype does not contain any rules.
1703 : : */
1704 [ # # ]: 0 : if (!ebitmap_get_bit(&policydb->filename_trans_ttypes, ttype))
1705 : 0 : return;
1706 : :
1707 : 0 : ft.stype = stype;
1708 : 0 : ft.ttype = ttype;
1709 : 0 : ft.tclass = tclass;
1710 : 0 : ft.name = objname;
1711 : :
1712 : 0 : otype = hashtab_search(policydb->filename_trans, &ft);
1713 [ # # ]: 0 : if (otype)
1714 : 0 : newcontext->type = otype->otype;
1715 : : }
1716 : :
1717 : 151672 : static int security_compute_sid(struct selinux_state *state,
1718 : : u32 ssid,
1719 : : u32 tsid,
1720 : : u16 orig_tclass,
1721 : : u32 specified,
1722 : : const char *objname,
1723 : : u32 *out_sid,
1724 : : bool kern)
1725 : : {
1726 : 151672 : struct policydb *policydb;
1727 : 151672 : struct sidtab *sidtab;
1728 : 151672 : struct class_datum *cladatum = NULL;
1729 : 151672 : struct context *scontext, *tcontext, newcontext;
1730 : 151672 : struct sidtab_entry *sentry, *tentry;
1731 : 151672 : struct role_trans *roletr = NULL;
1732 : 151672 : struct avtab_key avkey;
1733 : 151672 : struct avtab_datum *avdatum;
1734 : 151672 : struct avtab_node *node;
1735 : 151672 : u16 tclass;
1736 : 151672 : int rc = 0;
1737 : 151672 : bool sock;
1738 : :
1739 [ + - ]: 151672 : if (!selinux_initialized(state)) {
1740 [ + + ]: 151672 : switch (orig_tclass) {
1741 : 42868 : case SECCLASS_PROCESS: /* kernel value */
1742 : 42868 : *out_sid = ssid;
1743 : 42868 : break;
1744 : 108804 : default:
1745 : 108804 : *out_sid = tsid;
1746 : 108804 : break;
1747 : : }
1748 : 151672 : goto out;
1749 : : }
1750 : :
1751 : 0 : context_init(&newcontext);
1752 : :
1753 : 0 : read_lock(&state->ss->policy_rwlock);
1754 : :
1755 [ # # ]: 0 : if (kern) {
1756 [ # # ]: 0 : tclass = unmap_class(&state->ss->map, orig_tclass);
1757 : 0 : sock = security_is_socket_class(orig_tclass);
1758 : : } else {
1759 : 0 : tclass = orig_tclass;
1760 : 0 : sock = security_is_socket_class(map_class(&state->ss->map,
1761 : : tclass));
1762 : : }
1763 : :
1764 : 0 : policydb = &state->ss->policydb;
1765 : 0 : sidtab = state->ss->sidtab;
1766 : :
1767 : 0 : sentry = sidtab_search_entry(sidtab, ssid);
1768 [ # # ]: 0 : if (!sentry) {
1769 : 0 : pr_err("SELinux: %s: unrecognized SID %d\n",
1770 : : __func__, ssid);
1771 : 0 : rc = -EINVAL;
1772 : 0 : goto out_unlock;
1773 : : }
1774 : 0 : tentry = sidtab_search_entry(sidtab, tsid);
1775 [ # # ]: 0 : if (!tentry) {
1776 : 0 : pr_err("SELinux: %s: unrecognized SID %d\n",
1777 : : __func__, tsid);
1778 : 0 : rc = -EINVAL;
1779 : 0 : goto out_unlock;
1780 : : }
1781 : :
1782 : 0 : scontext = &sentry->context;
1783 : 0 : tcontext = &tentry->context;
1784 : :
1785 [ # # # # ]: 0 : if (tclass && tclass <= policydb->p_classes.nprim)
1786 : 0 : cladatum = policydb->class_val_to_struct[tclass - 1];
1787 : :
1788 : : /* Set the user identity. */
1789 [ # # # ]: 0 : switch (specified) {
1790 : 0 : case AVTAB_TRANSITION:
1791 : : case AVTAB_CHANGE:
1792 [ # # # # ]: 0 : if (cladatum && cladatum->default_user == DEFAULT_TARGET) {
1793 : 0 : newcontext.user = tcontext->user;
1794 : : } else {
1795 : : /* notice this gets both DEFAULT_SOURCE and unset */
1796 : : /* Use the process user identity. */
1797 : 0 : newcontext.user = scontext->user;
1798 : : }
1799 : : break;
1800 : 0 : case AVTAB_MEMBER:
1801 : : /* Use the related object owner. */
1802 : 0 : newcontext.user = tcontext->user;
1803 : 0 : break;
1804 : : }
1805 : :
1806 : : /* Set the role to default values. */
1807 [ # # # # ]: 0 : if (cladatum && cladatum->default_role == DEFAULT_SOURCE) {
1808 : 0 : newcontext.role = scontext->role;
1809 [ # # # # ]: 0 : } else if (cladatum && cladatum->default_role == DEFAULT_TARGET) {
1810 : 0 : newcontext.role = tcontext->role;
1811 : : } else {
1812 [ # # # # ]: 0 : if ((tclass == policydb->process_class) || (sock == true))
1813 : 0 : newcontext.role = scontext->role;
1814 : : else
1815 : 0 : newcontext.role = OBJECT_R_VAL;
1816 : : }
1817 : :
1818 : : /* Set the type to default values. */
1819 [ # # # # ]: 0 : if (cladatum && cladatum->default_type == DEFAULT_SOURCE) {
1820 : 0 : newcontext.type = scontext->type;
1821 [ # # # # ]: 0 : } else if (cladatum && cladatum->default_type == DEFAULT_TARGET) {
1822 : 0 : newcontext.type = tcontext->type;
1823 : : } else {
1824 [ # # # # ]: 0 : if ((tclass == policydb->process_class) || (sock == true)) {
1825 : : /* Use the type of process. */
1826 : 0 : newcontext.type = scontext->type;
1827 : : } else {
1828 : : /* Use the type of the related object. */
1829 : 0 : newcontext.type = tcontext->type;
1830 : : }
1831 : : }
1832 : :
1833 : : /* Look for a type transition/member/change rule. */
1834 : 0 : avkey.source_type = scontext->type;
1835 : 0 : avkey.target_type = tcontext->type;
1836 : 0 : avkey.target_class = tclass;
1837 : 0 : avkey.specified = specified;
1838 : 0 : avdatum = avtab_search(&policydb->te_avtab, &avkey);
1839 : :
1840 : : /* If no permanent rule, also check for enabled conditional rules */
1841 [ # # ]: 0 : if (!avdatum) {
1842 : 0 : node = avtab_search_node(&policydb->te_cond_avtab, &avkey);
1843 [ # # ]: 0 : for (; node; node = avtab_search_node_next(node, specified)) {
1844 [ # # ]: 0 : if (node->key.specified & AVTAB_ENABLED) {
1845 : 0 : avdatum = &node->datum;
1846 : 0 : break;
1847 : : }
1848 : : }
1849 : : }
1850 : :
1851 [ # # ]: 0 : if (avdatum) {
1852 : : /* Use the type from the type transition/member/change rule. */
1853 : 0 : newcontext.type = avdatum->u.data;
1854 : : }
1855 : :
1856 : : /* if we have a objname this is a file trans check so check those rules */
1857 [ # # ]: 0 : if (objname)
1858 : 0 : filename_compute_type(policydb, &newcontext, scontext->type,
1859 : : tcontext->type, tclass, objname);
1860 : :
1861 : : /* Check for class-specific changes. */
1862 [ # # ]: 0 : if (specified & AVTAB_TRANSITION) {
1863 : : /* Look for a role transition rule. */
1864 [ # # ]: 0 : for (roletr = policydb->role_tr; roletr;
1865 : 0 : roletr = roletr->next) {
1866 [ # # ]: 0 : if ((roletr->role == scontext->role) &&
1867 [ # # ]: 0 : (roletr->type == tcontext->type) &&
1868 [ # # ]: 0 : (roletr->tclass == tclass)) {
1869 : : /* Use the role transition rule. */
1870 : 0 : newcontext.role = roletr->new_role;
1871 : 0 : break;
1872 : : }
1873 : : }
1874 : : }
1875 : :
1876 : : /* Set the MLS attributes.
1877 : : This is done last because it may allocate memory. */
1878 : 0 : rc = mls_compute_sid(policydb, scontext, tcontext, tclass, specified,
1879 : : &newcontext, sock);
1880 [ # # ]: 0 : if (rc)
1881 : 0 : goto out_unlock;
1882 : :
1883 : : /* Check the validity of the context. */
1884 [ # # ]: 0 : if (!policydb_context_isvalid(policydb, &newcontext)) {
1885 : 0 : rc = compute_sid_handle_invalid_context(state, sentry, tentry,
1886 : : tclass, &newcontext);
1887 [ # # ]: 0 : if (rc)
1888 : 0 : goto out_unlock;
1889 : : }
1890 : : /* Obtain the sid for the context. */
1891 : 0 : rc = context_struct_to_sid(state, &newcontext, out_sid);
1892 : 0 : out_unlock:
1893 : 0 : read_unlock(&state->ss->policy_rwlock);
1894 : 0 : context_destroy(&newcontext);
1895 : 151672 : out:
1896 : 151672 : return rc;
1897 : : }
1898 : :
1899 : : /**
1900 : : * security_transition_sid - Compute the SID for a new subject/object.
1901 : : * @ssid: source security identifier
1902 : : * @tsid: target security identifier
1903 : : * @tclass: target security class
1904 : : * @out_sid: security identifier for new subject/object
1905 : : *
1906 : : * Compute a SID to use for labeling a new subject or object in the
1907 : : * class @tclass based on a SID pair (@ssid, @tsid).
1908 : : * Return -%EINVAL if any of the parameters are invalid, -%ENOMEM
1909 : : * if insufficient memory is available, or %0 if the new SID was
1910 : : * computed successfully.
1911 : : */
1912 : 151672 : int security_transition_sid(struct selinux_state *state,
1913 : : u32 ssid, u32 tsid, u16 tclass,
1914 : : const struct qstr *qstr, u32 *out_sid)
1915 : : {
1916 [ + + ]: 151672 : return security_compute_sid(state, ssid, tsid, tclass,
1917 : : AVTAB_TRANSITION,
1918 : : qstr ? qstr->name : NULL, out_sid, true);
1919 : : }
1920 : :
1921 : 0 : int security_transition_sid_user(struct selinux_state *state,
1922 : : u32 ssid, u32 tsid, u16 tclass,
1923 : : const char *objname, u32 *out_sid)
1924 : : {
1925 : 0 : return security_compute_sid(state, ssid, tsid, tclass,
1926 : : AVTAB_TRANSITION,
1927 : : objname, out_sid, false);
1928 : : }
1929 : :
1930 : : /**
1931 : : * security_member_sid - Compute the SID for member selection.
1932 : : * @ssid: source security identifier
1933 : : * @tsid: target security identifier
1934 : : * @tclass: target security class
1935 : : * @out_sid: security identifier for selected member
1936 : : *
1937 : : * Compute a SID to use when selecting a member of a polyinstantiated
1938 : : * object of class @tclass based on a SID pair (@ssid, @tsid).
1939 : : * Return -%EINVAL if any of the parameters are invalid, -%ENOMEM
1940 : : * if insufficient memory is available, or %0 if the SID was
1941 : : * computed successfully.
1942 : : */
1943 : 0 : int security_member_sid(struct selinux_state *state,
1944 : : u32 ssid,
1945 : : u32 tsid,
1946 : : u16 tclass,
1947 : : u32 *out_sid)
1948 : : {
1949 : 0 : return security_compute_sid(state, ssid, tsid, tclass,
1950 : : AVTAB_MEMBER, NULL,
1951 : : out_sid, false);
1952 : : }
1953 : :
1954 : : /**
1955 : : * security_change_sid - Compute the SID for object relabeling.
1956 : : * @ssid: source security identifier
1957 : : * @tsid: target security identifier
1958 : : * @tclass: target security class
1959 : : * @out_sid: security identifier for selected member
1960 : : *
1961 : : * Compute a SID to use for relabeling an object of class @tclass
1962 : : * based on a SID pair (@ssid, @tsid).
1963 : : * Return -%EINVAL if any of the parameters are invalid, -%ENOMEM
1964 : : * if insufficient memory is available, or %0 if the SID was
1965 : : * computed successfully.
1966 : : */
1967 : 0 : int security_change_sid(struct selinux_state *state,
1968 : : u32 ssid,
1969 : : u32 tsid,
1970 : : u16 tclass,
1971 : : u32 *out_sid)
1972 : : {
1973 : 0 : return security_compute_sid(state,
1974 : : ssid, tsid, tclass, AVTAB_CHANGE, NULL,
1975 : : out_sid, false);
1976 : : }
1977 : :
1978 : 0 : static inline int convert_context_handle_invalid_context(
1979 : : struct selinux_state *state,
1980 : : struct context *context)
1981 : : {
1982 : 0 : struct policydb *policydb = &state->ss->policydb;
1983 : 0 : char *s;
1984 : 0 : u32 len;
1985 : :
1986 [ # # ]: 0 : if (enforcing_enabled(state))
1987 : : return -EINVAL;
1988 : :
1989 [ # # ]: 0 : if (!context_struct_to_string(policydb, context, &s, &len)) {
1990 : 0 : pr_warn("SELinux: Context %s would be invalid if enforcing\n",
1991 : : s);
1992 : 0 : kfree(s);
1993 : : }
1994 : : return 0;
1995 : : }
1996 : :
1997 : : struct convert_context_args {
1998 : : struct selinux_state *state;
1999 : : struct policydb *oldp;
2000 : : struct policydb *newp;
2001 : : };
2002 : :
2003 : : /*
2004 : : * Convert the values in the security context
2005 : : * structure `oldc' from the values specified
2006 : : * in the policy `p->oldp' to the values specified
2007 : : * in the policy `p->newp', storing the new context
2008 : : * in `newc'. Verify that the context is valid
2009 : : * under the new policy.
2010 : : */
2011 : 0 : static int convert_context(struct context *oldc, struct context *newc, void *p)
2012 : : {
2013 : 0 : struct convert_context_args *args;
2014 : 0 : struct ocontext *oc;
2015 : 0 : struct role_datum *role;
2016 : 0 : struct type_datum *typdatum;
2017 : 0 : struct user_datum *usrdatum;
2018 : 0 : char *s;
2019 : 0 : u32 len;
2020 : 0 : int rc;
2021 : :
2022 : 0 : args = p;
2023 : :
2024 [ # # ]: 0 : if (oldc->str) {
2025 : 0 : s = kstrdup(oldc->str, GFP_KERNEL);
2026 [ # # ]: 0 : if (!s)
2027 : : return -ENOMEM;
2028 : :
2029 : 0 : rc = string_to_context_struct(args->newp, NULL, s,
2030 : : newc, SECSID_NULL);
2031 [ # # ]: 0 : if (rc == -EINVAL) {
2032 : : /*
2033 : : * Retain string representation for later mapping.
2034 : : *
2035 : : * IMPORTANT: We need to copy the contents of oldc->str
2036 : : * back into s again because string_to_context_struct()
2037 : : * may have garbled it.
2038 : : */
2039 : 0 : memcpy(s, oldc->str, oldc->len);
2040 : 0 : context_init(newc);
2041 : 0 : newc->str = s;
2042 : 0 : newc->len = oldc->len;
2043 : 0 : newc->hash = oldc->hash;
2044 : 0 : return 0;
2045 : : }
2046 : 0 : kfree(s);
2047 [ # # ]: 0 : if (rc) {
2048 : : /* Other error condition, e.g. ENOMEM. */
2049 : 0 : pr_err("SELinux: Unable to map context %s, rc = %d.\n",
2050 : : oldc->str, -rc);
2051 : 0 : return rc;
2052 : : }
2053 : 0 : pr_info("SELinux: Context %s became valid (mapped).\n",
2054 : : oldc->str);
2055 : 0 : return 0;
2056 : : }
2057 : :
2058 : 0 : context_init(newc);
2059 : :
2060 : : /* Convert the user. */
2061 : 0 : rc = -EINVAL;
2062 : 0 : usrdatum = hashtab_search(args->newp->p_users.table,
2063 : 0 : sym_name(args->oldp,
2064 : 0 : SYM_USERS, oldc->user - 1));
2065 [ # # ]: 0 : if (!usrdatum)
2066 : 0 : goto bad;
2067 : 0 : newc->user = usrdatum->value;
2068 : :
2069 : : /* Convert the role. */
2070 : 0 : rc = -EINVAL;
2071 : 0 : role = hashtab_search(args->newp->p_roles.table,
2072 : 0 : sym_name(args->oldp, SYM_ROLES, oldc->role - 1));
2073 [ # # ]: 0 : if (!role)
2074 : 0 : goto bad;
2075 : 0 : newc->role = role->value;
2076 : :
2077 : : /* Convert the type. */
2078 : 0 : rc = -EINVAL;
2079 : 0 : typdatum = hashtab_search(args->newp->p_types.table,
2080 : 0 : sym_name(args->oldp,
2081 : 0 : SYM_TYPES, oldc->type - 1));
2082 [ # # ]: 0 : if (!typdatum)
2083 : 0 : goto bad;
2084 : 0 : newc->type = typdatum->value;
2085 : :
2086 : : /* Convert the MLS fields if dealing with MLS policies */
2087 [ # # # # ]: 0 : if (args->oldp->mls_enabled && args->newp->mls_enabled) {
2088 : 0 : rc = mls_convert_context(args->oldp, args->newp, oldc, newc);
2089 [ # # ]: 0 : if (rc)
2090 : 0 : goto bad;
2091 [ # # # # ]: 0 : } else if (!args->oldp->mls_enabled && args->newp->mls_enabled) {
2092 : : /*
2093 : : * Switching between non-MLS and MLS policy:
2094 : : * ensure that the MLS fields of the context for all
2095 : : * existing entries in the sidtab are filled in with a
2096 : : * suitable default value, likely taken from one of the
2097 : : * initial SIDs.
2098 : : */
2099 : 0 : oc = args->newp->ocontexts[OCON_ISID];
2100 [ # # # # ]: 0 : while (oc && oc->sid[0] != SECINITSID_UNLABELED)
2101 : 0 : oc = oc->next;
2102 : 0 : rc = -EINVAL;
2103 [ # # ]: 0 : if (!oc) {
2104 : 0 : pr_err("SELinux: unable to look up"
2105 : : " the initial SIDs list\n");
2106 : 0 : goto bad;
2107 : : }
2108 : 0 : rc = mls_range_set(newc, &oc->context[0].range);
2109 [ # # ]: 0 : if (rc)
2110 : 0 : goto bad;
2111 : : }
2112 : :
2113 : : /* Check the validity of the new context. */
2114 [ # # ]: 0 : if (!policydb_context_isvalid(args->newp, newc)) {
2115 : 0 : rc = convert_context_handle_invalid_context(args->state, oldc);
2116 [ # # ]: 0 : if (rc)
2117 : 0 : goto bad;
2118 : : }
2119 : :
2120 : 0 : rc = context_add_hash(args->newp, newc);
2121 [ # # ]: 0 : if (rc)
2122 : 0 : goto bad;
2123 : :
2124 : : return 0;
2125 : 0 : bad:
2126 : : /* Map old representation to string and save it. */
2127 : 0 : rc = context_struct_to_string(args->oldp, oldc, &s, &len);
2128 [ # # ]: 0 : if (rc)
2129 : : return rc;
2130 : 0 : context_destroy(newc);
2131 : 0 : newc->str = s;
2132 : 0 : newc->len = len;
2133 : 0 : newc->hash = context_compute_hash(s);
2134 : 0 : pr_info("SELinux: Context %s became invalid (unmapped).\n",
2135 : : newc->str);
2136 : 0 : return 0;
2137 : : }
2138 : :
2139 : 0 : static void security_load_policycaps(struct selinux_state *state)
2140 : : {
2141 : 0 : struct policydb *p = &state->ss->policydb;
2142 : 0 : unsigned int i;
2143 : 0 : struct ebitmap_node *node;
2144 : :
2145 [ # # ]: 0 : for (i = 0; i < ARRAY_SIZE(state->policycap); i++)
2146 : 0 : state->policycap[i] = ebitmap_get_bit(&p->policycaps, i);
2147 : :
2148 [ # # ]: 0 : for (i = 0; i < ARRAY_SIZE(selinux_policycap_names); i++)
2149 : 0 : pr_info("SELinux: policy capability %s=%d\n",
2150 : : selinux_policycap_names[i],
2151 : : ebitmap_get_bit(&p->policycaps, i));
2152 : :
2153 [ # # ]: 0 : ebitmap_for_each_positive_bit(&p->policycaps, node, i) {
2154 [ # # ]: 0 : if (i >= ARRAY_SIZE(selinux_policycap_names))
2155 : 0 : pr_info("SELinux: unknown policy capability %u\n",
2156 : : i);
2157 : : }
2158 : 0 : }
2159 : :
2160 : : static int security_preserve_bools(struct selinux_state *state,
2161 : : struct policydb *newpolicydb);
2162 : :
2163 : : /**
2164 : : * security_load_policy - Load a security policy configuration.
2165 : : * @data: binary policy data
2166 : : * @len: length of data in bytes
2167 : : *
2168 : : * Load a new set of security policy configuration data,
2169 : : * validate it and convert the SID table as necessary.
2170 : : * This function will flush the access vector cache after
2171 : : * loading the new policy.
2172 : : */
2173 : 0 : int security_load_policy(struct selinux_state *state, void *data, size_t len)
2174 : : {
2175 : 0 : struct policydb *policydb;
2176 : 0 : struct sidtab *oldsidtab, *newsidtab;
2177 : 0 : struct policydb *oldpolicydb, *newpolicydb;
2178 : 0 : struct selinux_mapping *oldmapping;
2179 : 0 : struct selinux_map newmap;
2180 : 0 : struct sidtab_convert_params convert_params;
2181 : 0 : struct convert_context_args args;
2182 : 0 : u32 seqno;
2183 : 0 : int rc = 0;
2184 : 0 : struct policy_file file = { data, len }, *fp = &file;
2185 : :
2186 : 0 : policydb = &state->ss->policydb;
2187 : :
2188 : 0 : newsidtab = kmalloc(sizeof(*newsidtab), GFP_KERNEL);
2189 [ # # ]: 0 : if (!newsidtab)
2190 : : return -ENOMEM;
2191 : :
2192 [ # # ]: 0 : if (!selinux_initialized(state)) {
2193 : 0 : rc = policydb_read(policydb, fp);
2194 [ # # ]: 0 : if (rc) {
2195 : 0 : kfree(newsidtab);
2196 : 0 : return rc;
2197 : : }
2198 : :
2199 : 0 : policydb->len = len;
2200 : 0 : rc = selinux_set_mapping(policydb, secclass_map,
2201 : 0 : &state->ss->map);
2202 [ # # ]: 0 : if (rc) {
2203 : 0 : kfree(newsidtab);
2204 : 0 : policydb_destroy(policydb);
2205 : 0 : return rc;
2206 : : }
2207 : :
2208 : 0 : rc = policydb_load_isids(policydb, newsidtab);
2209 [ # # ]: 0 : if (rc) {
2210 : 0 : kfree(newsidtab);
2211 : 0 : policydb_destroy(policydb);
2212 : 0 : return rc;
2213 : : }
2214 : :
2215 : 0 : state->ss->sidtab = newsidtab;
2216 : 0 : security_load_policycaps(state);
2217 : 0 : selinux_mark_initialized(state);
2218 : 0 : seqno = ++state->ss->latest_granting;
2219 : 0 : selinux_complete_init();
2220 : 0 : avc_ss_reset(state->avc, seqno);
2221 : 0 : selnl_notify_policyload(seqno);
2222 : 0 : selinux_status_update_policyload(state, seqno);
2223 : 0 : selinux_netlbl_cache_invalidate();
2224 : 0 : selinux_xfrm_notify_policyload();
2225 : 0 : return 0;
2226 : : }
2227 : :
2228 : 0 : oldpolicydb = kcalloc(2, sizeof(*oldpolicydb), GFP_KERNEL);
2229 [ # # ]: 0 : if (!oldpolicydb) {
2230 : 0 : kfree(newsidtab);
2231 : 0 : return -ENOMEM;
2232 : : }
2233 : 0 : newpolicydb = oldpolicydb + 1;
2234 : :
2235 : 0 : rc = policydb_read(newpolicydb, fp);
2236 [ # # ]: 0 : if (rc) {
2237 : 0 : kfree(newsidtab);
2238 : 0 : goto out;
2239 : : }
2240 : :
2241 : 0 : newpolicydb->len = len;
2242 : : /* If switching between different policy types, log MLS status */
2243 [ # # # # ]: 0 : if (policydb->mls_enabled && !newpolicydb->mls_enabled)
2244 : 0 : pr_info("SELinux: Disabling MLS support...\n");
2245 [ # # # # ]: 0 : else if (!policydb->mls_enabled && newpolicydb->mls_enabled)
2246 : 0 : pr_info("SELinux: Enabling MLS support...\n");
2247 : :
2248 : 0 : rc = policydb_load_isids(newpolicydb, newsidtab);
2249 [ # # ]: 0 : if (rc) {
2250 : 0 : pr_err("SELinux: unable to load the initial SIDs\n");
2251 : 0 : policydb_destroy(newpolicydb);
2252 : 0 : kfree(newsidtab);
2253 : 0 : goto out;
2254 : : }
2255 : :
2256 : 0 : rc = selinux_set_mapping(newpolicydb, secclass_map, &newmap);
2257 [ # # ]: 0 : if (rc)
2258 : 0 : goto err;
2259 : :
2260 : 0 : rc = security_preserve_bools(state, newpolicydb);
2261 [ # # ]: 0 : if (rc) {
2262 : 0 : pr_err("SELinux: unable to preserve booleans\n");
2263 : 0 : goto err;
2264 : : }
2265 : :
2266 : 0 : oldsidtab = state->ss->sidtab;
2267 : :
2268 : : /*
2269 : : * Convert the internal representations of contexts
2270 : : * in the new SID table.
2271 : : */
2272 : 0 : args.state = state;
2273 : 0 : args.oldp = policydb;
2274 : 0 : args.newp = newpolicydb;
2275 : :
2276 : 0 : convert_params.func = convert_context;
2277 : 0 : convert_params.args = &args;
2278 : 0 : convert_params.target = newsidtab;
2279 : :
2280 : 0 : rc = sidtab_convert(oldsidtab, &convert_params);
2281 [ # # ]: 0 : if (rc) {
2282 : 0 : pr_err("SELinux: unable to convert the internal"
2283 : : " representation of contexts in the new SID"
2284 : : " table\n");
2285 : 0 : goto err;
2286 : : }
2287 : :
2288 : : /* Save the old policydb and SID table to free later. */
2289 : 0 : memcpy(oldpolicydb, policydb, sizeof(*policydb));
2290 : :
2291 : : /* Install the new policydb and SID table. */
2292 : 0 : write_lock_irq(&state->ss->policy_rwlock);
2293 : 0 : memcpy(policydb, newpolicydb, sizeof(*policydb));
2294 : 0 : state->ss->sidtab = newsidtab;
2295 : 0 : security_load_policycaps(state);
2296 : 0 : oldmapping = state->ss->map.mapping;
2297 : 0 : state->ss->map.mapping = newmap.mapping;
2298 : 0 : state->ss->map.size = newmap.size;
2299 : 0 : seqno = ++state->ss->latest_granting;
2300 : 0 : write_unlock_irq(&state->ss->policy_rwlock);
2301 : :
2302 : : /* Free the old policydb and SID table. */
2303 : 0 : policydb_destroy(oldpolicydb);
2304 : 0 : sidtab_destroy(oldsidtab);
2305 : 0 : kfree(oldsidtab);
2306 : 0 : kfree(oldmapping);
2307 : :
2308 : 0 : avc_ss_reset(state->avc, seqno);
2309 : 0 : selnl_notify_policyload(seqno);
2310 : 0 : selinux_status_update_policyload(state, seqno);
2311 : 0 : selinux_netlbl_cache_invalidate();
2312 : 0 : selinux_xfrm_notify_policyload();
2313 : :
2314 : 0 : rc = 0;
2315 : 0 : goto out;
2316 : :
2317 : 0 : err:
2318 : 0 : kfree(newmap.mapping);
2319 : 0 : sidtab_destroy(newsidtab);
2320 : 0 : kfree(newsidtab);
2321 : 0 : policydb_destroy(newpolicydb);
2322 : :
2323 : 0 : out:
2324 : 0 : kfree(oldpolicydb);
2325 : 0 : return rc;
2326 : : }
2327 : :
2328 : 0 : size_t security_policydb_len(struct selinux_state *state)
2329 : : {
2330 : 0 : struct policydb *p = &state->ss->policydb;
2331 : 0 : size_t len;
2332 : :
2333 : 0 : read_lock(&state->ss->policy_rwlock);
2334 : 0 : len = p->len;
2335 : 0 : read_unlock(&state->ss->policy_rwlock);
2336 : :
2337 : 0 : return len;
2338 : : }
2339 : :
2340 : : /**
2341 : : * security_port_sid - Obtain the SID for a port.
2342 : : * @protocol: protocol number
2343 : : * @port: port number
2344 : : * @out_sid: security identifier
2345 : : */
2346 : 28 : int security_port_sid(struct selinux_state *state,
2347 : : u8 protocol, u16 port, u32 *out_sid)
2348 : : {
2349 : 28 : struct policydb *policydb;
2350 : 28 : struct ocontext *c;
2351 : 28 : int rc = 0;
2352 : :
2353 : 28 : read_lock(&state->ss->policy_rwlock);
2354 : :
2355 : 28 : policydb = &state->ss->policydb;
2356 : :
2357 : 28 : c = policydb->ocontexts[OCON_PORT];
2358 [ - + ]: 28 : while (c) {
2359 [ # # ]: 0 : if (c->u.port.protocol == protocol &&
2360 [ # # ]: 0 : c->u.port.low_port <= port &&
2361 [ # # ]: 0 : c->u.port.high_port >= port)
2362 : : break;
2363 : 0 : c = c->next;
2364 : : }
2365 : :
2366 [ - + ]: 28 : if (c) {
2367 [ # # ]: 0 : if (!c->sid[0]) {
2368 : 0 : rc = context_struct_to_sid(state, &c->context[0],
2369 : : &c->sid[0]);
2370 [ # # ]: 0 : if (rc)
2371 : 0 : goto out;
2372 : : }
2373 : 0 : *out_sid = c->sid[0];
2374 : : } else {
2375 : 28 : *out_sid = SECINITSID_PORT;
2376 : : }
2377 : :
2378 : 28 : out:
2379 : 28 : read_unlock(&state->ss->policy_rwlock);
2380 : 28 : return rc;
2381 : : }
2382 : :
2383 : : /**
2384 : : * security_pkey_sid - Obtain the SID for a pkey.
2385 : : * @subnet_prefix: Subnet Prefix
2386 : : * @pkey_num: pkey number
2387 : : * @out_sid: security identifier
2388 : : */
2389 : 0 : int security_ib_pkey_sid(struct selinux_state *state,
2390 : : u64 subnet_prefix, u16 pkey_num, u32 *out_sid)
2391 : : {
2392 : 0 : struct policydb *policydb;
2393 : 0 : struct ocontext *c;
2394 : 0 : int rc = 0;
2395 : :
2396 : 0 : read_lock(&state->ss->policy_rwlock);
2397 : :
2398 : 0 : policydb = &state->ss->policydb;
2399 : :
2400 : 0 : c = policydb->ocontexts[OCON_IBPKEY];
2401 [ # # ]: 0 : while (c) {
2402 [ # # ]: 0 : if (c->u.ibpkey.low_pkey <= pkey_num &&
2403 [ # # ]: 0 : c->u.ibpkey.high_pkey >= pkey_num &&
2404 [ # # ]: 0 : c->u.ibpkey.subnet_prefix == subnet_prefix)
2405 : : break;
2406 : :
2407 : 0 : c = c->next;
2408 : : }
2409 : :
2410 [ # # ]: 0 : if (c) {
2411 [ # # ]: 0 : if (!c->sid[0]) {
2412 : 0 : rc = context_struct_to_sid(state,
2413 : : &c->context[0],
2414 : : &c->sid[0]);
2415 [ # # ]: 0 : if (rc)
2416 : 0 : goto out;
2417 : : }
2418 : 0 : *out_sid = c->sid[0];
2419 : : } else
2420 : 0 : *out_sid = SECINITSID_UNLABELED;
2421 : :
2422 : 0 : out:
2423 : 0 : read_unlock(&state->ss->policy_rwlock);
2424 : 0 : return rc;
2425 : : }
2426 : :
2427 : : /**
2428 : : * security_ib_endport_sid - Obtain the SID for a subnet management interface.
2429 : : * @dev_name: device name
2430 : : * @port: port number
2431 : : * @out_sid: security identifier
2432 : : */
2433 : 0 : int security_ib_endport_sid(struct selinux_state *state,
2434 : : const char *dev_name, u8 port_num, u32 *out_sid)
2435 : : {
2436 : 0 : struct policydb *policydb;
2437 : 0 : struct ocontext *c;
2438 : 0 : int rc = 0;
2439 : :
2440 : 0 : read_lock(&state->ss->policy_rwlock);
2441 : :
2442 : 0 : policydb = &state->ss->policydb;
2443 : :
2444 : 0 : c = policydb->ocontexts[OCON_IBENDPORT];
2445 [ # # ]: 0 : while (c) {
2446 [ # # ]: 0 : if (c->u.ibendport.port == port_num &&
2447 [ # # ]: 0 : !strncmp(c->u.ibendport.dev_name,
2448 : : dev_name,
2449 : : IB_DEVICE_NAME_MAX))
2450 : : break;
2451 : :
2452 : 0 : c = c->next;
2453 : : }
2454 : :
2455 [ # # ]: 0 : if (c) {
2456 [ # # ]: 0 : if (!c->sid[0]) {
2457 : 0 : rc = context_struct_to_sid(state, &c->context[0],
2458 : : &c->sid[0]);
2459 [ # # ]: 0 : if (rc)
2460 : 0 : goto out;
2461 : : }
2462 : 0 : *out_sid = c->sid[0];
2463 : : } else
2464 : 0 : *out_sid = SECINITSID_UNLABELED;
2465 : :
2466 : 0 : out:
2467 : 0 : read_unlock(&state->ss->policy_rwlock);
2468 : 0 : return rc;
2469 : : }
2470 : :
2471 : : /**
2472 : : * security_netif_sid - Obtain the SID for a network interface.
2473 : : * @name: interface name
2474 : : * @if_sid: interface SID
2475 : : */
2476 : 0 : int security_netif_sid(struct selinux_state *state,
2477 : : char *name, u32 *if_sid)
2478 : : {
2479 : 0 : struct policydb *policydb;
2480 : 0 : int rc = 0;
2481 : 0 : struct ocontext *c;
2482 : :
2483 : 0 : read_lock(&state->ss->policy_rwlock);
2484 : :
2485 : 0 : policydb = &state->ss->policydb;
2486 : :
2487 : 0 : c = policydb->ocontexts[OCON_NETIF];
2488 [ # # ]: 0 : while (c) {
2489 [ # # ]: 0 : if (strcmp(name, c->u.name) == 0)
2490 : : break;
2491 : 0 : c = c->next;
2492 : : }
2493 : :
2494 [ # # ]: 0 : if (c) {
2495 [ # # # # ]: 0 : if (!c->sid[0] || !c->sid[1]) {
2496 : 0 : rc = context_struct_to_sid(state, &c->context[0],
2497 : : &c->sid[0]);
2498 [ # # ]: 0 : if (rc)
2499 : 0 : goto out;
2500 : 0 : rc = context_struct_to_sid(state, &c->context[1],
2501 : : &c->sid[1]);
2502 [ # # ]: 0 : if (rc)
2503 : 0 : goto out;
2504 : : }
2505 : 0 : *if_sid = c->sid[0];
2506 : : } else
2507 : 0 : *if_sid = SECINITSID_NETIF;
2508 : :
2509 : 0 : out:
2510 : 0 : read_unlock(&state->ss->policy_rwlock);
2511 : 0 : return rc;
2512 : : }
2513 : :
2514 : 0 : static int match_ipv6_addrmask(u32 *input, u32 *addr, u32 *mask)
2515 : : {
2516 : 0 : int i, fail = 0;
2517 : :
2518 [ # # ]: 0 : for (i = 0; i < 4; i++)
2519 [ # # ]: 0 : if (addr[i] != (input[i] & mask[i])) {
2520 : : fail = 1;
2521 : : break;
2522 : : }
2523 : :
2524 : 0 : return !fail;
2525 : : }
2526 : :
2527 : : /**
2528 : : * security_node_sid - Obtain the SID for a node (host).
2529 : : * @domain: communication domain aka address family
2530 : : * @addrp: address
2531 : : * @addrlen: address length in bytes
2532 : : * @out_sid: security identifier
2533 : : */
2534 : 56 : int security_node_sid(struct selinux_state *state,
2535 : : u16 domain,
2536 : : void *addrp,
2537 : : u32 addrlen,
2538 : : u32 *out_sid)
2539 : : {
2540 : 56 : struct policydb *policydb;
2541 : 56 : int rc;
2542 : 56 : struct ocontext *c;
2543 : :
2544 : 56 : read_lock(&state->ss->policy_rwlock);
2545 : :
2546 : 56 : policydb = &state->ss->policydb;
2547 : :
2548 [ + + - ]: 56 : switch (domain) {
2549 : 28 : case AF_INET: {
2550 : 28 : u32 addr;
2551 : :
2552 : 28 : rc = -EINVAL;
2553 [ - + ]: 28 : if (addrlen != sizeof(u32))
2554 : 0 : goto out;
2555 : :
2556 : 28 : addr = *((u32 *)addrp);
2557 : :
2558 : 28 : c = policydb->ocontexts[OCON_NODE];
2559 [ - + ]: 28 : while (c) {
2560 [ # # ]: 0 : if (c->u.node.addr == (addr & c->u.node.mask))
2561 : : break;
2562 : 0 : c = c->next;
2563 : : }
2564 : : break;
2565 : : }
2566 : :
2567 : 28 : case AF_INET6:
2568 : 28 : rc = -EINVAL;
2569 [ - + ]: 28 : if (addrlen != sizeof(u64) * 2)
2570 : 0 : goto out;
2571 : 28 : c = policydb->ocontexts[OCON_NODE6];
2572 [ - + ]: 28 : while (c) {
2573 [ # # ]: 0 : if (match_ipv6_addrmask(addrp, c->u.node6.addr,
2574 : 0 : c->u.node6.mask))
2575 : : break;
2576 : 0 : c = c->next;
2577 : : }
2578 : : break;
2579 : :
2580 : 0 : default:
2581 : 0 : rc = 0;
2582 : 0 : *out_sid = SECINITSID_NODE;
2583 : 0 : goto out;
2584 : : }
2585 : :
2586 [ - + ]: 56 : if (c) {
2587 [ # # ]: 0 : if (!c->sid[0]) {
2588 : 0 : rc = context_struct_to_sid(state,
2589 : : &c->context[0],
2590 : : &c->sid[0]);
2591 [ # # ]: 0 : if (rc)
2592 : 0 : goto out;
2593 : : }
2594 : 0 : *out_sid = c->sid[0];
2595 : : } else {
2596 : 56 : *out_sid = SECINITSID_NODE;
2597 : : }
2598 : :
2599 : : rc = 0;
2600 : 56 : out:
2601 : 56 : read_unlock(&state->ss->policy_rwlock);
2602 : 56 : return rc;
2603 : : }
2604 : :
2605 : : #define SIDS_NEL 25
2606 : :
2607 : : /**
2608 : : * security_get_user_sids - Obtain reachable SIDs for a user.
2609 : : * @fromsid: starting SID
2610 : : * @username: username
2611 : : * @sids: array of reachable SIDs for user
2612 : : * @nel: number of elements in @sids
2613 : : *
2614 : : * Generate the set of SIDs for legal security contexts
2615 : : * for a given user that can be reached by @fromsid.
2616 : : * Set *@sids to point to a dynamically allocated
2617 : : * array containing the set of SIDs. Set *@nel to the
2618 : : * number of elements in the array.
2619 : : */
2620 : :
2621 : 0 : int security_get_user_sids(struct selinux_state *state,
2622 : : u32 fromsid,
2623 : : char *username,
2624 : : u32 **sids,
2625 : : u32 *nel)
2626 : : {
2627 : 0 : struct policydb *policydb;
2628 : 0 : struct sidtab *sidtab;
2629 : 0 : struct context *fromcon, usercon;
2630 : 0 : u32 *mysids = NULL, *mysids2, sid;
2631 : 0 : u32 mynel = 0, maxnel = SIDS_NEL;
2632 : 0 : struct user_datum *user;
2633 : 0 : struct role_datum *role;
2634 : 0 : struct ebitmap_node *rnode, *tnode;
2635 : 0 : int rc = 0, i, j;
2636 : :
2637 : 0 : *sids = NULL;
2638 : 0 : *nel = 0;
2639 : :
2640 [ # # ]: 0 : if (!selinux_initialized(state))
2641 : 0 : goto out;
2642 : :
2643 : 0 : read_lock(&state->ss->policy_rwlock);
2644 : :
2645 : 0 : policydb = &state->ss->policydb;
2646 : 0 : sidtab = state->ss->sidtab;
2647 : :
2648 : 0 : context_init(&usercon);
2649 : :
2650 : 0 : rc = -EINVAL;
2651 : 0 : fromcon = sidtab_search(sidtab, fromsid);
2652 [ # # ]: 0 : if (!fromcon)
2653 : 0 : goto out_unlock;
2654 : :
2655 : 0 : rc = -EINVAL;
2656 : 0 : user = hashtab_search(policydb->p_users.table, username);
2657 [ # # ]: 0 : if (!user)
2658 : 0 : goto out_unlock;
2659 : :
2660 : 0 : usercon.user = user->value;
2661 : :
2662 : 0 : rc = -ENOMEM;
2663 : 0 : mysids = kcalloc(maxnel, sizeof(*mysids), GFP_ATOMIC);
2664 [ # # ]: 0 : if (!mysids)
2665 : 0 : goto out_unlock;
2666 : :
2667 [ # # ]: 0 : ebitmap_for_each_positive_bit(&user->roles, rnode, i) {
2668 : 0 : role = policydb->role_val_to_struct[i];
2669 : 0 : usercon.role = i + 1;
2670 [ # # ]: 0 : ebitmap_for_each_positive_bit(&role->types, tnode, j) {
2671 : 0 : usercon.type = j + 1;
2672 : : /*
2673 : : * The same context struct is reused here so the hash
2674 : : * must be reset.
2675 : : */
2676 : 0 : usercon.hash = 0;
2677 : :
2678 [ # # ]: 0 : if (mls_setup_user_range(policydb, fromcon, user,
2679 : : &usercon))
2680 : 0 : continue;
2681 : :
2682 : 0 : rc = context_struct_to_sid(state, &usercon, &sid);
2683 [ # # ]: 0 : if (rc)
2684 : 0 : goto out_unlock;
2685 [ # # ]: 0 : if (mynel < maxnel) {
2686 : 0 : mysids[mynel++] = sid;
2687 : : } else {
2688 : 0 : rc = -ENOMEM;
2689 : 0 : maxnel += SIDS_NEL;
2690 : 0 : mysids2 = kcalloc(maxnel, sizeof(*mysids2), GFP_ATOMIC);
2691 [ # # ]: 0 : if (!mysids2)
2692 : 0 : goto out_unlock;
2693 : 0 : memcpy(mysids2, mysids, mynel * sizeof(*mysids2));
2694 : 0 : kfree(mysids);
2695 : 0 : mysids = mysids2;
2696 : 0 : mysids[mynel++] = sid;
2697 : : }
2698 : : }
2699 : : }
2700 : : rc = 0;
2701 : 0 : out_unlock:
2702 : 0 : read_unlock(&state->ss->policy_rwlock);
2703 [ # # ]: 0 : if (rc || !mynel) {
2704 : 0 : kfree(mysids);
2705 : 0 : goto out;
2706 : : }
2707 : :
2708 : 0 : rc = -ENOMEM;
2709 : 0 : mysids2 = kcalloc(mynel, sizeof(*mysids2), GFP_KERNEL);
2710 [ # # ]: 0 : if (!mysids2) {
2711 : 0 : kfree(mysids);
2712 : 0 : goto out;
2713 : : }
2714 [ # # ]: 0 : for (i = 0, j = 0; i < mynel; i++) {
2715 : 0 : struct av_decision dummy_avd;
2716 : 0 : rc = avc_has_perm_noaudit(state,
2717 : 0 : fromsid, mysids[i],
2718 : : SECCLASS_PROCESS, /* kernel value */
2719 : : PROCESS__TRANSITION, AVC_STRICT,
2720 : : &dummy_avd);
2721 [ # # ]: 0 : if (!rc)
2722 : 0 : mysids2[j++] = mysids[i];
2723 : 0 : cond_resched();
2724 : : }
2725 : 0 : rc = 0;
2726 : 0 : kfree(mysids);
2727 : 0 : *sids = mysids2;
2728 : 0 : *nel = j;
2729 : 0 : out:
2730 : 0 : return rc;
2731 : : }
2732 : :
2733 : : /**
2734 : : * __security_genfs_sid - Helper to obtain a SID for a file in a filesystem
2735 : : * @fstype: filesystem type
2736 : : * @path: path from root of mount
2737 : : * @sclass: file security class
2738 : : * @sid: SID for path
2739 : : *
2740 : : * Obtain a SID to use for a file in a filesystem that
2741 : : * cannot support xattr or use a fixed labeling behavior like
2742 : : * transition SIDs or task SIDs.
2743 : : *
2744 : : * The caller must acquire the policy_rwlock before calling this function.
2745 : : */
2746 : 0 : static inline int __security_genfs_sid(struct selinux_state *state,
2747 : : const char *fstype,
2748 : : char *path,
2749 : : u16 orig_sclass,
2750 : : u32 *sid)
2751 : : {
2752 : 0 : struct policydb *policydb = &state->ss->policydb;
2753 : 0 : int len;
2754 : 0 : u16 sclass;
2755 : 0 : struct genfs *genfs;
2756 : 0 : struct ocontext *c;
2757 : 0 : int rc, cmp = 0;
2758 : :
2759 [ # # # # ]: 0 : while (path[0] == '/' && path[1] == '/')
2760 : 0 : path++;
2761 : :
2762 [ # # ]: 0 : sclass = unmap_class(&state->ss->map, orig_sclass);
2763 : 0 : *sid = SECINITSID_UNLABELED;
2764 : :
2765 [ # # ]: 0 : for (genfs = policydb->genfs; genfs; genfs = genfs->next) {
2766 : 0 : cmp = strcmp(fstype, genfs->fstype);
2767 [ # # ]: 0 : if (cmp <= 0)
2768 : : break;
2769 : : }
2770 : :
2771 : 0 : rc = -ENOENT;
2772 [ # # ]: 0 : if (!genfs || cmp)
2773 : 0 : goto out;
2774 : :
2775 [ # # ]: 0 : for (c = genfs->head; c; c = c->next) {
2776 : 0 : len = strlen(c->u.name);
2777 [ # # # # ]: 0 : if ((!c->v.sclass || sclass == c->v.sclass) &&
2778 [ # # ]: 0 : (strncmp(c->u.name, path, len) == 0))
2779 : : break;
2780 : : }
2781 : :
2782 : 0 : rc = -ENOENT;
2783 [ # # ]: 0 : if (!c)
2784 : 0 : goto out;
2785 : :
2786 [ # # ]: 0 : if (!c->sid[0]) {
2787 : 0 : rc = context_struct_to_sid(state, &c->context[0], &c->sid[0]);
2788 [ # # ]: 0 : if (rc)
2789 : 0 : goto out;
2790 : : }
2791 : :
2792 : 0 : *sid = c->sid[0];
2793 : 0 : rc = 0;
2794 : 0 : out:
2795 : 0 : return rc;
2796 : : }
2797 : :
2798 : : /**
2799 : : * security_genfs_sid - Obtain a SID for a file in a filesystem
2800 : : * @fstype: filesystem type
2801 : : * @path: path from root of mount
2802 : : * @sclass: file security class
2803 : : * @sid: SID for path
2804 : : *
2805 : : * Acquire policy_rwlock before calling __security_genfs_sid() and release
2806 : : * it afterward.
2807 : : */
2808 : 0 : int security_genfs_sid(struct selinux_state *state,
2809 : : const char *fstype,
2810 : : char *path,
2811 : : u16 orig_sclass,
2812 : : u32 *sid)
2813 : : {
2814 : 0 : int retval;
2815 : :
2816 : 0 : read_lock(&state->ss->policy_rwlock);
2817 : 0 : retval = __security_genfs_sid(state, fstype, path, orig_sclass, sid);
2818 : 0 : read_unlock(&state->ss->policy_rwlock);
2819 : 0 : return retval;
2820 : : }
2821 : :
2822 : : /**
2823 : : * security_fs_use - Determine how to handle labeling for a filesystem.
2824 : : * @sb: superblock in question
2825 : : */
2826 : 0 : int security_fs_use(struct selinux_state *state, struct super_block *sb)
2827 : : {
2828 : 0 : struct policydb *policydb;
2829 : 0 : int rc = 0;
2830 : 0 : struct ocontext *c;
2831 : 0 : struct superblock_security_struct *sbsec = sb->s_security;
2832 : 0 : const char *fstype = sb->s_type->name;
2833 : :
2834 : 0 : read_lock(&state->ss->policy_rwlock);
2835 : :
2836 : 0 : policydb = &state->ss->policydb;
2837 : :
2838 : 0 : c = policydb->ocontexts[OCON_FSUSE];
2839 [ # # ]: 0 : while (c) {
2840 [ # # ]: 0 : if (strcmp(fstype, c->u.name) == 0)
2841 : : break;
2842 : 0 : c = c->next;
2843 : : }
2844 : :
2845 [ # # ]: 0 : if (c) {
2846 : 0 : sbsec->behavior = c->v.behavior;
2847 [ # # ]: 0 : if (!c->sid[0]) {
2848 : 0 : rc = context_struct_to_sid(state, &c->context[0],
2849 : : &c->sid[0]);
2850 [ # # ]: 0 : if (rc)
2851 : 0 : goto out;
2852 : : }
2853 : 0 : sbsec->sid = c->sid[0];
2854 : : } else {
2855 : 0 : rc = __security_genfs_sid(state, fstype, "/", SECCLASS_DIR,
2856 : : &sbsec->sid);
2857 [ # # ]: 0 : if (rc) {
2858 : 0 : sbsec->behavior = SECURITY_FS_USE_NONE;
2859 : 0 : rc = 0;
2860 : : } else {
2861 : 0 : sbsec->behavior = SECURITY_FS_USE_GENFS;
2862 : : }
2863 : : }
2864 : :
2865 : 0 : out:
2866 : 0 : read_unlock(&state->ss->policy_rwlock);
2867 : 0 : return rc;
2868 : : }
2869 : :
2870 : 28 : int security_get_bools(struct selinux_state *state,
2871 : : int *len, char ***names, int **values)
2872 : : {
2873 : 28 : struct policydb *policydb;
2874 : 28 : int i, rc;
2875 : :
2876 [ + - ]: 28 : if (!selinux_initialized(state)) {
2877 : 28 : *len = 0;
2878 : 28 : *names = NULL;
2879 : 28 : *values = NULL;
2880 : 28 : return 0;
2881 : : }
2882 : :
2883 : 0 : read_lock(&state->ss->policy_rwlock);
2884 : :
2885 : 0 : policydb = &state->ss->policydb;
2886 : :
2887 : 0 : *names = NULL;
2888 : 0 : *values = NULL;
2889 : :
2890 : 0 : rc = 0;
2891 : 0 : *len = policydb->p_bools.nprim;
2892 [ # # ]: 0 : if (!*len)
2893 : 0 : goto out;
2894 : :
2895 : 0 : rc = -ENOMEM;
2896 : 0 : *names = kcalloc(*len, sizeof(char *), GFP_ATOMIC);
2897 [ # # ]: 0 : if (!*names)
2898 : 0 : goto err;
2899 : :
2900 : 0 : rc = -ENOMEM;
2901 : 0 : *values = kcalloc(*len, sizeof(int), GFP_ATOMIC);
2902 [ # # ]: 0 : if (!*values)
2903 : 0 : goto err;
2904 : :
2905 [ # # ]: 0 : for (i = 0; i < *len; i++) {
2906 : 0 : (*values)[i] = policydb->bool_val_to_struct[i]->state;
2907 : :
2908 : 0 : rc = -ENOMEM;
2909 : 0 : (*names)[i] = kstrdup(sym_name(policydb, SYM_BOOLS, i),
2910 : : GFP_ATOMIC);
2911 [ # # ]: 0 : if (!(*names)[i])
2912 : 0 : goto err;
2913 : : }
2914 : : rc = 0;
2915 : 0 : out:
2916 : 0 : read_unlock(&state->ss->policy_rwlock);
2917 : 0 : return rc;
2918 : 0 : err:
2919 [ # # ]: 0 : if (*names) {
2920 [ # # ]: 0 : for (i = 0; i < *len; i++)
2921 : 0 : kfree((*names)[i]);
2922 : : }
2923 : 0 : kfree(*values);
2924 : 0 : goto out;
2925 : : }
2926 : :
2927 : :
2928 : 0 : int security_set_bools(struct selinux_state *state, int len, int *values)
2929 : : {
2930 : 0 : struct policydb *policydb;
2931 : 0 : int i, rc;
2932 : 0 : int lenp, seqno = 0;
2933 : 0 : struct cond_node *cur;
2934 : :
2935 : 0 : write_lock_irq(&state->ss->policy_rwlock);
2936 : :
2937 : 0 : policydb = &state->ss->policydb;
2938 : :
2939 : 0 : rc = -EFAULT;
2940 : 0 : lenp = policydb->p_bools.nprim;
2941 [ # # ]: 0 : if (len != lenp)
2942 : 0 : goto out;
2943 : :
2944 [ # # ]: 0 : for (i = 0; i < len; i++) {
2945 [ # # ]: 0 : if (!!values[i] != policydb->bool_val_to_struct[i]->state) {
2946 : 0 : audit_log(audit_context(), GFP_ATOMIC,
2947 : : AUDIT_MAC_CONFIG_CHANGE,
2948 : : "bool=%s val=%d old_val=%d auid=%u ses=%u",
2949 : : sym_name(policydb, SYM_BOOLS, i),
2950 : : !!values[i],
2951 : : policydb->bool_val_to_struct[i]->state,
2952 : : from_kuid(&init_user_ns, audit_get_loginuid(current)),
2953 : : audit_get_sessionid(current));
2954 : : }
2955 [ # # ]: 0 : if (values[i])
2956 : 0 : policydb->bool_val_to_struct[i]->state = 1;
2957 : : else
2958 : 0 : policydb->bool_val_to_struct[i]->state = 0;
2959 : : }
2960 : :
2961 [ # # ]: 0 : for (cur = policydb->cond_list; cur; cur = cur->next) {
2962 : 0 : rc = evaluate_cond_node(policydb, cur);
2963 [ # # ]: 0 : if (rc)
2964 : 0 : goto out;
2965 : : }
2966 : :
2967 : 0 : seqno = ++state->ss->latest_granting;
2968 : 0 : rc = 0;
2969 : 0 : out:
2970 : 0 : write_unlock_irq(&state->ss->policy_rwlock);
2971 [ # # ]: 0 : if (!rc) {
2972 : 0 : avc_ss_reset(state->avc, seqno);
2973 : 0 : selnl_notify_policyload(seqno);
2974 : 0 : selinux_status_update_policyload(state, seqno);
2975 : 0 : selinux_xfrm_notify_policyload();
2976 : : }
2977 : 0 : return rc;
2978 : : }
2979 : :
2980 : 0 : int security_get_bool_value(struct selinux_state *state,
2981 : : int index)
2982 : : {
2983 : 0 : struct policydb *policydb;
2984 : 0 : int rc;
2985 : 0 : int len;
2986 : :
2987 : 0 : read_lock(&state->ss->policy_rwlock);
2988 : :
2989 : 0 : policydb = &state->ss->policydb;
2990 : :
2991 : 0 : rc = -EFAULT;
2992 : 0 : len = policydb->p_bools.nprim;
2993 [ # # ]: 0 : if (index >= len)
2994 : 0 : goto out;
2995 : :
2996 : 0 : rc = policydb->bool_val_to_struct[index]->state;
2997 : 0 : out:
2998 : 0 : read_unlock(&state->ss->policy_rwlock);
2999 : 0 : return rc;
3000 : : }
3001 : :
3002 : 0 : static int security_preserve_bools(struct selinux_state *state,
3003 : : struct policydb *policydb)
3004 : : {
3005 : 0 : int rc, nbools = 0, *bvalues = NULL, i;
3006 : 0 : char **bnames = NULL;
3007 : 0 : struct cond_bool_datum *booldatum;
3008 : 0 : struct cond_node *cur;
3009 : :
3010 : 0 : rc = security_get_bools(state, &nbools, &bnames, &bvalues);
3011 [ # # ]: 0 : if (rc)
3012 : 0 : goto out;
3013 [ # # ]: 0 : for (i = 0; i < nbools; i++) {
3014 : 0 : booldatum = hashtab_search(policydb->p_bools.table, bnames[i]);
3015 [ # # ]: 0 : if (booldatum)
3016 : 0 : booldatum->state = bvalues[i];
3017 : : }
3018 [ # # ]: 0 : for (cur = policydb->cond_list; cur; cur = cur->next) {
3019 : 0 : rc = evaluate_cond_node(policydb, cur);
3020 [ # # ]: 0 : if (rc)
3021 : 0 : goto out;
3022 : : }
3023 : :
3024 : 0 : out:
3025 [ # # ]: 0 : if (bnames) {
3026 [ # # ]: 0 : for (i = 0; i < nbools; i++)
3027 : 0 : kfree(bnames[i]);
3028 : : }
3029 : 0 : kfree(bnames);
3030 : 0 : kfree(bvalues);
3031 : 0 : return rc;
3032 : : }
3033 : :
3034 : : /*
3035 : : * security_sid_mls_copy() - computes a new sid based on the given
3036 : : * sid and the mls portion of mls_sid.
3037 : : */
3038 : 812 : int security_sid_mls_copy(struct selinux_state *state,
3039 : : u32 sid, u32 mls_sid, u32 *new_sid)
3040 : : {
3041 : 812 : struct policydb *policydb = &state->ss->policydb;
3042 : 812 : struct sidtab *sidtab = state->ss->sidtab;
3043 : 812 : struct context *context1;
3044 : 812 : struct context *context2;
3045 : 812 : struct context newcon;
3046 : 812 : char *s;
3047 : 812 : u32 len;
3048 : 812 : int rc;
3049 : :
3050 : 812 : rc = 0;
3051 [ - + - - ]: 812 : if (!selinux_initialized(state) || !policydb->mls_enabled) {
3052 : 812 : *new_sid = sid;
3053 : 812 : goto out;
3054 : : }
3055 : :
3056 : 0 : context_init(&newcon);
3057 : :
3058 : 0 : read_lock(&state->ss->policy_rwlock);
3059 : :
3060 : 0 : rc = -EINVAL;
3061 : 0 : context1 = sidtab_search(sidtab, sid);
3062 [ # # ]: 0 : if (!context1) {
3063 : 0 : pr_err("SELinux: %s: unrecognized SID %d\n",
3064 : : __func__, sid);
3065 : 0 : goto out_unlock;
3066 : : }
3067 : :
3068 : 0 : rc = -EINVAL;
3069 : 0 : context2 = sidtab_search(sidtab, mls_sid);
3070 [ # # ]: 0 : if (!context2) {
3071 : 0 : pr_err("SELinux: %s: unrecognized SID %d\n",
3072 : : __func__, mls_sid);
3073 : 0 : goto out_unlock;
3074 : : }
3075 : :
3076 : 0 : newcon.user = context1->user;
3077 : 0 : newcon.role = context1->role;
3078 : 0 : newcon.type = context1->type;
3079 : 0 : rc = mls_context_cpy(&newcon, context2);
3080 [ # # ]: 0 : if (rc)
3081 : 0 : goto out_unlock;
3082 : :
3083 : : /* Check the validity of the new context. */
3084 [ # # ]: 0 : if (!policydb_context_isvalid(policydb, &newcon)) {
3085 : 0 : rc = convert_context_handle_invalid_context(state, &newcon);
3086 [ # # ]: 0 : if (rc) {
3087 [ # # ]: 0 : if (!context_struct_to_string(policydb, &newcon, &s,
3088 : : &len)) {
3089 : 0 : struct audit_buffer *ab;
3090 : :
3091 : 0 : ab = audit_log_start(audit_context(),
3092 : : GFP_ATOMIC,
3093 : : AUDIT_SELINUX_ERR);
3094 : 0 : audit_log_format(ab,
3095 : : "op=security_sid_mls_copy invalid_context=");
3096 : : /* don't record NUL with untrusted strings */
3097 : 0 : audit_log_n_untrustedstring(ab, s, len - 1);
3098 : 0 : audit_log_end(ab);
3099 : 0 : kfree(s);
3100 : : }
3101 : 0 : goto out_unlock;
3102 : : }
3103 : : }
3104 : 0 : rc = context_struct_to_sid(state, &newcon, new_sid);
3105 : 0 : out_unlock:
3106 : 0 : read_unlock(&state->ss->policy_rwlock);
3107 : 0 : context_destroy(&newcon);
3108 : 812 : out:
3109 : 812 : return rc;
3110 : : }
3111 : :
3112 : : /**
3113 : : * security_net_peersid_resolve - Compare and resolve two network peer SIDs
3114 : : * @nlbl_sid: NetLabel SID
3115 : : * @nlbl_type: NetLabel labeling protocol type
3116 : : * @xfrm_sid: XFRM SID
3117 : : *
3118 : : * Description:
3119 : : * Compare the @nlbl_sid and @xfrm_sid values and if the two SIDs can be
3120 : : * resolved into a single SID it is returned via @peer_sid and the function
3121 : : * returns zero. Otherwise @peer_sid is set to SECSID_NULL and the function
3122 : : * returns a negative value. A table summarizing the behavior is below:
3123 : : *
3124 : : * | function return | @sid
3125 : : * ------------------------------+-----------------+-----------------
3126 : : * no peer labels | 0 | SECSID_NULL
3127 : : * single peer label | 0 | <peer_label>
3128 : : * multiple, consistent labels | 0 | <peer_label>
3129 : : * multiple, inconsistent labels | -<errno> | SECSID_NULL
3130 : : *
3131 : : */
3132 : 0 : int security_net_peersid_resolve(struct selinux_state *state,
3133 : : u32 nlbl_sid, u32 nlbl_type,
3134 : : u32 xfrm_sid,
3135 : : u32 *peer_sid)
3136 : : {
3137 : 0 : struct policydb *policydb = &state->ss->policydb;
3138 : 0 : struct sidtab *sidtab = state->ss->sidtab;
3139 : 0 : int rc;
3140 : 0 : struct context *nlbl_ctx;
3141 : 0 : struct context *xfrm_ctx;
3142 : :
3143 : 0 : *peer_sid = SECSID_NULL;
3144 : :
3145 : : /* handle the common (which also happens to be the set of easy) cases
3146 : : * right away, these two if statements catch everything involving a
3147 : : * single or absent peer SID/label */
3148 [ # # ]: 0 : if (xfrm_sid == SECSID_NULL) {
3149 : 0 : *peer_sid = nlbl_sid;
3150 : 0 : return 0;
3151 : : }
3152 : : /* NOTE: an nlbl_type == NETLBL_NLTYPE_UNLABELED is a "fallback" label
3153 : : * and is treated as if nlbl_sid == SECSID_NULL when a XFRM SID/label
3154 : : * is present */
3155 [ # # ]: 0 : if (nlbl_sid == SECSID_NULL || nlbl_type == NETLBL_NLTYPE_UNLABELED) {
3156 : 0 : *peer_sid = xfrm_sid;
3157 : 0 : return 0;
3158 : : }
3159 : :
3160 : : /*
3161 : : * We don't need to check initialized here since the only way both
3162 : : * nlbl_sid and xfrm_sid are not equal to SECSID_NULL would be if the
3163 : : * security server was initialized and state->initialized was true.
3164 : : */
3165 [ # # ]: 0 : if (!policydb->mls_enabled)
3166 : : return 0;
3167 : :
3168 : 0 : read_lock(&state->ss->policy_rwlock);
3169 : :
3170 : 0 : rc = -EINVAL;
3171 : 0 : nlbl_ctx = sidtab_search(sidtab, nlbl_sid);
3172 [ # # ]: 0 : if (!nlbl_ctx) {
3173 : 0 : pr_err("SELinux: %s: unrecognized SID %d\n",
3174 : : __func__, nlbl_sid);
3175 : 0 : goto out;
3176 : : }
3177 : 0 : rc = -EINVAL;
3178 : 0 : xfrm_ctx = sidtab_search(sidtab, xfrm_sid);
3179 [ # # ]: 0 : if (!xfrm_ctx) {
3180 : 0 : pr_err("SELinux: %s: unrecognized SID %d\n",
3181 : : __func__, xfrm_sid);
3182 : 0 : goto out;
3183 : : }
3184 [ # # ]: 0 : rc = (mls_context_cmp(nlbl_ctx, xfrm_ctx) ? 0 : -EACCES);
3185 : 0 : if (rc)
3186 : 0 : goto out;
3187 : :
3188 : : /* at present NetLabel SIDs/labels really only carry MLS
3189 : : * information so if the MLS portion of the NetLabel SID
3190 : : * matches the MLS portion of the labeled XFRM SID/label
3191 : : * then pass along the XFRM SID as it is the most
3192 : : * expressive */
3193 : 0 : *peer_sid = xfrm_sid;
3194 : 0 : out:
3195 : 0 : read_unlock(&state->ss->policy_rwlock);
3196 : 0 : return rc;
3197 : : }
3198 : :
3199 : 0 : static int get_classes_callback(void *k, void *d, void *args)
3200 : : {
3201 : 0 : struct class_datum *datum = d;
3202 : 0 : char *name = k, **classes = args;
3203 : 0 : int value = datum->value - 1;
3204 : :
3205 : 0 : classes[value] = kstrdup(name, GFP_ATOMIC);
3206 [ # # ]: 0 : if (!classes[value])
3207 : 0 : return -ENOMEM;
3208 : :
3209 : : return 0;
3210 : : }
3211 : :
3212 : 28 : int security_get_classes(struct selinux_state *state,
3213 : : char ***classes, int *nclasses)
3214 : : {
3215 : 28 : struct policydb *policydb = &state->ss->policydb;
3216 : 28 : int rc;
3217 : :
3218 [ + - ]: 28 : if (!selinux_initialized(state)) {
3219 : 28 : *nclasses = 0;
3220 : 28 : *classes = NULL;
3221 : 28 : return 0;
3222 : : }
3223 : :
3224 : 0 : read_lock(&state->ss->policy_rwlock);
3225 : :
3226 : 0 : rc = -ENOMEM;
3227 : 0 : *nclasses = policydb->p_classes.nprim;
3228 : 0 : *classes = kcalloc(*nclasses, sizeof(**classes), GFP_ATOMIC);
3229 [ # # ]: 0 : if (!*classes)
3230 : 0 : goto out;
3231 : :
3232 : 0 : rc = hashtab_map(policydb->p_classes.table, get_classes_callback,
3233 : : *classes);
3234 [ # # ]: 0 : if (rc) {
3235 : : int i;
3236 [ # # ]: 0 : for (i = 0; i < *nclasses; i++)
3237 : 0 : kfree((*classes)[i]);
3238 : 0 : kfree(*classes);
3239 : : }
3240 : :
3241 : 0 : out:
3242 : 0 : read_unlock(&state->ss->policy_rwlock);
3243 : 0 : return rc;
3244 : : }
3245 : :
3246 : 0 : static int get_permissions_callback(void *k, void *d, void *args)
3247 : : {
3248 : 0 : struct perm_datum *datum = d;
3249 : 0 : char *name = k, **perms = args;
3250 : 0 : int value = datum->value - 1;
3251 : :
3252 : 0 : perms[value] = kstrdup(name, GFP_ATOMIC);
3253 [ # # ]: 0 : if (!perms[value])
3254 : 0 : return -ENOMEM;
3255 : :
3256 : : return 0;
3257 : : }
3258 : :
3259 : 0 : int security_get_permissions(struct selinux_state *state,
3260 : : char *class, char ***perms, int *nperms)
3261 : : {
3262 : 0 : struct policydb *policydb = &state->ss->policydb;
3263 : 0 : int rc, i;
3264 : 0 : struct class_datum *match;
3265 : :
3266 : 0 : read_lock(&state->ss->policy_rwlock);
3267 : :
3268 : 0 : rc = -EINVAL;
3269 : 0 : match = hashtab_search(policydb->p_classes.table, class);
3270 [ # # ]: 0 : if (!match) {
3271 : 0 : pr_err("SELinux: %s: unrecognized class %s\n",
3272 : : __func__, class);
3273 : 0 : goto out;
3274 : : }
3275 : :
3276 : 0 : rc = -ENOMEM;
3277 : 0 : *nperms = match->permissions.nprim;
3278 : 0 : *perms = kcalloc(*nperms, sizeof(**perms), GFP_ATOMIC);
3279 [ # # ]: 0 : if (!*perms)
3280 : 0 : goto out;
3281 : :
3282 [ # # ]: 0 : if (match->comdatum) {
3283 : 0 : rc = hashtab_map(match->comdatum->permissions.table,
3284 : : get_permissions_callback, *perms);
3285 [ # # ]: 0 : if (rc)
3286 : 0 : goto err;
3287 : : }
3288 : :
3289 : 0 : rc = hashtab_map(match->permissions.table, get_permissions_callback,
3290 : : *perms);
3291 [ # # ]: 0 : if (rc)
3292 : 0 : goto err;
3293 : :
3294 : 0 : out:
3295 : 0 : read_unlock(&state->ss->policy_rwlock);
3296 : 0 : return rc;
3297 : :
3298 : 0 : err:
3299 : 0 : read_unlock(&state->ss->policy_rwlock);
3300 [ # # ]: 0 : for (i = 0; i < *nperms; i++)
3301 : 0 : kfree((*perms)[i]);
3302 : 0 : kfree(*perms);
3303 : 0 : return rc;
3304 : : }
3305 : :
3306 : 0 : int security_get_reject_unknown(struct selinux_state *state)
3307 : : {
3308 : 0 : return state->ss->policydb.reject_unknown;
3309 : : }
3310 : :
3311 : 0 : int security_get_allow_unknown(struct selinux_state *state)
3312 : : {
3313 : 0 : return state->ss->policydb.allow_unknown;
3314 : : }
3315 : :
3316 : : /**
3317 : : * security_policycap_supported - Check for a specific policy capability
3318 : : * @req_cap: capability
3319 : : *
3320 : : * Description:
3321 : : * This function queries the currently loaded policy to see if it supports the
3322 : : * capability specified by @req_cap. Returns true (1) if the capability is
3323 : : * supported, false (0) if it isn't supported.
3324 : : *
3325 : : */
3326 : 0 : int security_policycap_supported(struct selinux_state *state,
3327 : : unsigned int req_cap)
3328 : : {
3329 : 0 : struct policydb *policydb = &state->ss->policydb;
3330 : 0 : int rc;
3331 : :
3332 : 0 : read_lock(&state->ss->policy_rwlock);
3333 : 0 : rc = ebitmap_get_bit(&policydb->policycaps, req_cap);
3334 : 0 : read_unlock(&state->ss->policy_rwlock);
3335 : :
3336 : 0 : return rc;
3337 : : }
3338 : :
3339 : : struct selinux_audit_rule {
3340 : : u32 au_seqno;
3341 : : struct context au_ctxt;
3342 : : };
3343 : :
3344 : 0 : void selinux_audit_rule_free(void *vrule)
3345 : : {
3346 : 0 : struct selinux_audit_rule *rule = vrule;
3347 : :
3348 [ # # ]: 0 : if (rule) {
3349 : 0 : context_destroy(&rule->au_ctxt);
3350 : 0 : kfree(rule);
3351 : : }
3352 : 0 : }
3353 : :
3354 : 0 : int selinux_audit_rule_init(u32 field, u32 op, char *rulestr, void **vrule)
3355 : : {
3356 : 0 : struct selinux_state *state = &selinux_state;
3357 : 0 : struct policydb *policydb = &state->ss->policydb;
3358 : 0 : struct selinux_audit_rule *tmprule;
3359 : 0 : struct role_datum *roledatum;
3360 : 0 : struct type_datum *typedatum;
3361 : 0 : struct user_datum *userdatum;
3362 : 0 : struct selinux_audit_rule **rule = (struct selinux_audit_rule **)vrule;
3363 : 0 : int rc = 0;
3364 : :
3365 : 0 : *rule = NULL;
3366 : :
3367 [ # # ]: 0 : if (!selinux_initialized(state))
3368 : : return -EOPNOTSUPP;
3369 : :
3370 [ # # # ]: 0 : switch (field) {
3371 : 0 : case AUDIT_SUBJ_USER:
3372 : : case AUDIT_SUBJ_ROLE:
3373 : : case AUDIT_SUBJ_TYPE:
3374 : : case AUDIT_OBJ_USER:
3375 : : case AUDIT_OBJ_ROLE:
3376 : : case AUDIT_OBJ_TYPE:
3377 : : /* only 'equals' and 'not equals' fit user, role, and type */
3378 [ # # ]: 0 : if (op != Audit_equal && op != Audit_not_equal)
3379 : : return -EINVAL;
3380 : : break;
3381 : 0 : case AUDIT_SUBJ_SEN:
3382 : : case AUDIT_SUBJ_CLR:
3383 : : case AUDIT_OBJ_LEV_LOW:
3384 : : case AUDIT_OBJ_LEV_HIGH:
3385 : : /* we do not allow a range, indicated by the presence of '-' */
3386 [ # # ]: 0 : if (strchr(rulestr, '-'))
3387 : : return -EINVAL;
3388 : : break;
3389 : : default:
3390 : : /* only the above fields are valid */
3391 : : return -EINVAL;
3392 : : }
3393 : :
3394 : 0 : tmprule = kzalloc(sizeof(struct selinux_audit_rule), GFP_KERNEL);
3395 [ # # ]: 0 : if (!tmprule)
3396 : : return -ENOMEM;
3397 : :
3398 : 0 : context_init(&tmprule->au_ctxt);
3399 : :
3400 : 0 : read_lock(&state->ss->policy_rwlock);
3401 : :
3402 : 0 : tmprule->au_seqno = state->ss->latest_granting;
3403 : :
3404 [ # # # # : 0 : switch (field) {
# ]
3405 : 0 : case AUDIT_SUBJ_USER:
3406 : : case AUDIT_OBJ_USER:
3407 : 0 : rc = -EINVAL;
3408 : 0 : userdatum = hashtab_search(policydb->p_users.table, rulestr);
3409 [ # # ]: 0 : if (!userdatum)
3410 : 0 : goto out;
3411 : 0 : tmprule->au_ctxt.user = userdatum->value;
3412 : 0 : break;
3413 : 0 : case AUDIT_SUBJ_ROLE:
3414 : : case AUDIT_OBJ_ROLE:
3415 : 0 : rc = -EINVAL;
3416 : 0 : roledatum = hashtab_search(policydb->p_roles.table, rulestr);
3417 [ # # ]: 0 : if (!roledatum)
3418 : 0 : goto out;
3419 : 0 : tmprule->au_ctxt.role = roledatum->value;
3420 : 0 : break;
3421 : 0 : case AUDIT_SUBJ_TYPE:
3422 : : case AUDIT_OBJ_TYPE:
3423 : 0 : rc = -EINVAL;
3424 : 0 : typedatum = hashtab_search(policydb->p_types.table, rulestr);
3425 [ # # ]: 0 : if (!typedatum)
3426 : 0 : goto out;
3427 : 0 : tmprule->au_ctxt.type = typedatum->value;
3428 : 0 : break;
3429 : 0 : case AUDIT_SUBJ_SEN:
3430 : : case AUDIT_SUBJ_CLR:
3431 : : case AUDIT_OBJ_LEV_LOW:
3432 : : case AUDIT_OBJ_LEV_HIGH:
3433 : 0 : rc = mls_from_string(policydb, rulestr, &tmprule->au_ctxt,
3434 : : GFP_ATOMIC);
3435 [ # # ]: 0 : if (rc)
3436 : 0 : goto out;
3437 : : break;
3438 : : }
3439 : : rc = 0;
3440 : 0 : out:
3441 : 0 : read_unlock(&state->ss->policy_rwlock);
3442 : :
3443 [ # # ]: 0 : if (rc) {
3444 : 0 : selinux_audit_rule_free(tmprule);
3445 : 0 : tmprule = NULL;
3446 : : }
3447 : :
3448 : 0 : *rule = tmprule;
3449 : :
3450 : 0 : return rc;
3451 : : }
3452 : :
3453 : : /* Check to see if the rule contains any selinux fields */
3454 : 0 : int selinux_audit_rule_known(struct audit_krule *rule)
3455 : : {
3456 : 0 : int i;
3457 : :
3458 [ # # ]: 0 : for (i = 0; i < rule->field_count; i++) {
3459 : 0 : struct audit_field *f = &rule->fields[i];
3460 [ # # ]: 0 : switch (f->type) {
3461 : : case AUDIT_SUBJ_USER:
3462 : : case AUDIT_SUBJ_ROLE:
3463 : : case AUDIT_SUBJ_TYPE:
3464 : : case AUDIT_SUBJ_SEN:
3465 : : case AUDIT_SUBJ_CLR:
3466 : : case AUDIT_OBJ_USER:
3467 : : case AUDIT_OBJ_ROLE:
3468 : : case AUDIT_OBJ_TYPE:
3469 : : case AUDIT_OBJ_LEV_LOW:
3470 : : case AUDIT_OBJ_LEV_HIGH:
3471 : : return 1;
3472 : : }
3473 : : }
3474 : :
3475 : : return 0;
3476 : : }
3477 : :
3478 : 0 : int selinux_audit_rule_match(u32 sid, u32 field, u32 op, void *vrule)
3479 : : {
3480 : 0 : struct selinux_state *state = &selinux_state;
3481 : 0 : struct context *ctxt;
3482 : 0 : struct mls_level *level;
3483 : 0 : struct selinux_audit_rule *rule = vrule;
3484 : 0 : int match = 0;
3485 : :
3486 [ # # ]: 0 : if (unlikely(!rule)) {
3487 [ # # ]: 0 : WARN_ONCE(1, "selinux_audit_rule_match: missing rule\n");
3488 : 0 : return -ENOENT;
3489 : : }
3490 : :
3491 : 0 : read_lock(&state->ss->policy_rwlock);
3492 : :
3493 [ # # ]: 0 : if (rule->au_seqno < state->ss->latest_granting) {
3494 : 0 : match = -ESTALE;
3495 : 0 : goto out;
3496 : : }
3497 : :
3498 : 0 : ctxt = sidtab_search(state->ss->sidtab, sid);
3499 [ # # ]: 0 : if (unlikely(!ctxt)) {
3500 [ # # ]: 0 : WARN_ONCE(1, "selinux_audit_rule_match: unrecognized SID %d\n",
3501 : : sid);
3502 : 0 : match = -ENOENT;
3503 : 0 : goto out;
3504 : : }
3505 : :
3506 : : /* a field/op pair that is not caught here will simply fall through
3507 : : without a match */
3508 [ # # # # : 0 : switch (field) {
# ]
3509 : 0 : case AUDIT_SUBJ_USER:
3510 : : case AUDIT_OBJ_USER:
3511 [ # # # ]: 0 : switch (op) {
3512 : 0 : case Audit_equal:
3513 : 0 : match = (ctxt->user == rule->au_ctxt.user);
3514 : 0 : break;
3515 : 0 : case Audit_not_equal:
3516 : 0 : match = (ctxt->user != rule->au_ctxt.user);
3517 : 0 : break;
3518 : : }
3519 : : break;
3520 : 0 : case AUDIT_SUBJ_ROLE:
3521 : : case AUDIT_OBJ_ROLE:
3522 [ # # # ]: 0 : switch (op) {
3523 : 0 : case Audit_equal:
3524 : 0 : match = (ctxt->role == rule->au_ctxt.role);
3525 : 0 : break;
3526 : 0 : case Audit_not_equal:
3527 : 0 : match = (ctxt->role != rule->au_ctxt.role);
3528 : 0 : break;
3529 : : }
3530 : : break;
3531 : 0 : case AUDIT_SUBJ_TYPE:
3532 : : case AUDIT_OBJ_TYPE:
3533 [ # # # ]: 0 : switch (op) {
3534 : 0 : case Audit_equal:
3535 : 0 : match = (ctxt->type == rule->au_ctxt.type);
3536 : 0 : break;
3537 : 0 : case Audit_not_equal:
3538 : 0 : match = (ctxt->type != rule->au_ctxt.type);
3539 : 0 : break;
3540 : : }
3541 : : break;
3542 : 0 : case AUDIT_SUBJ_SEN:
3543 : : case AUDIT_SUBJ_CLR:
3544 : : case AUDIT_OBJ_LEV_LOW:
3545 : : case AUDIT_OBJ_LEV_HIGH:
3546 : 0 : level = ((field == AUDIT_SUBJ_SEN ||
3547 : 0 : field == AUDIT_OBJ_LEV_LOW) ?
3548 [ # # ]: 0 : &ctxt->range.level[0] : &ctxt->range.level[1]);
3549 [ # # # # : 0 : switch (op) {
# # # ]
3550 : 0 : case Audit_equal:
3551 [ # # ]: 0 : match = mls_level_eq(&rule->au_ctxt.range.level[0],
3552 : : level);
3553 : : break;
3554 : 0 : case Audit_not_equal:
3555 [ # # ]: 0 : match = !mls_level_eq(&rule->au_ctxt.range.level[0],
3556 : : level);
3557 : 0 : break;
3558 : 0 : case Audit_lt:
3559 [ # # ]: 0 : match = (mls_level_dom(&rule->au_ctxt.range.level[0],
3560 : : level) &&
3561 : : !mls_level_eq(&rule->au_ctxt.range.level[0],
3562 : : level));
3563 : : break;
3564 : 0 : case Audit_le:
3565 [ # # ]: 0 : match = mls_level_dom(&rule->au_ctxt.range.level[0],
3566 : : level);
3567 : : break;
3568 : 0 : case Audit_gt:
3569 [ # # ]: 0 : match = (mls_level_dom(level,
3570 : : &rule->au_ctxt.range.level[0]) &&
3571 : : !mls_level_eq(level,
3572 : : &rule->au_ctxt.range.level[0]));
3573 : : break;
3574 : 0 : case Audit_ge:
3575 [ # # ]: 0 : match = mls_level_dom(level,
3576 : : &rule->au_ctxt.range.level[0]);
3577 : : break;
3578 : : }
3579 : : }
3580 : :
3581 : 0 : out:
3582 : 0 : read_unlock(&state->ss->policy_rwlock);
3583 : 0 : return match;
3584 : : }
3585 : :
3586 : : static int (*aurule_callback)(void) = audit_update_lsm_rules;
3587 : :
3588 : 0 : static int aurule_avc_callback(u32 event)
3589 : : {
3590 : 0 : int err = 0;
3591 : :
3592 [ # # # # ]: 0 : if (event == AVC_CALLBACK_RESET && aurule_callback)
3593 : 0 : err = aurule_callback();
3594 : 0 : return err;
3595 : : }
3596 : :
3597 : 28 : static int __init aurule_init(void)
3598 : : {
3599 : 28 : int err;
3600 : :
3601 : 28 : err = avc_add_callback(aurule_avc_callback, AVC_CALLBACK_RESET);
3602 [ - + ]: 28 : if (err)
3603 : 0 : panic("avc_add_callback() failed, error %d\n", err);
3604 : :
3605 : 28 : return err;
3606 : : }
3607 : : __initcall(aurule_init);
3608 : :
3609 : : #ifdef CONFIG_NETLABEL
3610 : : /**
3611 : : * security_netlbl_cache_add - Add an entry to the NetLabel cache
3612 : : * @secattr: the NetLabel packet security attributes
3613 : : * @sid: the SELinux SID
3614 : : *
3615 : : * Description:
3616 : : * Attempt to cache the context in @ctx, which was derived from the packet in
3617 : : * @skb, in the NetLabel subsystem cache. This function assumes @secattr has
3618 : : * already been initialized.
3619 : : *
3620 : : */
3621 : : static void security_netlbl_cache_add(struct netlbl_lsm_secattr *secattr,
3622 : : u32 sid)
3623 : : {
3624 : : u32 *sid_cache;
3625 : :
3626 : : sid_cache = kmalloc(sizeof(*sid_cache), GFP_ATOMIC);
3627 : : if (sid_cache == NULL)
3628 : : return;
3629 : : secattr->cache = netlbl_secattr_cache_alloc(GFP_ATOMIC);
3630 : : if (secattr->cache == NULL) {
3631 : : kfree(sid_cache);
3632 : : return;
3633 : : }
3634 : :
3635 : : *sid_cache = sid;
3636 : : secattr->cache->free = kfree;
3637 : : secattr->cache->data = sid_cache;
3638 : : secattr->flags |= NETLBL_SECATTR_CACHE;
3639 : : }
3640 : :
3641 : : /**
3642 : : * security_netlbl_secattr_to_sid - Convert a NetLabel secattr to a SELinux SID
3643 : : * @secattr: the NetLabel packet security attributes
3644 : : * @sid: the SELinux SID
3645 : : *
3646 : : * Description:
3647 : : * Convert the given NetLabel security attributes in @secattr into a
3648 : : * SELinux SID. If the @secattr field does not contain a full SELinux
3649 : : * SID/context then use SECINITSID_NETMSG as the foundation. If possible the
3650 : : * 'cache' field of @secattr is set and the CACHE flag is set; this is to
3651 : : * allow the @secattr to be used by NetLabel to cache the secattr to SID
3652 : : * conversion for future lookups. Returns zero on success, negative values on
3653 : : * failure.
3654 : : *
3655 : : */
3656 : 0 : int security_netlbl_secattr_to_sid(struct selinux_state *state,
3657 : : struct netlbl_lsm_secattr *secattr,
3658 : : u32 *sid)
3659 : : {
3660 : 0 : struct policydb *policydb = &state->ss->policydb;
3661 : 0 : struct sidtab *sidtab = state->ss->sidtab;
3662 : 0 : int rc;
3663 : 0 : struct context *ctx;
3664 : 0 : struct context ctx_new;
3665 : :
3666 [ # # ]: 0 : if (!selinux_initialized(state)) {
3667 : 0 : *sid = SECSID_NULL;
3668 : 0 : return 0;
3669 : : }
3670 : :
3671 : 0 : read_lock(&state->ss->policy_rwlock);
3672 : :
3673 [ # # ]: 0 : if (secattr->flags & NETLBL_SECATTR_CACHE)
3674 : 0 : *sid = *(u32 *)secattr->cache->data;
3675 [ # # ]: 0 : else if (secattr->flags & NETLBL_SECATTR_SECID)
3676 : 0 : *sid = secattr->attr.secid;
3677 [ # # ]: 0 : else if (secattr->flags & NETLBL_SECATTR_MLS_LVL) {
3678 : 0 : rc = -EIDRM;
3679 : 0 : ctx = sidtab_search(sidtab, SECINITSID_NETMSG);
3680 [ # # ]: 0 : if (ctx == NULL)
3681 : 0 : goto out;
3682 : :
3683 : 0 : context_init(&ctx_new);
3684 : 0 : ctx_new.user = ctx->user;
3685 : 0 : ctx_new.role = ctx->role;
3686 : 0 : ctx_new.type = ctx->type;
3687 : 0 : mls_import_netlbl_lvl(policydb, &ctx_new, secattr);
3688 [ # # ]: 0 : if (secattr->flags & NETLBL_SECATTR_MLS_CAT) {
3689 : 0 : rc = mls_import_netlbl_cat(policydb, &ctx_new, secattr);
3690 [ # # ]: 0 : if (rc)
3691 : 0 : goto out;
3692 : : }
3693 : 0 : rc = -EIDRM;
3694 [ # # ]: 0 : if (!mls_context_isvalid(policydb, &ctx_new))
3695 : 0 : goto out_free;
3696 : :
3697 : 0 : rc = context_struct_to_sid(state, &ctx_new, sid);
3698 [ # # ]: 0 : if (rc)
3699 : 0 : goto out_free;
3700 : :
3701 : 0 : security_netlbl_cache_add(secattr, *sid);
3702 : :
3703 : 0 : ebitmap_destroy(&ctx_new.range.level[0].cat);
3704 : : } else
3705 : 0 : *sid = SECSID_NULL;
3706 : :
3707 : 0 : read_unlock(&state->ss->policy_rwlock);
3708 : 0 : return 0;
3709 : 0 : out_free:
3710 : 0 : ebitmap_destroy(&ctx_new.range.level[0].cat);
3711 : 0 : out:
3712 : 0 : read_unlock(&state->ss->policy_rwlock);
3713 : 0 : return rc;
3714 : : }
3715 : :
3716 : : /**
3717 : : * security_netlbl_sid_to_secattr - Convert a SELinux SID to a NetLabel secattr
3718 : : * @sid: the SELinux SID
3719 : : * @secattr: the NetLabel packet security attributes
3720 : : *
3721 : : * Description:
3722 : : * Convert the given SELinux SID in @sid into a NetLabel security attribute.
3723 : : * Returns zero on success, negative values on failure.
3724 : : *
3725 : : */
3726 : 2800 : int security_netlbl_sid_to_secattr(struct selinux_state *state,
3727 : : u32 sid, struct netlbl_lsm_secattr *secattr)
3728 : : {
3729 : 2800 : struct policydb *policydb = &state->ss->policydb;
3730 : 2800 : int rc;
3731 : 2800 : struct context *ctx;
3732 : :
3733 [ - + ]: 2800 : if (!selinux_initialized(state))
3734 : : return 0;
3735 : :
3736 : 0 : read_lock(&state->ss->policy_rwlock);
3737 : :
3738 : 0 : rc = -ENOENT;
3739 : 0 : ctx = sidtab_search(state->ss->sidtab, sid);
3740 [ # # ]: 0 : if (ctx == NULL)
3741 : 0 : goto out;
3742 : :
3743 : 0 : rc = -ENOMEM;
3744 : 0 : secattr->domain = kstrdup(sym_name(policydb, SYM_TYPES, ctx->type - 1),
3745 : : GFP_ATOMIC);
3746 [ # # ]: 0 : if (secattr->domain == NULL)
3747 : 0 : goto out;
3748 : :
3749 : 0 : secattr->attr.secid = sid;
3750 : 0 : secattr->flags |= NETLBL_SECATTR_DOMAIN_CPY | NETLBL_SECATTR_SECID;
3751 : 0 : mls_export_netlbl_lvl(policydb, ctx, secattr);
3752 : 0 : rc = mls_export_netlbl_cat(policydb, ctx, secattr);
3753 : 0 : out:
3754 : 0 : read_unlock(&state->ss->policy_rwlock);
3755 : 0 : return rc;
3756 : : }
3757 : : #endif /* CONFIG_NETLABEL */
3758 : :
3759 : : /**
3760 : : * security_read_policy - read the policy.
3761 : : * @data: binary policy data
3762 : : * @len: length of data in bytes
3763 : : *
3764 : : */
3765 : 0 : int security_read_policy(struct selinux_state *state,
3766 : : void **data, size_t *len)
3767 : : {
3768 : 0 : struct policydb *policydb = &state->ss->policydb;
3769 : 0 : int rc;
3770 : 0 : struct policy_file fp;
3771 : :
3772 [ # # ]: 0 : if (!selinux_initialized(state))
3773 : : return -EINVAL;
3774 : :
3775 : 0 : *len = security_policydb_len(state);
3776 : :
3777 : 0 : *data = vmalloc_user(*len);
3778 [ # # ]: 0 : if (!*data)
3779 : : return -ENOMEM;
3780 : :
3781 : 0 : fp.data = *data;
3782 : 0 : fp.len = *len;
3783 : :
3784 : 0 : read_lock(&state->ss->policy_rwlock);
3785 : 0 : rc = policydb_write(policydb, &fp);
3786 : 0 : read_unlock(&state->ss->policy_rwlock);
3787 : :
3788 [ # # ]: 0 : if (rc)
3789 : : return rc;
3790 : :
3791 : 0 : *len = (unsigned long)fp.data - (unsigned long)*data;
3792 : 0 : return 0;
3793 : :
3794 : : }
|