diff options
Diffstat (limited to 'security/selinux/ss')
-rw-r--r-- | security/selinux/ss/Makefile | 2 | ||||
-rw-r--r-- | security/selinux/ss/avtab.h | 2 | ||||
-rw-r--r-- | security/selinux/ss/context.h | 12 | ||||
-rw-r--r-- | security/selinux/ss/ebitmap.c | 2 | ||||
-rw-r--r-- | security/selinux/ss/mls.c | 50 | ||||
-rw-r--r-- | security/selinux/ss/mls.h | 2 | ||||
-rw-r--r-- | security/selinux/ss/mls_types.h | 7 | ||||
-rw-r--r-- | security/selinux/ss/policydb.c | 174 | ||||
-rw-r--r-- | security/selinux/ss/policydb.h | 17 | ||||
-rw-r--r-- | security/selinux/ss/services.c | 665 | ||||
-rw-r--r-- | security/selinux/ss/symtab.c | 1 |
11 files changed, 527 insertions, 407 deletions
diff --git a/security/selinux/ss/Makefile b/security/selinux/ss/Makefile index bad78779b9b0..15d4e62917de 100644 --- a/security/selinux/ss/Makefile +++ b/security/selinux/ss/Makefile | |||
@@ -2,7 +2,7 @@ | |||
2 | # Makefile for building the SELinux security server as part of the kernel tree. | 2 | # Makefile for building the SELinux security server as part of the kernel tree. |
3 | # | 3 | # |
4 | 4 | ||
5 | EXTRA_CFLAGS += -Isecurity/selinux/include | 5 | EXTRA_CFLAGS += -Isecurity/selinux -Isecurity/selinux/include |
6 | obj-y := ss.o | 6 | obj-y := ss.o |
7 | 7 | ||
8 | ss-y := ebitmap.o hashtab.o symtab.o sidtab.o avtab.o policydb.o services.o conditional.o mls.o | 8 | ss-y := ebitmap.o hashtab.o symtab.o sidtab.o avtab.o policydb.o services.o conditional.o mls.o |
diff --git a/security/selinux/ss/avtab.h b/security/selinux/ss/avtab.h index 8da6a8428086..cd4f734e2749 100644 --- a/security/selinux/ss/avtab.h +++ b/security/selinux/ss/avtab.h | |||
@@ -82,7 +82,7 @@ struct avtab_node *avtab_search_node_next(struct avtab_node *node, int specified | |||
82 | void avtab_cache_init(void); | 82 | void avtab_cache_init(void); |
83 | void avtab_cache_destroy(void); | 83 | void avtab_cache_destroy(void); |
84 | 84 | ||
85 | #define MAX_AVTAB_HASH_BITS 13 | 85 | #define MAX_AVTAB_HASH_BITS 11 |
86 | #define MAX_AVTAB_HASH_BUCKETS (1 << MAX_AVTAB_HASH_BITS) | 86 | #define MAX_AVTAB_HASH_BUCKETS (1 << MAX_AVTAB_HASH_BITS) |
87 | #define MAX_AVTAB_HASH_MASK (MAX_AVTAB_HASH_BUCKETS-1) | 87 | #define MAX_AVTAB_HASH_MASK (MAX_AVTAB_HASH_BUCKETS-1) |
88 | #define MAX_AVTAB_SIZE MAX_AVTAB_HASH_BUCKETS | 88 | #define MAX_AVTAB_SIZE MAX_AVTAB_HASH_BUCKETS |
diff --git a/security/selinux/ss/context.h b/security/selinux/ss/context.h index d9dd7a2f6a8a..45e8fb0515f8 100644 --- a/security/selinux/ss/context.h +++ b/security/selinux/ss/context.h | |||
@@ -41,9 +41,6 @@ static inline int mls_context_cpy(struct context *dst, struct context *src) | |||
41 | { | 41 | { |
42 | int rc; | 42 | int rc; |
43 | 43 | ||
44 | if (!selinux_mls_enabled) | ||
45 | return 0; | ||
46 | |||
47 | dst->range.level[0].sens = src->range.level[0].sens; | 44 | dst->range.level[0].sens = src->range.level[0].sens; |
48 | rc = ebitmap_cpy(&dst->range.level[0].cat, &src->range.level[0].cat); | 45 | rc = ebitmap_cpy(&dst->range.level[0].cat, &src->range.level[0].cat); |
49 | if (rc) | 46 | if (rc) |
@@ -64,9 +61,6 @@ static inline int mls_context_cpy_low(struct context *dst, struct context *src) | |||
64 | { | 61 | { |
65 | int rc; | 62 | int rc; |
66 | 63 | ||
67 | if (!selinux_mls_enabled) | ||
68 | return 0; | ||
69 | |||
70 | dst->range.level[0].sens = src->range.level[0].sens; | 64 | dst->range.level[0].sens = src->range.level[0].sens; |
71 | rc = ebitmap_cpy(&dst->range.level[0].cat, &src->range.level[0].cat); | 65 | rc = ebitmap_cpy(&dst->range.level[0].cat, &src->range.level[0].cat); |
72 | if (rc) | 66 | if (rc) |
@@ -82,9 +76,6 @@ out: | |||
82 | 76 | ||
83 | static inline int mls_context_cmp(struct context *c1, struct context *c2) | 77 | static inline int mls_context_cmp(struct context *c1, struct context *c2) |
84 | { | 78 | { |
85 | if (!selinux_mls_enabled) | ||
86 | return 1; | ||
87 | |||
88 | return ((c1->range.level[0].sens == c2->range.level[0].sens) && | 79 | return ((c1->range.level[0].sens == c2->range.level[0].sens) && |
89 | ebitmap_cmp(&c1->range.level[0].cat, &c2->range.level[0].cat) && | 80 | ebitmap_cmp(&c1->range.level[0].cat, &c2->range.level[0].cat) && |
90 | (c1->range.level[1].sens == c2->range.level[1].sens) && | 81 | (c1->range.level[1].sens == c2->range.level[1].sens) && |
@@ -93,9 +84,6 @@ static inline int mls_context_cmp(struct context *c1, struct context *c2) | |||
93 | 84 | ||
94 | static inline void mls_context_destroy(struct context *c) | 85 | static inline void mls_context_destroy(struct context *c) |
95 | { | 86 | { |
96 | if (!selinux_mls_enabled) | ||
97 | return; | ||
98 | |||
99 | ebitmap_destroy(&c->range.level[0].cat); | 87 | ebitmap_destroy(&c->range.level[0].cat); |
100 | ebitmap_destroy(&c->range.level[1].cat); | 88 | ebitmap_destroy(&c->range.level[1].cat); |
101 | mls_context_init(c); | 89 | mls_context_init(c); |
diff --git a/security/selinux/ss/ebitmap.c b/security/selinux/ss/ebitmap.c index 68c7348d1acc..04b6145d767f 100644 --- a/security/selinux/ss/ebitmap.c +++ b/security/selinux/ss/ebitmap.c | |||
@@ -128,7 +128,7 @@ int ebitmap_netlbl_export(struct ebitmap *ebmap, | |||
128 | cmap_idx = delta / NETLBL_CATMAP_MAPSIZE; | 128 | cmap_idx = delta / NETLBL_CATMAP_MAPSIZE; |
129 | cmap_sft = delta % NETLBL_CATMAP_MAPSIZE; | 129 | cmap_sft = delta % NETLBL_CATMAP_MAPSIZE; |
130 | c_iter->bitmap[cmap_idx] | 130 | c_iter->bitmap[cmap_idx] |
131 | |= e_iter->maps[cmap_idx] << cmap_sft; | 131 | |= e_iter->maps[i] << cmap_sft; |
132 | } | 132 | } |
133 | e_iter = e_iter->next; | 133 | e_iter = e_iter->next; |
134 | } | 134 | } |
diff --git a/security/selinux/ss/mls.c b/security/selinux/ss/mls.c index b5407f16c2a4..372b773f8210 100644 --- a/security/selinux/ss/mls.c +++ b/security/selinux/ss/mls.c | |||
@@ -39,7 +39,7 @@ int mls_compute_context_len(struct context *context) | |||
39 | struct ebitmap *e; | 39 | struct ebitmap *e; |
40 | struct ebitmap_node *node; | 40 | struct ebitmap_node *node; |
41 | 41 | ||
42 | if (!selinux_mls_enabled) | 42 | if (!policydb.mls_enabled) |
43 | return 0; | 43 | return 0; |
44 | 44 | ||
45 | len = 1; /* for the beginning ":" */ | 45 | len = 1; /* for the beginning ":" */ |
@@ -93,7 +93,7 @@ void mls_sid_to_context(struct context *context, | |||
93 | struct ebitmap *e; | 93 | struct ebitmap *e; |
94 | struct ebitmap_node *node; | 94 | struct ebitmap_node *node; |
95 | 95 | ||
96 | if (!selinux_mls_enabled) | 96 | if (!policydb.mls_enabled) |
97 | return; | 97 | return; |
98 | 98 | ||
99 | scontextp = *scontext; | 99 | scontextp = *scontext; |
@@ -200,7 +200,7 @@ int mls_context_isvalid(struct policydb *p, struct context *c) | |||
200 | { | 200 | { |
201 | struct user_datum *usrdatum; | 201 | struct user_datum *usrdatum; |
202 | 202 | ||
203 | if (!selinux_mls_enabled) | 203 | if (!p->mls_enabled) |
204 | return 1; | 204 | return 1; |
205 | 205 | ||
206 | if (!mls_range_isvalid(p, &c->range)) | 206 | if (!mls_range_isvalid(p, &c->range)) |
@@ -253,7 +253,7 @@ int mls_context_to_sid(struct policydb *pol, | |||
253 | struct cat_datum *catdatum, *rngdatum; | 253 | struct cat_datum *catdatum, *rngdatum; |
254 | int l, rc = -EINVAL; | 254 | int l, rc = -EINVAL; |
255 | 255 | ||
256 | if (!selinux_mls_enabled) { | 256 | if (!pol->mls_enabled) { |
257 | if (def_sid != SECSID_NULL && oldc) | 257 | if (def_sid != SECSID_NULL && oldc) |
258 | *scontext += strlen(*scontext)+1; | 258 | *scontext += strlen(*scontext)+1; |
259 | return 0; | 259 | return 0; |
@@ -387,7 +387,7 @@ int mls_from_string(char *str, struct context *context, gfp_t gfp_mask) | |||
387 | char *tmpstr, *freestr; | 387 | char *tmpstr, *freestr; |
388 | int rc; | 388 | int rc; |
389 | 389 | ||
390 | if (!selinux_mls_enabled) | 390 | if (!policydb.mls_enabled) |
391 | return -EINVAL; | 391 | return -EINVAL; |
392 | 392 | ||
393 | /* we need freestr because mls_context_to_sid will change | 393 | /* we need freestr because mls_context_to_sid will change |
@@ -407,7 +407,7 @@ int mls_from_string(char *str, struct context *context, gfp_t gfp_mask) | |||
407 | /* | 407 | /* |
408 | * Copies the MLS range `range' into `context'. | 408 | * Copies the MLS range `range' into `context'. |
409 | */ | 409 | */ |
410 | static inline int mls_range_set(struct context *context, | 410 | int mls_range_set(struct context *context, |
411 | struct mls_range *range) | 411 | struct mls_range *range) |
412 | { | 412 | { |
413 | int l, rc = 0; | 413 | int l, rc = 0; |
@@ -427,7 +427,7 @@ static inline int mls_range_set(struct context *context, | |||
427 | int mls_setup_user_range(struct context *fromcon, struct user_datum *user, | 427 | int mls_setup_user_range(struct context *fromcon, struct user_datum *user, |
428 | struct context *usercon) | 428 | struct context *usercon) |
429 | { | 429 | { |
430 | if (selinux_mls_enabled) { | 430 | if (policydb.mls_enabled) { |
431 | struct mls_level *fromcon_sen = &(fromcon->range.level[0]); | 431 | struct mls_level *fromcon_sen = &(fromcon->range.level[0]); |
432 | struct mls_level *fromcon_clr = &(fromcon->range.level[1]); | 432 | struct mls_level *fromcon_clr = &(fromcon->range.level[1]); |
433 | struct mls_level *user_low = &(user->range.level[0]); | 433 | struct mls_level *user_low = &(user->range.level[0]); |
@@ -477,7 +477,7 @@ int mls_convert_context(struct policydb *oldp, | |||
477 | struct ebitmap_node *node; | 477 | struct ebitmap_node *node; |
478 | int l, i; | 478 | int l, i; |
479 | 479 | ||
480 | if (!selinux_mls_enabled) | 480 | if (!policydb.mls_enabled) |
481 | return 0; | 481 | return 0; |
482 | 482 | ||
483 | for (l = 0; l < 2; l++) { | 483 | for (l = 0; l < 2; l++) { |
@@ -513,26 +513,24 @@ int mls_compute_sid(struct context *scontext, | |||
513 | u32 specified, | 513 | u32 specified, |
514 | struct context *newcontext) | 514 | struct context *newcontext) |
515 | { | 515 | { |
516 | struct range_trans *rtr; | 516 | struct range_trans rtr; |
517 | struct mls_range *r; | ||
517 | 518 | ||
518 | if (!selinux_mls_enabled) | 519 | if (!policydb.mls_enabled) |
519 | return 0; | 520 | return 0; |
520 | 521 | ||
521 | switch (specified) { | 522 | switch (specified) { |
522 | case AVTAB_TRANSITION: | 523 | case AVTAB_TRANSITION: |
523 | /* Look for a range transition rule. */ | 524 | /* Look for a range transition rule. */ |
524 | for (rtr = policydb.range_tr; rtr; rtr = rtr->next) { | 525 | rtr.source_type = scontext->type; |
525 | if (rtr->source_type == scontext->type && | 526 | rtr.target_type = tcontext->type; |
526 | rtr->target_type == tcontext->type && | 527 | rtr.target_class = tclass; |
527 | rtr->target_class == tclass) { | 528 | r = hashtab_search(policydb.range_tr, &rtr); |
528 | /* Set the range from the rule */ | 529 | if (r) |
529 | return mls_range_set(newcontext, | 530 | return mls_range_set(newcontext, r); |
530 | &rtr->target_range); | ||
531 | } | ||
532 | } | ||
533 | /* Fallthrough */ | 531 | /* Fallthrough */ |
534 | case AVTAB_CHANGE: | 532 | case AVTAB_CHANGE: |
535 | if (tclass == SECCLASS_PROCESS) | 533 | if (tclass == policydb.process_class) |
536 | /* Use the process MLS attributes. */ | 534 | /* Use the process MLS attributes. */ |
537 | return mls_context_cpy(newcontext, scontext); | 535 | return mls_context_cpy(newcontext, scontext); |
538 | else | 536 | else |
@@ -541,8 +539,8 @@ int mls_compute_sid(struct context *scontext, | |||
541 | case AVTAB_MEMBER: | 539 | case AVTAB_MEMBER: |
542 | /* Use the process effective MLS attributes. */ | 540 | /* Use the process effective MLS attributes. */ |
543 | return mls_context_cpy_low(newcontext, scontext); | 541 | return mls_context_cpy_low(newcontext, scontext); |
544 | default: | 542 | |
545 | return -EINVAL; | 543 | /* fall through */ |
546 | } | 544 | } |
547 | return -EINVAL; | 545 | return -EINVAL; |
548 | } | 546 | } |
@@ -561,7 +559,7 @@ int mls_compute_sid(struct context *scontext, | |||
561 | void mls_export_netlbl_lvl(struct context *context, | 559 | void mls_export_netlbl_lvl(struct context *context, |
562 | struct netlbl_lsm_secattr *secattr) | 560 | struct netlbl_lsm_secattr *secattr) |
563 | { | 561 | { |
564 | if (!selinux_mls_enabled) | 562 | if (!policydb.mls_enabled) |
565 | return; | 563 | return; |
566 | 564 | ||
567 | secattr->attr.mls.lvl = context->range.level[0].sens - 1; | 565 | secattr->attr.mls.lvl = context->range.level[0].sens - 1; |
@@ -581,7 +579,7 @@ void mls_export_netlbl_lvl(struct context *context, | |||
581 | void mls_import_netlbl_lvl(struct context *context, | 579 | void mls_import_netlbl_lvl(struct context *context, |
582 | struct netlbl_lsm_secattr *secattr) | 580 | struct netlbl_lsm_secattr *secattr) |
583 | { | 581 | { |
584 | if (!selinux_mls_enabled) | 582 | if (!policydb.mls_enabled) |
585 | return; | 583 | return; |
586 | 584 | ||
587 | context->range.level[0].sens = secattr->attr.mls.lvl + 1; | 585 | context->range.level[0].sens = secattr->attr.mls.lvl + 1; |
@@ -603,7 +601,7 @@ int mls_export_netlbl_cat(struct context *context, | |||
603 | { | 601 | { |
604 | int rc; | 602 | int rc; |
605 | 603 | ||
606 | if (!selinux_mls_enabled) | 604 | if (!policydb.mls_enabled) |
607 | return 0; | 605 | return 0; |
608 | 606 | ||
609 | rc = ebitmap_netlbl_export(&context->range.level[0].cat, | 607 | rc = ebitmap_netlbl_export(&context->range.level[0].cat, |
@@ -631,7 +629,7 @@ int mls_import_netlbl_cat(struct context *context, | |||
631 | { | 629 | { |
632 | int rc; | 630 | int rc; |
633 | 631 | ||
634 | if (!selinux_mls_enabled) | 632 | if (!policydb.mls_enabled) |
635 | return 0; | 633 | return 0; |
636 | 634 | ||
637 | rc = ebitmap_netlbl_import(&context->range.level[0].cat, | 635 | rc = ebitmap_netlbl_import(&context->range.level[0].cat, |
diff --git a/security/selinux/ss/mls.h b/security/selinux/ss/mls.h index 1276715aaa8b..cd9152632e54 100644 --- a/security/selinux/ss/mls.h +++ b/security/selinux/ss/mls.h | |||
@@ -39,6 +39,8 @@ int mls_context_to_sid(struct policydb *p, | |||
39 | 39 | ||
40 | int mls_from_string(char *str, struct context *context, gfp_t gfp_mask); | 40 | int mls_from_string(char *str, struct context *context, gfp_t gfp_mask); |
41 | 41 | ||
42 | int mls_range_set(struct context *context, struct mls_range *range); | ||
43 | |||
42 | int mls_convert_context(struct policydb *oldp, | 44 | int mls_convert_context(struct policydb *oldp, |
43 | struct policydb *newp, | 45 | struct policydb *newp, |
44 | struct context *context); | 46 | struct context *context); |
diff --git a/security/selinux/ss/mls_types.h b/security/selinux/ss/mls_types.h index b6e943a21061..03bed52a8052 100644 --- a/security/selinux/ss/mls_types.h +++ b/security/selinux/ss/mls_types.h | |||
@@ -15,6 +15,7 @@ | |||
15 | #define _SS_MLS_TYPES_H_ | 15 | #define _SS_MLS_TYPES_H_ |
16 | 16 | ||
17 | #include "security.h" | 17 | #include "security.h" |
18 | #include "ebitmap.h" | ||
18 | 19 | ||
19 | struct mls_level { | 20 | struct mls_level { |
20 | u32 sens; /* sensitivity */ | 21 | u32 sens; /* sensitivity */ |
@@ -27,18 +28,12 @@ struct mls_range { | |||
27 | 28 | ||
28 | static inline int mls_level_eq(struct mls_level *l1, struct mls_level *l2) | 29 | static inline int mls_level_eq(struct mls_level *l1, struct mls_level *l2) |
29 | { | 30 | { |
30 | if (!selinux_mls_enabled) | ||
31 | return 1; | ||
32 | |||
33 | return ((l1->sens == l2->sens) && | 31 | return ((l1->sens == l2->sens) && |
34 | ebitmap_cmp(&l1->cat, &l2->cat)); | 32 | ebitmap_cmp(&l1->cat, &l2->cat)); |
35 | } | 33 | } |
36 | 34 | ||
37 | static inline int mls_level_dom(struct mls_level *l1, struct mls_level *l2) | 35 | static inline int mls_level_dom(struct mls_level *l1, struct mls_level *l2) |
38 | { | 36 | { |
39 | if (!selinux_mls_enabled) | ||
40 | return 1; | ||
41 | |||
42 | return ((l1->sens >= l2->sens) && | 37 | return ((l1->sens >= l2->sens) && |
43 | ebitmap_contains(&l1->cat, &l2->cat)); | 38 | ebitmap_contains(&l1->cat, &l2->cat)); |
44 | } | 39 | } |
diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c index 72e4a54973aa..23c6e53c102c 100644 --- a/security/selinux/ss/policydb.c +++ b/security/selinux/ss/policydb.c | |||
@@ -52,8 +52,6 @@ static char *symtab_name[SYM_NUM] = { | |||
52 | }; | 52 | }; |
53 | #endif | 53 | #endif |
54 | 54 | ||
55 | int selinux_mls_enabled; | ||
56 | |||
57 | static unsigned int symtab_sizes[SYM_NUM] = { | 55 | static unsigned int symtab_sizes[SYM_NUM] = { |
58 | 2, | 56 | 2, |
59 | 32, | 57 | 32, |
@@ -177,6 +175,21 @@ out_free_role: | |||
177 | goto out; | 175 | goto out; |
178 | } | 176 | } |
179 | 177 | ||
178 | static u32 rangetr_hash(struct hashtab *h, const void *k) | ||
179 | { | ||
180 | const struct range_trans *key = k; | ||
181 | return (key->source_type + (key->target_type << 3) + | ||
182 | (key->target_class << 5)) & (h->size - 1); | ||
183 | } | ||
184 | |||
185 | static int rangetr_cmp(struct hashtab *h, const void *k1, const void *k2) | ||
186 | { | ||
187 | const struct range_trans *key1 = k1, *key2 = k2; | ||
188 | return (key1->source_type != key2->source_type || | ||
189 | key1->target_type != key2->target_type || | ||
190 | key1->target_class != key2->target_class); | ||
191 | } | ||
192 | |||
180 | /* | 193 | /* |
181 | * Initialize a policy database structure. | 194 | * Initialize a policy database structure. |
182 | */ | 195 | */ |
@@ -204,6 +217,10 @@ static int policydb_init(struct policydb *p) | |||
204 | if (rc) | 217 | if (rc) |
205 | goto out_free_symtab; | 218 | goto out_free_symtab; |
206 | 219 | ||
220 | p->range_tr = hashtab_create(rangetr_hash, rangetr_cmp, 256); | ||
221 | if (!p->range_tr) | ||
222 | goto out_free_symtab; | ||
223 | |||
207 | ebitmap_init(&p->policycaps); | 224 | ebitmap_init(&p->policycaps); |
208 | ebitmap_init(&p->permissive_map); | 225 | ebitmap_init(&p->permissive_map); |
209 | 226 | ||
@@ -408,6 +425,20 @@ static void symtab_hash_eval(struct symtab *s) | |||
408 | info.slots_used, h->size, info.max_chain_len); | 425 | info.slots_used, h->size, info.max_chain_len); |
409 | } | 426 | } |
410 | } | 427 | } |
428 | |||
429 | static void rangetr_hash_eval(struct hashtab *h) | ||
430 | { | ||
431 | struct hashtab_info info; | ||
432 | |||
433 | hashtab_stat(h, &info); | ||
434 | printk(KERN_DEBUG "SELinux: rangetr: %d entries and %d/%d buckets used, " | ||
435 | "longest chain length %d\n", h->nel, | ||
436 | info.slots_used, h->size, info.max_chain_len); | ||
437 | } | ||
438 | #else | ||
439 | static inline void rangetr_hash_eval(struct hashtab *h) | ||
440 | { | ||
441 | } | ||
411 | #endif | 442 | #endif |
412 | 443 | ||
413 | /* | 444 | /* |
@@ -422,7 +453,7 @@ static int policydb_index_others(struct policydb *p) | |||
422 | 453 | ||
423 | printk(KERN_DEBUG "SELinux: %d users, %d roles, %d types, %d bools", | 454 | printk(KERN_DEBUG "SELinux: %d users, %d roles, %d types, %d bools", |
424 | p->p_users.nprim, p->p_roles.nprim, p->p_types.nprim, p->p_bools.nprim); | 455 | p->p_users.nprim, p->p_roles.nprim, p->p_types.nprim, p->p_bools.nprim); |
425 | if (selinux_mls_enabled) | 456 | if (p->mls_enabled) |
426 | printk(", %d sens, %d cats", p->p_levels.nprim, | 457 | printk(", %d sens, %d cats", p->p_levels.nprim, |
427 | p->p_cats.nprim); | 458 | p->p_cats.nprim); |
428 | printk("\n"); | 459 | printk("\n"); |
@@ -612,6 +643,17 @@ static int (*destroy_f[SYM_NUM]) (void *key, void *datum, void *datap) = | |||
612 | cat_destroy, | 643 | cat_destroy, |
613 | }; | 644 | }; |
614 | 645 | ||
646 | static int range_tr_destroy(void *key, void *datum, void *p) | ||
647 | { | ||
648 | struct mls_range *rt = datum; | ||
649 | kfree(key); | ||
650 | ebitmap_destroy(&rt->level[0].cat); | ||
651 | ebitmap_destroy(&rt->level[1].cat); | ||
652 | kfree(datum); | ||
653 | cond_resched(); | ||
654 | return 0; | ||
655 | } | ||
656 | |||
615 | static void ocontext_destroy(struct ocontext *c, int i) | 657 | static void ocontext_destroy(struct ocontext *c, int i) |
616 | { | 658 | { |
617 | context_destroy(&c->context[0]); | 659 | context_destroy(&c->context[0]); |
@@ -632,7 +674,6 @@ void policydb_destroy(struct policydb *p) | |||
632 | int i; | 674 | int i; |
633 | struct role_allow *ra, *lra = NULL; | 675 | struct role_allow *ra, *lra = NULL; |
634 | struct role_trans *tr, *ltr = NULL; | 676 | struct role_trans *tr, *ltr = NULL; |
635 | struct range_trans *rt, *lrt = NULL; | ||
636 | 677 | ||
637 | for (i = 0; i < SYM_NUM; i++) { | 678 | for (i = 0; i < SYM_NUM; i++) { |
638 | cond_resched(); | 679 | cond_resched(); |
@@ -693,27 +734,14 @@ void policydb_destroy(struct policydb *p) | |||
693 | } | 734 | } |
694 | kfree(lra); | 735 | kfree(lra); |
695 | 736 | ||
696 | for (rt = p->range_tr; rt; rt = rt->next) { | 737 | hashtab_map(p->range_tr, range_tr_destroy, NULL); |
697 | cond_resched(); | 738 | hashtab_destroy(p->range_tr); |
698 | if (lrt) { | ||
699 | ebitmap_destroy(&lrt->target_range.level[0].cat); | ||
700 | ebitmap_destroy(&lrt->target_range.level[1].cat); | ||
701 | kfree(lrt); | ||
702 | } | ||
703 | lrt = rt; | ||
704 | } | ||
705 | if (lrt) { | ||
706 | ebitmap_destroy(&lrt->target_range.level[0].cat); | ||
707 | ebitmap_destroy(&lrt->target_range.level[1].cat); | ||
708 | kfree(lrt); | ||
709 | } | ||
710 | 739 | ||
711 | if (p->type_attr_map) { | 740 | if (p->type_attr_map) { |
712 | for (i = 0; i < p->p_types.nprim; i++) | 741 | for (i = 0; i < p->p_types.nprim; i++) |
713 | ebitmap_destroy(&p->type_attr_map[i]); | 742 | ebitmap_destroy(&p->type_attr_map[i]); |
714 | } | 743 | } |
715 | kfree(p->type_attr_map); | 744 | kfree(p->type_attr_map); |
716 | kfree(p->undefined_perms); | ||
717 | ebitmap_destroy(&p->policycaps); | 745 | ebitmap_destroy(&p->policycaps); |
718 | ebitmap_destroy(&p->permissive_map); | 746 | ebitmap_destroy(&p->permissive_map); |
719 | 747 | ||
@@ -1640,6 +1668,40 @@ static int policydb_bounds_sanity_check(struct policydb *p) | |||
1640 | 1668 | ||
1641 | extern int ss_initialized; | 1669 | extern int ss_initialized; |
1642 | 1670 | ||
1671 | u16 string_to_security_class(struct policydb *p, const char *name) | ||
1672 | { | ||
1673 | struct class_datum *cladatum; | ||
1674 | |||
1675 | cladatum = hashtab_search(p->p_classes.table, name); | ||
1676 | if (!cladatum) | ||
1677 | return 0; | ||
1678 | |||
1679 | return cladatum->value; | ||
1680 | } | ||
1681 | |||
1682 | u32 string_to_av_perm(struct policydb *p, u16 tclass, const char *name) | ||
1683 | { | ||
1684 | struct class_datum *cladatum; | ||
1685 | struct perm_datum *perdatum = NULL; | ||
1686 | struct common_datum *comdatum; | ||
1687 | |||
1688 | if (!tclass || tclass > p->p_classes.nprim) | ||
1689 | return 0; | ||
1690 | |||
1691 | cladatum = p->class_val_to_struct[tclass-1]; | ||
1692 | comdatum = cladatum->comdatum; | ||
1693 | if (comdatum) | ||
1694 | perdatum = hashtab_search(comdatum->permissions.table, | ||
1695 | name); | ||
1696 | if (!perdatum) | ||
1697 | perdatum = hashtab_search(cladatum->permissions.table, | ||
1698 | name); | ||
1699 | if (!perdatum) | ||
1700 | return 0; | ||
1701 | |||
1702 | return 1U << (perdatum->value-1); | ||
1703 | } | ||
1704 | |||
1643 | /* | 1705 | /* |
1644 | * Read the configuration data from a policy database binary | 1706 | * Read the configuration data from a policy database binary |
1645 | * representation file into a policy database structure. | 1707 | * representation file into a policy database structure. |
@@ -1653,12 +1715,11 @@ int policydb_read(struct policydb *p, void *fp) | |||
1653 | int i, j, rc; | 1715 | int i, j, rc; |
1654 | __le32 buf[4]; | 1716 | __le32 buf[4]; |
1655 | u32 nodebuf[8]; | 1717 | u32 nodebuf[8]; |
1656 | u32 len, len2, config, nprim, nel, nel2; | 1718 | u32 len, len2, nprim, nel, nel2; |
1657 | char *policydb_str; | 1719 | char *policydb_str; |
1658 | struct policydb_compat_info *info; | 1720 | struct policydb_compat_info *info; |
1659 | struct range_trans *rt, *lrt; | 1721 | struct range_trans *rt; |
1660 | 1722 | struct mls_range *r; | |
1661 | config = 0; | ||
1662 | 1723 | ||
1663 | rc = policydb_init(p); | 1724 | rc = policydb_init(p); |
1664 | if (rc) | 1725 | if (rc) |
@@ -1707,7 +1768,7 @@ int policydb_read(struct policydb *p, void *fp) | |||
1707 | kfree(policydb_str); | 1768 | kfree(policydb_str); |
1708 | policydb_str = NULL; | 1769 | policydb_str = NULL; |
1709 | 1770 | ||
1710 | /* Read the version, config, and table sizes. */ | 1771 | /* Read the version and table sizes. */ |
1711 | rc = next_entry(buf, fp, sizeof(u32)*4); | 1772 | rc = next_entry(buf, fp, sizeof(u32)*4); |
1712 | if (rc < 0) | 1773 | if (rc < 0) |
1713 | goto bad; | 1774 | goto bad; |
@@ -1722,13 +1783,7 @@ int policydb_read(struct policydb *p, void *fp) | |||
1722 | } | 1783 | } |
1723 | 1784 | ||
1724 | if ((le32_to_cpu(buf[1]) & POLICYDB_CONFIG_MLS)) { | 1785 | if ((le32_to_cpu(buf[1]) & POLICYDB_CONFIG_MLS)) { |
1725 | if (ss_initialized && !selinux_mls_enabled) { | 1786 | p->mls_enabled = 1; |
1726 | printk(KERN_ERR "SELinux: Cannot switch between non-MLS" | ||
1727 | " and MLS policies\n"); | ||
1728 | goto bad; | ||
1729 | } | ||
1730 | selinux_mls_enabled = 1; | ||
1731 | config |= POLICYDB_CONFIG_MLS; | ||
1732 | 1787 | ||
1733 | if (p->policyvers < POLICYDB_VERSION_MLS) { | 1788 | if (p->policyvers < POLICYDB_VERSION_MLS) { |
1734 | printk(KERN_ERR "SELinux: security policydb version %d " | 1789 | printk(KERN_ERR "SELinux: security policydb version %d " |
@@ -1736,12 +1791,6 @@ int policydb_read(struct policydb *p, void *fp) | |||
1736 | p->policyvers); | 1791 | p->policyvers); |
1737 | goto bad; | 1792 | goto bad; |
1738 | } | 1793 | } |
1739 | } else { | ||
1740 | if (ss_initialized && selinux_mls_enabled) { | ||
1741 | printk(KERN_ERR "SELinux: Cannot switch between MLS and" | ||
1742 | " non-MLS policies\n"); | ||
1743 | goto bad; | ||
1744 | } | ||
1745 | } | 1794 | } |
1746 | p->reject_unknown = !!(le32_to_cpu(buf[1]) & REJECT_UNKNOWN); | 1795 | p->reject_unknown = !!(le32_to_cpu(buf[1]) & REJECT_UNKNOWN); |
1747 | p->allow_unknown = !!(le32_to_cpu(buf[1]) & ALLOW_UNKNOWN); | 1796 | p->allow_unknown = !!(le32_to_cpu(buf[1]) & ALLOW_UNKNOWN); |
@@ -1861,6 +1910,16 @@ int policydb_read(struct policydb *p, void *fp) | |||
1861 | if (rc) | 1910 | if (rc) |
1862 | goto bad; | 1911 | goto bad; |
1863 | 1912 | ||
1913 | p->process_class = string_to_security_class(p, "process"); | ||
1914 | if (!p->process_class) | ||
1915 | goto bad; | ||
1916 | p->process_trans_perms = string_to_av_perm(p, p->process_class, | ||
1917 | "transition"); | ||
1918 | p->process_trans_perms |= string_to_av_perm(p, p->process_class, | ||
1919 | "dyntransition"); | ||
1920 | if (!p->process_trans_perms) | ||
1921 | goto bad; | ||
1922 | |||
1864 | for (i = 0; i < info->ocon_num; i++) { | 1923 | for (i = 0; i < info->ocon_num; i++) { |
1865 | rc = next_entry(buf, fp, sizeof(u32)); | 1924 | rc = next_entry(buf, fp, sizeof(u32)); |
1866 | if (rc < 0) | 1925 | if (rc < 0) |
@@ -2079,44 +2138,61 @@ int policydb_read(struct policydb *p, void *fp) | |||
2079 | if (rc < 0) | 2138 | if (rc < 0) |
2080 | goto bad; | 2139 | goto bad; |
2081 | nel = le32_to_cpu(buf[0]); | 2140 | nel = le32_to_cpu(buf[0]); |
2082 | lrt = NULL; | ||
2083 | for (i = 0; i < nel; i++) { | 2141 | for (i = 0; i < nel; i++) { |
2084 | rt = kzalloc(sizeof(*rt), GFP_KERNEL); | 2142 | rt = kzalloc(sizeof(*rt), GFP_KERNEL); |
2085 | if (!rt) { | 2143 | if (!rt) { |
2086 | rc = -ENOMEM; | 2144 | rc = -ENOMEM; |
2087 | goto bad; | 2145 | goto bad; |
2088 | } | 2146 | } |
2089 | if (lrt) | ||
2090 | lrt->next = rt; | ||
2091 | else | ||
2092 | p->range_tr = rt; | ||
2093 | rc = next_entry(buf, fp, (sizeof(u32) * 2)); | 2147 | rc = next_entry(buf, fp, (sizeof(u32) * 2)); |
2094 | if (rc < 0) | 2148 | if (rc < 0) { |
2149 | kfree(rt); | ||
2095 | goto bad; | 2150 | goto bad; |
2151 | } | ||
2096 | rt->source_type = le32_to_cpu(buf[0]); | 2152 | rt->source_type = le32_to_cpu(buf[0]); |
2097 | rt->target_type = le32_to_cpu(buf[1]); | 2153 | rt->target_type = le32_to_cpu(buf[1]); |
2098 | if (new_rangetr) { | 2154 | if (new_rangetr) { |
2099 | rc = next_entry(buf, fp, sizeof(u32)); | 2155 | rc = next_entry(buf, fp, sizeof(u32)); |
2100 | if (rc < 0) | 2156 | if (rc < 0) { |
2157 | kfree(rt); | ||
2101 | goto bad; | 2158 | goto bad; |
2159 | } | ||
2102 | rt->target_class = le32_to_cpu(buf[0]); | 2160 | rt->target_class = le32_to_cpu(buf[0]); |
2103 | } else | 2161 | } else |
2104 | rt->target_class = SECCLASS_PROCESS; | 2162 | rt->target_class = p->process_class; |
2105 | if (!policydb_type_isvalid(p, rt->source_type) || | 2163 | if (!policydb_type_isvalid(p, rt->source_type) || |
2106 | !policydb_type_isvalid(p, rt->target_type) || | 2164 | !policydb_type_isvalid(p, rt->target_type) || |
2107 | !policydb_class_isvalid(p, rt->target_class)) { | 2165 | !policydb_class_isvalid(p, rt->target_class)) { |
2166 | kfree(rt); | ||
2108 | rc = -EINVAL; | 2167 | rc = -EINVAL; |
2109 | goto bad; | 2168 | goto bad; |
2110 | } | 2169 | } |
2111 | rc = mls_read_range_helper(&rt->target_range, fp); | 2170 | r = kzalloc(sizeof(*r), GFP_KERNEL); |
2112 | if (rc) | 2171 | if (!r) { |
2172 | kfree(rt); | ||
2173 | rc = -ENOMEM; | ||
2174 | goto bad; | ||
2175 | } | ||
2176 | rc = mls_read_range_helper(r, fp); | ||
2177 | if (rc) { | ||
2178 | kfree(rt); | ||
2179 | kfree(r); | ||
2113 | goto bad; | 2180 | goto bad; |
2114 | if (!mls_range_isvalid(p, &rt->target_range)) { | 2181 | } |
2182 | if (!mls_range_isvalid(p, r)) { | ||
2115 | printk(KERN_WARNING "SELinux: rangetrans: invalid range\n"); | 2183 | printk(KERN_WARNING "SELinux: rangetrans: invalid range\n"); |
2184 | kfree(rt); | ||
2185 | kfree(r); | ||
2186 | goto bad; | ||
2187 | } | ||
2188 | rc = hashtab_insert(p->range_tr, rt, r); | ||
2189 | if (rc) { | ||
2190 | kfree(rt); | ||
2191 | kfree(r); | ||
2116 | goto bad; | 2192 | goto bad; |
2117 | } | 2193 | } |
2118 | lrt = rt; | ||
2119 | } | 2194 | } |
2195 | rangetr_hash_eval(p->range_tr); | ||
2120 | } | 2196 | } |
2121 | 2197 | ||
2122 | p->type_attr_map = kmalloc(p->p_types.nprim*sizeof(struct ebitmap), GFP_KERNEL); | 2198 | p->type_attr_map = kmalloc(p->p_types.nprim*sizeof(struct ebitmap), GFP_KERNEL); |
diff --git a/security/selinux/ss/policydb.h b/security/selinux/ss/policydb.h index 55152d498b53..26d9adf8542b 100644 --- a/security/selinux/ss/policydb.h +++ b/security/selinux/ss/policydb.h | |||
@@ -27,6 +27,8 @@ | |||
27 | #include "symtab.h" | 27 | #include "symtab.h" |
28 | #include "avtab.h" | 28 | #include "avtab.h" |
29 | #include "sidtab.h" | 29 | #include "sidtab.h" |
30 | #include "ebitmap.h" | ||
31 | #include "mls_types.h" | ||
30 | #include "context.h" | 32 | #include "context.h" |
31 | #include "constraint.h" | 33 | #include "constraint.h" |
32 | 34 | ||
@@ -113,8 +115,6 @@ struct range_trans { | |||
113 | u32 source_type; | 115 | u32 source_type; |
114 | u32 target_type; | 116 | u32 target_type; |
115 | u32 target_class; | 117 | u32 target_class; |
116 | struct mls_range target_range; | ||
117 | struct range_trans *next; | ||
118 | }; | 118 | }; |
119 | 119 | ||
120 | /* Boolean data type */ | 120 | /* Boolean data type */ |
@@ -187,6 +187,8 @@ struct genfs { | |||
187 | 187 | ||
188 | /* The policy database */ | 188 | /* The policy database */ |
189 | struct policydb { | 189 | struct policydb { |
190 | int mls_enabled; | ||
191 | |||
190 | /* symbol tables */ | 192 | /* symbol tables */ |
191 | struct symtab symtab[SYM_NUM]; | 193 | struct symtab symtab[SYM_NUM]; |
192 | #define p_commons symtab[SYM_COMMONS] | 194 | #define p_commons symtab[SYM_COMMONS] |
@@ -240,8 +242,8 @@ struct policydb { | |||
240 | fixed labeling behavior. */ | 242 | fixed labeling behavior. */ |
241 | struct genfs *genfs; | 243 | struct genfs *genfs; |
242 | 244 | ||
243 | /* range transitions */ | 245 | /* range transitions table (range_trans_key -> mls_range) */ |
244 | struct range_trans *range_tr; | 246 | struct hashtab *range_tr; |
245 | 247 | ||
246 | /* type -> attribute reverse mapping */ | 248 | /* type -> attribute reverse mapping */ |
247 | struct ebitmap *type_attr_map; | 249 | struct ebitmap *type_attr_map; |
@@ -254,7 +256,9 @@ struct policydb { | |||
254 | 256 | ||
255 | unsigned int reject_unknown : 1; | 257 | unsigned int reject_unknown : 1; |
256 | unsigned int allow_unknown : 1; | 258 | unsigned int allow_unknown : 1; |
257 | u32 *undefined_perms; | 259 | |
260 | u16 process_class; | ||
261 | u32 process_trans_perms; | ||
258 | }; | 262 | }; |
259 | 263 | ||
260 | extern void policydb_destroy(struct policydb *p); | 264 | extern void policydb_destroy(struct policydb *p); |
@@ -295,5 +299,8 @@ static inline int next_entry(void *buf, struct policy_file *fp, size_t bytes) | |||
295 | return 0; | 299 | return 0; |
296 | } | 300 | } |
297 | 301 | ||
302 | extern u16 string_to_security_class(struct policydb *p, const char *name); | ||
303 | extern u32 string_to_av_perm(struct policydb *p, u16 tclass, const char *name); | ||
304 | |||
298 | #endif /* _SS_POLICYDB_H_ */ | 305 | #endif /* _SS_POLICYDB_H_ */ |
299 | 306 | ||
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index ff17820d35ec..cf27b3ee1a95 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c | |||
@@ -26,6 +26,10 @@ | |||
26 | * | 26 | * |
27 | * Added support for bounds domain and audit messaged on masked permissions | 27 | * Added support for bounds domain and audit messaged on masked permissions |
28 | * | 28 | * |
29 | * Updated: Guido Trentalancia <guido@trentalancia.com> | ||
30 | * | ||
31 | * Added support for runtime switching of the policy type | ||
32 | * | ||
29 | * Copyright (C) 2008, 2009 NEC Corporation | 33 | * Copyright (C) 2008, 2009 NEC Corporation |
30 | * Copyright (C) 2006, 2007 Hewlett-Packard Development Company, L.P. | 34 | * Copyright (C) 2006, 2007 Hewlett-Packard Development Company, L.P. |
31 | * Copyright (C) 2004-2006 Trusted Computer Solutions, Inc. | 35 | * Copyright (C) 2004-2006 Trusted Computer Solutions, Inc. |
@@ -65,16 +69,10 @@ | |||
65 | #include "audit.h" | 69 | #include "audit.h" |
66 | 70 | ||
67 | extern void selnl_notify_policyload(u32 seqno); | 71 | extern void selnl_notify_policyload(u32 seqno); |
68 | unsigned int policydb_loaded_version; | ||
69 | 72 | ||
70 | int selinux_policycap_netpeer; | 73 | int selinux_policycap_netpeer; |
71 | int selinux_policycap_openperm; | 74 | int selinux_policycap_openperm; |
72 | 75 | ||
73 | /* | ||
74 | * This is declared in avc.c | ||
75 | */ | ||
76 | extern const struct selinux_class_perm selinux_class_perm; | ||
77 | |||
78 | static DEFINE_RWLOCK(policy_rwlock); | 76 | static DEFINE_RWLOCK(policy_rwlock); |
79 | 77 | ||
80 | static struct sidtab sidtab; | 78 | static struct sidtab sidtab; |
@@ -93,11 +91,156 @@ static u32 latest_granting; | |||
93 | static int context_struct_to_string(struct context *context, char **scontext, | 91 | static int context_struct_to_string(struct context *context, char **scontext, |
94 | u32 *scontext_len); | 92 | u32 *scontext_len); |
95 | 93 | ||
96 | static int context_struct_compute_av(struct context *scontext, | 94 | static void context_struct_compute_av(struct context *scontext, |
97 | struct context *tcontext, | 95 | struct context *tcontext, |
98 | u16 tclass, | 96 | u16 tclass, |
99 | u32 requested, | 97 | struct av_decision *avd); |
100 | struct av_decision *avd); | 98 | |
99 | struct selinux_mapping { | ||
100 | u16 value; /* policy value */ | ||
101 | unsigned num_perms; | ||
102 | u32 perms[sizeof(u32) * 8]; | ||
103 | }; | ||
104 | |||
105 | static struct selinux_mapping *current_mapping; | ||
106 | static u16 current_mapping_size; | ||
107 | |||
108 | static int selinux_set_mapping(struct policydb *pol, | ||
109 | struct security_class_mapping *map, | ||
110 | struct selinux_mapping **out_map_p, | ||
111 | u16 *out_map_size) | ||
112 | { | ||
113 | struct selinux_mapping *out_map = NULL; | ||
114 | size_t size = sizeof(struct selinux_mapping); | ||
115 | u16 i, j; | ||
116 | unsigned k; | ||
117 | bool print_unknown_handle = false; | ||
118 | |||
119 | /* Find number of classes in the input mapping */ | ||
120 | if (!map) | ||
121 | return -EINVAL; | ||
122 | i = 0; | ||
123 | while (map[i].name) | ||
124 | i++; | ||
125 | |||
126 | /* Allocate space for the class records, plus one for class zero */ | ||
127 | out_map = kcalloc(++i, size, GFP_ATOMIC); | ||
128 | if (!out_map) | ||
129 | return -ENOMEM; | ||
130 | |||
131 | /* Store the raw class and permission values */ | ||
132 | j = 0; | ||
133 | while (map[j].name) { | ||
134 | struct security_class_mapping *p_in = map + (j++); | ||
135 | struct selinux_mapping *p_out = out_map + j; | ||
136 | |||
137 | /* An empty class string skips ahead */ | ||
138 | if (!strcmp(p_in->name, "")) { | ||
139 | p_out->num_perms = 0; | ||
140 | continue; | ||
141 | } | ||
142 | |||
143 | p_out->value = string_to_security_class(pol, p_in->name); | ||
144 | if (!p_out->value) { | ||
145 | printk(KERN_INFO | ||
146 | "SELinux: Class %s not defined in policy.\n", | ||
147 | p_in->name); | ||
148 | if (pol->reject_unknown) | ||
149 | goto err; | ||
150 | p_out->num_perms = 0; | ||
151 | print_unknown_handle = true; | ||
152 | continue; | ||
153 | } | ||
154 | |||
155 | k = 0; | ||
156 | while (p_in->perms && p_in->perms[k]) { | ||
157 | /* An empty permission string skips ahead */ | ||
158 | if (!*p_in->perms[k]) { | ||
159 | k++; | ||
160 | continue; | ||
161 | } | ||
162 | p_out->perms[k] = string_to_av_perm(pol, p_out->value, | ||
163 | p_in->perms[k]); | ||
164 | if (!p_out->perms[k]) { | ||
165 | printk(KERN_INFO | ||
166 | "SELinux: Permission %s in class %s not defined in policy.\n", | ||
167 | p_in->perms[k], p_in->name); | ||
168 | if (pol->reject_unknown) | ||
169 | goto err; | ||
170 | print_unknown_handle = true; | ||
171 | } | ||
172 | |||
173 | k++; | ||
174 | } | ||
175 | p_out->num_perms = k; | ||
176 | } | ||
177 | |||
178 | if (print_unknown_handle) | ||
179 | printk(KERN_INFO "SELinux: the above unknown classes and permissions will be %s\n", | ||
180 | pol->allow_unknown ? "allowed" : "denied"); | ||
181 | |||
182 | *out_map_p = out_map; | ||
183 | *out_map_size = i; | ||
184 | return 0; | ||
185 | err: | ||
186 | kfree(out_map); | ||
187 | return -EINVAL; | ||
188 | } | ||
189 | |||
190 | /* | ||
191 | * Get real, policy values from mapped values | ||
192 | */ | ||
193 | |||
194 | static u16 unmap_class(u16 tclass) | ||
195 | { | ||
196 | if (tclass < current_mapping_size) | ||
197 | return current_mapping[tclass].value; | ||
198 | |||
199 | return tclass; | ||
200 | } | ||
201 | |||
202 | static void map_decision(u16 tclass, struct av_decision *avd, | ||
203 | int allow_unknown) | ||
204 | { | ||
205 | if (tclass < current_mapping_size) { | ||
206 | unsigned i, n = current_mapping[tclass].num_perms; | ||
207 | u32 result; | ||
208 | |||
209 | for (i = 0, result = 0; i < n; i++) { | ||
210 | if (avd->allowed & current_mapping[tclass].perms[i]) | ||
211 | result |= 1<<i; | ||
212 | if (allow_unknown && !current_mapping[tclass].perms[i]) | ||
213 | result |= 1<<i; | ||
214 | } | ||
215 | avd->allowed = result; | ||
216 | |||
217 | for (i = 0, result = 0; i < n; i++) | ||
218 | if (avd->auditallow & current_mapping[tclass].perms[i]) | ||
219 | result |= 1<<i; | ||
220 | avd->auditallow = result; | ||
221 | |||
222 | for (i = 0, result = 0; i < n; i++) { | ||
223 | if (avd->auditdeny & current_mapping[tclass].perms[i]) | ||
224 | result |= 1<<i; | ||
225 | if (!allow_unknown && !current_mapping[tclass].perms[i]) | ||
226 | result |= 1<<i; | ||
227 | } | ||
228 | /* | ||
229 | * In case the kernel has a bug and requests a permission | ||
230 | * between num_perms and the maximum permission number, we | ||
231 | * should audit that denial | ||
232 | */ | ||
233 | for (; i < (sizeof(u32)*8); i++) | ||
234 | result |= 1<<i; | ||
235 | avd->auditdeny = result; | ||
236 | } | ||
237 | } | ||
238 | |||
239 | int security_mls_enabled(void) | ||
240 | { | ||
241 | return policydb.mls_enabled; | ||
242 | } | ||
243 | |||
101 | /* | 244 | /* |
102 | * Return the boolean value of a constraint expression | 245 | * Return the boolean value of a constraint expression |
103 | * when it is applied to the specified source and target | 246 | * when it is applied to the specified source and target |
@@ -312,7 +455,8 @@ static void security_dump_masked_av(struct context *scontext, | |||
312 | char *scontext_name = NULL; | 455 | char *scontext_name = NULL; |
313 | char *tcontext_name = NULL; | 456 | char *tcontext_name = NULL; |
314 | char *permission_names[32]; | 457 | char *permission_names[32]; |
315 | int index, length; | 458 | int index; |
459 | u32 length; | ||
316 | bool need_comma = false; | 460 | bool need_comma = false; |
317 | 461 | ||
318 | if (!permissions) | 462 | if (!permissions) |
@@ -379,7 +523,6 @@ out: | |||
379 | static void type_attribute_bounds_av(struct context *scontext, | 523 | static void type_attribute_bounds_av(struct context *scontext, |
380 | struct context *tcontext, | 524 | struct context *tcontext, |
381 | u16 tclass, | 525 | u16 tclass, |
382 | u32 requested, | ||
383 | struct av_decision *avd) | 526 | struct av_decision *avd) |
384 | { | 527 | { |
385 | struct context lo_scontext; | 528 | struct context lo_scontext; |
@@ -400,7 +543,6 @@ static void type_attribute_bounds_av(struct context *scontext, | |||
400 | context_struct_compute_av(&lo_scontext, | 543 | context_struct_compute_av(&lo_scontext, |
401 | tcontext, | 544 | tcontext, |
402 | tclass, | 545 | tclass, |
403 | requested, | ||
404 | &lo_avd); | 546 | &lo_avd); |
405 | if ((lo_avd.allowed & avd->allowed) == avd->allowed) | 547 | if ((lo_avd.allowed & avd->allowed) == avd->allowed) |
406 | return; /* no masked permission */ | 548 | return; /* no masked permission */ |
@@ -416,7 +558,6 @@ static void type_attribute_bounds_av(struct context *scontext, | |||
416 | context_struct_compute_av(scontext, | 558 | context_struct_compute_av(scontext, |
417 | &lo_tcontext, | 559 | &lo_tcontext, |
418 | tclass, | 560 | tclass, |
419 | requested, | ||
420 | &lo_avd); | 561 | &lo_avd); |
421 | if ((lo_avd.allowed & avd->allowed) == avd->allowed) | 562 | if ((lo_avd.allowed & avd->allowed) == avd->allowed) |
422 | return; /* no masked permission */ | 563 | return; /* no masked permission */ |
@@ -433,7 +574,6 @@ static void type_attribute_bounds_av(struct context *scontext, | |||
433 | context_struct_compute_av(&lo_scontext, | 574 | context_struct_compute_av(&lo_scontext, |
434 | &lo_tcontext, | 575 | &lo_tcontext, |
435 | tclass, | 576 | tclass, |
436 | requested, | ||
437 | &lo_avd); | 577 | &lo_avd); |
438 | if ((lo_avd.allowed & avd->allowed) == avd->allowed) | 578 | if ((lo_avd.allowed & avd->allowed) == avd->allowed) |
439 | return; /* no masked permission */ | 579 | return; /* no masked permission */ |
@@ -454,11 +594,10 @@ static void type_attribute_bounds_av(struct context *scontext, | |||
454 | * Compute access vectors based on a context structure pair for | 594 | * Compute access vectors based on a context structure pair for |
455 | * the permissions in a particular class. | 595 | * the permissions in a particular class. |
456 | */ | 596 | */ |
457 | static int context_struct_compute_av(struct context *scontext, | 597 | static void context_struct_compute_av(struct context *scontext, |
458 | struct context *tcontext, | 598 | struct context *tcontext, |
459 | u16 tclass, | 599 | u16 tclass, |
460 | u32 requested, | 600 | struct av_decision *avd) |
461 | struct av_decision *avd) | ||
462 | { | 601 | { |
463 | struct constraint_node *constraint; | 602 | struct constraint_node *constraint; |
464 | struct role_allow *ra; | 603 | struct role_allow *ra; |
@@ -467,56 +606,17 @@ static int context_struct_compute_av(struct context *scontext, | |||
467 | struct class_datum *tclass_datum; | 606 | struct class_datum *tclass_datum; |
468 | struct ebitmap *sattr, *tattr; | 607 | struct ebitmap *sattr, *tattr; |
469 | struct ebitmap_node *snode, *tnode; | 608 | struct ebitmap_node *snode, *tnode; |
470 | const struct selinux_class_perm *kdefs = &selinux_class_perm; | ||
471 | unsigned int i, j; | 609 | unsigned int i, j; |
472 | 610 | ||
473 | /* | ||
474 | * Remap extended Netlink classes for old policy versions. | ||
475 | * Do this here rather than socket_type_to_security_class() | ||
476 | * in case a newer policy version is loaded, allowing sockets | ||
477 | * to remain in the correct class. | ||
478 | */ | ||
479 | if (policydb_loaded_version < POLICYDB_VERSION_NLCLASS) | ||
480 | if (tclass >= SECCLASS_NETLINK_ROUTE_SOCKET && | ||
481 | tclass <= SECCLASS_NETLINK_DNRT_SOCKET) | ||
482 | tclass = SECCLASS_NETLINK_SOCKET; | ||
483 | |||
484 | /* | ||
485 | * Initialize the access vectors to the default values. | ||
486 | */ | ||
487 | avd->allowed = 0; | 611 | avd->allowed = 0; |
488 | avd->auditallow = 0; | 612 | avd->auditallow = 0; |
489 | avd->auditdeny = 0xffffffff; | 613 | avd->auditdeny = 0xffffffff; |
490 | avd->seqno = latest_granting; | ||
491 | avd->flags = 0; | ||
492 | 614 | ||
493 | /* | 615 | if (unlikely(!tclass || tclass > policydb.p_classes.nprim)) { |
494 | * Check for all the invalid cases. | 616 | if (printk_ratelimit()) |
495 | * - tclass 0 | 617 | printk(KERN_WARNING "SELinux: Invalid class %hu\n", tclass); |
496 | * - tclass > policy and > kernel | 618 | return; |
497 | * - tclass > policy but is a userspace class | 619 | } |
498 | * - tclass > policy but we do not allow unknowns | ||
499 | */ | ||
500 | if (unlikely(!tclass)) | ||
501 | goto inval_class; | ||
502 | if (unlikely(tclass > policydb.p_classes.nprim)) | ||
503 | if (tclass > kdefs->cts_len || | ||
504 | !kdefs->class_to_string[tclass] || | ||
505 | !policydb.allow_unknown) | ||
506 | goto inval_class; | ||
507 | |||
508 | /* | ||
509 | * Kernel class and we allow unknown so pad the allow decision | ||
510 | * the pad will be all 1 for unknown classes. | ||
511 | */ | ||
512 | if (tclass <= kdefs->cts_len && policydb.allow_unknown) | ||
513 | avd->allowed = policydb.undefined_perms[tclass - 1]; | ||
514 | |||
515 | /* | ||
516 | * Not in policy. Since decision is completed (all 1 or all 0) return. | ||
517 | */ | ||
518 | if (unlikely(tclass > policydb.p_classes.nprim)) | ||
519 | return 0; | ||
520 | 620 | ||
521 | tclass_datum = policydb.class_val_to_struct[tclass - 1]; | 621 | tclass_datum = policydb.class_val_to_struct[tclass - 1]; |
522 | 622 | ||
@@ -568,8 +668,8 @@ static int context_struct_compute_av(struct context *scontext, | |||
568 | * role is changing, then check the (current_role, new_role) | 668 | * role is changing, then check the (current_role, new_role) |
569 | * pair. | 669 | * pair. |
570 | */ | 670 | */ |
571 | if (tclass == SECCLASS_PROCESS && | 671 | if (tclass == policydb.process_class && |
572 | (avd->allowed & (PROCESS__TRANSITION | PROCESS__DYNTRANSITION)) && | 672 | (avd->allowed & policydb.process_trans_perms) && |
573 | scontext->role != tcontext->role) { | 673 | scontext->role != tcontext->role) { |
574 | for (ra = policydb.role_allow; ra; ra = ra->next) { | 674 | for (ra = policydb.role_allow; ra; ra = ra->next) { |
575 | if (scontext->role == ra->role && | 675 | if (scontext->role == ra->role && |
@@ -577,8 +677,7 @@ static int context_struct_compute_av(struct context *scontext, | |||
577 | break; | 677 | break; |
578 | } | 678 | } |
579 | if (!ra) | 679 | if (!ra) |
580 | avd->allowed &= ~(PROCESS__TRANSITION | | 680 | avd->allowed &= ~policydb.process_trans_perms; |
581 | PROCESS__DYNTRANSITION); | ||
582 | } | 681 | } |
583 | 682 | ||
584 | /* | 683 | /* |
@@ -587,24 +686,7 @@ static int context_struct_compute_av(struct context *scontext, | |||
587 | * permission and notice it to userspace via audit. | 686 | * permission and notice it to userspace via audit. |
588 | */ | 687 | */ |
589 | type_attribute_bounds_av(scontext, tcontext, | 688 | type_attribute_bounds_av(scontext, tcontext, |
590 | tclass, requested, avd); | 689 | tclass, avd); |
591 | |||
592 | return 0; | ||
593 | |||
594 | inval_class: | ||
595 | if (!tclass || tclass > kdefs->cts_len || | ||
596 | !kdefs->class_to_string[tclass]) { | ||
597 | if (printk_ratelimit()) | ||
598 | printk(KERN_ERR "SELinux: %s: unrecognized class %d\n", | ||
599 | __func__, tclass); | ||
600 | return -EINVAL; | ||
601 | } | ||
602 | |||
603 | /* | ||
604 | * Known to the kernel, but not to the policy. | ||
605 | * Handle as a denial (allowed is 0). | ||
606 | */ | ||
607 | return 0; | ||
608 | } | 690 | } |
609 | 691 | ||
610 | static int security_validtrans_handle_fail(struct context *ocontext, | 692 | static int security_validtrans_handle_fail(struct context *ocontext, |
@@ -636,13 +718,14 @@ out: | |||
636 | } | 718 | } |
637 | 719 | ||
638 | int security_validate_transition(u32 oldsid, u32 newsid, u32 tasksid, | 720 | int security_validate_transition(u32 oldsid, u32 newsid, u32 tasksid, |
639 | u16 tclass) | 721 | u16 orig_tclass) |
640 | { | 722 | { |
641 | struct context *ocontext; | 723 | struct context *ocontext; |
642 | struct context *ncontext; | 724 | struct context *ncontext; |
643 | struct context *tcontext; | 725 | struct context *tcontext; |
644 | struct class_datum *tclass_datum; | 726 | struct class_datum *tclass_datum; |
645 | struct constraint_node *constraint; | 727 | struct constraint_node *constraint; |
728 | u16 tclass; | ||
646 | int rc = 0; | 729 | int rc = 0; |
647 | 730 | ||
648 | if (!ss_initialized) | 731 | if (!ss_initialized) |
@@ -650,16 +733,7 @@ int security_validate_transition(u32 oldsid, u32 newsid, u32 tasksid, | |||
650 | 733 | ||
651 | read_lock(&policy_rwlock); | 734 | read_lock(&policy_rwlock); |
652 | 735 | ||
653 | /* | 736 | tclass = unmap_class(orig_tclass); |
654 | * Remap extended Netlink classes for old policy versions. | ||
655 | * Do this here rather than socket_type_to_security_class() | ||
656 | * in case a newer policy version is loaded, allowing sockets | ||
657 | * to remain in the correct class. | ||
658 | */ | ||
659 | if (policydb_loaded_version < POLICYDB_VERSION_NLCLASS) | ||
660 | if (tclass >= SECCLASS_NETLINK_ROUTE_SOCKET && | ||
661 | tclass <= SECCLASS_NETLINK_DNRT_SOCKET) | ||
662 | tclass = SECCLASS_NETLINK_SOCKET; | ||
663 | 737 | ||
664 | if (!tclass || tclass > policydb.p_classes.nprim) { | 738 | if (!tclass || tclass > policydb.p_classes.nprim) { |
665 | printk(KERN_ERR "SELinux: %s: unrecognized class %d\n", | 739 | printk(KERN_ERR "SELinux: %s: unrecognized class %d\n", |
@@ -741,7 +815,7 @@ int security_bounded_transition(u32 old_sid, u32 new_sid) | |||
741 | goto out; | 815 | goto out; |
742 | } | 816 | } |
743 | 817 | ||
744 | /* type/domain unchaned */ | 818 | /* type/domain unchanged */ |
745 | if (old_context->type == new_context->type) { | 819 | if (old_context->type == new_context->type) { |
746 | rc = 0; | 820 | rc = 0; |
747 | goto out; | 821 | goto out; |
@@ -769,7 +843,7 @@ int security_bounded_transition(u32 old_sid, u32 new_sid) | |||
769 | if (rc) { | 843 | if (rc) { |
770 | char *old_name = NULL; | 844 | char *old_name = NULL; |
771 | char *new_name = NULL; | 845 | char *new_name = NULL; |
772 | int length; | 846 | u32 length; |
773 | 847 | ||
774 | if (!context_struct_to_string(old_context, | 848 | if (!context_struct_to_string(old_context, |
775 | &old_name, &length) && | 849 | &old_name, &length) && |
@@ -791,63 +865,116 @@ out: | |||
791 | return rc; | 865 | return rc; |
792 | } | 866 | } |
793 | 867 | ||
868 | static void avd_init(struct av_decision *avd) | ||
869 | { | ||
870 | avd->allowed = 0; | ||
871 | avd->auditallow = 0; | ||
872 | avd->auditdeny = 0xffffffff; | ||
873 | avd->seqno = latest_granting; | ||
874 | avd->flags = 0; | ||
875 | } | ||
876 | |||
794 | 877 | ||
795 | /** | 878 | /** |
796 | * security_compute_av - Compute access vector decisions. | 879 | * security_compute_av - Compute access vector decisions. |
797 | * @ssid: source security identifier | 880 | * @ssid: source security identifier |
798 | * @tsid: target security identifier | 881 | * @tsid: target security identifier |
799 | * @tclass: target security class | 882 | * @tclass: target security class |
800 | * @requested: requested permissions | ||
801 | * @avd: access vector decisions | 883 | * @avd: access vector decisions |
802 | * | 884 | * |
803 | * Compute a set of access vector decisions based on the | 885 | * Compute a set of access vector decisions based on the |
804 | * SID pair (@ssid, @tsid) for the permissions in @tclass. | 886 | * SID pair (@ssid, @tsid) for the permissions in @tclass. |
805 | * Return -%EINVAL if any of the parameters are invalid or %0 | ||
806 | * if the access vector decisions were computed successfully. | ||
807 | */ | 887 | */ |
808 | int security_compute_av(u32 ssid, | 888 | void security_compute_av(u32 ssid, |
809 | u32 tsid, | 889 | u32 tsid, |
810 | u16 tclass, | 890 | u16 orig_tclass, |
811 | u32 requested, | 891 | struct av_decision *avd) |
812 | struct av_decision *avd) | ||
813 | { | 892 | { |
893 | u16 tclass; | ||
814 | struct context *scontext = NULL, *tcontext = NULL; | 894 | struct context *scontext = NULL, *tcontext = NULL; |
815 | int rc = 0; | ||
816 | |||
817 | if (!ss_initialized) { | ||
818 | avd->allowed = 0xffffffff; | ||
819 | avd->auditallow = 0; | ||
820 | avd->auditdeny = 0xffffffff; | ||
821 | avd->seqno = latest_granting; | ||
822 | return 0; | ||
823 | } | ||
824 | 895 | ||
825 | read_lock(&policy_rwlock); | 896 | read_lock(&policy_rwlock); |
897 | avd_init(avd); | ||
898 | if (!ss_initialized) | ||
899 | goto allow; | ||
826 | 900 | ||
827 | scontext = sidtab_search(&sidtab, ssid); | 901 | scontext = sidtab_search(&sidtab, ssid); |
828 | if (!scontext) { | 902 | if (!scontext) { |
829 | printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n", | 903 | printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n", |
830 | __func__, ssid); | 904 | __func__, ssid); |
831 | rc = -EINVAL; | ||
832 | goto out; | 905 | goto out; |
833 | } | 906 | } |
907 | |||
908 | /* permissive domain? */ | ||
909 | if (ebitmap_get_bit(&policydb.permissive_map, scontext->type)) | ||
910 | avd->flags |= AVD_FLAGS_PERMISSIVE; | ||
911 | |||
834 | tcontext = sidtab_search(&sidtab, tsid); | 912 | tcontext = sidtab_search(&sidtab, tsid); |
835 | if (!tcontext) { | 913 | if (!tcontext) { |
836 | printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n", | 914 | printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n", |
837 | __func__, tsid); | 915 | __func__, tsid); |
838 | rc = -EINVAL; | ||
839 | goto out; | 916 | goto out; |
840 | } | 917 | } |
841 | 918 | ||
842 | rc = context_struct_compute_av(scontext, tcontext, tclass, | 919 | tclass = unmap_class(orig_tclass); |
843 | requested, avd); | 920 | if (unlikely(orig_tclass && !tclass)) { |
921 | if (policydb.allow_unknown) | ||
922 | goto allow; | ||
923 | goto out; | ||
924 | } | ||
925 | context_struct_compute_av(scontext, tcontext, tclass, avd); | ||
926 | map_decision(orig_tclass, avd, policydb.allow_unknown); | ||
927 | out: | ||
928 | read_unlock(&policy_rwlock); | ||
929 | return; | ||
930 | allow: | ||
931 | avd->allowed = 0xffffffff; | ||
932 | goto out; | ||
933 | } | ||
934 | |||
935 | void security_compute_av_user(u32 ssid, | ||
936 | u32 tsid, | ||
937 | u16 tclass, | ||
938 | struct av_decision *avd) | ||
939 | { | ||
940 | struct context *scontext = NULL, *tcontext = NULL; | ||
941 | |||
942 | read_lock(&policy_rwlock); | ||
943 | avd_init(avd); | ||
944 | if (!ss_initialized) | ||
945 | goto allow; | ||
946 | |||
947 | scontext = sidtab_search(&sidtab, ssid); | ||
948 | if (!scontext) { | ||
949 | printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n", | ||
950 | __func__, ssid); | ||
951 | goto out; | ||
952 | } | ||
844 | 953 | ||
845 | /* permissive domain? */ | 954 | /* permissive domain? */ |
846 | if (ebitmap_get_bit(&policydb.permissive_map, scontext->type)) | 955 | if (ebitmap_get_bit(&policydb.permissive_map, scontext->type)) |
847 | avd->flags |= AVD_FLAGS_PERMISSIVE; | 956 | avd->flags |= AVD_FLAGS_PERMISSIVE; |
848 | out: | 957 | |
958 | tcontext = sidtab_search(&sidtab, tsid); | ||
959 | if (!tcontext) { | ||
960 | printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n", | ||
961 | __func__, tsid); | ||
962 | goto out; | ||
963 | } | ||
964 | |||
965 | if (unlikely(!tclass)) { | ||
966 | if (policydb.allow_unknown) | ||
967 | goto allow; | ||
968 | goto out; | ||
969 | } | ||
970 | |||
971 | context_struct_compute_av(scontext, tcontext, tclass, avd); | ||
972 | out: | ||
849 | read_unlock(&policy_rwlock); | 973 | read_unlock(&policy_rwlock); |
850 | return rc; | 974 | return; |
975 | allow: | ||
976 | avd->allowed = 0xffffffff; | ||
977 | goto out; | ||
851 | } | 978 | } |
852 | 979 | ||
853 | /* | 980 | /* |
@@ -1204,20 +1331,22 @@ out: | |||
1204 | 1331 | ||
1205 | static int security_compute_sid(u32 ssid, | 1332 | static int security_compute_sid(u32 ssid, |
1206 | u32 tsid, | 1333 | u32 tsid, |
1207 | u16 tclass, | 1334 | u16 orig_tclass, |
1208 | u32 specified, | 1335 | u32 specified, |
1209 | u32 *out_sid) | 1336 | u32 *out_sid, |
1337 | bool kern) | ||
1210 | { | 1338 | { |
1211 | struct context *scontext = NULL, *tcontext = NULL, newcontext; | 1339 | struct context *scontext = NULL, *tcontext = NULL, newcontext; |
1212 | struct role_trans *roletr = NULL; | 1340 | struct role_trans *roletr = NULL; |
1213 | struct avtab_key avkey; | 1341 | struct avtab_key avkey; |
1214 | struct avtab_datum *avdatum; | 1342 | struct avtab_datum *avdatum; |
1215 | struct avtab_node *node; | 1343 | struct avtab_node *node; |
1344 | u16 tclass; | ||
1216 | int rc = 0; | 1345 | int rc = 0; |
1217 | 1346 | ||
1218 | if (!ss_initialized) { | 1347 | if (!ss_initialized) { |
1219 | switch (tclass) { | 1348 | switch (orig_tclass) { |
1220 | case SECCLASS_PROCESS: | 1349 | case SECCLASS_PROCESS: /* kernel value */ |
1221 | *out_sid = ssid; | 1350 | *out_sid = ssid; |
1222 | break; | 1351 | break; |
1223 | default: | 1352 | default: |
@@ -1231,6 +1360,11 @@ static int security_compute_sid(u32 ssid, | |||
1231 | 1360 | ||
1232 | read_lock(&policy_rwlock); | 1361 | read_lock(&policy_rwlock); |
1233 | 1362 | ||
1363 | if (kern) | ||
1364 | tclass = unmap_class(orig_tclass); | ||
1365 | else | ||
1366 | tclass = orig_tclass; | ||
1367 | |||
1234 | scontext = sidtab_search(&sidtab, ssid); | 1368 | scontext = sidtab_search(&sidtab, ssid); |
1235 | if (!scontext) { | 1369 | if (!scontext) { |
1236 | printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n", | 1370 | printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n", |
@@ -1260,13 +1394,11 @@ static int security_compute_sid(u32 ssid, | |||
1260 | } | 1394 | } |
1261 | 1395 | ||
1262 | /* Set the role and type to default values. */ | 1396 | /* Set the role and type to default values. */ |
1263 | switch (tclass) { | 1397 | if (tclass == policydb.process_class) { |
1264 | case SECCLASS_PROCESS: | ||
1265 | /* Use the current role and type of process. */ | 1398 | /* Use the current role and type of process. */ |
1266 | newcontext.role = scontext->role; | 1399 | newcontext.role = scontext->role; |
1267 | newcontext.type = scontext->type; | 1400 | newcontext.type = scontext->type; |
1268 | break; | 1401 | } else { |
1269 | default: | ||
1270 | /* Use the well-defined object role. */ | 1402 | /* Use the well-defined object role. */ |
1271 | newcontext.role = OBJECT_R_VAL; | 1403 | newcontext.role = OBJECT_R_VAL; |
1272 | /* Use the type of the related object. */ | 1404 | /* Use the type of the related object. */ |
@@ -1297,8 +1429,7 @@ static int security_compute_sid(u32 ssid, | |||
1297 | } | 1429 | } |
1298 | 1430 | ||
1299 | /* Check for class-specific changes. */ | 1431 | /* Check for class-specific changes. */ |
1300 | switch (tclass) { | 1432 | if (tclass == policydb.process_class) { |
1301 | case SECCLASS_PROCESS: | ||
1302 | if (specified & AVTAB_TRANSITION) { | 1433 | if (specified & AVTAB_TRANSITION) { |
1303 | /* Look for a role transition rule. */ | 1434 | /* Look for a role transition rule. */ |
1304 | for (roletr = policydb.role_tr; roletr; | 1435 | for (roletr = policydb.role_tr; roletr; |
@@ -1311,9 +1442,6 @@ static int security_compute_sid(u32 ssid, | |||
1311 | } | 1442 | } |
1312 | } | 1443 | } |
1313 | } | 1444 | } |
1314 | break; | ||
1315 | default: | ||
1316 | break; | ||
1317 | } | 1445 | } |
1318 | 1446 | ||
1319 | /* Set the MLS attributes. | 1447 | /* Set the MLS attributes. |
@@ -1358,7 +1486,17 @@ int security_transition_sid(u32 ssid, | |||
1358 | u16 tclass, | 1486 | u16 tclass, |
1359 | u32 *out_sid) | 1487 | u32 *out_sid) |
1360 | { | 1488 | { |
1361 | return security_compute_sid(ssid, tsid, tclass, AVTAB_TRANSITION, out_sid); | 1489 | return security_compute_sid(ssid, tsid, tclass, AVTAB_TRANSITION, |
1490 | out_sid, true); | ||
1491 | } | ||
1492 | |||
1493 | int security_transition_sid_user(u32 ssid, | ||
1494 | u32 tsid, | ||
1495 | u16 tclass, | ||
1496 | u32 *out_sid) | ||
1497 | { | ||
1498 | return security_compute_sid(ssid, tsid, tclass, AVTAB_TRANSITION, | ||
1499 | out_sid, false); | ||
1362 | } | 1500 | } |
1363 | 1501 | ||
1364 | /** | 1502 | /** |
@@ -1379,7 +1517,8 @@ int security_member_sid(u32 ssid, | |||
1379 | u16 tclass, | 1517 | u16 tclass, |
1380 | u32 *out_sid) | 1518 | u32 *out_sid) |
1381 | { | 1519 | { |
1382 | return security_compute_sid(ssid, tsid, tclass, AVTAB_MEMBER, out_sid); | 1520 | return security_compute_sid(ssid, tsid, tclass, AVTAB_MEMBER, out_sid, |
1521 | false); | ||
1383 | } | 1522 | } |
1384 | 1523 | ||
1385 | /** | 1524 | /** |
@@ -1400,144 +1539,8 @@ int security_change_sid(u32 ssid, | |||
1400 | u16 tclass, | 1539 | u16 tclass, |
1401 | u32 *out_sid) | 1540 | u32 *out_sid) |
1402 | { | 1541 | { |
1403 | return security_compute_sid(ssid, tsid, tclass, AVTAB_CHANGE, out_sid); | 1542 | return security_compute_sid(ssid, tsid, tclass, AVTAB_CHANGE, out_sid, |
1404 | } | 1543 | false); |
1405 | |||
1406 | /* | ||
1407 | * Verify that each kernel class that is defined in the | ||
1408 | * policy is correct | ||
1409 | */ | ||
1410 | static int validate_classes(struct policydb *p) | ||
1411 | { | ||
1412 | int i, j; | ||
1413 | struct class_datum *cladatum; | ||
1414 | struct perm_datum *perdatum; | ||
1415 | u32 nprim, tmp, common_pts_len, perm_val, pol_val; | ||
1416 | u16 class_val; | ||
1417 | const struct selinux_class_perm *kdefs = &selinux_class_perm; | ||
1418 | const char *def_class, *def_perm, *pol_class; | ||
1419 | struct symtab *perms; | ||
1420 | bool print_unknown_handle = 0; | ||
1421 | |||
1422 | if (p->allow_unknown) { | ||
1423 | u32 num_classes = kdefs->cts_len; | ||
1424 | p->undefined_perms = kcalloc(num_classes, sizeof(u32), GFP_KERNEL); | ||
1425 | if (!p->undefined_perms) | ||
1426 | return -ENOMEM; | ||
1427 | } | ||
1428 | |||
1429 | for (i = 1; i < kdefs->cts_len; i++) { | ||
1430 | def_class = kdefs->class_to_string[i]; | ||
1431 | if (!def_class) | ||
1432 | continue; | ||
1433 | if (i > p->p_classes.nprim) { | ||
1434 | printk(KERN_INFO | ||
1435 | "SELinux: class %s not defined in policy\n", | ||
1436 | def_class); | ||
1437 | if (p->reject_unknown) | ||
1438 | return -EINVAL; | ||
1439 | if (p->allow_unknown) | ||
1440 | p->undefined_perms[i-1] = ~0U; | ||
1441 | print_unknown_handle = 1; | ||
1442 | continue; | ||
1443 | } | ||
1444 | pol_class = p->p_class_val_to_name[i-1]; | ||
1445 | if (strcmp(pol_class, def_class)) { | ||
1446 | printk(KERN_ERR | ||
1447 | "SELinux: class %d is incorrect, found %s but should be %s\n", | ||
1448 | i, pol_class, def_class); | ||
1449 | return -EINVAL; | ||
1450 | } | ||
1451 | } | ||
1452 | for (i = 0; i < kdefs->av_pts_len; i++) { | ||
1453 | class_val = kdefs->av_perm_to_string[i].tclass; | ||
1454 | perm_val = kdefs->av_perm_to_string[i].value; | ||
1455 | def_perm = kdefs->av_perm_to_string[i].name; | ||
1456 | if (class_val > p->p_classes.nprim) | ||
1457 | continue; | ||
1458 | pol_class = p->p_class_val_to_name[class_val-1]; | ||
1459 | cladatum = hashtab_search(p->p_classes.table, pol_class); | ||
1460 | BUG_ON(!cladatum); | ||
1461 | perms = &cladatum->permissions; | ||
1462 | nprim = 1 << (perms->nprim - 1); | ||
1463 | if (perm_val > nprim) { | ||
1464 | printk(KERN_INFO | ||
1465 | "SELinux: permission %s in class %s not defined in policy\n", | ||
1466 | def_perm, pol_class); | ||
1467 | if (p->reject_unknown) | ||
1468 | return -EINVAL; | ||
1469 | if (p->allow_unknown) | ||
1470 | p->undefined_perms[class_val-1] |= perm_val; | ||
1471 | print_unknown_handle = 1; | ||
1472 | continue; | ||
1473 | } | ||
1474 | perdatum = hashtab_search(perms->table, def_perm); | ||
1475 | if (perdatum == NULL) { | ||
1476 | printk(KERN_ERR | ||
1477 | "SELinux: permission %s in class %s not found in policy, bad policy\n", | ||
1478 | def_perm, pol_class); | ||
1479 | return -EINVAL; | ||
1480 | } | ||
1481 | pol_val = 1 << (perdatum->value - 1); | ||
1482 | if (pol_val != perm_val) { | ||
1483 | printk(KERN_ERR | ||
1484 | "SELinux: permission %s in class %s has incorrect value\n", | ||
1485 | def_perm, pol_class); | ||
1486 | return -EINVAL; | ||
1487 | } | ||
1488 | } | ||
1489 | for (i = 0; i < kdefs->av_inherit_len; i++) { | ||
1490 | class_val = kdefs->av_inherit[i].tclass; | ||
1491 | if (class_val > p->p_classes.nprim) | ||
1492 | continue; | ||
1493 | pol_class = p->p_class_val_to_name[class_val-1]; | ||
1494 | cladatum = hashtab_search(p->p_classes.table, pol_class); | ||
1495 | BUG_ON(!cladatum); | ||
1496 | if (!cladatum->comdatum) { | ||
1497 | printk(KERN_ERR | ||
1498 | "SELinux: class %s should have an inherits clause but does not\n", | ||
1499 | pol_class); | ||
1500 | return -EINVAL; | ||
1501 | } | ||
1502 | tmp = kdefs->av_inherit[i].common_base; | ||
1503 | common_pts_len = 0; | ||
1504 | while (!(tmp & 0x01)) { | ||
1505 | common_pts_len++; | ||
1506 | tmp >>= 1; | ||
1507 | } | ||
1508 | perms = &cladatum->comdatum->permissions; | ||
1509 | for (j = 0; j < common_pts_len; j++) { | ||
1510 | def_perm = kdefs->av_inherit[i].common_pts[j]; | ||
1511 | if (j >= perms->nprim) { | ||
1512 | printk(KERN_INFO | ||
1513 | "SELinux: permission %s in class %s not defined in policy\n", | ||
1514 | def_perm, pol_class); | ||
1515 | if (p->reject_unknown) | ||
1516 | return -EINVAL; | ||
1517 | if (p->allow_unknown) | ||
1518 | p->undefined_perms[class_val-1] |= (1 << j); | ||
1519 | print_unknown_handle = 1; | ||
1520 | continue; | ||
1521 | } | ||
1522 | perdatum = hashtab_search(perms->table, def_perm); | ||
1523 | if (perdatum == NULL) { | ||
1524 | printk(KERN_ERR | ||
1525 | "SELinux: permission %s in class %s not found in policy, bad policy\n", | ||
1526 | def_perm, pol_class); | ||
1527 | return -EINVAL; | ||
1528 | } | ||
1529 | if (perdatum->value != j + 1) { | ||
1530 | printk(KERN_ERR | ||
1531 | "SELinux: permission %s in class %s has incorrect value\n", | ||
1532 | def_perm, pol_class); | ||
1533 | return -EINVAL; | ||
1534 | } | ||
1535 | } | ||
1536 | } | ||
1537 | if (print_unknown_handle) | ||
1538 | printk(KERN_INFO "SELinux: the above unknown classes and permissions will be %s\n", | ||
1539 | (security_get_allow_unknown() ? "allowed" : "denied")); | ||
1540 | return 0; | ||
1541 | } | 1544 | } |
1542 | 1545 | ||
1543 | /* Clone the SID into the new SID table. */ | 1546 | /* Clone the SID into the new SID table. */ |
@@ -1547,7 +1550,10 @@ static int clone_sid(u32 sid, | |||
1547 | { | 1550 | { |
1548 | struct sidtab *s = arg; | 1551 | struct sidtab *s = arg; |
1549 | 1552 | ||
1550 | return sidtab_insert(s, sid, context); | 1553 | if (sid > SECINITSID_NUM) |
1554 | return sidtab_insert(s, sid, context); | ||
1555 | else | ||
1556 | return 0; | ||
1551 | } | 1557 | } |
1552 | 1558 | ||
1553 | static inline int convert_context_handle_invalid_context(struct context *context) | 1559 | static inline int convert_context_handle_invalid_context(struct context *context) |
@@ -1588,12 +1594,17 @@ static int convert_context(u32 key, | |||
1588 | { | 1594 | { |
1589 | struct convert_context_args *args; | 1595 | struct convert_context_args *args; |
1590 | struct context oldc; | 1596 | struct context oldc; |
1597 | struct ocontext *oc; | ||
1598 | struct mls_range *range; | ||
1591 | struct role_datum *role; | 1599 | struct role_datum *role; |
1592 | struct type_datum *typdatum; | 1600 | struct type_datum *typdatum; |
1593 | struct user_datum *usrdatum; | 1601 | struct user_datum *usrdatum; |
1594 | char *s; | 1602 | char *s; |
1595 | u32 len; | 1603 | u32 len; |
1596 | int rc; | 1604 | int rc = 0; |
1605 | |||
1606 | if (key <= SECINITSID_NUM) | ||
1607 | goto out; | ||
1597 | 1608 | ||
1598 | args = p; | 1609 | args = p; |
1599 | 1610 | ||
@@ -1655,9 +1666,39 @@ static int convert_context(u32 key, | |||
1655 | goto bad; | 1666 | goto bad; |
1656 | c->type = typdatum->value; | 1667 | c->type = typdatum->value; |
1657 | 1668 | ||
1658 | rc = mls_convert_context(args->oldp, args->newp, c); | 1669 | /* Convert the MLS fields if dealing with MLS policies */ |
1659 | if (rc) | 1670 | if (args->oldp->mls_enabled && args->newp->mls_enabled) { |
1660 | goto bad; | 1671 | rc = mls_convert_context(args->oldp, args->newp, c); |
1672 | if (rc) | ||
1673 | goto bad; | ||
1674 | } else if (args->oldp->mls_enabled && !args->newp->mls_enabled) { | ||
1675 | /* | ||
1676 | * Switching between MLS and non-MLS policy: | ||
1677 | * free any storage used by the MLS fields in the | ||
1678 | * context for all existing entries in the sidtab. | ||
1679 | */ | ||
1680 | mls_context_destroy(c); | ||
1681 | } else if (!args->oldp->mls_enabled && args->newp->mls_enabled) { | ||
1682 | /* | ||
1683 | * Switching between non-MLS and MLS policy: | ||
1684 | * ensure that the MLS fields of the context for all | ||
1685 | * existing entries in the sidtab are filled in with a | ||
1686 | * suitable default value, likely taken from one of the | ||
1687 | * initial SIDs. | ||
1688 | */ | ||
1689 | oc = args->newp->ocontexts[OCON_ISID]; | ||
1690 | while (oc && oc->sid[0] != SECINITSID_UNLABELED) | ||
1691 | oc = oc->next; | ||
1692 | if (!oc) { | ||
1693 | printk(KERN_ERR "SELinux: unable to look up" | ||
1694 | " the initial SIDs list\n"); | ||
1695 | goto bad; | ||
1696 | } | ||
1697 | range = &oc->context[0].range; | ||
1698 | rc = mls_range_set(c, range); | ||
1699 | if (rc) | ||
1700 | goto bad; | ||
1701 | } | ||
1661 | 1702 | ||
1662 | /* Check the validity of the new context. */ | 1703 | /* Check the validity of the new context. */ |
1663 | if (!policydb_context_isvalid(args->newp, c)) { | 1704 | if (!policydb_context_isvalid(args->newp, c)) { |
@@ -1710,8 +1751,10 @@ int security_load_policy(void *data, size_t len) | |||
1710 | { | 1751 | { |
1711 | struct policydb oldpolicydb, newpolicydb; | 1752 | struct policydb oldpolicydb, newpolicydb; |
1712 | struct sidtab oldsidtab, newsidtab; | 1753 | struct sidtab oldsidtab, newsidtab; |
1754 | struct selinux_mapping *oldmap, *map = NULL; | ||
1713 | struct convert_context_args args; | 1755 | struct convert_context_args args; |
1714 | u32 seqno; | 1756 | u32 seqno; |
1757 | u16 map_size; | ||
1715 | int rc = 0; | 1758 | int rc = 0; |
1716 | struct policy_file file = { data, len }, *fp = &file; | 1759 | struct policy_file file = { data, len }, *fp = &file; |
1717 | 1760 | ||
@@ -1721,22 +1764,19 @@ int security_load_policy(void *data, size_t len) | |||
1721 | avtab_cache_destroy(); | 1764 | avtab_cache_destroy(); |
1722 | return -EINVAL; | 1765 | return -EINVAL; |
1723 | } | 1766 | } |
1724 | if (policydb_load_isids(&policydb, &sidtab)) { | 1767 | if (selinux_set_mapping(&policydb, secclass_map, |
1768 | ¤t_mapping, | ||
1769 | ¤t_mapping_size)) { | ||
1725 | policydb_destroy(&policydb); | 1770 | policydb_destroy(&policydb); |
1726 | avtab_cache_destroy(); | 1771 | avtab_cache_destroy(); |
1727 | return -EINVAL; | 1772 | return -EINVAL; |
1728 | } | 1773 | } |
1729 | /* Verify that the kernel defined classes are correct. */ | 1774 | if (policydb_load_isids(&policydb, &sidtab)) { |
1730 | if (validate_classes(&policydb)) { | ||
1731 | printk(KERN_ERR | ||
1732 | "SELinux: the definition of a class is incorrect\n"); | ||
1733 | sidtab_destroy(&sidtab); | ||
1734 | policydb_destroy(&policydb); | 1775 | policydb_destroy(&policydb); |
1735 | avtab_cache_destroy(); | 1776 | avtab_cache_destroy(); |
1736 | return -EINVAL; | 1777 | return -EINVAL; |
1737 | } | 1778 | } |
1738 | security_load_policycaps(); | 1779 | security_load_policycaps(); |
1739 | policydb_loaded_version = policydb.policyvers; | ||
1740 | ss_initialized = 1; | 1780 | ss_initialized = 1; |
1741 | seqno = ++latest_granting; | 1781 | seqno = ++latest_granting; |
1742 | selinux_complete_init(); | 1782 | selinux_complete_init(); |
@@ -1754,18 +1794,22 @@ int security_load_policy(void *data, size_t len) | |||
1754 | if (policydb_read(&newpolicydb, fp)) | 1794 | if (policydb_read(&newpolicydb, fp)) |
1755 | return -EINVAL; | 1795 | return -EINVAL; |
1756 | 1796 | ||
1757 | if (sidtab_init(&newsidtab)) { | 1797 | /* If switching between different policy types, log MLS status */ |
1798 | if (policydb.mls_enabled && !newpolicydb.mls_enabled) | ||
1799 | printk(KERN_INFO "SELinux: Disabling MLS support...\n"); | ||
1800 | else if (!policydb.mls_enabled && newpolicydb.mls_enabled) | ||
1801 | printk(KERN_INFO "SELinux: Enabling MLS support...\n"); | ||
1802 | |||
1803 | rc = policydb_load_isids(&newpolicydb, &newsidtab); | ||
1804 | if (rc) { | ||
1805 | printk(KERN_ERR "SELinux: unable to load the initial SIDs\n"); | ||
1758 | policydb_destroy(&newpolicydb); | 1806 | policydb_destroy(&newpolicydb); |
1759 | return -ENOMEM; | 1807 | return rc; |
1760 | } | 1808 | } |
1761 | 1809 | ||
1762 | /* Verify that the kernel defined classes are correct. */ | 1810 | if (selinux_set_mapping(&newpolicydb, secclass_map, |
1763 | if (validate_classes(&newpolicydb)) { | 1811 | &map, &map_size)) |
1764 | printk(KERN_ERR | ||
1765 | "SELinux: the definition of a class is incorrect\n"); | ||
1766 | rc = -EINVAL; | ||
1767 | goto err; | 1812 | goto err; |
1768 | } | ||
1769 | 1813 | ||
1770 | rc = security_preserve_bools(&newpolicydb); | 1814 | rc = security_preserve_bools(&newpolicydb); |
1771 | if (rc) { | 1815 | if (rc) { |
@@ -1787,8 +1831,12 @@ int security_load_policy(void *data, size_t len) | |||
1787 | args.oldp = &policydb; | 1831 | args.oldp = &policydb; |
1788 | args.newp = &newpolicydb; | 1832 | args.newp = &newpolicydb; |
1789 | rc = sidtab_map(&newsidtab, convert_context, &args); | 1833 | rc = sidtab_map(&newsidtab, convert_context, &args); |
1790 | if (rc) | 1834 | if (rc) { |
1835 | printk(KERN_ERR "SELinux: unable to convert the internal" | ||
1836 | " representation of contexts in the new SID" | ||
1837 | " table\n"); | ||
1791 | goto err; | 1838 | goto err; |
1839 | } | ||
1792 | 1840 | ||
1793 | /* Save the old policydb and SID table to free later. */ | 1841 | /* Save the old policydb and SID table to free later. */ |
1794 | memcpy(&oldpolicydb, &policydb, sizeof policydb); | 1842 | memcpy(&oldpolicydb, &policydb, sizeof policydb); |
@@ -1799,13 +1847,16 @@ int security_load_policy(void *data, size_t len) | |||
1799 | memcpy(&policydb, &newpolicydb, sizeof policydb); | 1847 | memcpy(&policydb, &newpolicydb, sizeof policydb); |
1800 | sidtab_set(&sidtab, &newsidtab); | 1848 | sidtab_set(&sidtab, &newsidtab); |
1801 | security_load_policycaps(); | 1849 | security_load_policycaps(); |
1850 | oldmap = current_mapping; | ||
1851 | current_mapping = map; | ||
1852 | current_mapping_size = map_size; | ||
1802 | seqno = ++latest_granting; | 1853 | seqno = ++latest_granting; |
1803 | policydb_loaded_version = policydb.policyvers; | ||
1804 | write_unlock_irq(&policy_rwlock); | 1854 | write_unlock_irq(&policy_rwlock); |
1805 | 1855 | ||
1806 | /* Free the old policydb and SID table. */ | 1856 | /* Free the old policydb and SID table. */ |
1807 | policydb_destroy(&oldpolicydb); | 1857 | policydb_destroy(&oldpolicydb); |
1808 | sidtab_destroy(&oldsidtab); | 1858 | sidtab_destroy(&oldsidtab); |
1859 | kfree(oldmap); | ||
1809 | 1860 | ||
1810 | avc_ss_reset(seqno); | 1861 | avc_ss_reset(seqno); |
1811 | selnl_notify_policyload(seqno); | 1862 | selnl_notify_policyload(seqno); |
@@ -1815,6 +1866,7 @@ int security_load_policy(void *data, size_t len) | |||
1815 | return 0; | 1866 | return 0; |
1816 | 1867 | ||
1817 | err: | 1868 | err: |
1869 | kfree(map); | ||
1818 | sidtab_destroy(&newsidtab); | 1870 | sidtab_destroy(&newsidtab); |
1819 | policydb_destroy(&newpolicydb); | 1871 | policydb_destroy(&newpolicydb); |
1820 | return rc; | 1872 | return rc; |
@@ -2091,7 +2143,7 @@ out_unlock: | |||
2091 | } | 2143 | } |
2092 | for (i = 0, j = 0; i < mynel; i++) { | 2144 | for (i = 0, j = 0; i < mynel; i++) { |
2093 | rc = avc_has_perm_noaudit(fromsid, mysids[i], | 2145 | rc = avc_has_perm_noaudit(fromsid, mysids[i], |
2094 | SECCLASS_PROCESS, | 2146 | SECCLASS_PROCESS, /* kernel value */ |
2095 | PROCESS__TRANSITION, AVC_STRICT, | 2147 | PROCESS__TRANSITION, AVC_STRICT, |
2096 | NULL); | 2148 | NULL); |
2097 | if (!rc) | 2149 | if (!rc) |
@@ -2119,10 +2171,11 @@ out: | |||
2119 | */ | 2171 | */ |
2120 | int security_genfs_sid(const char *fstype, | 2172 | int security_genfs_sid(const char *fstype, |
2121 | char *path, | 2173 | char *path, |
2122 | u16 sclass, | 2174 | u16 orig_sclass, |
2123 | u32 *sid) | 2175 | u32 *sid) |
2124 | { | 2176 | { |
2125 | int len; | 2177 | int len; |
2178 | u16 sclass; | ||
2126 | struct genfs *genfs; | 2179 | struct genfs *genfs; |
2127 | struct ocontext *c; | 2180 | struct ocontext *c; |
2128 | int rc = 0, cmp = 0; | 2181 | int rc = 0, cmp = 0; |
@@ -2132,6 +2185,8 @@ int security_genfs_sid(const char *fstype, | |||
2132 | 2185 | ||
2133 | read_lock(&policy_rwlock); | 2186 | read_lock(&policy_rwlock); |
2134 | 2187 | ||
2188 | sclass = unmap_class(orig_sclass); | ||
2189 | |||
2135 | for (genfs = policydb.genfs; genfs; genfs = genfs->next) { | 2190 | for (genfs = policydb.genfs; genfs; genfs = genfs->next) { |
2136 | cmp = strcmp(fstype, genfs->fstype); | 2191 | cmp = strcmp(fstype, genfs->fstype); |
2137 | if (cmp <= 0) | 2192 | if (cmp <= 0) |
@@ -2377,7 +2432,7 @@ int security_sid_mls_copy(u32 sid, u32 mls_sid, u32 *new_sid) | |||
2377 | u32 len; | 2432 | u32 len; |
2378 | int rc = 0; | 2433 | int rc = 0; |
2379 | 2434 | ||
2380 | if (!ss_initialized || !selinux_mls_enabled) { | 2435 | if (!ss_initialized || !policydb.mls_enabled) { |
2381 | *new_sid = sid; | 2436 | *new_sid = sid; |
2382 | goto out; | 2437 | goto out; |
2383 | } | 2438 | } |
@@ -2478,7 +2533,7 @@ int security_net_peersid_resolve(u32 nlbl_sid, u32 nlbl_type, | |||
2478 | /* we don't need to check ss_initialized here since the only way both | 2533 | /* we don't need to check ss_initialized here since the only way both |
2479 | * nlbl_sid and xfrm_sid are not equal to SECSID_NULL would be if the | 2534 | * nlbl_sid and xfrm_sid are not equal to SECSID_NULL would be if the |
2480 | * security server was initialized and ss_initialized was true */ | 2535 | * security server was initialized and ss_initialized was true */ |
2481 | if (!selinux_mls_enabled) { | 2536 | if (!policydb.mls_enabled) { |
2482 | *peer_sid = SECSID_NULL; | 2537 | *peer_sid = SECSID_NULL; |
2483 | return 0; | 2538 | return 0; |
2484 | } | 2539 | } |
@@ -2535,7 +2590,7 @@ int security_get_classes(char ***classes, int *nclasses) | |||
2535 | read_lock(&policy_rwlock); | 2590 | read_lock(&policy_rwlock); |
2536 | 2591 | ||
2537 | *nclasses = policydb.p_classes.nprim; | 2592 | *nclasses = policydb.p_classes.nprim; |
2538 | *classes = kcalloc(*nclasses, sizeof(*classes), GFP_ATOMIC); | 2593 | *classes = kcalloc(*nclasses, sizeof(**classes), GFP_ATOMIC); |
2539 | if (!*classes) | 2594 | if (!*classes) |
2540 | goto out; | 2595 | goto out; |
2541 | 2596 | ||
@@ -2582,7 +2637,7 @@ int security_get_permissions(char *class, char ***perms, int *nperms) | |||
2582 | } | 2637 | } |
2583 | 2638 | ||
2584 | *nperms = match->permissions.nprim; | 2639 | *nperms = match->permissions.nprim; |
2585 | *perms = kcalloc(*nperms, sizeof(*perms), GFP_ATOMIC); | 2640 | *perms = kcalloc(*nperms, sizeof(**perms), GFP_ATOMIC); |
2586 | if (!*perms) | 2641 | if (!*perms) |
2587 | goto out; | 2642 | goto out; |
2588 | 2643 | ||
diff --git a/security/selinux/ss/symtab.c b/security/selinux/ss/symtab.c index 837658a98a54..bcf9f620426e 100644 --- a/security/selinux/ss/symtab.c +++ b/security/selinux/ss/symtab.c | |||
@@ -4,7 +4,6 @@ | |||
4 | * Author : Stephen Smalley, <sds@epoch.ncsc.mil> | 4 | * Author : Stephen Smalley, <sds@epoch.ncsc.mil> |
5 | */ | 5 | */ |
6 | #include <linux/kernel.h> | 6 | #include <linux/kernel.h> |
7 | #include <linux/slab.h> | ||
8 | #include <linux/string.h> | 7 | #include <linux/string.h> |
9 | #include <linux/errno.h> | 8 | #include <linux/errno.h> |
10 | #include "symtab.h" | 9 | #include "symtab.h" |