diff options
author | Guido Trentalancia <guido@trentalancia.com> | 2010-02-03 10:40:20 -0500 |
---|---|---|
committer | James Morris <jmorris@namei.org> | 2010-02-03 17:06:36 -0500 |
commit | 0719aaf5ead7555b7b7a4a080ebf2826a871384e (patch) | |
tree | 19c0b16b1013d84a8b8092737d38e60f3dd7e939 /security/selinux | |
parent | 42596eafdd75257a640f64701b9b07090bcd84b0 (diff) |
selinux: allow MLS->non-MLS and vice versa upon policy reload
Allow runtime switching between different policy types (e.g. from a MLS/MCS
policy to a non-MLS/non-MCS policy or viceversa).
Signed-off-by: Guido Trentalancia <guido@trentalancia.com>
Acked-by: Stephen Smalley <sds@tycho.nsa.gov>
Signed-off-by: James Morris <jmorris@namei.org>
Diffstat (limited to 'security/selinux')
-rw-r--r-- | security/selinux/include/security.h | 3 | ||||
-rw-r--r-- | security/selinux/selinuxfs.c | 3 | ||||
-rw-r--r-- | security/selinux/ss/context.h | 12 | ||||
-rw-r--r-- | security/selinux/ss/mls.c | 26 | ||||
-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 | 24 | ||||
-rw-r--r-- | security/selinux/ss/policydb.h | 4 | ||||
-rw-r--r-- | security/selinux/ss/services.c | 62 |
9 files changed, 84 insertions, 59 deletions
diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h index 022cf067aa3f..1f7c2491d3dc 100644 --- a/security/selinux/include/security.h +++ b/security/selinux/include/security.h | |||
@@ -57,7 +57,6 @@ | |||
57 | struct netlbl_lsm_secattr; | 57 | struct netlbl_lsm_secattr; |
58 | 58 | ||
59 | extern int selinux_enabled; | 59 | extern int selinux_enabled; |
60 | extern int selinux_mls_enabled; | ||
61 | 60 | ||
62 | /* Policy capabilities */ | 61 | /* Policy capabilities */ |
63 | enum { | 62 | enum { |
@@ -80,6 +79,8 @@ extern int selinux_policycap_openperm; | |||
80 | /* limitation of boundary depth */ | 79 | /* limitation of boundary depth */ |
81 | #define POLICYDB_BOUNDS_MAXDEPTH 4 | 80 | #define POLICYDB_BOUNDS_MAXDEPTH 4 |
82 | 81 | ||
82 | int security_mls_enabled(void); | ||
83 | |||
83 | int security_load_policy(void *data, size_t len); | 84 | int security_load_policy(void *data, size_t len); |
84 | 85 | ||
85 | int security_policycap_supported(unsigned int req_cap); | 86 | int security_policycap_supported(unsigned int req_cap); |
diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c index b7bb0f5ec07c..a1cfc464bbb9 100644 --- a/security/selinux/selinuxfs.c +++ b/security/selinux/selinuxfs.c | |||
@@ -282,7 +282,8 @@ static ssize_t sel_read_mls(struct file *filp, char __user *buf, | |||
282 | char tmpbuf[TMPBUFLEN]; | 282 | char tmpbuf[TMPBUFLEN]; |
283 | ssize_t length; | 283 | ssize_t length; |
284 | 284 | ||
285 | length = scnprintf(tmpbuf, TMPBUFLEN, "%d", selinux_mls_enabled); | 285 | length = scnprintf(tmpbuf, TMPBUFLEN, "%d", |
286 | security_mls_enabled()); | ||
286 | return simple_read_from_buffer(buf, count, ppos, tmpbuf, length); | 287 | return simple_read_from_buffer(buf, count, ppos, tmpbuf, length); |
287 | } | 288 | } |
288 | 289 | ||
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/mls.c b/security/selinux/ss/mls.c index 443ae7370144..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++) { |
@@ -516,7 +516,7 @@ int mls_compute_sid(struct context *scontext, | |||
516 | struct range_trans rtr; | 516 | struct range_trans rtr; |
517 | struct mls_range *r; | 517 | struct mls_range *r; |
518 | 518 | ||
519 | if (!selinux_mls_enabled) | 519 | if (!policydb.mls_enabled) |
520 | return 0; | 520 | return 0; |
521 | 521 | ||
522 | switch (specified) { | 522 | switch (specified) { |
@@ -559,7 +559,7 @@ int mls_compute_sid(struct context *scontext, | |||
559 | void mls_export_netlbl_lvl(struct context *context, | 559 | void mls_export_netlbl_lvl(struct context *context, |
560 | struct netlbl_lsm_secattr *secattr) | 560 | struct netlbl_lsm_secattr *secattr) |
561 | { | 561 | { |
562 | if (!selinux_mls_enabled) | 562 | if (!policydb.mls_enabled) |
563 | return; | 563 | return; |
564 | 564 | ||
565 | secattr->attr.mls.lvl = context->range.level[0].sens - 1; | 565 | secattr->attr.mls.lvl = context->range.level[0].sens - 1; |
@@ -579,7 +579,7 @@ void mls_export_netlbl_lvl(struct context *context, | |||
579 | void mls_import_netlbl_lvl(struct context *context, | 579 | void mls_import_netlbl_lvl(struct context *context, |
580 | struct netlbl_lsm_secattr *secattr) | 580 | struct netlbl_lsm_secattr *secattr) |
581 | { | 581 | { |
582 | if (!selinux_mls_enabled) | 582 | if (!policydb.mls_enabled) |
583 | return; | 583 | return; |
584 | 584 | ||
585 | context->range.level[0].sens = secattr->attr.mls.lvl + 1; | 585 | context->range.level[0].sens = secattr->attr.mls.lvl + 1; |
@@ -601,7 +601,7 @@ int mls_export_netlbl_cat(struct context *context, | |||
601 | { | 601 | { |
602 | int rc; | 602 | int rc; |
603 | 603 | ||
604 | if (!selinux_mls_enabled) | 604 | if (!policydb.mls_enabled) |
605 | return 0; | 605 | return 0; |
606 | 606 | ||
607 | rc = ebitmap_netlbl_export(&context->range.level[0].cat, | 607 | rc = ebitmap_netlbl_export(&context->range.level[0].cat, |
@@ -629,7 +629,7 @@ int mls_import_netlbl_cat(struct context *context, | |||
629 | { | 629 | { |
630 | int rc; | 630 | int rc; |
631 | 631 | ||
632 | if (!selinux_mls_enabled) | 632 | if (!policydb.mls_enabled) |
633 | return 0; | 633 | return 0; |
634 | 634 | ||
635 | 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 5b92c0219207..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, |
@@ -455,7 +453,7 @@ static int policydb_index_others(struct policydb *p) | |||
455 | 453 | ||
456 | 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", |
457 | 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); |
458 | if (selinux_mls_enabled) | 456 | if (p->mls_enabled) |
459 | printk(", %d sens, %d cats", p->p_levels.nprim, | 457 | printk(", %d sens, %d cats", p->p_levels.nprim, |
460 | p->p_cats.nprim); | 458 | p->p_cats.nprim); |
461 | printk("\n"); | 459 | printk("\n"); |
@@ -1717,14 +1715,12 @@ int policydb_read(struct policydb *p, void *fp) | |||
1717 | int i, j, rc; | 1715 | int i, j, rc; |
1718 | __le32 buf[4]; | 1716 | __le32 buf[4]; |
1719 | u32 nodebuf[8]; | 1717 | u32 nodebuf[8]; |
1720 | u32 len, len2, config, nprim, nel, nel2; | 1718 | u32 len, len2, nprim, nel, nel2; |
1721 | char *policydb_str; | 1719 | char *policydb_str; |
1722 | struct policydb_compat_info *info; | 1720 | struct policydb_compat_info *info; |
1723 | struct range_trans *rt; | 1721 | struct range_trans *rt; |
1724 | struct mls_range *r; | 1722 | struct mls_range *r; |
1725 | 1723 | ||
1726 | config = 0; | ||
1727 | |||
1728 | rc = policydb_init(p); | 1724 | rc = policydb_init(p); |
1729 | if (rc) | 1725 | if (rc) |
1730 | goto out; | 1726 | goto out; |
@@ -1772,7 +1768,7 @@ int policydb_read(struct policydb *p, void *fp) | |||
1772 | kfree(policydb_str); | 1768 | kfree(policydb_str); |
1773 | policydb_str = NULL; | 1769 | policydb_str = NULL; |
1774 | 1770 | ||
1775 | /* Read the version, config, and table sizes. */ | 1771 | /* Read the version and table sizes. */ |
1776 | rc = next_entry(buf, fp, sizeof(u32)*4); | 1772 | rc = next_entry(buf, fp, sizeof(u32)*4); |
1777 | if (rc < 0) | 1773 | if (rc < 0) |
1778 | goto bad; | 1774 | goto bad; |
@@ -1787,13 +1783,7 @@ int policydb_read(struct policydb *p, void *fp) | |||
1787 | } | 1783 | } |
1788 | 1784 | ||
1789 | if ((le32_to_cpu(buf[1]) & POLICYDB_CONFIG_MLS)) { | 1785 | if ((le32_to_cpu(buf[1]) & POLICYDB_CONFIG_MLS)) { |
1790 | if (ss_initialized && !selinux_mls_enabled) { | 1786 | p->mls_enabled = 1; |
1791 | printk(KERN_ERR "SELinux: Cannot switch between non-MLS" | ||
1792 | " and MLS policies\n"); | ||
1793 | goto bad; | ||
1794 | } | ||
1795 | selinux_mls_enabled = 1; | ||
1796 | config |= POLICYDB_CONFIG_MLS; | ||
1797 | 1787 | ||
1798 | if (p->policyvers < POLICYDB_VERSION_MLS) { | 1788 | if (p->policyvers < POLICYDB_VERSION_MLS) { |
1799 | printk(KERN_ERR "SELinux: security policydb version %d " | 1789 | printk(KERN_ERR "SELinux: security policydb version %d " |
@@ -1801,12 +1791,6 @@ int policydb_read(struct policydb *p, void *fp) | |||
1801 | p->policyvers); | 1791 | p->policyvers); |
1802 | goto bad; | 1792 | goto bad; |
1803 | } | 1793 | } |
1804 | } else { | ||
1805 | if (ss_initialized && selinux_mls_enabled) { | ||
1806 | printk(KERN_ERR "SELinux: Cannot switch between MLS and" | ||
1807 | " non-MLS policies\n"); | ||
1808 | goto bad; | ||
1809 | } | ||
1810 | } | 1794 | } |
1811 | p->reject_unknown = !!(le32_to_cpu(buf[1]) & REJECT_UNKNOWN); | 1795 | p->reject_unknown = !!(le32_to_cpu(buf[1]) & REJECT_UNKNOWN); |
1812 | p->allow_unknown = !!(le32_to_cpu(buf[1]) & ALLOW_UNKNOWN); | 1796 | p->allow_unknown = !!(le32_to_cpu(buf[1]) & ALLOW_UNKNOWN); |
diff --git a/security/selinux/ss/policydb.h b/security/selinux/ss/policydb.h index 193736b64de8..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 | ||
@@ -185,6 +187,8 @@ struct genfs { | |||
185 | 187 | ||
186 | /* The policy database */ | 188 | /* The policy database */ |
187 | struct policydb { | 189 | struct policydb { |
190 | int mls_enabled; | ||
191 | |||
188 | /* symbol tables */ | 192 | /* symbol tables */ |
189 | struct symtab symtab[SYM_NUM]; | 193 | struct symtab symtab[SYM_NUM]; |
190 | #define p_commons symtab[SYM_COMMONS] | 194 | #define p_commons symtab[SYM_COMMONS] |
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index 2abbc49914e6..4e976f58b980 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. |
@@ -232,6 +236,10 @@ static void map_decision(u16 tclass, struct av_decision *avd, | |||
232 | } | 236 | } |
233 | } | 237 | } |
234 | 238 | ||
239 | int security_mls_enabled(void) | ||
240 | { | ||
241 | return policydb.mls_enabled; | ||
242 | } | ||
235 | 243 | ||
236 | /* | 244 | /* |
237 | * Return the boolean value of a constraint expression | 245 | * Return the boolean value of a constraint expression |
@@ -1550,6 +1558,8 @@ static int convert_context(u32 key, | |||
1550 | { | 1558 | { |
1551 | struct convert_context_args *args; | 1559 | struct convert_context_args *args; |
1552 | struct context oldc; | 1560 | struct context oldc; |
1561 | struct ocontext *oc; | ||
1562 | struct mls_range *range; | ||
1553 | struct role_datum *role; | 1563 | struct role_datum *role; |
1554 | struct type_datum *typdatum; | 1564 | struct type_datum *typdatum; |
1555 | struct user_datum *usrdatum; | 1565 | struct user_datum *usrdatum; |
@@ -1620,9 +1630,39 @@ static int convert_context(u32 key, | |||
1620 | goto bad; | 1630 | goto bad; |
1621 | c->type = typdatum->value; | 1631 | c->type = typdatum->value; |
1622 | 1632 | ||
1623 | rc = mls_convert_context(args->oldp, args->newp, c); | 1633 | /* Convert the MLS fields if dealing with MLS policies */ |
1624 | if (rc) | 1634 | if (args->oldp->mls_enabled && args->newp->mls_enabled) { |
1625 | goto bad; | 1635 | rc = mls_convert_context(args->oldp, args->newp, c); |
1636 | if (rc) | ||
1637 | goto bad; | ||
1638 | } else if (args->oldp->mls_enabled && !args->newp->mls_enabled) { | ||
1639 | /* | ||
1640 | * Switching between MLS and non-MLS policy: | ||
1641 | * free any storage used by the MLS fields in the | ||
1642 | * context for all existing entries in the sidtab. | ||
1643 | */ | ||
1644 | mls_context_destroy(c); | ||
1645 | } else if (!args->oldp->mls_enabled && args->newp->mls_enabled) { | ||
1646 | /* | ||
1647 | * Switching between non-MLS and MLS policy: | ||
1648 | * ensure that the MLS fields of the context for all | ||
1649 | * existing entries in the sidtab are filled in with a | ||
1650 | * suitable default value, likely taken from one of the | ||
1651 | * initial SIDs. | ||
1652 | */ | ||
1653 | oc = args->newp->ocontexts[OCON_ISID]; | ||
1654 | while (oc && oc->sid[0] != SECINITSID_UNLABELED) | ||
1655 | oc = oc->next; | ||
1656 | if (!oc) { | ||
1657 | printk(KERN_ERR "SELinux: unable to look up" | ||
1658 | " the initial SIDs list\n"); | ||
1659 | goto bad; | ||
1660 | } | ||
1661 | range = &oc->context[0].range; | ||
1662 | rc = mls_range_set(c, range); | ||
1663 | if (rc) | ||
1664 | goto bad; | ||
1665 | } | ||
1626 | 1666 | ||
1627 | /* Check the validity of the new context. */ | 1667 | /* Check the validity of the new context. */ |
1628 | if (!policydb_context_isvalid(args->newp, c)) { | 1668 | if (!policydb_context_isvalid(args->newp, c)) { |
@@ -1718,6 +1758,12 @@ int security_load_policy(void *data, size_t len) | |||
1718 | if (policydb_read(&newpolicydb, fp)) | 1758 | if (policydb_read(&newpolicydb, fp)) |
1719 | return -EINVAL; | 1759 | return -EINVAL; |
1720 | 1760 | ||
1761 | /* If switching between different policy types, log MLS status */ | ||
1762 | if (policydb.mls_enabled && !newpolicydb.mls_enabled) | ||
1763 | printk(KERN_INFO "SELinux: Disabling MLS support...\n"); | ||
1764 | else if (!policydb.mls_enabled && newpolicydb.mls_enabled) | ||
1765 | printk(KERN_INFO "SELinux: Enabling MLS support...\n"); | ||
1766 | |||
1721 | rc = policydb_load_isids(&newpolicydb, &newsidtab); | 1767 | rc = policydb_load_isids(&newpolicydb, &newsidtab); |
1722 | if (rc) { | 1768 | if (rc) { |
1723 | printk(KERN_ERR "SELinux: unable to load the initial SIDs\n"); | 1769 | printk(KERN_ERR "SELinux: unable to load the initial SIDs\n"); |
@@ -1749,8 +1795,12 @@ int security_load_policy(void *data, size_t len) | |||
1749 | args.oldp = &policydb; | 1795 | args.oldp = &policydb; |
1750 | args.newp = &newpolicydb; | 1796 | args.newp = &newpolicydb; |
1751 | rc = sidtab_map(&newsidtab, convert_context, &args); | 1797 | rc = sidtab_map(&newsidtab, convert_context, &args); |
1752 | if (rc) | 1798 | if (rc) { |
1799 | printk(KERN_ERR "SELinux: unable to convert the internal" | ||
1800 | " representation of contexts in the new SID" | ||
1801 | " table\n"); | ||
1753 | goto err; | 1802 | goto err; |
1803 | } | ||
1754 | 1804 | ||
1755 | /* Save the old policydb and SID table to free later. */ | 1805 | /* Save the old policydb and SID table to free later. */ |
1756 | memcpy(&oldpolicydb, &policydb, sizeof policydb); | 1806 | memcpy(&oldpolicydb, &policydb, sizeof policydb); |
@@ -2346,7 +2396,7 @@ int security_sid_mls_copy(u32 sid, u32 mls_sid, u32 *new_sid) | |||
2346 | u32 len; | 2396 | u32 len; |
2347 | int rc = 0; | 2397 | int rc = 0; |
2348 | 2398 | ||
2349 | if (!ss_initialized || !selinux_mls_enabled) { | 2399 | if (!ss_initialized || !policydb.mls_enabled) { |
2350 | *new_sid = sid; | 2400 | *new_sid = sid; |
2351 | goto out; | 2401 | goto out; |
2352 | } | 2402 | } |
@@ -2447,7 +2497,7 @@ int security_net_peersid_resolve(u32 nlbl_sid, u32 nlbl_type, | |||
2447 | /* we don't need to check ss_initialized here since the only way both | 2497 | /* we don't need to check ss_initialized here since the only way both |
2448 | * nlbl_sid and xfrm_sid are not equal to SECSID_NULL would be if the | 2498 | * nlbl_sid and xfrm_sid are not equal to SECSID_NULL would be if the |
2449 | * security server was initialized and ss_initialized was true */ | 2499 | * security server was initialized and ss_initialized was true */ |
2450 | if (!selinux_mls_enabled) { | 2500 | if (!policydb.mls_enabled) { |
2451 | *peer_sid = SECSID_NULL; | 2501 | *peer_sid = SECSID_NULL; |
2452 | return 0; | 2502 | return 0; |
2453 | } | 2503 | } |