diff options
author | James Morris <jmorris@namei.org> | 2010-02-28 17:36:31 -0500 |
---|---|---|
committer | James Morris <jmorris@namei.org> | 2010-02-28 17:36:31 -0500 |
commit | b4ccebdd37ff70d349321a198f416ba737a5e833 (patch) | |
tree | 275d717070346722c3aacd8355fb4f743216e03b /security/selinux | |
parent | 30ff056c42c665b9ea535d8515890857ae382540 (diff) | |
parent | ef57471a73b67a7b65fd8708fd55c77cb7c619af (diff) |
Merge branch 'next' into for-linus
Diffstat (limited to 'security/selinux')
-rw-r--r-- | security/selinux/avc.c | 22 | ||||
-rw-r--r-- | security/selinux/hooks.c | 41 | ||||
-rw-r--r-- | security/selinux/include/security.h | 13 | ||||
-rw-r--r-- | security/selinux/selinuxfs.c | 12 | ||||
-rw-r--r-- | security/selinux/ss/context.h | 12 | ||||
-rw-r--r-- | security/selinux/ss/mls.c | 48 | ||||
-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 | 127 | ||||
-rw-r--r-- | security/selinux/ss/policydb.h | 10 | ||||
-rw-r--r-- | security/selinux/ss/services.c | 273 |
11 files changed, 302 insertions, 265 deletions
diff --git a/security/selinux/avc.c b/security/selinux/avc.c index f2dde268165a..db0fd9f33499 100644 --- a/security/selinux/avc.c +++ b/security/selinux/avc.c | |||
@@ -489,17 +489,14 @@ void avc_audit(u32 ssid, u32 tsid, | |||
489 | struct common_audit_data stack_data; | 489 | struct common_audit_data stack_data; |
490 | u32 denied, audited; | 490 | u32 denied, audited; |
491 | denied = requested & ~avd->allowed; | 491 | denied = requested & ~avd->allowed; |
492 | if (denied) { | 492 | if (denied) |
493 | audited = denied; | 493 | audited = denied & avd->auditdeny; |
494 | if (!(audited & avd->auditdeny)) | 494 | else if (result) |
495 | return; | ||
496 | } else if (result) { | ||
497 | audited = denied = requested; | 495 | audited = denied = requested; |
498 | } else { | 496 | else |
499 | audited = requested; | 497 | audited = requested & avd->auditallow; |
500 | if (!(audited & avd->auditallow)) | 498 | if (!audited) |
501 | return; | 499 | return; |
502 | } | ||
503 | if (!a) { | 500 | if (!a) { |
504 | a = &stack_data; | 501 | a = &stack_data; |
505 | memset(a, 0, sizeof(*a)); | 502 | memset(a, 0, sizeof(*a)); |
@@ -746,9 +743,7 @@ int avc_has_perm_noaudit(u32 ssid, u32 tsid, | |||
746 | else | 743 | else |
747 | avd = &avd_entry; | 744 | avd = &avd_entry; |
748 | 745 | ||
749 | rc = security_compute_av(ssid, tsid, tclass, requested, avd); | 746 | security_compute_av(ssid, tsid, tclass, avd); |
750 | if (rc) | ||
751 | goto out; | ||
752 | rcu_read_lock(); | 747 | rcu_read_lock(); |
753 | node = avc_insert(ssid, tsid, tclass, avd); | 748 | node = avc_insert(ssid, tsid, tclass, avd); |
754 | } else { | 749 | } else { |
@@ -770,7 +765,6 @@ int avc_has_perm_noaudit(u32 ssid, u32 tsid, | |||
770 | } | 765 | } |
771 | 766 | ||
772 | rcu_read_unlock(); | 767 | rcu_read_unlock(); |
773 | out: | ||
774 | return rc; | 768 | return rc; |
775 | } | 769 | } |
776 | 770 | ||
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 9a2ee845e9d4..5feecb41009d 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c | |||
@@ -76,6 +76,7 @@ | |||
76 | #include <linux/selinux.h> | 76 | #include <linux/selinux.h> |
77 | #include <linux/mutex.h> | 77 | #include <linux/mutex.h> |
78 | #include <linux/posix-timers.h> | 78 | #include <linux/posix-timers.h> |
79 | #include <linux/syslog.h> | ||
79 | 80 | ||
80 | #include "avc.h" | 81 | #include "avc.h" |
81 | #include "objsec.h" | 82 | #include "objsec.h" |
@@ -125,13 +126,6 @@ __setup("selinux=", selinux_enabled_setup); | |||
125 | int selinux_enabled = 1; | 126 | int selinux_enabled = 1; |
126 | #endif | 127 | #endif |
127 | 128 | ||
128 | |||
129 | /* | ||
130 | * Minimal support for a secondary security module, | ||
131 | * just to allow the use of the capability module. | ||
132 | */ | ||
133 | static struct security_operations *secondary_ops; | ||
134 | |||
135 | /* Lists of inode and superblock security structures initialized | 129 | /* Lists of inode and superblock security structures initialized |
136 | before the policy was loaded. */ | 130 | before the policy was loaded. */ |
137 | static LIST_HEAD(superblock_security_head); | 131 | static LIST_HEAD(superblock_security_head); |
@@ -2049,29 +2043,30 @@ static int selinux_quota_on(struct dentry *dentry) | |||
2049 | return dentry_has_perm(cred, NULL, dentry, FILE__QUOTAON); | 2043 | return dentry_has_perm(cred, NULL, dentry, FILE__QUOTAON); |
2050 | } | 2044 | } |
2051 | 2045 | ||
2052 | static int selinux_syslog(int type) | 2046 | static int selinux_syslog(int type, bool from_file) |
2053 | { | 2047 | { |
2054 | int rc; | 2048 | int rc; |
2055 | 2049 | ||
2056 | rc = cap_syslog(type); | 2050 | rc = cap_syslog(type, from_file); |
2057 | if (rc) | 2051 | if (rc) |
2058 | return rc; | 2052 | return rc; |
2059 | 2053 | ||
2060 | switch (type) { | 2054 | switch (type) { |
2061 | case 3: /* Read last kernel messages */ | 2055 | case SYSLOG_ACTION_READ_ALL: /* Read last kernel messages */ |
2062 | case 10: /* Return size of the log buffer */ | 2056 | case SYSLOG_ACTION_SIZE_BUFFER: /* Return size of the log buffer */ |
2063 | rc = task_has_system(current, SYSTEM__SYSLOG_READ); | 2057 | rc = task_has_system(current, SYSTEM__SYSLOG_READ); |
2064 | break; | 2058 | break; |
2065 | case 6: /* Disable logging to console */ | 2059 | case SYSLOG_ACTION_CONSOLE_OFF: /* Disable logging to console */ |
2066 | case 7: /* Enable logging to console */ | 2060 | case SYSLOG_ACTION_CONSOLE_ON: /* Enable logging to console */ |
2067 | case 8: /* Set level of messages printed to console */ | 2061 | /* Set level of messages printed to console */ |
2062 | case SYSLOG_ACTION_CONSOLE_LEVEL: | ||
2068 | rc = task_has_system(current, SYSTEM__SYSLOG_CONSOLE); | 2063 | rc = task_has_system(current, SYSTEM__SYSLOG_CONSOLE); |
2069 | break; | 2064 | break; |
2070 | case 0: /* Close log */ | 2065 | case SYSLOG_ACTION_CLOSE: /* Close log */ |
2071 | case 1: /* Open log */ | 2066 | case SYSLOG_ACTION_OPEN: /* Open log */ |
2072 | case 2: /* Read from log */ | 2067 | case SYSLOG_ACTION_READ: /* Read from log */ |
2073 | case 4: /* Read/clear last kernel messages */ | 2068 | case SYSLOG_ACTION_READ_CLEAR: /* Read/clear last kernel messages */ |
2074 | case 5: /* Clear ring buffer */ | 2069 | case SYSLOG_ACTION_CLEAR: /* Clear ring buffer */ |
2075 | default: | 2070 | default: |
2076 | rc = task_has_system(current, SYSTEM__SYSLOG_MOD); | 2071 | rc = task_has_system(current, SYSTEM__SYSLOG_MOD); |
2077 | break; | 2072 | break; |
@@ -3334,7 +3329,7 @@ static int selinux_kernel_create_files_as(struct cred *new, struct inode *inode) | |||
3334 | 3329 | ||
3335 | if (ret == 0) | 3330 | if (ret == 0) |
3336 | tsec->create_sid = isec->sid; | 3331 | tsec->create_sid = isec->sid; |
3337 | return 0; | 3332 | return ret; |
3338 | } | 3333 | } |
3339 | 3334 | ||
3340 | static int selinux_kernel_module_request(char *kmod_name) | 3335 | static int selinux_kernel_module_request(char *kmod_name) |
@@ -5672,9 +5667,6 @@ static __init int selinux_init(void) | |||
5672 | 0, SLAB_PANIC, NULL); | 5667 | 0, SLAB_PANIC, NULL); |
5673 | avc_init(); | 5668 | avc_init(); |
5674 | 5669 | ||
5675 | secondary_ops = security_ops; | ||
5676 | if (!secondary_ops) | ||
5677 | panic("SELinux: No initial security operations\n"); | ||
5678 | if (register_security(&selinux_ops)) | 5670 | if (register_security(&selinux_ops)) |
5679 | panic("SELinux: Unable to register with kernel.\n"); | 5671 | panic("SELinux: Unable to register with kernel.\n"); |
5680 | 5672 | ||
@@ -5835,8 +5827,7 @@ int selinux_disable(void) | |||
5835 | selinux_disabled = 1; | 5827 | selinux_disabled = 1; |
5836 | selinux_enabled = 0; | 5828 | selinux_enabled = 0; |
5837 | 5829 | ||
5838 | /* Reset security_ops to the secondary module, dummy or capability. */ | 5830 | reset_security_ops(); |
5839 | security_ops = secondary_ops; | ||
5840 | 5831 | ||
5841 | /* Try to destroy the avc node cache */ | 5832 | /* Try to destroy the avc node cache */ |
5842 | avc_disable(); | 5833 | avc_disable(); |
diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h index 2553266ad793..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); |
@@ -96,13 +97,11 @@ struct av_decision { | |||
96 | /* definitions of av_decision.flags */ | 97 | /* definitions of av_decision.flags */ |
97 | #define AVD_FLAGS_PERMISSIVE 0x0001 | 98 | #define AVD_FLAGS_PERMISSIVE 0x0001 |
98 | 99 | ||
99 | int security_compute_av(u32 ssid, u32 tsid, | 100 | void security_compute_av(u32 ssid, u32 tsid, |
100 | u16 tclass, u32 requested, | 101 | u16 tclass, struct av_decision *avd); |
101 | struct av_decision *avd); | ||
102 | 102 | ||
103 | int security_compute_av_user(u32 ssid, u32 tsid, | 103 | void security_compute_av_user(u32 ssid, u32 tsid, |
104 | u16 tclass, u32 requested, | 104 | u16 tclass, struct av_decision *avd); |
105 | struct av_decision *avd); | ||
106 | 105 | ||
107 | int security_transition_sid(u32 ssid, u32 tsid, | 106 | int security_transition_sid(u32 ssid, u32 tsid, |
108 | u16 tclass, u32 *out_sid); | 107 | u16 tclass, u32 *out_sid); |
diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c index fab36fdf2769..cd191bbec03c 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 | ||
@@ -494,7 +495,6 @@ static ssize_t sel_write_access(struct file *file, char *buf, size_t size) | |||
494 | char *scon, *tcon; | 495 | char *scon, *tcon; |
495 | u32 ssid, tsid; | 496 | u32 ssid, tsid; |
496 | u16 tclass; | 497 | u16 tclass; |
497 | u32 req; | ||
498 | struct av_decision avd; | 498 | struct av_decision avd; |
499 | ssize_t length; | 499 | ssize_t length; |
500 | 500 | ||
@@ -512,7 +512,7 @@ static ssize_t sel_write_access(struct file *file, char *buf, size_t size) | |||
512 | goto out; | 512 | goto out; |
513 | 513 | ||
514 | length = -EINVAL; | 514 | length = -EINVAL; |
515 | if (sscanf(buf, "%s %s %hu %x", scon, tcon, &tclass, &req) != 4) | 515 | if (sscanf(buf, "%s %s %hu", scon, tcon, &tclass) != 3) |
516 | goto out2; | 516 | goto out2; |
517 | 517 | ||
518 | length = security_context_to_sid(scon, strlen(scon)+1, &ssid); | 518 | length = security_context_to_sid(scon, strlen(scon)+1, &ssid); |
@@ -522,9 +522,7 @@ static ssize_t sel_write_access(struct file *file, char *buf, size_t size) | |||
522 | if (length < 0) | 522 | if (length < 0) |
523 | goto out2; | 523 | goto out2; |
524 | 524 | ||
525 | length = security_compute_av_user(ssid, tsid, tclass, req, &avd); | 525 | security_compute_av_user(ssid, tsid, tclass, &avd); |
526 | if (length < 0) | ||
527 | goto out2; | ||
528 | 526 | ||
529 | length = scnprintf(buf, SIMPLE_TRANSACTION_LIMIT, | 527 | length = scnprintf(buf, SIMPLE_TRANSACTION_LIMIT, |
530 | "%x %x %x %x %u %x", | 528 | "%x %x %x %x %u %x", |
@@ -979,6 +977,8 @@ static int sel_make_bools(void) | |||
979 | u32 sid; | 977 | u32 sid; |
980 | 978 | ||
981 | /* remove any existing files */ | 979 | /* remove any existing files */ |
980 | for (i = 0; i < bool_num; i++) | ||
981 | kfree(bool_pending_names[i]); | ||
982 | kfree(bool_pending_names); | 982 | kfree(bool_pending_names); |
983 | kfree(bool_pending_values); | 983 | kfree(bool_pending_values); |
984 | bool_pending_names = NULL; | 984 | bool_pending_names = NULL; |
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 3f2b2706b5bb..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,23 +513,21 @@ 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 == policydb.process_class) | 533 | if (tclass == policydb.process_class) |
@@ -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 f03667213ea8..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,20 +734,8 @@ 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++) |
@@ -1686,12 +1715,11 @@ int policydb_read(struct policydb *p, void *fp) | |||
1686 | int i, j, rc; | 1715 | int i, j, rc; |
1687 | __le32 buf[4]; | 1716 | __le32 buf[4]; |
1688 | u32 nodebuf[8]; | 1717 | u32 nodebuf[8]; |
1689 | u32 len, len2, config, nprim, nel, nel2; | 1718 | u32 len, len2, nprim, nel, nel2; |
1690 | char *policydb_str; | 1719 | char *policydb_str; |
1691 | struct policydb_compat_info *info; | 1720 | struct policydb_compat_info *info; |
1692 | struct range_trans *rt, *lrt; | 1721 | struct range_trans *rt; |
1693 | 1722 | struct mls_range *r; | |
1694 | config = 0; | ||
1695 | 1723 | ||
1696 | rc = policydb_init(p); | 1724 | rc = policydb_init(p); |
1697 | if (rc) | 1725 | if (rc) |
@@ -1740,7 +1768,7 @@ int policydb_read(struct policydb *p, void *fp) | |||
1740 | kfree(policydb_str); | 1768 | kfree(policydb_str); |
1741 | policydb_str = NULL; | 1769 | policydb_str = NULL; |
1742 | 1770 | ||
1743 | /* Read the version, config, and table sizes. */ | 1771 | /* Read the version and table sizes. */ |
1744 | rc = next_entry(buf, fp, sizeof(u32)*4); | 1772 | rc = next_entry(buf, fp, sizeof(u32)*4); |
1745 | if (rc < 0) | 1773 | if (rc < 0) |
1746 | goto bad; | 1774 | goto bad; |
@@ -1755,13 +1783,7 @@ int policydb_read(struct policydb *p, void *fp) | |||
1755 | } | 1783 | } |
1756 | 1784 | ||
1757 | if ((le32_to_cpu(buf[1]) & POLICYDB_CONFIG_MLS)) { | 1785 | if ((le32_to_cpu(buf[1]) & POLICYDB_CONFIG_MLS)) { |
1758 | if (ss_initialized && !selinux_mls_enabled) { | 1786 | p->mls_enabled = 1; |
1759 | printk(KERN_ERR "SELinux: Cannot switch between non-MLS" | ||
1760 | " and MLS policies\n"); | ||
1761 | goto bad; | ||
1762 | } | ||
1763 | selinux_mls_enabled = 1; | ||
1764 | config |= POLICYDB_CONFIG_MLS; | ||
1765 | 1787 | ||
1766 | if (p->policyvers < POLICYDB_VERSION_MLS) { | 1788 | if (p->policyvers < POLICYDB_VERSION_MLS) { |
1767 | printk(KERN_ERR "SELinux: security policydb version %d " | 1789 | printk(KERN_ERR "SELinux: security policydb version %d " |
@@ -1769,12 +1791,6 @@ int policydb_read(struct policydb *p, void *fp) | |||
1769 | p->policyvers); | 1791 | p->policyvers); |
1770 | goto bad; | 1792 | goto bad; |
1771 | } | 1793 | } |
1772 | } else { | ||
1773 | if (ss_initialized && selinux_mls_enabled) { | ||
1774 | printk(KERN_ERR "SELinux: Cannot switch between MLS and" | ||
1775 | " non-MLS policies\n"); | ||
1776 | goto bad; | ||
1777 | } | ||
1778 | } | 1794 | } |
1779 | p->reject_unknown = !!(le32_to_cpu(buf[1]) & REJECT_UNKNOWN); | 1795 | p->reject_unknown = !!(le32_to_cpu(buf[1]) & REJECT_UNKNOWN); |
1780 | p->allow_unknown = !!(le32_to_cpu(buf[1]) & ALLOW_UNKNOWN); | 1796 | p->allow_unknown = !!(le32_to_cpu(buf[1]) & ALLOW_UNKNOWN); |
@@ -2122,44 +2138,61 @@ int policydb_read(struct policydb *p, void *fp) | |||
2122 | if (rc < 0) | 2138 | if (rc < 0) |
2123 | goto bad; | 2139 | goto bad; |
2124 | nel = le32_to_cpu(buf[0]); | 2140 | nel = le32_to_cpu(buf[0]); |
2125 | lrt = NULL; | ||
2126 | for (i = 0; i < nel; i++) { | 2141 | for (i = 0; i < nel; i++) { |
2127 | rt = kzalloc(sizeof(*rt), GFP_KERNEL); | 2142 | rt = kzalloc(sizeof(*rt), GFP_KERNEL); |
2128 | if (!rt) { | 2143 | if (!rt) { |
2129 | rc = -ENOMEM; | 2144 | rc = -ENOMEM; |
2130 | goto bad; | 2145 | goto bad; |
2131 | } | 2146 | } |
2132 | if (lrt) | ||
2133 | lrt->next = rt; | ||
2134 | else | ||
2135 | p->range_tr = rt; | ||
2136 | rc = next_entry(buf, fp, (sizeof(u32) * 2)); | 2147 | rc = next_entry(buf, fp, (sizeof(u32) * 2)); |
2137 | if (rc < 0) | 2148 | if (rc < 0) { |
2149 | kfree(rt); | ||
2138 | goto bad; | 2150 | goto bad; |
2151 | } | ||
2139 | rt->source_type = le32_to_cpu(buf[0]); | 2152 | rt->source_type = le32_to_cpu(buf[0]); |
2140 | rt->target_type = le32_to_cpu(buf[1]); | 2153 | rt->target_type = le32_to_cpu(buf[1]); |
2141 | if (new_rangetr) { | 2154 | if (new_rangetr) { |
2142 | rc = next_entry(buf, fp, sizeof(u32)); | 2155 | rc = next_entry(buf, fp, sizeof(u32)); |
2143 | if (rc < 0) | 2156 | if (rc < 0) { |
2157 | kfree(rt); | ||
2144 | goto bad; | 2158 | goto bad; |
2159 | } | ||
2145 | rt->target_class = le32_to_cpu(buf[0]); | 2160 | rt->target_class = le32_to_cpu(buf[0]); |
2146 | } else | 2161 | } else |
2147 | rt->target_class = p->process_class; | 2162 | rt->target_class = p->process_class; |
2148 | if (!policydb_type_isvalid(p, rt->source_type) || | 2163 | if (!policydb_type_isvalid(p, rt->source_type) || |
2149 | !policydb_type_isvalid(p, rt->target_type) || | 2164 | !policydb_type_isvalid(p, rt->target_type) || |
2150 | !policydb_class_isvalid(p, rt->target_class)) { | 2165 | !policydb_class_isvalid(p, rt->target_class)) { |
2166 | kfree(rt); | ||
2151 | rc = -EINVAL; | 2167 | rc = -EINVAL; |
2152 | goto bad; | 2168 | goto bad; |
2153 | } | 2169 | } |
2154 | rc = mls_read_range_helper(&rt->target_range, fp); | 2170 | r = kzalloc(sizeof(*r), GFP_KERNEL); |
2155 | if (rc) | 2171 | if (!r) { |
2172 | kfree(rt); | ||
2173 | rc = -ENOMEM; | ||
2156 | goto bad; | 2174 | goto bad; |
2157 | if (!mls_range_isvalid(p, &rt->target_range)) { | 2175 | } |
2176 | rc = mls_read_range_helper(r, fp); | ||
2177 | if (rc) { | ||
2178 | kfree(rt); | ||
2179 | kfree(r); | ||
2180 | goto bad; | ||
2181 | } | ||
2182 | if (!mls_range_isvalid(p, r)) { | ||
2158 | 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); | ||
2159 | goto bad; | 2192 | goto bad; |
2160 | } | 2193 | } |
2161 | lrt = rt; | ||
2162 | } | 2194 | } |
2195 | rangetr_hash_eval(p->range_tr); | ||
2163 | } | 2196 | } |
2164 | 2197 | ||
2165 | 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 cdcc5700946f..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; |
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index b3efae204ac7..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. |
@@ -87,11 +91,10 @@ static u32 latest_granting; | |||
87 | static int context_struct_to_string(struct context *context, char **scontext, | 91 | static int context_struct_to_string(struct context *context, char **scontext, |
88 | u32 *scontext_len); | 92 | u32 *scontext_len); |
89 | 93 | ||
90 | static int context_struct_compute_av(struct context *scontext, | 94 | static void context_struct_compute_av(struct context *scontext, |
91 | struct context *tcontext, | 95 | struct context *tcontext, |
92 | u16 tclass, | 96 | u16 tclass, |
93 | u32 requested, | 97 | struct av_decision *avd); |
94 | struct av_decision *avd); | ||
95 | 98 | ||
96 | struct selinux_mapping { | 99 | struct selinux_mapping { |
97 | u16 value; /* policy value */ | 100 | u16 value; /* policy value */ |
@@ -196,23 +199,6 @@ static u16 unmap_class(u16 tclass) | |||
196 | return tclass; | 199 | return tclass; |
197 | } | 200 | } |
198 | 201 | ||
199 | static u32 unmap_perm(u16 tclass, u32 tperm) | ||
200 | { | ||
201 | if (tclass < current_mapping_size) { | ||
202 | unsigned i; | ||
203 | u32 kperm = 0; | ||
204 | |||
205 | for (i = 0; i < current_mapping[tclass].num_perms; i++) | ||
206 | if (tperm & (1<<i)) { | ||
207 | kperm |= current_mapping[tclass].perms[i]; | ||
208 | tperm &= ~(1<<i); | ||
209 | } | ||
210 | return kperm; | ||
211 | } | ||
212 | |||
213 | return tperm; | ||
214 | } | ||
215 | |||
216 | static void map_decision(u16 tclass, struct av_decision *avd, | 202 | static void map_decision(u16 tclass, struct av_decision *avd, |
217 | int allow_unknown) | 203 | int allow_unknown) |
218 | { | 204 | { |
@@ -250,6 +236,10 @@ static void map_decision(u16 tclass, struct av_decision *avd, | |||
250 | } | 236 | } |
251 | } | 237 | } |
252 | 238 | ||
239 | int security_mls_enabled(void) | ||
240 | { | ||
241 | return policydb.mls_enabled; | ||
242 | } | ||
253 | 243 | ||
254 | /* | 244 | /* |
255 | * Return the boolean value of a constraint expression | 245 | * Return the boolean value of a constraint expression |
@@ -465,7 +455,8 @@ static void security_dump_masked_av(struct context *scontext, | |||
465 | char *scontext_name = NULL; | 455 | char *scontext_name = NULL; |
466 | char *tcontext_name = NULL; | 456 | char *tcontext_name = NULL; |
467 | char *permission_names[32]; | 457 | char *permission_names[32]; |
468 | int index, length; | 458 | int index; |
459 | u32 length; | ||
469 | bool need_comma = false; | 460 | bool need_comma = false; |
470 | 461 | ||
471 | if (!permissions) | 462 | if (!permissions) |
@@ -532,7 +523,6 @@ out: | |||
532 | static void type_attribute_bounds_av(struct context *scontext, | 523 | static void type_attribute_bounds_av(struct context *scontext, |
533 | struct context *tcontext, | 524 | struct context *tcontext, |
534 | u16 tclass, | 525 | u16 tclass, |
535 | u32 requested, | ||
536 | struct av_decision *avd) | 526 | struct av_decision *avd) |
537 | { | 527 | { |
538 | struct context lo_scontext; | 528 | struct context lo_scontext; |
@@ -553,7 +543,6 @@ static void type_attribute_bounds_av(struct context *scontext, | |||
553 | context_struct_compute_av(&lo_scontext, | 543 | context_struct_compute_av(&lo_scontext, |
554 | tcontext, | 544 | tcontext, |
555 | tclass, | 545 | tclass, |
556 | requested, | ||
557 | &lo_avd); | 546 | &lo_avd); |
558 | if ((lo_avd.allowed & avd->allowed) == avd->allowed) | 547 | if ((lo_avd.allowed & avd->allowed) == avd->allowed) |
559 | return; /* no masked permission */ | 548 | return; /* no masked permission */ |
@@ -569,7 +558,6 @@ static void type_attribute_bounds_av(struct context *scontext, | |||
569 | context_struct_compute_av(scontext, | 558 | context_struct_compute_av(scontext, |
570 | &lo_tcontext, | 559 | &lo_tcontext, |
571 | tclass, | 560 | tclass, |
572 | requested, | ||
573 | &lo_avd); | 561 | &lo_avd); |
574 | if ((lo_avd.allowed & avd->allowed) == avd->allowed) | 562 | if ((lo_avd.allowed & avd->allowed) == avd->allowed) |
575 | return; /* no masked permission */ | 563 | return; /* no masked permission */ |
@@ -586,7 +574,6 @@ static void type_attribute_bounds_av(struct context *scontext, | |||
586 | context_struct_compute_av(&lo_scontext, | 574 | context_struct_compute_av(&lo_scontext, |
587 | &lo_tcontext, | 575 | &lo_tcontext, |
588 | tclass, | 576 | tclass, |
589 | requested, | ||
590 | &lo_avd); | 577 | &lo_avd); |
591 | if ((lo_avd.allowed & avd->allowed) == avd->allowed) | 578 | if ((lo_avd.allowed & avd->allowed) == avd->allowed) |
592 | return; /* no masked permission */ | 579 | return; /* no masked permission */ |
@@ -607,11 +594,10 @@ static void type_attribute_bounds_av(struct context *scontext, | |||
607 | * Compute access vectors based on a context structure pair for | 594 | * Compute access vectors based on a context structure pair for |
608 | * the permissions in a particular class. | 595 | * the permissions in a particular class. |
609 | */ | 596 | */ |
610 | static int context_struct_compute_av(struct context *scontext, | 597 | static void context_struct_compute_av(struct context *scontext, |
611 | struct context *tcontext, | 598 | struct context *tcontext, |
612 | u16 tclass, | 599 | u16 tclass, |
613 | u32 requested, | 600 | struct av_decision *avd) |
614 | struct av_decision *avd) | ||
615 | { | 601 | { |
616 | struct constraint_node *constraint; | 602 | struct constraint_node *constraint; |
617 | struct role_allow *ra; | 603 | struct role_allow *ra; |
@@ -622,19 +608,14 @@ static int context_struct_compute_av(struct context *scontext, | |||
622 | struct ebitmap_node *snode, *tnode; | 608 | struct ebitmap_node *snode, *tnode; |
623 | unsigned int i, j; | 609 | unsigned int i, j; |
624 | 610 | ||
625 | /* | ||
626 | * Initialize the access vectors to the default values. | ||
627 | */ | ||
628 | avd->allowed = 0; | 611 | avd->allowed = 0; |
629 | avd->auditallow = 0; | 612 | avd->auditallow = 0; |
630 | avd->auditdeny = 0xffffffff; | 613 | avd->auditdeny = 0xffffffff; |
631 | avd->seqno = latest_granting; | ||
632 | avd->flags = 0; | ||
633 | 614 | ||
634 | if (unlikely(!tclass || tclass > policydb.p_classes.nprim)) { | 615 | if (unlikely(!tclass || tclass > policydb.p_classes.nprim)) { |
635 | if (printk_ratelimit()) | 616 | if (printk_ratelimit()) |
636 | printk(KERN_WARNING "SELinux: Invalid class %hu\n", tclass); | 617 | printk(KERN_WARNING "SELinux: Invalid class %hu\n", tclass); |
637 | return -EINVAL; | 618 | return; |
638 | } | 619 | } |
639 | 620 | ||
640 | tclass_datum = policydb.class_val_to_struct[tclass - 1]; | 621 | tclass_datum = policydb.class_val_to_struct[tclass - 1]; |
@@ -705,9 +686,7 @@ static int context_struct_compute_av(struct context *scontext, | |||
705 | * permission and notice it to userspace via audit. | 686 | * permission and notice it to userspace via audit. |
706 | */ | 687 | */ |
707 | type_attribute_bounds_av(scontext, tcontext, | 688 | type_attribute_bounds_av(scontext, tcontext, |
708 | tclass, requested, avd); | 689 | tclass, avd); |
709 | |||
710 | return 0; | ||
711 | } | 690 | } |
712 | 691 | ||
713 | static int security_validtrans_handle_fail(struct context *ocontext, | 692 | static int security_validtrans_handle_fail(struct context *ocontext, |
@@ -864,7 +843,7 @@ int security_bounded_transition(u32 old_sid, u32 new_sid) | |||
864 | if (rc) { | 843 | if (rc) { |
865 | char *old_name = NULL; | 844 | char *old_name = NULL; |
866 | char *new_name = NULL; | 845 | char *new_name = NULL; |
867 | int length; | 846 | u32 length; |
868 | 847 | ||
869 | if (!context_struct_to_string(old_context, | 848 | if (!context_struct_to_string(old_context, |
870 | &old_name, &length) && | 849 | &old_name, &length) && |
@@ -886,110 +865,116 @@ out: | |||
886 | return rc; | 865 | return rc; |
887 | } | 866 | } |
888 | 867 | ||
889 | 868 | static void avd_init(struct av_decision *avd) | |
890 | static int security_compute_av_core(u32 ssid, | ||
891 | u32 tsid, | ||
892 | u16 tclass, | ||
893 | u32 requested, | ||
894 | struct av_decision *avd) | ||
895 | { | 869 | { |
896 | struct context *scontext = NULL, *tcontext = NULL; | 870 | avd->allowed = 0; |
897 | int rc = 0; | 871 | avd->auditallow = 0; |
898 | 872 | avd->auditdeny = 0xffffffff; | |
899 | scontext = sidtab_search(&sidtab, ssid); | 873 | avd->seqno = latest_granting; |
900 | if (!scontext) { | 874 | avd->flags = 0; |
901 | printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n", | ||
902 | __func__, ssid); | ||
903 | return -EINVAL; | ||
904 | } | ||
905 | tcontext = sidtab_search(&sidtab, tsid); | ||
906 | if (!tcontext) { | ||
907 | printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n", | ||
908 | __func__, tsid); | ||
909 | return -EINVAL; | ||
910 | } | ||
911 | |||
912 | rc = context_struct_compute_av(scontext, tcontext, tclass, | ||
913 | requested, avd); | ||
914 | |||
915 | /* permissive domain? */ | ||
916 | if (ebitmap_get_bit(&policydb.permissive_map, scontext->type)) | ||
917 | avd->flags |= AVD_FLAGS_PERMISSIVE; | ||
918 | |||
919 | return rc; | ||
920 | } | 875 | } |
921 | 876 | ||
877 | |||
922 | /** | 878 | /** |
923 | * security_compute_av - Compute access vector decisions. | 879 | * security_compute_av - Compute access vector decisions. |
924 | * @ssid: source security identifier | 880 | * @ssid: source security identifier |
925 | * @tsid: target security identifier | 881 | * @tsid: target security identifier |
926 | * @tclass: target security class | 882 | * @tclass: target security class |
927 | * @requested: requested permissions | ||
928 | * @avd: access vector decisions | 883 | * @avd: access vector decisions |
929 | * | 884 | * |
930 | * Compute a set of access vector decisions based on the | 885 | * Compute a set of access vector decisions based on the |
931 | * SID pair (@ssid, @tsid) for the permissions in @tclass. | 886 | * SID pair (@ssid, @tsid) for the permissions in @tclass. |
932 | * Return -%EINVAL if any of the parameters are invalid or %0 | ||
933 | * if the access vector decisions were computed successfully. | ||
934 | */ | 887 | */ |
935 | int security_compute_av(u32 ssid, | 888 | void security_compute_av(u32 ssid, |
936 | u32 tsid, | 889 | u32 tsid, |
937 | u16 orig_tclass, | 890 | u16 orig_tclass, |
938 | u32 orig_requested, | 891 | struct av_decision *avd) |
939 | struct av_decision *avd) | ||
940 | { | 892 | { |
941 | u16 tclass; | 893 | u16 tclass; |
942 | u32 requested; | 894 | struct context *scontext = NULL, *tcontext = NULL; |
943 | int rc; | ||
944 | 895 | ||
945 | read_lock(&policy_rwlock); | 896 | read_lock(&policy_rwlock); |
946 | 897 | avd_init(avd); | |
947 | if (!ss_initialized) | 898 | if (!ss_initialized) |
948 | goto allow; | 899 | goto allow; |
949 | 900 | ||
950 | requested = unmap_perm(orig_tclass, orig_requested); | 901 | scontext = sidtab_search(&sidtab, ssid); |
902 | if (!scontext) { | ||
903 | printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n", | ||
904 | __func__, ssid); | ||
905 | goto out; | ||
906 | } | ||
907 | |||
908 | /* permissive domain? */ | ||
909 | if (ebitmap_get_bit(&policydb.permissive_map, scontext->type)) | ||
910 | avd->flags |= AVD_FLAGS_PERMISSIVE; | ||
911 | |||
912 | tcontext = sidtab_search(&sidtab, tsid); | ||
913 | if (!tcontext) { | ||
914 | printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n", | ||
915 | __func__, tsid); | ||
916 | goto out; | ||
917 | } | ||
918 | |||
951 | tclass = unmap_class(orig_tclass); | 919 | tclass = unmap_class(orig_tclass); |
952 | if (unlikely(orig_tclass && !tclass)) { | 920 | if (unlikely(orig_tclass && !tclass)) { |
953 | if (policydb.allow_unknown) | 921 | if (policydb.allow_unknown) |
954 | goto allow; | 922 | goto allow; |
955 | rc = -EINVAL; | ||
956 | goto out; | 923 | goto out; |
957 | } | 924 | } |
958 | rc = security_compute_av_core(ssid, tsid, tclass, requested, avd); | 925 | context_struct_compute_av(scontext, tcontext, tclass, avd); |
959 | map_decision(orig_tclass, avd, policydb.allow_unknown); | 926 | map_decision(orig_tclass, avd, policydb.allow_unknown); |
960 | out: | 927 | out: |
961 | read_unlock(&policy_rwlock); | 928 | read_unlock(&policy_rwlock); |
962 | return rc; | 929 | return; |
963 | allow: | 930 | allow: |
964 | avd->allowed = 0xffffffff; | 931 | avd->allowed = 0xffffffff; |
965 | avd->auditallow = 0; | ||
966 | avd->auditdeny = 0xffffffff; | ||
967 | avd->seqno = latest_granting; | ||
968 | avd->flags = 0; | ||
969 | rc = 0; | ||
970 | goto out; | 932 | goto out; |
971 | } | 933 | } |
972 | 934 | ||
973 | int security_compute_av_user(u32 ssid, | 935 | void security_compute_av_user(u32 ssid, |
974 | u32 tsid, | 936 | u32 tsid, |
975 | u16 tclass, | 937 | u16 tclass, |
976 | u32 requested, | 938 | struct av_decision *avd) |
977 | struct av_decision *avd) | ||
978 | { | 939 | { |
979 | int rc; | 940 | struct context *scontext = NULL, *tcontext = NULL; |
980 | 941 | ||
981 | if (!ss_initialized) { | 942 | read_lock(&policy_rwlock); |
982 | avd->allowed = 0xffffffff; | 943 | avd_init(avd); |
983 | avd->auditallow = 0; | 944 | if (!ss_initialized) |
984 | avd->auditdeny = 0xffffffff; | 945 | goto allow; |
985 | avd->seqno = latest_granting; | 946 | |
986 | return 0; | 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; | ||
987 | } | 952 | } |
988 | 953 | ||
989 | read_lock(&policy_rwlock); | 954 | /* permissive domain? */ |
990 | rc = security_compute_av_core(ssid, tsid, tclass, requested, avd); | 955 | if (ebitmap_get_bit(&policydb.permissive_map, scontext->type)) |
956 | avd->flags |= AVD_FLAGS_PERMISSIVE; | ||
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: | ||
991 | read_unlock(&policy_rwlock); | 973 | read_unlock(&policy_rwlock); |
992 | return rc; | 974 | return; |
975 | allow: | ||
976 | avd->allowed = 0xffffffff; | ||
977 | goto out; | ||
993 | } | 978 | } |
994 | 979 | ||
995 | /* | 980 | /* |
@@ -1565,7 +1550,10 @@ static int clone_sid(u32 sid, | |||
1565 | { | 1550 | { |
1566 | struct sidtab *s = arg; | 1551 | struct sidtab *s = arg; |
1567 | 1552 | ||
1568 | return sidtab_insert(s, sid, context); | 1553 | if (sid > SECINITSID_NUM) |
1554 | return sidtab_insert(s, sid, context); | ||
1555 | else | ||
1556 | return 0; | ||
1569 | } | 1557 | } |
1570 | 1558 | ||
1571 | static inline int convert_context_handle_invalid_context(struct context *context) | 1559 | static inline int convert_context_handle_invalid_context(struct context *context) |
@@ -1606,12 +1594,17 @@ static int convert_context(u32 key, | |||
1606 | { | 1594 | { |
1607 | struct convert_context_args *args; | 1595 | struct convert_context_args *args; |
1608 | struct context oldc; | 1596 | struct context oldc; |
1597 | struct ocontext *oc; | ||
1598 | struct mls_range *range; | ||
1609 | struct role_datum *role; | 1599 | struct role_datum *role; |
1610 | struct type_datum *typdatum; | 1600 | struct type_datum *typdatum; |
1611 | struct user_datum *usrdatum; | 1601 | struct user_datum *usrdatum; |
1612 | char *s; | 1602 | char *s; |
1613 | u32 len; | 1603 | u32 len; |
1614 | int rc; | 1604 | int rc = 0; |
1605 | |||
1606 | if (key <= SECINITSID_NUM) | ||
1607 | goto out; | ||
1615 | 1608 | ||
1616 | args = p; | 1609 | args = p; |
1617 | 1610 | ||
@@ -1673,9 +1666,39 @@ static int convert_context(u32 key, | |||
1673 | goto bad; | 1666 | goto bad; |
1674 | c->type = typdatum->value; | 1667 | c->type = typdatum->value; |
1675 | 1668 | ||
1676 | rc = mls_convert_context(args->oldp, args->newp, c); | 1669 | /* Convert the MLS fields if dealing with MLS policies */ |
1677 | if (rc) | 1670 | if (args->oldp->mls_enabled && args->newp->mls_enabled) { |
1678 | 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 | } | ||
1679 | 1702 | ||
1680 | /* Check the validity of the new context. */ | 1703 | /* Check the validity of the new context. */ |
1681 | if (!policydb_context_isvalid(args->newp, c)) { | 1704 | if (!policydb_context_isvalid(args->newp, c)) { |
@@ -1771,9 +1794,17 @@ int security_load_policy(void *data, size_t len) | |||
1771 | if (policydb_read(&newpolicydb, fp)) | 1794 | if (policydb_read(&newpolicydb, fp)) |
1772 | return -EINVAL; | 1795 | return -EINVAL; |
1773 | 1796 | ||
1774 | 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"); | ||
1775 | policydb_destroy(&newpolicydb); | 1806 | policydb_destroy(&newpolicydb); |
1776 | return -ENOMEM; | 1807 | return rc; |
1777 | } | 1808 | } |
1778 | 1809 | ||
1779 | if (selinux_set_mapping(&newpolicydb, secclass_map, | 1810 | if (selinux_set_mapping(&newpolicydb, secclass_map, |
@@ -1800,8 +1831,12 @@ int security_load_policy(void *data, size_t len) | |||
1800 | args.oldp = &policydb; | 1831 | args.oldp = &policydb; |
1801 | args.newp = &newpolicydb; | 1832 | args.newp = &newpolicydb; |
1802 | rc = sidtab_map(&newsidtab, convert_context, &args); | 1833 | rc = sidtab_map(&newsidtab, convert_context, &args); |
1803 | 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"); | ||
1804 | goto err; | 1838 | goto err; |
1839 | } | ||
1805 | 1840 | ||
1806 | /* Save the old policydb and SID table to free later. */ | 1841 | /* Save the old policydb and SID table to free later. */ |
1807 | memcpy(&oldpolicydb, &policydb, sizeof policydb); | 1842 | memcpy(&oldpolicydb, &policydb, sizeof policydb); |
@@ -2397,7 +2432,7 @@ int security_sid_mls_copy(u32 sid, u32 mls_sid, u32 *new_sid) | |||
2397 | u32 len; | 2432 | u32 len; |
2398 | int rc = 0; | 2433 | int rc = 0; |
2399 | 2434 | ||
2400 | if (!ss_initialized || !selinux_mls_enabled) { | 2435 | if (!ss_initialized || !policydb.mls_enabled) { |
2401 | *new_sid = sid; | 2436 | *new_sid = sid; |
2402 | goto out; | 2437 | goto out; |
2403 | } | 2438 | } |
@@ -2498,7 +2533,7 @@ int security_net_peersid_resolve(u32 nlbl_sid, u32 nlbl_type, | |||
2498 | /* 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 |
2499 | * 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 |
2500 | * security server was initialized and ss_initialized was true */ | 2535 | * security server was initialized and ss_initialized was true */ |
2501 | if (!selinux_mls_enabled) { | 2536 | if (!policydb.mls_enabled) { |
2502 | *peer_sid = SECSID_NULL; | 2537 | *peer_sid = SECSID_NULL; |
2503 | return 0; | 2538 | return 0; |
2504 | } | 2539 | } |
@@ -2555,7 +2590,7 @@ int security_get_classes(char ***classes, int *nclasses) | |||
2555 | read_lock(&policy_rwlock); | 2590 | read_lock(&policy_rwlock); |
2556 | 2591 | ||
2557 | *nclasses = policydb.p_classes.nprim; | 2592 | *nclasses = policydb.p_classes.nprim; |
2558 | *classes = kcalloc(*nclasses, sizeof(*classes), GFP_ATOMIC); | 2593 | *classes = kcalloc(*nclasses, sizeof(**classes), GFP_ATOMIC); |
2559 | if (!*classes) | 2594 | if (!*classes) |
2560 | goto out; | 2595 | goto out; |
2561 | 2596 | ||
@@ -2602,7 +2637,7 @@ int security_get_permissions(char *class, char ***perms, int *nperms) | |||
2602 | } | 2637 | } |
2603 | 2638 | ||
2604 | *nperms = match->permissions.nprim; | 2639 | *nperms = match->permissions.nprim; |
2605 | *perms = kcalloc(*nperms, sizeof(*perms), GFP_ATOMIC); | 2640 | *perms = kcalloc(*nperms, sizeof(**perms), GFP_ATOMIC); |
2606 | if (!*perms) | 2641 | if (!*perms) |
2607 | goto out; | 2642 | goto out; |
2608 | 2643 | ||