diff options
author | Paul Moore <pmoore@redhat.com> | 2014-03-31 09:49:07 -0400 |
---|---|---|
committer | Paul Moore <pmoore@redhat.com> | 2014-03-31 09:49:07 -0400 |
commit | 6d32c850621b0be75777b9102b14f6268bbd9f0f (patch) | |
tree | fec325f5c1ae763f5eccb3ca1254ab9d9d164b05 /security | |
parent | eee3094683fbc7fe6bcdaef58c1ef31f8460cdca (diff) | |
parent | 455c6fdbd219161bd09b1165f11699d6d73de11c (diff) |
Merge tag 'v3.14' into next
Linux 3.14
Diffstat (limited to 'security')
-rw-r--r-- | security/Kconfig | 2 | ||||
-rw-r--r-- | security/capability.c | 3 | ||||
-rw-r--r-- | security/device_cgroup.c | 7 | ||||
-rw-r--r-- | security/integrity/ima/ima_template_lib.c | 18 | ||||
-rw-r--r-- | security/keys/keyring.c | 6 | ||||
-rw-r--r-- | security/security.c | 6 | ||||
-rw-r--r-- | security/selinux/hooks.c | 13 | ||||
-rw-r--r-- | security/selinux/include/security.h | 2 | ||||
-rw-r--r-- | security/selinux/include/xfrm.h | 3 | ||||
-rw-r--r-- | security/selinux/nlmsgtab.c | 2 | ||||
-rw-r--r-- | security/selinux/selinuxfs.c | 28 | ||||
-rw-r--r-- | security/selinux/ss/policydb.c | 8 | ||||
-rw-r--r-- | security/selinux/ss/services.c | 22 | ||||
-rw-r--r-- | security/selinux/xfrm.c | 14 | ||||
-rw-r--r-- | security/smack/smack.h | 5 | ||||
-rw-r--r-- | security/smack/smack_lsm.c | 145 | ||||
-rw-r--r-- | security/smack/smackfs.c | 134 |
17 files changed, 260 insertions, 158 deletions
diff --git a/security/Kconfig b/security/Kconfig index e9c6ac724fef..beb86b500adf 100644 --- a/security/Kconfig +++ b/security/Kconfig | |||
@@ -103,7 +103,7 @@ config INTEL_TXT | |||
103 | config LSM_MMAP_MIN_ADDR | 103 | config LSM_MMAP_MIN_ADDR |
104 | int "Low address space for LSM to protect from user allocation" | 104 | int "Low address space for LSM to protect from user allocation" |
105 | depends on SECURITY && SECURITY_SELINUX | 105 | depends on SECURITY && SECURITY_SELINUX |
106 | default 32768 if ARM | 106 | default 32768 if ARM || (ARM64 && COMPAT) |
107 | default 65536 | 107 | default 65536 |
108 | help | 108 | help |
109 | This is the portion of low virtual memory which should be protected | 109 | This is the portion of low virtual memory which should be protected |
diff --git a/security/capability.c b/security/capability.c index 8b4f24ae4338..21e2b9cae685 100644 --- a/security/capability.c +++ b/security/capability.c | |||
@@ -757,7 +757,8 @@ static void cap_skb_owned_by(struct sk_buff *skb, struct sock *sk) | |||
757 | 757 | ||
758 | #ifdef CONFIG_SECURITY_NETWORK_XFRM | 758 | #ifdef CONFIG_SECURITY_NETWORK_XFRM |
759 | static int cap_xfrm_policy_alloc_security(struct xfrm_sec_ctx **ctxp, | 759 | static int cap_xfrm_policy_alloc_security(struct xfrm_sec_ctx **ctxp, |
760 | struct xfrm_user_sec_ctx *sec_ctx) | 760 | struct xfrm_user_sec_ctx *sec_ctx, |
761 | gfp_t gfp) | ||
761 | { | 762 | { |
762 | return 0; | 763 | return 0; |
763 | } | 764 | } |
diff --git a/security/device_cgroup.c b/security/device_cgroup.c index 7c2a0a71049e..d3b6d2cd3a06 100644 --- a/security/device_cgroup.c +++ b/security/device_cgroup.c | |||
@@ -274,10 +274,9 @@ static void set_majmin(char *str, unsigned m) | |||
274 | sprintf(str, "%u", m); | 274 | sprintf(str, "%u", m); |
275 | } | 275 | } |
276 | 276 | ||
277 | static int devcgroup_seq_read(struct cgroup_subsys_state *css, | 277 | static int devcgroup_seq_show(struct seq_file *m, void *v) |
278 | struct cftype *cft, struct seq_file *m) | ||
279 | { | 278 | { |
280 | struct dev_cgroup *devcgroup = css_to_devcgroup(css); | 279 | struct dev_cgroup *devcgroup = css_to_devcgroup(seq_css(m)); |
281 | struct dev_exception_item *ex; | 280 | struct dev_exception_item *ex; |
282 | char maj[MAJMINLEN], min[MAJMINLEN], acc[ACCLEN]; | 281 | char maj[MAJMINLEN], min[MAJMINLEN], acc[ACCLEN]; |
283 | 282 | ||
@@ -679,7 +678,7 @@ static struct cftype dev_cgroup_files[] = { | |||
679 | }, | 678 | }, |
680 | { | 679 | { |
681 | .name = "list", | 680 | .name = "list", |
682 | .read_seq_string = devcgroup_seq_read, | 681 | .seq_show = devcgroup_seq_show, |
683 | .private = DEVCG_LIST, | 682 | .private = DEVCG_LIST, |
684 | }, | 683 | }, |
685 | { } /* terminate */ | 684 | { } /* terminate */ |
diff --git a/security/integrity/ima/ima_template_lib.c b/security/integrity/ima/ima_template_lib.c index c38adcc910fb..1683bbf289a4 100644 --- a/security/integrity/ima/ima_template_lib.c +++ b/security/integrity/ima/ima_template_lib.c | |||
@@ -162,8 +162,7 @@ void ima_show_template_sig(struct seq_file *m, enum ima_show_type show, | |||
162 | } | 162 | } |
163 | 163 | ||
164 | static int ima_eventdigest_init_common(u8 *digest, u32 digestsize, u8 hash_algo, | 164 | static int ima_eventdigest_init_common(u8 *digest, u32 digestsize, u8 hash_algo, |
165 | struct ima_field_data *field_data, | 165 | struct ima_field_data *field_data) |
166 | bool size_limit) | ||
167 | { | 166 | { |
168 | /* | 167 | /* |
169 | * digest formats: | 168 | * digest formats: |
@@ -176,11 +175,10 @@ static int ima_eventdigest_init_common(u8 *digest, u32 digestsize, u8 hash_algo, | |||
176 | enum data_formats fmt = DATA_FMT_DIGEST; | 175 | enum data_formats fmt = DATA_FMT_DIGEST; |
177 | u32 offset = 0; | 176 | u32 offset = 0; |
178 | 177 | ||
179 | if (!size_limit) { | 178 | if (hash_algo < HASH_ALGO__LAST) { |
180 | fmt = DATA_FMT_DIGEST_WITH_ALGO; | 179 | fmt = DATA_FMT_DIGEST_WITH_ALGO; |
181 | if (hash_algo < HASH_ALGO__LAST) | 180 | offset += snprintf(buffer, CRYPTO_MAX_ALG_NAME + 1, "%s", |
182 | offset += snprintf(buffer, CRYPTO_MAX_ALG_NAME + 1, | 181 | hash_algo_name[hash_algo]); |
183 | "%s", hash_algo_name[hash_algo]); | ||
184 | buffer[offset] = ':'; | 182 | buffer[offset] = ':'; |
185 | offset += 2; | 183 | offset += 2; |
186 | } | 184 | } |
@@ -243,8 +241,8 @@ int ima_eventdigest_init(struct integrity_iint_cache *iint, struct file *file, | |||
243 | cur_digest = hash.hdr.digest; | 241 | cur_digest = hash.hdr.digest; |
244 | cur_digestsize = hash.hdr.length; | 242 | cur_digestsize = hash.hdr.length; |
245 | out: | 243 | out: |
246 | return ima_eventdigest_init_common(cur_digest, cur_digestsize, -1, | 244 | return ima_eventdigest_init_common(cur_digest, cur_digestsize, |
247 | field_data, true); | 245 | HASH_ALGO__LAST, field_data); |
248 | } | 246 | } |
249 | 247 | ||
250 | /* | 248 | /* |
@@ -255,7 +253,7 @@ int ima_eventdigest_ng_init(struct integrity_iint_cache *iint, | |||
255 | struct evm_ima_xattr_data *xattr_value, | 253 | struct evm_ima_xattr_data *xattr_value, |
256 | int xattr_len, struct ima_field_data *field_data) | 254 | int xattr_len, struct ima_field_data *field_data) |
257 | { | 255 | { |
258 | u8 *cur_digest = NULL, hash_algo = HASH_ALGO__LAST; | 256 | u8 *cur_digest = NULL, hash_algo = HASH_ALGO_SHA1; |
259 | u32 cur_digestsize = 0; | 257 | u32 cur_digestsize = 0; |
260 | 258 | ||
261 | /* If iint is NULL, we are recording a violation. */ | 259 | /* If iint is NULL, we are recording a violation. */ |
@@ -268,7 +266,7 @@ int ima_eventdigest_ng_init(struct integrity_iint_cache *iint, | |||
268 | hash_algo = iint->ima_hash->algo; | 266 | hash_algo = iint->ima_hash->algo; |
269 | out: | 267 | out: |
270 | return ima_eventdigest_init_common(cur_digest, cur_digestsize, | 268 | return ima_eventdigest_init_common(cur_digest, cur_digestsize, |
271 | hash_algo, field_data, false); | 269 | hash_algo, field_data); |
272 | } | 270 | } |
273 | 271 | ||
274 | static int ima_eventname_init_common(struct integrity_iint_cache *iint, | 272 | static int ima_eventname_init_common(struct integrity_iint_cache *iint, |
diff --git a/security/keys/keyring.c b/security/keys/keyring.c index d46cbc5e335e..2fb2576dc644 100644 --- a/security/keys/keyring.c +++ b/security/keys/keyring.c | |||
@@ -1000,7 +1000,11 @@ static int keyring_detect_cycle_iterator(const void *object, | |||
1000 | 1000 | ||
1001 | kenter("{%d}", key->serial); | 1001 | kenter("{%d}", key->serial); |
1002 | 1002 | ||
1003 | BUG_ON(key != ctx->match_data); | 1003 | /* We might get a keyring with matching index-key that is nonetheless a |
1004 | * different keyring. */ | ||
1005 | if (key != ctx->match_data) | ||
1006 | return 0; | ||
1007 | |||
1004 | ctx->result = ERR_PTR(-EDEADLK); | 1008 | ctx->result = ERR_PTR(-EDEADLK); |
1005 | return 1; | 1009 | return 1; |
1006 | } | 1010 | } |
diff --git a/security/security.c b/security/security.c index 15b6928592ef..919cad93ac82 100644 --- a/security/security.c +++ b/security/security.c | |||
@@ -1317,9 +1317,11 @@ void security_skb_owned_by(struct sk_buff *skb, struct sock *sk) | |||
1317 | 1317 | ||
1318 | #ifdef CONFIG_SECURITY_NETWORK_XFRM | 1318 | #ifdef CONFIG_SECURITY_NETWORK_XFRM |
1319 | 1319 | ||
1320 | int security_xfrm_policy_alloc(struct xfrm_sec_ctx **ctxp, struct xfrm_user_sec_ctx *sec_ctx) | 1320 | int security_xfrm_policy_alloc(struct xfrm_sec_ctx **ctxp, |
1321 | struct xfrm_user_sec_ctx *sec_ctx, | ||
1322 | gfp_t gfp) | ||
1321 | { | 1323 | { |
1322 | return security_ops->xfrm_policy_alloc_security(ctxp, sec_ctx); | 1324 | return security_ops->xfrm_policy_alloc_security(ctxp, sec_ctx, gfp); |
1323 | } | 1325 | } |
1324 | EXPORT_SYMBOL(security_xfrm_policy_alloc); | 1326 | EXPORT_SYMBOL(security_xfrm_policy_alloc); |
1325 | 1327 | ||
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 8b1656f053f8..d58946dca8c9 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c | |||
@@ -668,7 +668,7 @@ static int selinux_set_mnt_opts(struct super_block *sb, | |||
668 | if (flags[i] == SBLABEL_MNT) | 668 | if (flags[i] == SBLABEL_MNT) |
669 | continue; | 669 | continue; |
670 | rc = security_context_to_sid(mount_options[i], | 670 | rc = security_context_to_sid(mount_options[i], |
671 | strlen(mount_options[i]), &sid); | 671 | strlen(mount_options[i]), &sid, GFP_KERNEL); |
672 | if (rc) { | 672 | if (rc) { |
673 | printk(KERN_WARNING "SELinux: security_context_to_sid" | 673 | printk(KERN_WARNING "SELinux: security_context_to_sid" |
674 | "(%s) failed for (dev %s, type %s) errno=%d\n", | 674 | "(%s) failed for (dev %s, type %s) errno=%d\n", |
@@ -2507,7 +2507,8 @@ static int selinux_sb_remount(struct super_block *sb, void *data) | |||
2507 | if (flags[i] == SBLABEL_MNT) | 2507 | if (flags[i] == SBLABEL_MNT) |
2508 | continue; | 2508 | continue; |
2509 | len = strlen(mount_options[i]); | 2509 | len = strlen(mount_options[i]); |
2510 | rc = security_context_to_sid(mount_options[i], len, &sid); | 2510 | rc = security_context_to_sid(mount_options[i], len, &sid, |
2511 | GFP_KERNEL); | ||
2511 | if (rc) { | 2512 | if (rc) { |
2512 | printk(KERN_WARNING "SELinux: security_context_to_sid" | 2513 | printk(KERN_WARNING "SELinux: security_context_to_sid" |
2513 | "(%s) failed for (dev %s, type %s) errno=%d\n", | 2514 | "(%s) failed for (dev %s, type %s) errno=%d\n", |
@@ -2911,7 +2912,7 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name, | |||
2911 | if (rc) | 2912 | if (rc) |
2912 | return rc; | 2913 | return rc; |
2913 | 2914 | ||
2914 | rc = security_context_to_sid(value, size, &newsid); | 2915 | rc = security_context_to_sid(value, size, &newsid, GFP_KERNEL); |
2915 | if (rc == -EINVAL) { | 2916 | if (rc == -EINVAL) { |
2916 | if (!capable(CAP_MAC_ADMIN)) { | 2917 | if (!capable(CAP_MAC_ADMIN)) { |
2917 | struct audit_buffer *ab; | 2918 | struct audit_buffer *ab; |
@@ -3068,7 +3069,7 @@ static int selinux_inode_setsecurity(struct inode *inode, const char *name, | |||
3068 | if (!value || !size) | 3069 | if (!value || !size) |
3069 | return -EACCES; | 3070 | return -EACCES; |
3070 | 3071 | ||
3071 | rc = security_context_to_sid((void *)value, size, &newsid); | 3072 | rc = security_context_to_sid((void *)value, size, &newsid, GFP_KERNEL); |
3072 | if (rc) | 3073 | if (rc) |
3073 | return rc; | 3074 | return rc; |
3074 | 3075 | ||
@@ -5543,7 +5544,7 @@ static int selinux_setprocattr(struct task_struct *p, | |||
5543 | str[size-1] = 0; | 5544 | str[size-1] = 0; |
5544 | size--; | 5545 | size--; |
5545 | } | 5546 | } |
5546 | error = security_context_to_sid(value, size, &sid); | 5547 | error = security_context_to_sid(value, size, &sid, GFP_KERNEL); |
5547 | if (error == -EINVAL && !strcmp(name, "fscreate")) { | 5548 | if (error == -EINVAL && !strcmp(name, "fscreate")) { |
5548 | if (!capable(CAP_MAC_ADMIN)) { | 5549 | if (!capable(CAP_MAC_ADMIN)) { |
5549 | struct audit_buffer *ab; | 5550 | struct audit_buffer *ab; |
@@ -5652,7 +5653,7 @@ static int selinux_secid_to_secctx(u32 secid, char **secdata, u32 *seclen) | |||
5652 | 5653 | ||
5653 | static int selinux_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid) | 5654 | static int selinux_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid) |
5654 | { | 5655 | { |
5655 | return security_context_to_sid(secdata, seclen, secid); | 5656 | return security_context_to_sid(secdata, seclen, secid, GFP_KERNEL); |
5656 | } | 5657 | } |
5657 | 5658 | ||
5658 | static void selinux_release_secctx(char *secdata, u32 seclen) | 5659 | static void selinux_release_secctx(char *secdata, u32 seclen) |
diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h index 8ed8daf7f1ee..ce7852cf526b 100644 --- a/security/selinux/include/security.h +++ b/security/selinux/include/security.h | |||
@@ -134,7 +134,7 @@ int security_sid_to_context(u32 sid, char **scontext, | |||
134 | int security_sid_to_context_force(u32 sid, char **scontext, u32 *scontext_len); | 134 | int security_sid_to_context_force(u32 sid, char **scontext, u32 *scontext_len); |
135 | 135 | ||
136 | int security_context_to_sid(const char *scontext, u32 scontext_len, | 136 | int security_context_to_sid(const char *scontext, u32 scontext_len, |
137 | u32 *out_sid); | 137 | u32 *out_sid, gfp_t gfp); |
138 | 138 | ||
139 | int security_context_to_sid_default(const char *scontext, u32 scontext_len, | 139 | int security_context_to_sid_default(const char *scontext, u32 scontext_len, |
140 | u32 *out_sid, u32 def_sid, gfp_t gfp_flags); | 140 | u32 *out_sid, u32 def_sid, gfp_t gfp_flags); |
diff --git a/security/selinux/include/xfrm.h b/security/selinux/include/xfrm.h index 48c3cc94c168..9f0584710c85 100644 --- a/security/selinux/include/xfrm.h +++ b/security/selinux/include/xfrm.h | |||
@@ -10,7 +10,8 @@ | |||
10 | #include <net/flow.h> | 10 | #include <net/flow.h> |
11 | 11 | ||
12 | int selinux_xfrm_policy_alloc(struct xfrm_sec_ctx **ctxp, | 12 | int selinux_xfrm_policy_alloc(struct xfrm_sec_ctx **ctxp, |
13 | struct xfrm_user_sec_ctx *uctx); | 13 | struct xfrm_user_sec_ctx *uctx, |
14 | gfp_t gfp); | ||
14 | int selinux_xfrm_policy_clone(struct xfrm_sec_ctx *old_ctx, | 15 | int selinux_xfrm_policy_clone(struct xfrm_sec_ctx *old_ctx, |
15 | struct xfrm_sec_ctx **new_ctxp); | 16 | struct xfrm_sec_ctx **new_ctxp); |
16 | void selinux_xfrm_policy_free(struct xfrm_sec_ctx *ctx); | 17 | void selinux_xfrm_policy_free(struct xfrm_sec_ctx *ctx); |
diff --git a/security/selinux/nlmsgtab.c b/security/selinux/nlmsgtab.c index 332ac8a80cf5..2df7b900e259 100644 --- a/security/selinux/nlmsgtab.c +++ b/security/selinux/nlmsgtab.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <linux/inet_diag.h> | 17 | #include <linux/inet_diag.h> |
18 | #include <linux/xfrm.h> | 18 | #include <linux/xfrm.h> |
19 | #include <linux/audit.h> | 19 | #include <linux/audit.h> |
20 | #include <linux/sock_diag.h> | ||
20 | 21 | ||
21 | #include "flask.h" | 22 | #include "flask.h" |
22 | #include "av_permissions.h" | 23 | #include "av_permissions.h" |
@@ -78,6 +79,7 @@ static struct nlmsg_perm nlmsg_tcpdiag_perms[] = | |||
78 | { | 79 | { |
79 | { TCPDIAG_GETSOCK, NETLINK_TCPDIAG_SOCKET__NLMSG_READ }, | 80 | { TCPDIAG_GETSOCK, NETLINK_TCPDIAG_SOCKET__NLMSG_READ }, |
80 | { DCCPDIAG_GETSOCK, NETLINK_TCPDIAG_SOCKET__NLMSG_READ }, | 81 | { DCCPDIAG_GETSOCK, NETLINK_TCPDIAG_SOCKET__NLMSG_READ }, |
82 | { SOCK_DIAG_BY_FAMILY, NETLINK_TCPDIAG_SOCKET__NLMSG_READ }, | ||
81 | }; | 83 | }; |
82 | 84 | ||
83 | static struct nlmsg_perm nlmsg_xfrm_perms[] = | 85 | static struct nlmsg_perm nlmsg_xfrm_perms[] = |
diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c index 5122affe06a8..d60c0ee66387 100644 --- a/security/selinux/selinuxfs.c +++ b/security/selinux/selinuxfs.c | |||
@@ -576,7 +576,7 @@ static ssize_t sel_write_context(struct file *file, char *buf, size_t size) | |||
576 | if (length) | 576 | if (length) |
577 | goto out; | 577 | goto out; |
578 | 578 | ||
579 | length = security_context_to_sid(buf, size, &sid); | 579 | length = security_context_to_sid(buf, size, &sid, GFP_KERNEL); |
580 | if (length) | 580 | if (length) |
581 | goto out; | 581 | goto out; |
582 | 582 | ||
@@ -731,11 +731,13 @@ static ssize_t sel_write_access(struct file *file, char *buf, size_t size) | |||
731 | if (sscanf(buf, "%s %s %hu", scon, tcon, &tclass) != 3) | 731 | if (sscanf(buf, "%s %s %hu", scon, tcon, &tclass) != 3) |
732 | goto out; | 732 | goto out; |
733 | 733 | ||
734 | length = security_context_to_sid(scon, strlen(scon) + 1, &ssid); | 734 | length = security_context_to_sid(scon, strlen(scon) + 1, &ssid, |
735 | GFP_KERNEL); | ||
735 | if (length) | 736 | if (length) |
736 | goto out; | 737 | goto out; |
737 | 738 | ||
738 | length = security_context_to_sid(tcon, strlen(tcon) + 1, &tsid); | 739 | length = security_context_to_sid(tcon, strlen(tcon) + 1, &tsid, |
740 | GFP_KERNEL); | ||
739 | if (length) | 741 | if (length) |
740 | goto out; | 742 | goto out; |
741 | 743 | ||
@@ -817,11 +819,13 @@ static ssize_t sel_write_create(struct file *file, char *buf, size_t size) | |||
817 | objname = namebuf; | 819 | objname = namebuf; |
818 | } | 820 | } |
819 | 821 | ||
820 | length = security_context_to_sid(scon, strlen(scon) + 1, &ssid); | 822 | length = security_context_to_sid(scon, strlen(scon) + 1, &ssid, |
823 | GFP_KERNEL); | ||
821 | if (length) | 824 | if (length) |
822 | goto out; | 825 | goto out; |
823 | 826 | ||
824 | length = security_context_to_sid(tcon, strlen(tcon) + 1, &tsid); | 827 | length = security_context_to_sid(tcon, strlen(tcon) + 1, &tsid, |
828 | GFP_KERNEL); | ||
825 | if (length) | 829 | if (length) |
826 | goto out; | 830 | goto out; |
827 | 831 | ||
@@ -878,11 +882,13 @@ static ssize_t sel_write_relabel(struct file *file, char *buf, size_t size) | |||
878 | if (sscanf(buf, "%s %s %hu", scon, tcon, &tclass) != 3) | 882 | if (sscanf(buf, "%s %s %hu", scon, tcon, &tclass) != 3) |
879 | goto out; | 883 | goto out; |
880 | 884 | ||
881 | length = security_context_to_sid(scon, strlen(scon) + 1, &ssid); | 885 | length = security_context_to_sid(scon, strlen(scon) + 1, &ssid, |
886 | GFP_KERNEL); | ||
882 | if (length) | 887 | if (length) |
883 | goto out; | 888 | goto out; |
884 | 889 | ||
885 | length = security_context_to_sid(tcon, strlen(tcon) + 1, &tsid); | 890 | length = security_context_to_sid(tcon, strlen(tcon) + 1, &tsid, |
891 | GFP_KERNEL); | ||
886 | if (length) | 892 | if (length) |
887 | goto out; | 893 | goto out; |
888 | 894 | ||
@@ -934,7 +940,7 @@ static ssize_t sel_write_user(struct file *file, char *buf, size_t size) | |||
934 | if (sscanf(buf, "%s %s", con, user) != 2) | 940 | if (sscanf(buf, "%s %s", con, user) != 2) |
935 | goto out; | 941 | goto out; |
936 | 942 | ||
937 | length = security_context_to_sid(con, strlen(con) + 1, &sid); | 943 | length = security_context_to_sid(con, strlen(con) + 1, &sid, GFP_KERNEL); |
938 | if (length) | 944 | if (length) |
939 | goto out; | 945 | goto out; |
940 | 946 | ||
@@ -994,11 +1000,13 @@ static ssize_t sel_write_member(struct file *file, char *buf, size_t size) | |||
994 | if (sscanf(buf, "%s %s %hu", scon, tcon, &tclass) != 3) | 1000 | if (sscanf(buf, "%s %s %hu", scon, tcon, &tclass) != 3) |
995 | goto out; | 1001 | goto out; |
996 | 1002 | ||
997 | length = security_context_to_sid(scon, strlen(scon) + 1, &ssid); | 1003 | length = security_context_to_sid(scon, strlen(scon) + 1, &ssid, |
1004 | GFP_KERNEL); | ||
998 | if (length) | 1005 | if (length) |
999 | goto out; | 1006 | goto out; |
1000 | 1007 | ||
1001 | length = security_context_to_sid(tcon, strlen(tcon) + 1, &tsid); | 1008 | length = security_context_to_sid(tcon, strlen(tcon) + 1, &tsid, |
1009 | GFP_KERNEL); | ||
1002 | if (length) | 1010 | if (length) |
1003 | goto out; | 1011 | goto out; |
1004 | 1012 | ||
diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c index c0f498842129..9c5cdc2caaef 100644 --- a/security/selinux/ss/policydb.c +++ b/security/selinux/ss/policydb.c | |||
@@ -3338,10 +3338,10 @@ static int filename_write_helper(void *key, void *data, void *ptr) | |||
3338 | if (rc) | 3338 | if (rc) |
3339 | return rc; | 3339 | return rc; |
3340 | 3340 | ||
3341 | buf[0] = ft->stype; | 3341 | buf[0] = cpu_to_le32(ft->stype); |
3342 | buf[1] = ft->ttype; | 3342 | buf[1] = cpu_to_le32(ft->ttype); |
3343 | buf[2] = ft->tclass; | 3343 | buf[2] = cpu_to_le32(ft->tclass); |
3344 | buf[3] = otype->otype; | 3344 | buf[3] = cpu_to_le32(otype->otype); |
3345 | 3345 | ||
3346 | rc = put_entry(buf, sizeof(u32), 4, fp); | 3346 | rc = put_entry(buf, sizeof(u32), 4, fp); |
3347 | if (rc) | 3347 | if (rc) |
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index fc5a63a05a1c..4bca49414a40 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c | |||
@@ -1232,6 +1232,10 @@ static int security_context_to_sid_core(const char *scontext, u32 scontext_len, | |||
1232 | struct context context; | 1232 | struct context context; |
1233 | int rc = 0; | 1233 | int rc = 0; |
1234 | 1234 | ||
1235 | /* An empty security context is never valid. */ | ||
1236 | if (!scontext_len) | ||
1237 | return -EINVAL; | ||
1238 | |||
1235 | if (!ss_initialized) { | 1239 | if (!ss_initialized) { |
1236 | int i; | 1240 | int i; |
1237 | 1241 | ||
@@ -1285,16 +1289,18 @@ out: | |||
1285 | * @scontext: security context | 1289 | * @scontext: security context |
1286 | * @scontext_len: length in bytes | 1290 | * @scontext_len: length in bytes |
1287 | * @sid: security identifier, SID | 1291 | * @sid: security identifier, SID |
1292 | * @gfp: context for the allocation | ||
1288 | * | 1293 | * |
1289 | * Obtains a SID associated with the security context that | 1294 | * Obtains a SID associated with the security context that |
1290 | * has the string representation specified by @scontext. | 1295 | * has the string representation specified by @scontext. |
1291 | * Returns -%EINVAL if the context is invalid, -%ENOMEM if insufficient | 1296 | * Returns -%EINVAL if the context is invalid, -%ENOMEM if insufficient |
1292 | * memory is available, or 0 on success. | 1297 | * memory is available, or 0 on success. |
1293 | */ | 1298 | */ |
1294 | int security_context_to_sid(const char *scontext, u32 scontext_len, u32 *sid) | 1299 | int security_context_to_sid(const char *scontext, u32 scontext_len, u32 *sid, |
1300 | gfp_t gfp) | ||
1295 | { | 1301 | { |
1296 | return security_context_to_sid_core(scontext, scontext_len, | 1302 | return security_context_to_sid_core(scontext, scontext_len, |
1297 | sid, SECSID_NULL, GFP_KERNEL, 0); | 1303 | sid, SECSID_NULL, gfp, 0); |
1298 | } | 1304 | } |
1299 | 1305 | ||
1300 | /** | 1306 | /** |
@@ -2948,25 +2954,21 @@ int selinux_audit_rule_match(u32 sid, u32 field, u32 op, void *vrule, | |||
2948 | struct selinux_audit_rule *rule = vrule; | 2954 | struct selinux_audit_rule *rule = vrule; |
2949 | int match = 0; | 2955 | int match = 0; |
2950 | 2956 | ||
2951 | if (!rule) { | 2957 | if (unlikely(!rule)) { |
2952 | audit_log(actx, GFP_ATOMIC, AUDIT_SELINUX_ERR, | 2958 | WARN_ONCE(1, "selinux_audit_rule_match: missing rule\n"); |
2953 | "selinux_audit_rule_match: missing rule\n"); | ||
2954 | return -ENOENT; | 2959 | return -ENOENT; |
2955 | } | 2960 | } |
2956 | 2961 | ||
2957 | read_lock(&policy_rwlock); | 2962 | read_lock(&policy_rwlock); |
2958 | 2963 | ||
2959 | if (rule->au_seqno < latest_granting) { | 2964 | if (rule->au_seqno < latest_granting) { |
2960 | audit_log(actx, GFP_ATOMIC, AUDIT_SELINUX_ERR, | ||
2961 | "selinux_audit_rule_match: stale rule\n"); | ||
2962 | match = -ESTALE; | 2965 | match = -ESTALE; |
2963 | goto out; | 2966 | goto out; |
2964 | } | 2967 | } |
2965 | 2968 | ||
2966 | ctxt = sidtab_search(&sidtab, sid); | 2969 | ctxt = sidtab_search(&sidtab, sid); |
2967 | if (!ctxt) { | 2970 | if (unlikely(!ctxt)) { |
2968 | audit_log(actx, GFP_ATOMIC, AUDIT_SELINUX_ERR, | 2971 | WARN_ONCE(1, "selinux_audit_rule_match: unrecognized SID %d\n", |
2969 | "selinux_audit_rule_match: unrecognized SID %d\n", | ||
2970 | sid); | 2972 | sid); |
2971 | match = -ENOENT; | 2973 | match = -ENOENT; |
2972 | goto out; | 2974 | goto out; |
diff --git a/security/selinux/xfrm.c b/security/selinux/xfrm.c index 0462cb3ff0a7..98b042630a9e 100644 --- a/security/selinux/xfrm.c +++ b/security/selinux/xfrm.c | |||
@@ -78,7 +78,8 @@ static inline int selinux_authorizable_xfrm(struct xfrm_state *x) | |||
78 | * xfrm_user_sec_ctx context. | 78 | * xfrm_user_sec_ctx context. |
79 | */ | 79 | */ |
80 | static int selinux_xfrm_alloc_user(struct xfrm_sec_ctx **ctxp, | 80 | static int selinux_xfrm_alloc_user(struct xfrm_sec_ctx **ctxp, |
81 | struct xfrm_user_sec_ctx *uctx) | 81 | struct xfrm_user_sec_ctx *uctx, |
82 | gfp_t gfp) | ||
82 | { | 83 | { |
83 | int rc; | 84 | int rc; |
84 | const struct task_security_struct *tsec = current_security(); | 85 | const struct task_security_struct *tsec = current_security(); |
@@ -94,7 +95,7 @@ static int selinux_xfrm_alloc_user(struct xfrm_sec_ctx **ctxp, | |||
94 | if (str_len >= PAGE_SIZE) | 95 | if (str_len >= PAGE_SIZE) |
95 | return -ENOMEM; | 96 | return -ENOMEM; |
96 | 97 | ||
97 | ctx = kmalloc(sizeof(*ctx) + str_len + 1, GFP_KERNEL); | 98 | ctx = kmalloc(sizeof(*ctx) + str_len + 1, gfp); |
98 | if (!ctx) | 99 | if (!ctx) |
99 | return -ENOMEM; | 100 | return -ENOMEM; |
100 | 101 | ||
@@ -103,7 +104,7 @@ static int selinux_xfrm_alloc_user(struct xfrm_sec_ctx **ctxp, | |||
103 | ctx->ctx_len = str_len; | 104 | ctx->ctx_len = str_len; |
104 | memcpy(ctx->ctx_str, &uctx[1], str_len); | 105 | memcpy(ctx->ctx_str, &uctx[1], str_len); |
105 | ctx->ctx_str[str_len] = '\0'; | 106 | ctx->ctx_str[str_len] = '\0'; |
106 | rc = security_context_to_sid(ctx->ctx_str, str_len, &ctx->ctx_sid); | 107 | rc = security_context_to_sid(ctx->ctx_str, str_len, &ctx->ctx_sid, gfp); |
107 | if (rc) | 108 | if (rc) |
108 | goto err; | 109 | goto err; |
109 | 110 | ||
@@ -282,9 +283,10 @@ int selinux_xfrm_skb_sid(struct sk_buff *skb, u32 *sid) | |||
282 | * LSM hook implementation that allocs and transfers uctx spec to xfrm_policy. | 283 | * LSM hook implementation that allocs and transfers uctx spec to xfrm_policy. |
283 | */ | 284 | */ |
284 | int selinux_xfrm_policy_alloc(struct xfrm_sec_ctx **ctxp, | 285 | int selinux_xfrm_policy_alloc(struct xfrm_sec_ctx **ctxp, |
285 | struct xfrm_user_sec_ctx *uctx) | 286 | struct xfrm_user_sec_ctx *uctx, |
287 | gfp_t gfp) | ||
286 | { | 288 | { |
287 | return selinux_xfrm_alloc_user(ctxp, uctx); | 289 | return selinux_xfrm_alloc_user(ctxp, uctx, gfp); |
288 | } | 290 | } |
289 | 291 | ||
290 | /* | 292 | /* |
@@ -332,7 +334,7 @@ int selinux_xfrm_policy_delete(struct xfrm_sec_ctx *ctx) | |||
332 | int selinux_xfrm_state_alloc(struct xfrm_state *x, | 334 | int selinux_xfrm_state_alloc(struct xfrm_state *x, |
333 | struct xfrm_user_sec_ctx *uctx) | 335 | struct xfrm_user_sec_ctx *uctx) |
334 | { | 336 | { |
335 | return selinux_xfrm_alloc_user(&x->security, uctx); | 337 | return selinux_xfrm_alloc_user(&x->security, uctx, GFP_KERNEL); |
336 | } | 338 | } |
337 | 339 | ||
338 | /* | 340 | /* |
diff --git a/security/smack/smack.h b/security/smack/smack.h index 364cc64fce71..d072fd32212d 100644 --- a/security/smack/smack.h +++ b/security/smack/smack.h | |||
@@ -241,7 +241,8 @@ u32 smack_to_secid(const char *); | |||
241 | extern int smack_cipso_direct; | 241 | extern int smack_cipso_direct; |
242 | extern int smack_cipso_mapped; | 242 | extern int smack_cipso_mapped; |
243 | extern struct smack_known *smack_net_ambient; | 243 | extern struct smack_known *smack_net_ambient; |
244 | extern char *smack_onlycap; | 244 | extern struct smack_known *smack_onlycap; |
245 | extern struct smack_known *smack_syslog_label; | ||
245 | extern const char *smack_cipso_option; | 246 | extern const char *smack_cipso_option; |
246 | 247 | ||
247 | extern struct smack_known smack_known_floor; | 248 | extern struct smack_known smack_known_floor; |
@@ -312,7 +313,7 @@ static inline int smack_privileged(int cap) | |||
312 | 313 | ||
313 | if (!capable(cap)) | 314 | if (!capable(cap)) |
314 | return 0; | 315 | return 0; |
315 | if (smack_onlycap == NULL || smack_onlycap == skp->smk_known) | 316 | if (smack_onlycap == NULL || smack_onlycap == skp) |
316 | return 1; | 317 | return 1; |
317 | return 0; | 318 | return 0; |
318 | } | 319 | } |
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index b0be893ad44d..14f52be78c75 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c | |||
@@ -219,8 +219,6 @@ static int smack_ptrace_traceme(struct task_struct *ptp) | |||
219 | * smack_syslog - Smack approval on syslog | 219 | * smack_syslog - Smack approval on syslog |
220 | * @type: message type | 220 | * @type: message type |
221 | * | 221 | * |
222 | * Require that the task has the floor label | ||
223 | * | ||
224 | * Returns 0 on success, error code otherwise. | 222 | * Returns 0 on success, error code otherwise. |
225 | */ | 223 | */ |
226 | static int smack_syslog(int typefrom_file) | 224 | static int smack_syslog(int typefrom_file) |
@@ -231,7 +229,7 @@ static int smack_syslog(int typefrom_file) | |||
231 | if (smack_privileged(CAP_MAC_OVERRIDE)) | 229 | if (smack_privileged(CAP_MAC_OVERRIDE)) |
232 | return 0; | 230 | return 0; |
233 | 231 | ||
234 | if (skp != &smack_known_floor) | 232 | if (smack_syslog_label != NULL && smack_syslog_label != skp) |
235 | rc = -EACCES; | 233 | rc = -EACCES; |
236 | 234 | ||
237 | return rc; | 235 | return rc; |
@@ -341,10 +339,12 @@ static int smack_sb_kern_mount(struct super_block *sb, int flags, void *data) | |||
341 | struct inode *inode = root->d_inode; | 339 | struct inode *inode = root->d_inode; |
342 | struct superblock_smack *sp = sb->s_security; | 340 | struct superblock_smack *sp = sb->s_security; |
343 | struct inode_smack *isp; | 341 | struct inode_smack *isp; |
342 | struct smack_known *skp; | ||
344 | char *op; | 343 | char *op; |
345 | char *commap; | 344 | char *commap; |
346 | char *nsp; | 345 | char *nsp; |
347 | int transmute = 0; | 346 | int transmute = 0; |
347 | int specified = 0; | ||
348 | 348 | ||
349 | if (sp->smk_initialized) | 349 | if (sp->smk_initialized) |
350 | return 0; | 350 | return 0; |
@@ -359,34 +359,56 @@ static int smack_sb_kern_mount(struct super_block *sb, int flags, void *data) | |||
359 | if (strncmp(op, SMK_FSHAT, strlen(SMK_FSHAT)) == 0) { | 359 | if (strncmp(op, SMK_FSHAT, strlen(SMK_FSHAT)) == 0) { |
360 | op += strlen(SMK_FSHAT); | 360 | op += strlen(SMK_FSHAT); |
361 | nsp = smk_import(op, 0); | 361 | nsp = smk_import(op, 0); |
362 | if (nsp != NULL) | 362 | if (nsp != NULL) { |
363 | sp->smk_hat = nsp; | 363 | sp->smk_hat = nsp; |
364 | specified = 1; | ||
365 | } | ||
364 | } else if (strncmp(op, SMK_FSFLOOR, strlen(SMK_FSFLOOR)) == 0) { | 366 | } else if (strncmp(op, SMK_FSFLOOR, strlen(SMK_FSFLOOR)) == 0) { |
365 | op += strlen(SMK_FSFLOOR); | 367 | op += strlen(SMK_FSFLOOR); |
366 | nsp = smk_import(op, 0); | 368 | nsp = smk_import(op, 0); |
367 | if (nsp != NULL) | 369 | if (nsp != NULL) { |
368 | sp->smk_floor = nsp; | 370 | sp->smk_floor = nsp; |
371 | specified = 1; | ||
372 | } | ||
369 | } else if (strncmp(op, SMK_FSDEFAULT, | 373 | } else if (strncmp(op, SMK_FSDEFAULT, |
370 | strlen(SMK_FSDEFAULT)) == 0) { | 374 | strlen(SMK_FSDEFAULT)) == 0) { |
371 | op += strlen(SMK_FSDEFAULT); | 375 | op += strlen(SMK_FSDEFAULT); |
372 | nsp = smk_import(op, 0); | 376 | nsp = smk_import(op, 0); |
373 | if (nsp != NULL) | 377 | if (nsp != NULL) { |
374 | sp->smk_default = nsp; | 378 | sp->smk_default = nsp; |
379 | specified = 1; | ||
380 | } | ||
375 | } else if (strncmp(op, SMK_FSROOT, strlen(SMK_FSROOT)) == 0) { | 381 | } else if (strncmp(op, SMK_FSROOT, strlen(SMK_FSROOT)) == 0) { |
376 | op += strlen(SMK_FSROOT); | 382 | op += strlen(SMK_FSROOT); |
377 | nsp = smk_import(op, 0); | 383 | nsp = smk_import(op, 0); |
378 | if (nsp != NULL) | 384 | if (nsp != NULL) { |
379 | sp->smk_root = nsp; | 385 | sp->smk_root = nsp; |
386 | specified = 1; | ||
387 | } | ||
380 | } else if (strncmp(op, SMK_FSTRANS, strlen(SMK_FSTRANS)) == 0) { | 388 | } else if (strncmp(op, SMK_FSTRANS, strlen(SMK_FSTRANS)) == 0) { |
381 | op += strlen(SMK_FSTRANS); | 389 | op += strlen(SMK_FSTRANS); |
382 | nsp = smk_import(op, 0); | 390 | nsp = smk_import(op, 0); |
383 | if (nsp != NULL) { | 391 | if (nsp != NULL) { |
384 | sp->smk_root = nsp; | 392 | sp->smk_root = nsp; |
385 | transmute = 1; | 393 | transmute = 1; |
394 | specified = 1; | ||
386 | } | 395 | } |
387 | } | 396 | } |
388 | } | 397 | } |
389 | 398 | ||
399 | if (!smack_privileged(CAP_MAC_ADMIN)) { | ||
400 | /* | ||
401 | * Unprivileged mounts don't get to specify Smack values. | ||
402 | */ | ||
403 | if (specified) | ||
404 | return -EPERM; | ||
405 | /* | ||
406 | * Unprivileged mounts get root and default from the caller. | ||
407 | */ | ||
408 | skp = smk_of_current(); | ||
409 | sp->smk_root = skp->smk_known; | ||
410 | sp->smk_default = skp->smk_known; | ||
411 | } | ||
390 | /* | 412 | /* |
391 | * Initialize the root inode. | 413 | * Initialize the root inode. |
392 | */ | 414 | */ |
@@ -423,53 +445,6 @@ static int smack_sb_statfs(struct dentry *dentry) | |||
423 | return rc; | 445 | return rc; |
424 | } | 446 | } |
425 | 447 | ||
426 | /** | ||
427 | * smack_sb_mount - Smack check for mounting | ||
428 | * @dev_name: unused | ||
429 | * @path: mount point | ||
430 | * @type: unused | ||
431 | * @flags: unused | ||
432 | * @data: unused | ||
433 | * | ||
434 | * Returns 0 if current can write the floor of the filesystem | ||
435 | * being mounted on, an error code otherwise. | ||
436 | */ | ||
437 | static int smack_sb_mount(const char *dev_name, struct path *path, | ||
438 | const char *type, unsigned long flags, void *data) | ||
439 | { | ||
440 | struct superblock_smack *sbp = path->dentry->d_sb->s_security; | ||
441 | struct smk_audit_info ad; | ||
442 | |||
443 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH); | ||
444 | smk_ad_setfield_u_fs_path(&ad, *path); | ||
445 | |||
446 | return smk_curacc(sbp->smk_floor, MAY_WRITE, &ad); | ||
447 | } | ||
448 | |||
449 | /** | ||
450 | * smack_sb_umount - Smack check for unmounting | ||
451 | * @mnt: file system to unmount | ||
452 | * @flags: unused | ||
453 | * | ||
454 | * Returns 0 if current can write the floor of the filesystem | ||
455 | * being unmounted, an error code otherwise. | ||
456 | */ | ||
457 | static int smack_sb_umount(struct vfsmount *mnt, int flags) | ||
458 | { | ||
459 | struct superblock_smack *sbp; | ||
460 | struct smk_audit_info ad; | ||
461 | struct path path; | ||
462 | |||
463 | path.dentry = mnt->mnt_root; | ||
464 | path.mnt = mnt; | ||
465 | |||
466 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH); | ||
467 | smk_ad_setfield_u_fs_path(&ad, path); | ||
468 | |||
469 | sbp = path.dentry->d_sb->s_security; | ||
470 | return smk_curacc(sbp->smk_floor, MAY_WRITE, &ad); | ||
471 | } | ||
472 | |||
473 | /* | 448 | /* |
474 | * BPRM hooks | 449 | * BPRM hooks |
475 | */ | 450 | */ |
@@ -837,31 +812,43 @@ static int smack_inode_setxattr(struct dentry *dentry, const char *name, | |||
837 | const void *value, size_t size, int flags) | 812 | const void *value, size_t size, int flags) |
838 | { | 813 | { |
839 | struct smk_audit_info ad; | 814 | struct smk_audit_info ad; |
815 | struct smack_known *skp; | ||
816 | int check_priv = 0; | ||
817 | int check_import = 0; | ||
818 | int check_star = 0; | ||
840 | int rc = 0; | 819 | int rc = 0; |
841 | 820 | ||
821 | /* | ||
822 | * Check label validity here so import won't fail in post_setxattr | ||
823 | */ | ||
842 | if (strcmp(name, XATTR_NAME_SMACK) == 0 || | 824 | if (strcmp(name, XATTR_NAME_SMACK) == 0 || |
843 | strcmp(name, XATTR_NAME_SMACKIPIN) == 0 || | 825 | strcmp(name, XATTR_NAME_SMACKIPIN) == 0 || |
844 | strcmp(name, XATTR_NAME_SMACKIPOUT) == 0 || | 826 | strcmp(name, XATTR_NAME_SMACKIPOUT) == 0) { |
845 | strcmp(name, XATTR_NAME_SMACKEXEC) == 0 || | 827 | check_priv = 1; |
846 | strcmp(name, XATTR_NAME_SMACKMMAP) == 0) { | 828 | check_import = 1; |
847 | if (!smack_privileged(CAP_MAC_ADMIN)) | 829 | } else if (strcmp(name, XATTR_NAME_SMACKEXEC) == 0 || |
848 | rc = -EPERM; | 830 | strcmp(name, XATTR_NAME_SMACKMMAP) == 0) { |
849 | /* | 831 | check_priv = 1; |
850 | * check label validity here so import wont fail on | 832 | check_import = 1; |
851 | * post_setxattr | 833 | check_star = 1; |
852 | */ | ||
853 | if (size == 0 || size >= SMK_LONGLABEL || | ||
854 | smk_import(value, size) == NULL) | ||
855 | rc = -EINVAL; | ||
856 | } else if (strcmp(name, XATTR_NAME_SMACKTRANSMUTE) == 0) { | 834 | } else if (strcmp(name, XATTR_NAME_SMACKTRANSMUTE) == 0) { |
857 | if (!smack_privileged(CAP_MAC_ADMIN)) | 835 | check_priv = 1; |
858 | rc = -EPERM; | ||
859 | if (size != TRANS_TRUE_SIZE || | 836 | if (size != TRANS_TRUE_SIZE || |
860 | strncmp(value, TRANS_TRUE, TRANS_TRUE_SIZE) != 0) | 837 | strncmp(value, TRANS_TRUE, TRANS_TRUE_SIZE) != 0) |
861 | rc = -EINVAL; | 838 | rc = -EINVAL; |
862 | } else | 839 | } else |
863 | rc = cap_inode_setxattr(dentry, name, value, size, flags); | 840 | rc = cap_inode_setxattr(dentry, name, value, size, flags); |
864 | 841 | ||
842 | if (check_priv && !smack_privileged(CAP_MAC_ADMIN)) | ||
843 | rc = -EPERM; | ||
844 | |||
845 | if (rc == 0 && check_import) { | ||
846 | skp = smk_import_entry(value, size); | ||
847 | if (skp == NULL || (check_star && | ||
848 | (skp == &smack_known_star || skp == &smack_known_web))) | ||
849 | rc = -EINVAL; | ||
850 | } | ||
851 | |||
865 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_DENTRY); | 852 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_DENTRY); |
866 | smk_ad_setfield_u_fs_path_dentry(&ad, dentry); | 853 | smk_ad_setfield_u_fs_path_dentry(&ad, dentry); |
867 | 854 | ||
@@ -1364,7 +1351,7 @@ static int smack_file_receive(struct file *file) | |||
1364 | int may = 0; | 1351 | int may = 0; |
1365 | struct smk_audit_info ad; | 1352 | struct smk_audit_info ad; |
1366 | 1353 | ||
1367 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK); | 1354 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH); |
1368 | smk_ad_setfield_u_fs_path(&ad, file->f_path); | 1355 | smk_ad_setfield_u_fs_path(&ad, file->f_path); |
1369 | /* | 1356 | /* |
1370 | * This code relies on bitmasks. | 1357 | * This code relies on bitmasks. |
@@ -2847,8 +2834,17 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode) | |||
2847 | if (rc >= 0) | 2834 | if (rc >= 0) |
2848 | transflag = SMK_INODE_TRANSMUTE; | 2835 | transflag = SMK_INODE_TRANSMUTE; |
2849 | } | 2836 | } |
2850 | isp->smk_task = smk_fetch(XATTR_NAME_SMACKEXEC, inode, dp); | 2837 | /* |
2851 | isp->smk_mmap = smk_fetch(XATTR_NAME_SMACKMMAP, inode, dp); | 2838 | * Don't let the exec or mmap label be "*" or "@". |
2839 | */ | ||
2840 | skp = smk_fetch(XATTR_NAME_SMACKEXEC, inode, dp); | ||
2841 | if (skp == &smack_known_star || skp == &smack_known_web) | ||
2842 | skp = NULL; | ||
2843 | isp->smk_task = skp; | ||
2844 | skp = smk_fetch(XATTR_NAME_SMACKMMAP, inode, dp); | ||
2845 | if (skp == &smack_known_star || skp == &smack_known_web) | ||
2846 | skp = NULL; | ||
2847 | isp->smk_mmap = skp; | ||
2852 | 2848 | ||
2853 | dput(dp); | 2849 | dput(dp); |
2854 | break; | 2850 | break; |
@@ -3620,9 +3616,8 @@ static int smack_audit_rule_match(u32 secid, u32 field, u32 op, void *vrule, | |||
3620 | struct smack_known *skp; | 3616 | struct smack_known *skp; |
3621 | char *rule = vrule; | 3617 | char *rule = vrule; |
3622 | 3618 | ||
3623 | if (!rule) { | 3619 | if (unlikely(!rule)) { |
3624 | audit_log(actx, GFP_ATOMIC, AUDIT_SELINUX_ERR, | 3620 | WARN_ONCE(1, "Smack: missing rule\n"); |
3625 | "Smack: missing rule\n"); | ||
3626 | return -ENOENT; | 3621 | return -ENOENT; |
3627 | } | 3622 | } |
3628 | 3623 | ||
@@ -3743,8 +3738,6 @@ struct security_operations smack_ops = { | |||
3743 | .sb_copy_data = smack_sb_copy_data, | 3738 | .sb_copy_data = smack_sb_copy_data, |
3744 | .sb_kern_mount = smack_sb_kern_mount, | 3739 | .sb_kern_mount = smack_sb_kern_mount, |
3745 | .sb_statfs = smack_sb_statfs, | 3740 | .sb_statfs = smack_sb_statfs, |
3746 | .sb_mount = smack_sb_mount, | ||
3747 | .sb_umount = smack_sb_umount, | ||
3748 | 3741 | ||
3749 | .bprm_set_creds = smack_bprm_set_creds, | 3742 | .bprm_set_creds = smack_bprm_set_creds, |
3750 | .bprm_committing_creds = smack_bprm_committing_creds, | 3743 | .bprm_committing_creds = smack_bprm_committing_creds, |
diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c index 160aa08e3cd5..3198cfe1dcc6 100644 --- a/security/smack/smackfs.c +++ b/security/smack/smackfs.c | |||
@@ -52,6 +52,7 @@ enum smk_inos { | |||
52 | SMK_CIPSO2 = 17, /* load long label -> CIPSO mapping */ | 52 | SMK_CIPSO2 = 17, /* load long label -> CIPSO mapping */ |
53 | SMK_REVOKE_SUBJ = 18, /* set rules with subject label to '-' */ | 53 | SMK_REVOKE_SUBJ = 18, /* set rules with subject label to '-' */ |
54 | SMK_CHANGE_RULE = 19, /* change or add rules (long labels) */ | 54 | SMK_CHANGE_RULE = 19, /* change or add rules (long labels) */ |
55 | SMK_SYSLOG = 20, /* change syslog label) */ | ||
55 | }; | 56 | }; |
56 | 57 | ||
57 | /* | 58 | /* |
@@ -59,6 +60,7 @@ enum smk_inos { | |||
59 | */ | 60 | */ |
60 | static DEFINE_MUTEX(smack_cipso_lock); | 61 | static DEFINE_MUTEX(smack_cipso_lock); |
61 | static DEFINE_MUTEX(smack_ambient_lock); | 62 | static DEFINE_MUTEX(smack_ambient_lock); |
63 | static DEFINE_MUTEX(smack_syslog_lock); | ||
62 | static DEFINE_MUTEX(smk_netlbladdr_lock); | 64 | static DEFINE_MUTEX(smk_netlbladdr_lock); |
63 | 65 | ||
64 | /* | 66 | /* |
@@ -90,7 +92,13 @@ int smack_cipso_mapped = SMACK_CIPSO_MAPPED_DEFAULT; | |||
90 | * everyone. It is expected that the hat (^) label | 92 | * everyone. It is expected that the hat (^) label |
91 | * will be used if any label is used. | 93 | * will be used if any label is used. |
92 | */ | 94 | */ |
93 | char *smack_onlycap; | 95 | struct smack_known *smack_onlycap; |
96 | |||
97 | /* | ||
98 | * If this value is set restrict syslog use to the label specified. | ||
99 | * It can be reset via smackfs/syslog | ||
100 | */ | ||
101 | struct smack_known *smack_syslog_label; | ||
94 | 102 | ||
95 | /* | 103 | /* |
96 | * Certain IP addresses may be designated as single label hosts. | 104 | * Certain IP addresses may be designated as single label hosts. |
@@ -301,7 +309,8 @@ static int smk_perm_from_str(const char *string) | |||
301 | * @import: if non-zero, import labels | 309 | * @import: if non-zero, import labels |
302 | * @len: label length limit | 310 | * @len: label length limit |
303 | * | 311 | * |
304 | * Returns 0 on success, -1 on failure | 312 | * Returns 0 on success, -EINVAL on failure and -ENOENT when either subject |
313 | * or object is missing. | ||
305 | */ | 314 | */ |
306 | static int smk_fill_rule(const char *subject, const char *object, | 315 | static int smk_fill_rule(const char *subject, const char *object, |
307 | const char *access1, const char *access2, | 316 | const char *access1, const char *access2, |
@@ -314,28 +323,28 @@ static int smk_fill_rule(const char *subject, const char *object, | |||
314 | if (import) { | 323 | if (import) { |
315 | rule->smk_subject = smk_import_entry(subject, len); | 324 | rule->smk_subject = smk_import_entry(subject, len); |
316 | if (rule->smk_subject == NULL) | 325 | if (rule->smk_subject == NULL) |
317 | return -1; | 326 | return -EINVAL; |
318 | 327 | ||
319 | rule->smk_object = smk_import(object, len); | 328 | rule->smk_object = smk_import(object, len); |
320 | if (rule->smk_object == NULL) | 329 | if (rule->smk_object == NULL) |
321 | return -1; | 330 | return -EINVAL; |
322 | } else { | 331 | } else { |
323 | cp = smk_parse_smack(subject, len); | 332 | cp = smk_parse_smack(subject, len); |
324 | if (cp == NULL) | 333 | if (cp == NULL) |
325 | return -1; | 334 | return -EINVAL; |
326 | skp = smk_find_entry(cp); | 335 | skp = smk_find_entry(cp); |
327 | kfree(cp); | 336 | kfree(cp); |
328 | if (skp == NULL) | 337 | if (skp == NULL) |
329 | return -1; | 338 | return -ENOENT; |
330 | rule->smk_subject = skp; | 339 | rule->smk_subject = skp; |
331 | 340 | ||
332 | cp = smk_parse_smack(object, len); | 341 | cp = smk_parse_smack(object, len); |
333 | if (cp == NULL) | 342 | if (cp == NULL) |
334 | return -1; | 343 | return -EINVAL; |
335 | skp = smk_find_entry(cp); | 344 | skp = smk_find_entry(cp); |
336 | kfree(cp); | 345 | kfree(cp); |
337 | if (skp == NULL) | 346 | if (skp == NULL) |
338 | return -1; | 347 | return -ENOENT; |
339 | rule->smk_object = skp->smk_known; | 348 | rule->smk_object = skp->smk_known; |
340 | } | 349 | } |
341 | 350 | ||
@@ -381,6 +390,7 @@ static ssize_t smk_parse_long_rule(char *data, struct smack_parsed_rule *rule, | |||
381 | { | 390 | { |
382 | ssize_t cnt = 0; | 391 | ssize_t cnt = 0; |
383 | char *tok[4]; | 392 | char *tok[4]; |
393 | int rc; | ||
384 | int i; | 394 | int i; |
385 | 395 | ||
386 | /* | 396 | /* |
@@ -405,10 +415,8 @@ static ssize_t smk_parse_long_rule(char *data, struct smack_parsed_rule *rule, | |||
405 | while (i < 4) | 415 | while (i < 4) |
406 | tok[i++] = NULL; | 416 | tok[i++] = NULL; |
407 | 417 | ||
408 | if (smk_fill_rule(tok[0], tok[1], tok[2], tok[3], rule, import, 0)) | 418 | rc = smk_fill_rule(tok[0], tok[1], tok[2], tok[3], rule, import, 0); |
409 | return -1; | 419 | return rc == 0 ? cnt : rc; |
410 | |||
411 | return cnt; | ||
412 | } | 420 | } |
413 | 421 | ||
414 | #define SMK_FIXED24_FMT 0 /* Fixed 24byte label format */ | 422 | #define SMK_FIXED24_FMT 0 /* Fixed 24byte label format */ |
@@ -1603,7 +1611,7 @@ static const struct file_operations smk_ambient_ops = { | |||
1603 | }; | 1611 | }; |
1604 | 1612 | ||
1605 | /** | 1613 | /** |
1606 | * smk_read_onlycap - read() for /smack/onlycap | 1614 | * smk_read_onlycap - read() for smackfs/onlycap |
1607 | * @filp: file pointer, not actually used | 1615 | * @filp: file pointer, not actually used |
1608 | * @buf: where to put the result | 1616 | * @buf: where to put the result |
1609 | * @cn: maximum to send along | 1617 | * @cn: maximum to send along |
@@ -1622,7 +1630,7 @@ static ssize_t smk_read_onlycap(struct file *filp, char __user *buf, | |||
1622 | return 0; | 1630 | return 0; |
1623 | 1631 | ||
1624 | if (smack_onlycap != NULL) | 1632 | if (smack_onlycap != NULL) |
1625 | smack = smack_onlycap; | 1633 | smack = smack_onlycap->smk_known; |
1626 | 1634 | ||
1627 | asize = strlen(smack) + 1; | 1635 | asize = strlen(smack) + 1; |
1628 | 1636 | ||
@@ -1633,7 +1641,7 @@ static ssize_t smk_read_onlycap(struct file *filp, char __user *buf, | |||
1633 | } | 1641 | } |
1634 | 1642 | ||
1635 | /** | 1643 | /** |
1636 | * smk_write_onlycap - write() for /smack/onlycap | 1644 | * smk_write_onlycap - write() for smackfs/onlycap |
1637 | * @file: file pointer, not actually used | 1645 | * @file: file pointer, not actually used |
1638 | * @buf: where to get the data from | 1646 | * @buf: where to get the data from |
1639 | * @count: bytes sent | 1647 | * @count: bytes sent |
@@ -1656,7 +1664,7 @@ static ssize_t smk_write_onlycap(struct file *file, const char __user *buf, | |||
1656 | * explicitly for clarity. The smk_access() implementation | 1664 | * explicitly for clarity. The smk_access() implementation |
1657 | * would use smk_access(smack_onlycap, MAY_WRITE) | 1665 | * would use smk_access(smack_onlycap, MAY_WRITE) |
1658 | */ | 1666 | */ |
1659 | if (smack_onlycap != NULL && smack_onlycap != skp->smk_known) | 1667 | if (smack_onlycap != NULL && smack_onlycap != skp) |
1660 | return -EPERM; | 1668 | return -EPERM; |
1661 | 1669 | ||
1662 | data = kzalloc(count, GFP_KERNEL); | 1670 | data = kzalloc(count, GFP_KERNEL); |
@@ -1676,7 +1684,7 @@ static ssize_t smk_write_onlycap(struct file *file, const char __user *buf, | |||
1676 | if (copy_from_user(data, buf, count) != 0) | 1684 | if (copy_from_user(data, buf, count) != 0) |
1677 | rc = -EFAULT; | 1685 | rc = -EFAULT; |
1678 | else | 1686 | else |
1679 | smack_onlycap = smk_import(data, count); | 1687 | smack_onlycap = smk_import_entry(data, count); |
1680 | 1688 | ||
1681 | kfree(data); | 1689 | kfree(data); |
1682 | return rc; | 1690 | return rc; |
@@ -1856,11 +1864,12 @@ static ssize_t smk_user_access(struct file *file, const char __user *buf, | |||
1856 | res = smk_parse_long_rule(data, &rule, 0, 3); | 1864 | res = smk_parse_long_rule(data, &rule, 0, 3); |
1857 | } | 1865 | } |
1858 | 1866 | ||
1859 | if (res < 0) | 1867 | if (res >= 0) |
1868 | res = smk_access(rule.smk_subject, rule.smk_object, | ||
1869 | rule.smk_access1, NULL); | ||
1870 | else if (res != -ENOENT) | ||
1860 | return -EINVAL; | 1871 | return -EINVAL; |
1861 | 1872 | ||
1862 | res = smk_access(rule.smk_subject, rule.smk_object, | ||
1863 | rule.smk_access1, NULL); | ||
1864 | data[0] = res == 0 ? '1' : '0'; | 1873 | data[0] = res == 0 ? '1' : '0'; |
1865 | data[1] = '\0'; | 1874 | data[1] = '\0'; |
1866 | 1875 | ||
@@ -2143,7 +2152,7 @@ static ssize_t smk_write_change_rule(struct file *file, const char __user *buf, | |||
2143 | /* | 2152 | /* |
2144 | * Must have privilege. | 2153 | * Must have privilege. |
2145 | */ | 2154 | */ |
2146 | if (!capable(CAP_MAC_ADMIN)) | 2155 | if (!smack_privileged(CAP_MAC_ADMIN)) |
2147 | return -EPERM; | 2156 | return -EPERM; |
2148 | 2157 | ||
2149 | return smk_write_rules_list(file, buf, count, ppos, NULL, NULL, | 2158 | return smk_write_rules_list(file, buf, count, ppos, NULL, NULL, |
@@ -2158,12 +2167,89 @@ static const struct file_operations smk_change_rule_ops = { | |||
2158 | }; | 2167 | }; |
2159 | 2168 | ||
2160 | /** | 2169 | /** |
2161 | * smk_fill_super - fill the /smackfs superblock | 2170 | * smk_read_syslog - read() for smackfs/syslog |
2171 | * @filp: file pointer, not actually used | ||
2172 | * @buf: where to put the result | ||
2173 | * @cn: maximum to send along | ||
2174 | * @ppos: where to start | ||
2175 | * | ||
2176 | * Returns number of bytes read or error code, as appropriate | ||
2177 | */ | ||
2178 | static ssize_t smk_read_syslog(struct file *filp, char __user *buf, | ||
2179 | size_t cn, loff_t *ppos) | ||
2180 | { | ||
2181 | struct smack_known *skp; | ||
2182 | ssize_t rc = -EINVAL; | ||
2183 | int asize; | ||
2184 | |||
2185 | if (*ppos != 0) | ||
2186 | return 0; | ||
2187 | |||
2188 | if (smack_syslog_label == NULL) | ||
2189 | skp = &smack_known_star; | ||
2190 | else | ||
2191 | skp = smack_syslog_label; | ||
2192 | |||
2193 | asize = strlen(skp->smk_known) + 1; | ||
2194 | |||
2195 | if (cn >= asize) | ||
2196 | rc = simple_read_from_buffer(buf, cn, ppos, skp->smk_known, | ||
2197 | asize); | ||
2198 | |||
2199 | return rc; | ||
2200 | } | ||
2201 | |||
2202 | /** | ||
2203 | * smk_write_syslog - write() for smackfs/syslog | ||
2204 | * @file: file pointer, not actually used | ||
2205 | * @buf: where to get the data from | ||
2206 | * @count: bytes sent | ||
2207 | * @ppos: where to start | ||
2208 | * | ||
2209 | * Returns number of bytes written or error code, as appropriate | ||
2210 | */ | ||
2211 | static ssize_t smk_write_syslog(struct file *file, const char __user *buf, | ||
2212 | size_t count, loff_t *ppos) | ||
2213 | { | ||
2214 | char *data; | ||
2215 | struct smack_known *skp; | ||
2216 | int rc = count; | ||
2217 | |||
2218 | if (!smack_privileged(CAP_MAC_ADMIN)) | ||
2219 | return -EPERM; | ||
2220 | |||
2221 | data = kzalloc(count, GFP_KERNEL); | ||
2222 | if (data == NULL) | ||
2223 | return -ENOMEM; | ||
2224 | |||
2225 | if (copy_from_user(data, buf, count) != 0) | ||
2226 | rc = -EFAULT; | ||
2227 | else { | ||
2228 | skp = smk_import_entry(data, count); | ||
2229 | if (skp == NULL) | ||
2230 | rc = -EINVAL; | ||
2231 | else | ||
2232 | smack_syslog_label = smk_import_entry(data, count); | ||
2233 | } | ||
2234 | |||
2235 | kfree(data); | ||
2236 | return rc; | ||
2237 | } | ||
2238 | |||
2239 | static const struct file_operations smk_syslog_ops = { | ||
2240 | .read = smk_read_syslog, | ||
2241 | .write = smk_write_syslog, | ||
2242 | .llseek = default_llseek, | ||
2243 | }; | ||
2244 | |||
2245 | |||
2246 | /** | ||
2247 | * smk_fill_super - fill the smackfs superblock | ||
2162 | * @sb: the empty superblock | 2248 | * @sb: the empty superblock |
2163 | * @data: unused | 2249 | * @data: unused |
2164 | * @silent: unused | 2250 | * @silent: unused |
2165 | * | 2251 | * |
2166 | * Fill in the well known entries for /smack | 2252 | * Fill in the well known entries for the smack filesystem |
2167 | * | 2253 | * |
2168 | * Returns 0 on success, an error code on failure | 2254 | * Returns 0 on success, an error code on failure |
2169 | */ | 2255 | */ |
@@ -2208,6 +2294,8 @@ static int smk_fill_super(struct super_block *sb, void *data, int silent) | |||
2208 | S_IRUGO|S_IWUSR}, | 2294 | S_IRUGO|S_IWUSR}, |
2209 | [SMK_CHANGE_RULE] = { | 2295 | [SMK_CHANGE_RULE] = { |
2210 | "change-rule", &smk_change_rule_ops, S_IRUGO|S_IWUSR}, | 2296 | "change-rule", &smk_change_rule_ops, S_IRUGO|S_IWUSR}, |
2297 | [SMK_SYSLOG] = { | ||
2298 | "syslog", &smk_syslog_ops, S_IRUGO|S_IWUSR}, | ||
2211 | /* last one */ | 2299 | /* last one */ |
2212 | {""} | 2300 | {""} |
2213 | }; | 2301 | }; |