aboutsummaryrefslogtreecommitdiffstats
path: root/security
diff options
context:
space:
mode:
authorJames Morris <jmorris@namei.org>2009-01-06 17:58:22 -0500
committerJames Morris <jmorris@namei.org>2009-01-06 17:58:22 -0500
commitac8cc0fa5395fe2278e305a4cbed48e90d88d878 (patch)
tree515f577bfddd054ee4373228be7c974dfb8133af /security
parent238c6d54830c624f34ac9cf123ac04aebfca5013 (diff)
parent3699c53c485bf0168e6500d0ed18bf931584dd7c (diff)
Merge branch 'next' into for-linus
Diffstat (limited to 'security')
-rw-r--r--security/commoncap.c29
-rw-r--r--security/keys/keyctl.c2
-rw-r--r--security/security.c26
-rw-r--r--security/selinux/Kconfig27
-rw-r--r--security/selinux/avc.c16
-rw-r--r--security/selinux/hooks.c22
-rw-r--r--security/selinux/include/avc_ss.h4
-rw-r--r--security/selinux/selinuxfs.c16
-rw-r--r--security/selinux/ss/context.h2
-rw-r--r--security/smack/smack.h31
-rw-r--r--security/smack/smack_access.c28
-rw-r--r--security/smack/smack_lsm.c310
-rw-r--r--security/smack/smackfs.c369
13 files changed, 616 insertions, 266 deletions
diff --git a/security/commoncap.c b/security/commoncap.c
index 69fc9952650..7cd61a5f520 100644
--- a/security/commoncap.c
+++ b/security/commoncap.c
@@ -45,26 +45,22 @@ EXPORT_SYMBOL(cap_netlink_recv);
45/** 45/**
46 * cap_capable - Determine whether a task has a particular effective capability 46 * cap_capable - Determine whether a task has a particular effective capability
47 * @tsk: The task to query 47 * @tsk: The task to query
48 * @cred: The credentials to use
48 * @cap: The capability to check for 49 * @cap: The capability to check for
49 * @audit: Whether to write an audit message or not 50 * @audit: Whether to write an audit message or not
50 * 51 *
51 * Determine whether the nominated task has the specified capability amongst 52 * Determine whether the nominated task has the specified capability amongst
52 * its effective set, returning 0 if it does, -ve if it does not. 53 * its effective set, returning 0 if it does, -ve if it does not.
53 * 54 *
54 * NOTE WELL: cap_capable() cannot be used like the kernel's capable() 55 * NOTE WELL: cap_has_capability() cannot be used like the kernel's capable()
55 * function. That is, it has the reverse semantics: cap_capable() returns 0 56 * and has_capability() functions. That is, it has the reverse semantics:
56 * when a task has a capability, but the kernel's capable() returns 1 for this 57 * cap_has_capability() returns 0 when a task has a capability, but the
57 * case. 58 * kernel's capable() and has_capability() returns 1 for this case.
58 */ 59 */
59int cap_capable(struct task_struct *tsk, int cap, int audit) 60int cap_capable(struct task_struct *tsk, const struct cred *cred, int cap,
61 int audit)
60{ 62{
61 __u32 cap_raised; 63 return cap_raised(cred->cap_effective, cap) ? 0 : -EPERM;
62
63 /* Derived from include/linux/sched.h:capable. */
64 rcu_read_lock();
65 cap_raised = cap_raised(__task_cred(tsk)->cap_effective, cap);
66 rcu_read_unlock();
67 return cap_raised ? 0 : -EPERM;
68} 64}
69 65
70/** 66/**
@@ -160,7 +156,8 @@ static inline int cap_inh_is_capped(void)
160 /* they are so limited unless the current task has the CAP_SETPCAP 156 /* they are so limited unless the current task has the CAP_SETPCAP
161 * capability 157 * capability
162 */ 158 */
163 if (cap_capable(current, CAP_SETPCAP, SECURITY_CAP_AUDIT) == 0) 159 if (cap_capable(current, current_cred(), CAP_SETPCAP,
160 SECURITY_CAP_AUDIT) == 0)
164 return 0; 161 return 0;
165#endif 162#endif
166 return 1; 163 return 1;
@@ -869,7 +866,8 @@ int cap_task_prctl(int option, unsigned long arg2, unsigned long arg3,
869 & (new->securebits ^ arg2)) /*[1]*/ 866 & (new->securebits ^ arg2)) /*[1]*/
870 || ((new->securebits & SECURE_ALL_LOCKS & ~arg2)) /*[2]*/ 867 || ((new->securebits & SECURE_ALL_LOCKS & ~arg2)) /*[2]*/
871 || (arg2 & ~(SECURE_ALL_LOCKS | SECURE_ALL_BITS)) /*[3]*/ 868 || (arg2 & ~(SECURE_ALL_LOCKS | SECURE_ALL_BITS)) /*[3]*/
872 || (cap_capable(current, CAP_SETPCAP, SECURITY_CAP_AUDIT) != 0) /*[4]*/ 869 || (cap_capable(current, current_cred(), CAP_SETPCAP,
870 SECURITY_CAP_AUDIT) != 0) /*[4]*/
873 /* 871 /*
874 * [1] no changing of bits that are locked 872 * [1] no changing of bits that are locked
875 * [2] no unlocking of locks 873 * [2] no unlocking of locks
@@ -950,7 +948,8 @@ int cap_vm_enough_memory(struct mm_struct *mm, long pages)
950{ 948{
951 int cap_sys_admin = 0; 949 int cap_sys_admin = 0;
952 950
953 if (cap_capable(current, CAP_SYS_ADMIN, SECURITY_CAP_NOAUDIT) == 0) 951 if (cap_capable(current, current_cred(), CAP_SYS_ADMIN,
952 SECURITY_CAP_NOAUDIT) == 0)
954 cap_sys_admin = 1; 953 cap_sys_admin = 1;
955 return __vm_enough_memory(mm, pages, cap_sys_admin); 954 return __vm_enough_memory(mm, pages, cap_sys_admin);
956} 955}
diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c
index 6688765bd8b..09796797d12 100644
--- a/security/keys/keyctl.c
+++ b/security/keys/keyctl.c
@@ -1294,7 +1294,7 @@ asmlinkage long sys_keyctl(int option, unsigned long arg2, unsigned long arg3,
1294 1294
1295 case KEYCTL_GET_SECURITY: 1295 case KEYCTL_GET_SECURITY:
1296 return keyctl_get_security((key_serial_t) arg2, 1296 return keyctl_get_security((key_serial_t) arg2,
1297 (char *) arg3, 1297 (char __user *) arg3,
1298 (size_t) arg4); 1298 (size_t) arg4);
1299 1299
1300 default: 1300 default:
diff --git a/security/security.c b/security/security.c
index 678d4d07b85..c3586c0d97e 100644
--- a/security/security.c
+++ b/security/security.c
@@ -154,14 +154,32 @@ int security_capset(struct cred *new, const struct cred *old,
154 effective, inheritable, permitted); 154 effective, inheritable, permitted);
155} 155}
156 156
157int security_capable(struct task_struct *tsk, int cap) 157int security_capable(int cap)
158{ 158{
159 return security_ops->capable(tsk, cap, SECURITY_CAP_AUDIT); 159 return security_ops->capable(current, current_cred(), cap,
160 SECURITY_CAP_AUDIT);
160} 161}
161 162
162int security_capable_noaudit(struct task_struct *tsk, int cap) 163int security_real_capable(struct task_struct *tsk, int cap)
163{ 164{
164 return security_ops->capable(tsk, cap, SECURITY_CAP_NOAUDIT); 165 const struct cred *cred;
166 int ret;
167
168 cred = get_task_cred(tsk);
169 ret = security_ops->capable(tsk, cred, cap, SECURITY_CAP_AUDIT);
170 put_cred(cred);
171 return ret;
172}
173
174int security_real_capable_noaudit(struct task_struct *tsk, int cap)
175{
176 const struct cred *cred;
177 int ret;
178
179 cred = get_task_cred(tsk);
180 ret = security_ops->capable(tsk, cred, cap, SECURITY_CAP_NOAUDIT);
181 put_cred(cred);
182 return ret;
165} 183}
166 184
167int security_acct(struct file *file) 185int security_acct(struct file *file)
diff --git a/security/selinux/Kconfig b/security/selinux/Kconfig
index 26301dd651d..bca1b74a4a2 100644
--- a/security/selinux/Kconfig
+++ b/security/selinux/Kconfig
@@ -94,33 +94,6 @@ config SECURITY_SELINUX_CHECKREQPROT_VALUE
94 94
95 If you are unsure how to answer this question, answer 1. 95 If you are unsure how to answer this question, answer 1.
96 96
97config SECURITY_SELINUX_ENABLE_SECMARK_DEFAULT
98 bool "NSA SELinux enable new secmark network controls by default"
99 depends on SECURITY_SELINUX
100 default n
101 help
102 This option determines whether the new secmark-based network
103 controls will be enabled by default. If not, the old internal
104 per-packet controls will be enabled by default, preserving
105 old behavior.
106
107 If you enable the new controls, you will need updated
108 SELinux userspace libraries, tools and policy. Typically,
109 your distribution will provide these and enable the new controls
110 in the kernel they also distribute.
111
112 Note that this option can be overridden at boot with the
113 selinux_compat_net parameter, and after boot via
114 /selinux/compat_net. See Documentation/kernel-parameters.txt
115 for details on this parameter.
116
117 If you enable the new network controls, you will likely
118 also require the SECMARK and CONNSECMARK targets, as
119 well as any conntrack helpers for protocols which you
120 wish to control.
121
122 If you are unsure what to do here, select N.
123
124config SECURITY_SELINUX_POLICYDB_VERSION_MAX 97config SECURITY_SELINUX_POLICYDB_VERSION_MAX
125 bool "NSA SELinux maximum supported policy format version" 98 bool "NSA SELinux maximum supported policy format version"
126 depends on SECURITY_SELINUX 99 depends on SECURITY_SELINUX
diff --git a/security/selinux/avc.c b/security/selinux/avc.c
index d43bd6baeea..eb41f43e277 100644
--- a/security/selinux/avc.c
+++ b/security/selinux/avc.c
@@ -53,18 +53,20 @@ static const char *class_to_string[] = {
53#undef S_ 53#undef S_
54 54
55static const struct av_inherit av_inherit[] = { 55static const struct av_inherit av_inherit[] = {
56#define S_(c, i, b) { c, common_##i##_perm_to_string, b }, 56#define S_(c, i, b) { .tclass = c,\
57 .common_pts = common_##i##_perm_to_string,\
58 .common_base = b },
57#include "av_inherit.h" 59#include "av_inherit.h"
58#undef S_ 60#undef S_
59}; 61};
60 62
61const struct selinux_class_perm selinux_class_perm = { 63const struct selinux_class_perm selinux_class_perm = {
62 av_perm_to_string, 64 .av_perm_to_string = av_perm_to_string,
63 ARRAY_SIZE(av_perm_to_string), 65 .av_pts_len = ARRAY_SIZE(av_perm_to_string),
64 class_to_string, 66 .class_to_string = class_to_string,
65 ARRAY_SIZE(class_to_string), 67 .cts_len = ARRAY_SIZE(class_to_string),
66 av_inherit, 68 .av_inherit = av_inherit,
67 ARRAY_SIZE(av_inherit) 69 .av_inherit_len = ARRAY_SIZE(av_inherit)
68}; 70};
69 71
70#define AVC_CACHE_SLOTS 512 72#define AVC_CACHE_SLOTS 512
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index dbeaa783b2a..00815973d41 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -1433,12 +1433,13 @@ static int current_has_perm(const struct task_struct *tsk,
1433 1433
1434/* Check whether a task is allowed to use a capability. */ 1434/* Check whether a task is allowed to use a capability. */
1435static int task_has_capability(struct task_struct *tsk, 1435static int task_has_capability(struct task_struct *tsk,
1436 const struct cred *cred,
1436 int cap, int audit) 1437 int cap, int audit)
1437{ 1438{
1438 struct avc_audit_data ad; 1439 struct avc_audit_data ad;
1439 struct av_decision avd; 1440 struct av_decision avd;
1440 u16 sclass; 1441 u16 sclass;
1441 u32 sid = task_sid(tsk); 1442 u32 sid = cred_sid(cred);
1442 u32 av = CAP_TO_MASK(cap); 1443 u32 av = CAP_TO_MASK(cap);
1443 int rc; 1444 int rc;
1444 1445
@@ -1865,15 +1866,16 @@ static int selinux_capset(struct cred *new, const struct cred *old,
1865 return cred_has_perm(old, new, PROCESS__SETCAP); 1866 return cred_has_perm(old, new, PROCESS__SETCAP);
1866} 1867}
1867 1868
1868static int selinux_capable(struct task_struct *tsk, int cap, int audit) 1869static int selinux_capable(struct task_struct *tsk, const struct cred *cred,
1870 int cap, int audit)
1869{ 1871{
1870 int rc; 1872 int rc;
1871 1873
1872 rc = secondary_ops->capable(tsk, cap, audit); 1874 rc = secondary_ops->capable(tsk, cred, cap, audit);
1873 if (rc) 1875 if (rc)
1874 return rc; 1876 return rc;
1875 1877
1876 return task_has_capability(tsk, cap, audit); 1878 return task_has_capability(tsk, cred, cap, audit);
1877} 1879}
1878 1880
1879static int selinux_sysctl_get_sid(ctl_table *table, u16 tclass, u32 *sid) 1881static int selinux_sysctl_get_sid(ctl_table *table, u16 tclass, u32 *sid)
@@ -2037,7 +2039,8 @@ static int selinux_vm_enough_memory(struct mm_struct *mm, long pages)
2037{ 2039{
2038 int rc, cap_sys_admin = 0; 2040 int rc, cap_sys_admin = 0;
2039 2041
2040 rc = selinux_capable(current, CAP_SYS_ADMIN, SECURITY_CAP_NOAUDIT); 2042 rc = selinux_capable(current, current_cred(), CAP_SYS_ADMIN,
2043 SECURITY_CAP_NOAUDIT);
2041 if (rc == 0) 2044 if (rc == 0)
2042 cap_sys_admin = 1; 2045 cap_sys_admin = 1;
2043 2046
@@ -2880,7 +2883,8 @@ static int selinux_inode_getsecurity(const struct inode *inode, const char *name
2880 * and lack of permission just means that we fall back to the 2883 * and lack of permission just means that we fall back to the
2881 * in-core context value, not a denial. 2884 * in-core context value, not a denial.
2882 */ 2885 */
2883 error = selinux_capable(current, CAP_MAC_ADMIN, SECURITY_CAP_NOAUDIT); 2886 error = selinux_capable(current, current_cred(), CAP_MAC_ADMIN,
2887 SECURITY_CAP_NOAUDIT);
2884 if (!error) 2888 if (!error)
2885 error = security_sid_to_context_force(isec->sid, &context, 2889 error = security_sid_to_context_force(isec->sid, &context,
2886 &size); 2890 &size);
@@ -4185,7 +4189,7 @@ static int selinux_sock_rcv_skb_iptables_compat(struct sock *sk,
4185static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb, 4189static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb,
4186 u16 family) 4190 u16 family)
4187{ 4191{
4188 int err; 4192 int err = 0;
4189 struct sk_security_struct *sksec = sk->sk_security; 4193 struct sk_security_struct *sksec = sk->sk_security;
4190 u32 peer_sid; 4194 u32 peer_sid;
4191 u32 sk_sid = sksec->sid; 4195 u32 sk_sid = sksec->sid;
@@ -4202,7 +4206,7 @@ static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb,
4202 if (selinux_compat_net) 4206 if (selinux_compat_net)
4203 err = selinux_sock_rcv_skb_iptables_compat(sk, skb, &ad, 4207 err = selinux_sock_rcv_skb_iptables_compat(sk, skb, &ad,
4204 family, addrp); 4208 family, addrp);
4205 else 4209 else if (selinux_secmark_enabled())
4206 err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET, 4210 err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET,
4207 PACKET__RECV, &ad); 4211 PACKET__RECV, &ad);
4208 if (err) 4212 if (err)
@@ -4705,7 +4709,7 @@ static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb,
4705 if (selinux_ip_postroute_iptables_compat(skb->sk, ifindex, 4709 if (selinux_ip_postroute_iptables_compat(skb->sk, ifindex,
4706 &ad, family, addrp)) 4710 &ad, family, addrp))
4707 return NF_DROP; 4711 return NF_DROP;
4708 } else { 4712 } else if (selinux_secmark_enabled()) {
4709 if (avc_has_perm(sksec->sid, skb->secmark, 4713 if (avc_has_perm(sksec->sid, skb->secmark,
4710 SECCLASS_PACKET, PACKET__SEND, &ad)) 4714 SECCLASS_PACKET, PACKET__SEND, &ad))
4711 return NF_DROP; 4715 return NF_DROP;
diff --git a/security/selinux/include/avc_ss.h b/security/selinux/include/avc_ss.h
index c0d314d9f8e..bb1ec801bdf 100644
--- a/security/selinux/include/avc_ss.h
+++ b/security/selinux/include/avc_ss.h
@@ -17,16 +17,16 @@ struct av_perm_to_string {
17}; 17};
18 18
19struct av_inherit { 19struct av_inherit {
20 u16 tclass;
21 const char **common_pts; 20 const char **common_pts;
22 u32 common_base; 21 u32 common_base;
22 u16 tclass;
23}; 23};
24 24
25struct selinux_class_perm { 25struct selinux_class_perm {
26 const struct av_perm_to_string *av_perm_to_string; 26 const struct av_perm_to_string *av_perm_to_string;
27 u32 av_pts_len; 27 u32 av_pts_len;
28 const char **class_to_string;
29 u32 cts_len; 28 u32 cts_len;
29 const char **class_to_string;
30 const struct av_inherit *av_inherit; 30 const struct av_inherit *av_inherit;
31 u32 av_inherit_len; 31 u32 av_inherit_len;
32}; 32};
diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c
index 8f612c8becb..01ec6d2c6b9 100644
--- a/security/selinux/selinuxfs.c
+++ b/security/selinux/selinuxfs.c
@@ -47,13 +47,7 @@ static char *policycap_names[] = {
47 47
48unsigned int selinux_checkreqprot = CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE; 48unsigned int selinux_checkreqprot = CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE;
49 49
50#ifdef CONFIG_SECURITY_SELINUX_ENABLE_SECMARK_DEFAULT 50int selinux_compat_net = 0;
51#define SELINUX_COMPAT_NET_VALUE 0
52#else
53#define SELINUX_COMPAT_NET_VALUE 1
54#endif
55
56int selinux_compat_net = SELINUX_COMPAT_NET_VALUE;
57 51
58static int __init checkreqprot_setup(char *str) 52static int __init checkreqprot_setup(char *str)
59{ 53{
@@ -494,7 +488,13 @@ static ssize_t sel_write_compat_net(struct file *file, const char __user *buf,
494 if (sscanf(page, "%d", &new_value) != 1) 488 if (sscanf(page, "%d", &new_value) != 1)
495 goto out; 489 goto out;
496 490
497 selinux_compat_net = new_value ? 1 : 0; 491 if (new_value) {
492 printk(KERN_NOTICE
493 "SELinux: compat_net is deprecated, please use secmark"
494 " instead\n");
495 selinux_compat_net = 1;
496 } else
497 selinux_compat_net = 0;
498 length = count; 498 length = count;
499out: 499out:
500 free_page((unsigned long) page); 500 free_page((unsigned long) page);
diff --git a/security/selinux/ss/context.h b/security/selinux/ss/context.h
index 658c2bd17da..d9dd7a2f6a8 100644
--- a/security/selinux/ss/context.h
+++ b/security/selinux/ss/context.h
@@ -27,9 +27,9 @@ struct context {
27 u32 user; 27 u32 user;
28 u32 role; 28 u32 role;
29 u32 type; 29 u32 type;
30 u32 len; /* length of string in bytes */
30 struct mls_range range; 31 struct mls_range range;
31 char *str; /* string representation if context cannot be mapped. */ 32 char *str; /* string representation if context cannot be mapped. */
32 u32 len; /* length of string in bytes */
33}; 33};
34 34
35static inline void mls_context_init(struct context *c) 35static inline void mls_context_init(struct context *c)
diff --git a/security/smack/smack.h b/security/smack/smack.h
index 31dce559595..b79582e4fbf 100644
--- a/security/smack/smack.h
+++ b/security/smack/smack.h
@@ -16,6 +16,7 @@
16#include <linux/capability.h> 16#include <linux/capability.h>
17#include <linux/spinlock.h> 17#include <linux/spinlock.h>
18#include <linux/security.h> 18#include <linux/security.h>
19#include <linux/in.h>
19#include <net/netlabel.h> 20#include <net/netlabel.h>
20 21
21/* 22/*
@@ -39,6 +40,7 @@ struct superblock_smack {
39struct socket_smack { 40struct socket_smack {
40 char *smk_out; /* outbound label */ 41 char *smk_out; /* outbound label */
41 char *smk_in; /* inbound label */ 42 char *smk_in; /* inbound label */
43 int smk_labeled; /* label scheme */
42 char smk_packet[SMK_LABELLEN]; /* TCP peer label */ 44 char smk_packet[SMK_LABELLEN]; /* TCP peer label */
43}; 45};
44 46
@@ -80,6 +82,16 @@ struct smack_cipso {
80}; 82};
81 83
82/* 84/*
85 * An entry in the table identifying hosts.
86 */
87struct smk_netlbladdr {
88 struct smk_netlbladdr *smk_next;
89 struct sockaddr_in smk_host; /* network address */
90 struct in_addr smk_mask; /* network mask */
91 char *smk_label; /* label */
92};
93
94/*
83 * This is the repository for labels seen so that it is 95 * This is the repository for labels seen so that it is
84 * not necessary to keep allocating tiny chuncks of memory 96 * not necessary to keep allocating tiny chuncks of memory
85 * and so that they can be shared. 97 * and so that they can be shared.
@@ -127,6 +139,20 @@ struct smack_known {
127#define XATTR_NAME_SMACKIPOUT XATTR_SECURITY_PREFIX XATTR_SMACK_IPOUT 139#define XATTR_NAME_SMACKIPOUT XATTR_SECURITY_PREFIX XATTR_SMACK_IPOUT
128 140
129/* 141/*
142 * How communications on this socket are treated.
143 * Usually it's determined by the underlying netlabel code
144 * but there are certain cases, including single label hosts
145 * and potentially single label interfaces for which the
146 * treatment can not be known in advance.
147 *
148 * The possibility of additional labeling schemes being
149 * introduced in the future exists as well.
150 */
151#define SMACK_UNLABELED_SOCKET 0
152#define SMACK_CIPSO_SOCKET 1
153
154/*
155 * smackfs magic number
130 * smackfs macic number 156 * smackfs macic number
131 */ 157 */
132#define SMACK_MAGIC 0x43415d53 /* "SMAC" */ 158#define SMACK_MAGIC 0x43415d53 /* "SMAC" */
@@ -141,6 +167,7 @@ struct smack_known {
141 * CIPSO defaults. 167 * CIPSO defaults.
142 */ 168 */
143#define SMACK_CIPSO_DOI_DEFAULT 3 /* Historical */ 169#define SMACK_CIPSO_DOI_DEFAULT 3 /* Historical */
170#define SMACK_CIPSO_DOI_INVALID -1 /* Not a DOI */
144#define SMACK_CIPSO_DIRECT_DEFAULT 250 /* Arbitrary */ 171#define SMACK_CIPSO_DIRECT_DEFAULT 250 /* Arbitrary */
145#define SMACK_CIPSO_MAXCATVAL 63 /* Bigger gets harder */ 172#define SMACK_CIPSO_MAXCATVAL 63 /* Bigger gets harder */
146#define SMACK_CIPSO_MAXLEVEL 255 /* CIPSO 2.2 standard */ 173#define SMACK_CIPSO_MAXLEVEL 255 /* CIPSO 2.2 standard */
@@ -176,7 +203,6 @@ u32 smack_to_secid(const char *);
176 * Shared data. 203 * Shared data.
177 */ 204 */
178extern int smack_cipso_direct; 205extern int smack_cipso_direct;
179extern int smack_net_nltype;
180extern char *smack_net_ambient; 206extern char *smack_net_ambient;
181extern char *smack_onlycap; 207extern char *smack_onlycap;
182 208
@@ -186,9 +212,10 @@ extern struct smack_known smack_known_hat;
186extern struct smack_known smack_known_huh; 212extern struct smack_known smack_known_huh;
187extern struct smack_known smack_known_invalid; 213extern struct smack_known smack_known_invalid;
188extern struct smack_known smack_known_star; 214extern struct smack_known smack_known_star;
189extern struct smack_known smack_known_unset; 215extern struct smack_known smack_known_web;
190 216
191extern struct smk_list_entry *smack_list; 217extern struct smk_list_entry *smack_list;
218extern struct smk_netlbladdr *smack_netlbladdrs;
192extern struct security_operations smack_ops; 219extern struct security_operations smack_ops;
193 220
194/* 221/*
diff --git a/security/smack/smack_access.c b/security/smack/smack_access.c
index 247cec3b5a4..2e0b83e77ff 100644
--- a/security/smack/smack_access.c
+++ b/security/smack/smack_access.c
@@ -15,15 +15,8 @@
15#include <linux/sched.h> 15#include <linux/sched.h>
16#include "smack.h" 16#include "smack.h"
17 17
18struct smack_known smack_known_unset = {
19 .smk_next = NULL,
20 .smk_known = "UNSET",
21 .smk_secid = 1,
22 .smk_cipso = NULL,
23};
24
25struct smack_known smack_known_huh = { 18struct smack_known smack_known_huh = {
26 .smk_next = &smack_known_unset, 19 .smk_next = NULL,
27 .smk_known = "?", 20 .smk_known = "?",
28 .smk_secid = 2, 21 .smk_secid = 2,
29 .smk_cipso = NULL, 22 .smk_cipso = NULL,
@@ -57,7 +50,14 @@ struct smack_known smack_known_invalid = {
57 .smk_cipso = NULL, 50 .smk_cipso = NULL,
58}; 51};
59 52
60struct smack_known *smack_known = &smack_known_invalid; 53struct smack_known smack_known_web = {
54 .smk_next = &smack_known_invalid,
55 .smk_known = "@",
56 .smk_secid = 7,
57 .smk_cipso = NULL,
58};
59
60struct smack_known *smack_known = &smack_known_web;
61 61
62/* 62/*
63 * The initial value needs to be bigger than any of the 63 * The initial value needs to be bigger than any of the
@@ -99,6 +99,16 @@ int smk_access(char *subject_label, char *object_label, int request)
99 strcmp(subject_label, smack_known_star.smk_known) == 0) 99 strcmp(subject_label, smack_known_star.smk_known) == 0)
100 return -EACCES; 100 return -EACCES;
101 /* 101 /*
102 * An internet object can be accessed by any subject.
103 * Tasks cannot be assigned the internet label.
104 * An internet subject can access any object.
105 */
106 if (object_label == smack_known_web.smk_known ||
107 subject_label == smack_known_web.smk_known ||
108 strcmp(object_label, smack_known_web.smk_known) == 0 ||
109 strcmp(subject_label, smack_known_web.smk_known) == 0)
110 return 0;
111 /*
102 * A star object can be accessed by any subject. 112 * A star object can be accessed by any subject.
103 */ 113 */
104 if (object_label == smack_known_star.smk_known || 114 if (object_label == smack_known_star.smk_known ||
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index 848212fd484..0278bc08304 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -1277,6 +1277,7 @@ static int smack_sk_alloc_security(struct sock *sk, int family, gfp_t gfp_flags)
1277 1277
1278 ssp->smk_in = csp; 1278 ssp->smk_in = csp;
1279 ssp->smk_out = csp; 1279 ssp->smk_out = csp;
1280 ssp->smk_labeled = SMACK_CIPSO_SOCKET;
1280 ssp->smk_packet[0] = '\0'; 1281 ssp->smk_packet[0] = '\0';
1281 1282
1282 sk->sk_security = ssp; 1283 sk->sk_security = ssp;
@@ -1341,45 +1342,69 @@ static void smack_to_secattr(char *smack, struct netlbl_lsm_secattr *nlsp)
1341 struct smack_cipso cipso; 1342 struct smack_cipso cipso;
1342 int rc; 1343 int rc;
1343 1344
1344 switch (smack_net_nltype) { 1345 nlsp->domain = smack;
1345 case NETLBL_NLTYPE_CIPSOV4: 1346 nlsp->flags = NETLBL_SECATTR_DOMAIN | NETLBL_SECATTR_MLS_LVL;
1346 nlsp->domain = smack;
1347 nlsp->flags = NETLBL_SECATTR_DOMAIN | NETLBL_SECATTR_MLS_LVL;
1348 1347
1349 rc = smack_to_cipso(smack, &cipso); 1348 rc = smack_to_cipso(smack, &cipso);
1350 if (rc == 0) { 1349 if (rc == 0) {
1351 nlsp->attr.mls.lvl = cipso.smk_level; 1350 nlsp->attr.mls.lvl = cipso.smk_level;
1352 smack_set_catset(cipso.smk_catset, nlsp); 1351 smack_set_catset(cipso.smk_catset, nlsp);
1353 } else { 1352 } else {
1354 nlsp->attr.mls.lvl = smack_cipso_direct; 1353 nlsp->attr.mls.lvl = smack_cipso_direct;
1355 smack_set_catset(smack, nlsp); 1354 smack_set_catset(smack, nlsp);
1356 }
1357 break;
1358 default:
1359 break;
1360 } 1355 }
1361} 1356}
1362 1357
1363/** 1358/**
1364 * smack_netlabel - Set the secattr on a socket 1359 * smack_netlabel - Set the secattr on a socket
1365 * @sk: the socket 1360 * @sk: the socket
1361 * @labeled: socket label scheme
1366 * 1362 *
1367 * Convert the outbound smack value (smk_out) to a 1363 * Convert the outbound smack value (smk_out) to a
1368 * secattr and attach it to the socket. 1364 * secattr and attach it to the socket.
1369 * 1365 *
1370 * Returns 0 on success or an error code 1366 * Returns 0 on success or an error code
1371 */ 1367 */
1372static int smack_netlabel(struct sock *sk) 1368static int smack_netlabel(struct sock *sk, int labeled)
1373{ 1369{
1374 struct socket_smack *ssp; 1370 struct socket_smack *ssp;
1375 struct netlbl_lsm_secattr secattr; 1371 struct netlbl_lsm_secattr secattr;
1376 int rc; 1372 int rc = 0;
1377 1373
1378 ssp = sk->sk_security; 1374 ssp = sk->sk_security;
1379 netlbl_secattr_init(&secattr); 1375 /*
1380 smack_to_secattr(ssp->smk_out, &secattr); 1376 * Usually the netlabel code will handle changing the
1381 rc = netlbl_sock_setattr(sk, &secattr); 1377 * packet labeling based on the label.
1382 netlbl_secattr_destroy(&secattr); 1378 * The case of a single label host is different, because
1379 * a single label host should never get a labeled packet
1380 * even though the label is usually associated with a packet
1381 * label.
1382 */
1383 local_bh_disable();
1384 bh_lock_sock_nested(sk);
1385
1386 if (ssp->smk_out == smack_net_ambient ||
1387 labeled == SMACK_UNLABELED_SOCKET)
1388 netlbl_sock_delattr(sk);
1389 else {
1390 netlbl_secattr_init(&secattr);
1391 smack_to_secattr(ssp->smk_out, &secattr);
1392 rc = netlbl_sock_setattr(sk, &secattr);
1393 netlbl_secattr_destroy(&secattr);
1394 }
1395
1396 bh_unlock_sock(sk);
1397 local_bh_enable();
1398 /*
1399 * Remember the label scheme used so that it is not
1400 * necessary to do the netlabel setting if it has not
1401 * changed the next time through.
1402 *
1403 * The -EDESTADDRREQ case is an indication that there's
1404 * a single level host involved.
1405 */
1406 if (rc == 0)
1407 ssp->smk_labeled = labeled;
1383 1408
1384 return rc; 1409 return rc;
1385} 1410}
@@ -1432,7 +1457,7 @@ static int smack_inode_setsecurity(struct inode *inode, const char *name,
1432 ssp->smk_in = sp; 1457 ssp->smk_in = sp;
1433 else if (strcmp(name, XATTR_SMACK_IPOUT) == 0) { 1458 else if (strcmp(name, XATTR_SMACK_IPOUT) == 0) {
1434 ssp->smk_out = sp; 1459 ssp->smk_out = sp;
1435 rc = smack_netlabel(sock->sk); 1460 rc = smack_netlabel(sock->sk, SMACK_CIPSO_SOCKET);
1436 if (rc != 0) 1461 if (rc != 0)
1437 printk(KERN_WARNING "Smack: \"%s\" netlbl error %d.\n", 1462 printk(KERN_WARNING "Smack: \"%s\" netlbl error %d.\n",
1438 __func__, -rc); 1463 __func__, -rc);
@@ -1462,7 +1487,108 @@ static int smack_socket_post_create(struct socket *sock, int family,
1462 /* 1487 /*
1463 * Set the outbound netlbl. 1488 * Set the outbound netlbl.
1464 */ 1489 */
1465 return smack_netlabel(sock->sk); 1490 return smack_netlabel(sock->sk, SMACK_CIPSO_SOCKET);
1491}
1492
1493
1494/**
1495 * smack_host_label - check host based restrictions
1496 * @sip: the object end
1497 *
1498 * looks for host based access restrictions
1499 *
1500 * This version will only be appropriate for really small
1501 * sets of single label hosts. Because of the masking
1502 * it cannot shortcut out on the first match. There are
1503 * numerious ways to address the problem, but none of them
1504 * have been applied here.
1505 *
1506 * Returns the label of the far end or NULL if it's not special.
1507 */
1508static char *smack_host_label(struct sockaddr_in *sip)
1509{
1510 struct smk_netlbladdr *snp;
1511 char *bestlabel = NULL;
1512 struct in_addr *siap = &sip->sin_addr;
1513 struct in_addr *liap;
1514 struct in_addr *miap;
1515 struct in_addr bestmask;
1516
1517 if (siap->s_addr == 0)
1518 return NULL;
1519
1520 bestmask.s_addr = 0;
1521
1522 for (snp = smack_netlbladdrs; snp != NULL; snp = snp->smk_next) {
1523 liap = &snp->smk_host.sin_addr;
1524 miap = &snp->smk_mask;
1525 /*
1526 * If the addresses match after applying the list entry mask
1527 * the entry matches the address. If it doesn't move along to
1528 * the next entry.
1529 */
1530 if ((liap->s_addr & miap->s_addr) !=
1531 (siap->s_addr & miap->s_addr))
1532 continue;
1533 /*
1534 * If the list entry mask identifies a single address
1535 * it can't get any more specific.
1536 */
1537 if (miap->s_addr == 0xffffffff)
1538 return snp->smk_label;
1539 /*
1540 * If the list entry mask is less specific than the best
1541 * already found this entry is uninteresting.
1542 */
1543 if ((miap->s_addr | bestmask.s_addr) == bestmask.s_addr)
1544 continue;
1545 /*
1546 * This is better than any entry found so far.
1547 */
1548 bestmask.s_addr = miap->s_addr;
1549 bestlabel = snp->smk_label;
1550 }
1551
1552 return bestlabel;
1553}
1554
1555/**
1556 * smack_socket_connect - connect access check
1557 * @sock: the socket
1558 * @sap: the other end
1559 * @addrlen: size of sap
1560 *
1561 * Verifies that a connection may be possible
1562 *
1563 * Returns 0 on success, and error code otherwise
1564 */
1565static int smack_socket_connect(struct socket *sock, struct sockaddr *sap,
1566 int addrlen)
1567{
1568 struct socket_smack *ssp = sock->sk->sk_security;
1569 char *hostsp;
1570 int rc;
1571
1572 if (sock->sk == NULL || sock->sk->sk_family != PF_INET)
1573 return 0;
1574
1575 if (addrlen < sizeof(struct sockaddr_in))
1576 return -EINVAL;
1577
1578 hostsp = smack_host_label((struct sockaddr_in *)sap);
1579 if (hostsp == NULL) {
1580 if (ssp->smk_labeled != SMACK_CIPSO_SOCKET)
1581 return smack_netlabel(sock->sk, SMACK_CIPSO_SOCKET);
1582 return 0;
1583 }
1584
1585 rc = smk_access(ssp->smk_out, hostsp, MAY_WRITE);
1586 if (rc != 0)
1587 return rc;
1588
1589 if (ssp->smk_labeled != SMACK_UNLABELED_SOCKET)
1590 return smack_netlabel(sock->sk, SMACK_UNLABELED_SOCKET);
1591 return 0;
1466} 1592}
1467 1593
1468/** 1594/**
@@ -2101,8 +2227,14 @@ static int smack_setprocattr(struct task_struct *p, char *name,
2101 if (newsmack == NULL) 2227 if (newsmack == NULL)
2102 return -EINVAL; 2228 return -EINVAL;
2103 2229
2230 /*
2231 * No process is ever allowed the web ("@") label.
2232 */
2233 if (newsmack == smack_known_web.smk_known)
2234 return -EPERM;
2235
2104 new = prepare_creds(); 2236 new = prepare_creds();
2105 if (!new) 2237 if (new == NULL)
2106 return -ENOMEM; 2238 return -ENOMEM;
2107 new->security = newsmack; 2239 new->security = newsmack;
2108 commit_creds(new); 2240 commit_creds(new);
@@ -2144,6 +2276,49 @@ static int smack_unix_may_send(struct socket *sock, struct socket *other)
2144} 2276}
2145 2277
2146/** 2278/**
2279 * smack_socket_sendmsg - Smack check based on destination host
2280 * @sock: the socket
2281 * @msghdr: the message
2282 * @size: the size of the message
2283 *
2284 * Return 0 if the current subject can write to the destination
2285 * host. This is only a question if the destination is a single
2286 * label host.
2287 */
2288static int smack_socket_sendmsg(struct socket *sock, struct msghdr *msg,
2289 int size)
2290{
2291 struct sockaddr_in *sip = (struct sockaddr_in *) msg->msg_name;
2292 struct socket_smack *ssp = sock->sk->sk_security;
2293 char *hostsp;
2294 int rc;
2295
2296 /*
2297 * Perfectly reasonable for this to be NULL
2298 */
2299 if (sip == NULL || sip->sin_family != PF_INET)
2300 return 0;
2301
2302 hostsp = smack_host_label(sip);
2303 if (hostsp == NULL) {
2304 if (ssp->smk_labeled != SMACK_CIPSO_SOCKET)
2305 return smack_netlabel(sock->sk, SMACK_CIPSO_SOCKET);
2306 return 0;
2307 }
2308
2309 rc = smk_access(ssp->smk_out, hostsp, MAY_WRITE);
2310 if (rc != 0)
2311 return rc;
2312
2313 if (ssp->smk_labeled != SMACK_UNLABELED_SOCKET)
2314 return smack_netlabel(sock->sk, SMACK_UNLABELED_SOCKET);
2315
2316 return 0;
2317
2318}
2319
2320
2321/**
2147 * smack_from_secattr - Convert a netlabel attr.mls.lvl/attr.mls.cat 2322 * smack_from_secattr - Convert a netlabel attr.mls.lvl/attr.mls.cat
2148 * pair to smack 2323 * pair to smack
2149 * @sap: netlabel secattr 2324 * @sap: netlabel secattr
@@ -2154,44 +2329,66 @@ static int smack_unix_may_send(struct socket *sock, struct socket *other)
2154static void smack_from_secattr(struct netlbl_lsm_secattr *sap, char *sip) 2329static void smack_from_secattr(struct netlbl_lsm_secattr *sap, char *sip)
2155{ 2330{
2156 char smack[SMK_LABELLEN]; 2331 char smack[SMK_LABELLEN];
2332 char *sp;
2157 int pcat; 2333 int pcat;
2158 2334
2159 if ((sap->flags & NETLBL_SECATTR_MLS_LVL) == 0) { 2335 if ((sap->flags & NETLBL_SECATTR_MLS_LVL) != 0) {
2160 /* 2336 /*
2337 * Looks like a CIPSO packet.
2161 * If there are flags but no level netlabel isn't 2338 * If there are flags but no level netlabel isn't
2162 * behaving the way we expect it to. 2339 * behaving the way we expect it to.
2163 * 2340 *
2341 * Get the categories, if any
2164 * Without guidance regarding the smack value 2342 * Without guidance regarding the smack value
2165 * for the packet fall back on the network 2343 * for the packet fall back on the network
2166 * ambient value. 2344 * ambient value.
2167 */ 2345 */
2168 strncpy(sip, smack_net_ambient, SMK_MAXLEN); 2346 memset(smack, '\0', SMK_LABELLEN);
2347 if ((sap->flags & NETLBL_SECATTR_MLS_CAT) != 0)
2348 for (pcat = -1;;) {
2349 pcat = netlbl_secattr_catmap_walk(
2350 sap->attr.mls.cat, pcat + 1);
2351 if (pcat < 0)
2352 break;
2353 smack_catset_bit(pcat, smack);
2354 }
2355 /*
2356 * If it is CIPSO using smack direct mapping
2357 * we are already done. WeeHee.
2358 */
2359 if (sap->attr.mls.lvl == smack_cipso_direct) {
2360 memcpy(sip, smack, SMK_MAXLEN);
2361 return;
2362 }
2363 /*
2364 * Look it up in the supplied table if it is not
2365 * a direct mapping.
2366 */
2367 smack_from_cipso(sap->attr.mls.lvl, smack, sip);
2169 return; 2368 return;
2170 } 2369 }
2171 /* 2370 if ((sap->flags & NETLBL_SECATTR_SECID) != 0) {
2172 * Get the categories, if any 2371 /*
2173 */ 2372 * Looks like a fallback, which gives us a secid.
2174 memset(smack, '\0', SMK_LABELLEN); 2373 */
2175 if ((sap->flags & NETLBL_SECATTR_MLS_CAT) != 0) 2374 sp = smack_from_secid(sap->attr.secid);
2176 for (pcat = -1;;) { 2375 /*
2177 pcat = netlbl_secattr_catmap_walk(sap->attr.mls.cat, 2376 * This has got to be a bug because it is
2178 pcat + 1); 2377 * impossible to specify a fallback without
2179 if (pcat < 0) 2378 * specifying the label, which will ensure
2180 break; 2379 * it has a secid, and the only way to get a
2181 smack_catset_bit(pcat, smack); 2380 * secid is from a fallback.
2182 } 2381 */
2183 /* 2382 BUG_ON(sp == NULL);
2184 * If it is CIPSO using smack direct mapping 2383 strncpy(sip, sp, SMK_MAXLEN);
2185 * we are already done. WeeHee.
2186 */
2187 if (sap->attr.mls.lvl == smack_cipso_direct) {
2188 memcpy(sip, smack, SMK_MAXLEN);
2189 return; 2384 return;
2190 } 2385 }
2191 /* 2386 /*
2192 * Look it up in the supplied table if it is not a direct mapping. 2387 * Without guidance regarding the smack value
2388 * for the packet fall back on the network
2389 * ambient value.
2193 */ 2390 */
2194 smack_from_cipso(sap->attr.mls.lvl, smack, sip); 2391 strncpy(sip, smack_net_ambient, SMK_MAXLEN);
2195 return; 2392 return;
2196} 2393}
2197 2394
@@ -2207,6 +2404,7 @@ static int smack_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
2207 struct netlbl_lsm_secattr secattr; 2404 struct netlbl_lsm_secattr secattr;
2208 struct socket_smack *ssp = sk->sk_security; 2405 struct socket_smack *ssp = sk->sk_security;
2209 char smack[SMK_LABELLEN]; 2406 char smack[SMK_LABELLEN];
2407 char *csp;
2210 int rc; 2408 int rc;
2211 2409
2212 if (sk->sk_family != PF_INET && sk->sk_family != PF_INET6) 2410 if (sk->sk_family != PF_INET && sk->sk_family != PF_INET6)
@@ -2215,21 +2413,24 @@ static int smack_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
2215 /* 2413 /*
2216 * Translate what netlabel gave us. 2414 * Translate what netlabel gave us.
2217 */ 2415 */
2218 memset(smack, '\0', SMK_LABELLEN);
2219 netlbl_secattr_init(&secattr); 2416 netlbl_secattr_init(&secattr);
2417
2220 rc = netlbl_skbuff_getattr(skb, sk->sk_family, &secattr); 2418 rc = netlbl_skbuff_getattr(skb, sk->sk_family, &secattr);
2221 if (rc == 0) 2419 if (rc == 0) {
2222 smack_from_secattr(&secattr, smack); 2420 smack_from_secattr(&secattr, smack);
2223 else 2421 csp = smack;
2224 strncpy(smack, smack_net_ambient, SMK_MAXLEN); 2422 } else
2423 csp = smack_net_ambient;
2424
2225 netlbl_secattr_destroy(&secattr); 2425 netlbl_secattr_destroy(&secattr);
2426
2226 /* 2427 /*
2227 * Receiving a packet requires that the other end 2428 * Receiving a packet requires that the other end
2228 * be able to write here. Read access is not required. 2429 * be able to write here. Read access is not required.
2229 * This is the simplist possible security model 2430 * This is the simplist possible security model
2230 * for networking. 2431 * for networking.
2231 */ 2432 */
2232 rc = smk_access(smack, ssp->smk_in, MAY_WRITE); 2433 rc = smk_access(csp, ssp->smk_in, MAY_WRITE);
2233 if (rc != 0) 2434 if (rc != 0)
2234 netlbl_skbuff_err(skb, rc, 0); 2435 netlbl_skbuff_err(skb, rc, 0);
2235 return rc; 2436 return rc;
@@ -2298,7 +2499,6 @@ static int smack_socket_getpeersec_dgram(struct socket *sock,
2298 /* 2499 /*
2299 * Translate what netlabel gave us. 2500 * Translate what netlabel gave us.
2300 */ 2501 */
2301 memset(smack, '\0', SMK_LABELLEN);
2302 netlbl_secattr_init(&secattr); 2502 netlbl_secattr_init(&secattr);
2303 rc = netlbl_skbuff_getattr(skb, family, &secattr); 2503 rc = netlbl_skbuff_getattr(skb, family, &secattr);
2304 if (rc == 0) 2504 if (rc == 0)
@@ -2341,7 +2541,7 @@ static void smack_sock_graft(struct sock *sk, struct socket *parent)
2341 ssp->smk_in = ssp->smk_out = current_security(); 2541 ssp->smk_in = ssp->smk_out = current_security();
2342 ssp->smk_packet[0] = '\0'; 2542 ssp->smk_packet[0] = '\0';
2343 2543
2344 rc = smack_netlabel(sk); 2544 rc = smack_netlabel(sk, SMACK_CIPSO_SOCKET);
2345 if (rc != 0) 2545 if (rc != 0)
2346 printk(KERN_WARNING "Smack: \"%s\" netlbl error %d.\n", 2546 printk(KERN_WARNING "Smack: \"%s\" netlbl error %d.\n",
2347 __func__, -rc); 2547 __func__, -rc);
@@ -2367,7 +2567,6 @@ static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb,
2367 if (skb == NULL) 2567 if (skb == NULL)
2368 return -EACCES; 2568 return -EACCES;
2369 2569
2370 memset(smack, '\0', SMK_LABELLEN);
2371 netlbl_secattr_init(&skb_secattr); 2570 netlbl_secattr_init(&skb_secattr);
2372 rc = netlbl_skbuff_getattr(skb, sk->sk_family, &skb_secattr); 2571 rc = netlbl_skbuff_getattr(skb, sk->sk_family, &skb_secattr);
2373 if (rc == 0) 2572 if (rc == 0)
@@ -2732,6 +2931,8 @@ struct security_operations smack_ops = {
2732 .unix_may_send = smack_unix_may_send, 2931 .unix_may_send = smack_unix_may_send,
2733 2932
2734 .socket_post_create = smack_socket_post_create, 2933 .socket_post_create = smack_socket_post_create,
2934 .socket_connect = smack_socket_connect,
2935 .socket_sendmsg = smack_socket_sendmsg,
2735 .socket_sock_rcv_skb = smack_socket_sock_rcv_skb, 2936 .socket_sock_rcv_skb = smack_socket_sock_rcv_skb,
2736 .socket_getpeersec_stream = smack_socket_getpeersec_stream, 2937 .socket_getpeersec_stream = smack_socket_getpeersec_stream,
2737 .socket_getpeersec_dgram = smack_socket_getpeersec_dgram, 2938 .socket_getpeersec_dgram = smack_socket_getpeersec_dgram,
@@ -2783,7 +2984,6 @@ static __init int smack_init(void)
2783 /* 2984 /*
2784 * Initialize locks 2985 * Initialize locks
2785 */ 2986 */
2786 spin_lock_init(&smack_known_unset.smk_cipsolock);
2787 spin_lock_init(&smack_known_huh.smk_cipsolock); 2987 spin_lock_init(&smack_known_huh.smk_cipsolock);
2788 spin_lock_init(&smack_known_hat.smk_cipsolock); 2988 spin_lock_init(&smack_known_hat.smk_cipsolock);
2789 spin_lock_init(&smack_known_star.smk_cipsolock); 2989 spin_lock_init(&smack_known_star.smk_cipsolock);
diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c
index 247dc9ebbc7..bf107a389ac 100644
--- a/security/smack/smackfs.c
+++ b/security/smack/smackfs.c
@@ -20,6 +20,7 @@
20#include <linux/vmalloc.h> 20#include <linux/vmalloc.h>
21#include <linux/security.h> 21#include <linux/security.h>
22#include <linux/mutex.h> 22#include <linux/mutex.h>
23#include <net/net_namespace.h>
23#include <net/netlabel.h> 24#include <net/netlabel.h>
24#include <net/cipso_ipv4.h> 25#include <net/cipso_ipv4.h>
25#include <linux/seq_file.h> 26#include <linux/seq_file.h>
@@ -38,7 +39,7 @@ enum smk_inos {
38 SMK_DOI = 5, /* CIPSO DOI */ 39 SMK_DOI = 5, /* CIPSO DOI */
39 SMK_DIRECT = 6, /* CIPSO level indicating direct label */ 40 SMK_DIRECT = 6, /* CIPSO level indicating direct label */
40 SMK_AMBIENT = 7, /* internet ambient label */ 41 SMK_AMBIENT = 7, /* internet ambient label */
41 SMK_NLTYPE = 8, /* label scheme to use by default */ 42 SMK_NETLBLADDR = 8, /* single label hosts */
42 SMK_ONLYCAP = 9, /* the only "capable" label */ 43 SMK_ONLYCAP = 9, /* the only "capable" label */
43}; 44};
44 45
@@ -48,6 +49,7 @@ enum smk_inos {
48static DEFINE_MUTEX(smack_list_lock); 49static DEFINE_MUTEX(smack_list_lock);
49static DEFINE_MUTEX(smack_cipso_lock); 50static DEFINE_MUTEX(smack_cipso_lock);
50static DEFINE_MUTEX(smack_ambient_lock); 51static DEFINE_MUTEX(smack_ambient_lock);
52static DEFINE_MUTEX(smk_netlbladdr_lock);
51 53
52/* 54/*
53 * This is the "ambient" label for network traffic. 55 * This is the "ambient" label for network traffic.
@@ -57,12 +59,6 @@ static DEFINE_MUTEX(smack_ambient_lock);
57char *smack_net_ambient = smack_known_floor.smk_known; 59char *smack_net_ambient = smack_known_floor.smk_known;
58 60
59/* 61/*
60 * This is the default packet marking scheme for network traffic.
61 * It can be reset via smackfs/nltype
62 */
63int smack_net_nltype = NETLBL_NLTYPE_CIPSOV4;
64
65/*
66 * This is the level in a CIPSO header that indicates a 62 * This is the level in a CIPSO header that indicates a
67 * smack label is contained directly in the category set. 63 * smack label is contained directly in the category set.
68 * It can be reset via smackfs/direct 64 * It can be reset via smackfs/direct
@@ -79,6 +75,13 @@ int smack_cipso_direct = SMACK_CIPSO_DIRECT_DEFAULT;
79 */ 75 */
80char *smack_onlycap; 76char *smack_onlycap;
81 77
78/*
79 * Certain IP addresses may be designated as single label hosts.
80 * Packets are sent there unlabeled, but only from tasks that
81 * can write to the specified label.
82 */
83struct smk_netlbladdr *smack_netlbladdrs;
84
82static int smk_cipso_doi_value = SMACK_CIPSO_DOI_DEFAULT; 85static int smk_cipso_doi_value = SMACK_CIPSO_DOI_DEFAULT;
83struct smk_list_entry *smack_list; 86struct smk_list_entry *smack_list;
84 87
@@ -104,6 +107,24 @@ struct smk_list_entry *smack_list;
104#define SMK_ACCESSLEN (sizeof(SMK_ACCESS) - 1) 107#define SMK_ACCESSLEN (sizeof(SMK_ACCESS) - 1)
105#define SMK_LOADLEN (SMK_LABELLEN + SMK_LABELLEN + SMK_ACCESSLEN) 108#define SMK_LOADLEN (SMK_LABELLEN + SMK_LABELLEN + SMK_ACCESSLEN)
106 109
110/**
111 * smk_netlabel_audit_set - fill a netlbl_audit struct
112 * @nap: structure to fill
113 */
114static void smk_netlabel_audit_set(struct netlbl_audit *nap)
115{
116 nap->loginuid = audit_get_loginuid(current);
117 nap->sessionid = audit_get_sessionid(current);
118 nap->secid = smack_to_secid(current_security());
119}
120
121/*
122 * Values for parsing single label host rules
123 * "1.2.3.4 X"
124 * "192.168.138.129/32 abcdefghijklmnopqrstuvw"
125 */
126#define SMK_NETLBLADDRMIN 9
127#define SMK_NETLBLADDRMAX 42
107 128
108/* 129/*
109 * Seq_file read operations for /smack/load 130 * Seq_file read operations for /smack/load
@@ -344,13 +365,11 @@ static void smk_cipso_doi(void)
344{ 365{
345 int rc; 366 int rc;
346 struct cipso_v4_doi *doip; 367 struct cipso_v4_doi *doip;
347 struct netlbl_audit audit_info; 368 struct netlbl_audit nai;
348 369
349 audit_info.loginuid = audit_get_loginuid(current); 370 smk_netlabel_audit_set(&nai);
350 audit_info.sessionid = audit_get_sessionid(current);
351 audit_info.secid = smack_to_secid(current_security());
352 371
353 rc = netlbl_cfg_map_del(NULL, &audit_info); 372 rc = netlbl_cfg_map_del(NULL, PF_INET, NULL, NULL, &nai);
354 if (rc != 0) 373 if (rc != 0)
355 printk(KERN_WARNING "%s:%d remove rc = %d\n", 374 printk(KERN_WARNING "%s:%d remove rc = %d\n",
356 __func__, __LINE__, rc); 375 __func__, __LINE__, rc);
@@ -365,11 +384,19 @@ static void smk_cipso_doi(void)
365 for (rc = 1; rc < CIPSO_V4_TAG_MAXCNT; rc++) 384 for (rc = 1; rc < CIPSO_V4_TAG_MAXCNT; rc++)
366 doip->tags[rc] = CIPSO_V4_TAG_INVALID; 385 doip->tags[rc] = CIPSO_V4_TAG_INVALID;
367 386
368 rc = netlbl_cfg_cipsov4_add_map(doip, NULL, &audit_info); 387 rc = netlbl_cfg_cipsov4_add(doip, &nai);
369 if (rc != 0) { 388 if (rc != 0) {
370 printk(KERN_WARNING "%s:%d add rc = %d\n", 389 printk(KERN_WARNING "%s:%d cipso add rc = %d\n",
371 __func__, __LINE__, rc); 390 __func__, __LINE__, rc);
372 kfree(doip); 391 kfree(doip);
392 return;
393 }
394 rc = netlbl_cfg_cipsov4_map_add(doip->doi, NULL, NULL, NULL, &nai);
395 if (rc != 0) {
396 printk(KERN_WARNING "%s:%d map add rc = %d\n",
397 __func__, __LINE__, rc);
398 kfree(doip);
399 return;
373 } 400 }
374} 401}
375 402
@@ -379,20 +406,19 @@ static void smk_cipso_doi(void)
379static void smk_unlbl_ambient(char *oldambient) 406static void smk_unlbl_ambient(char *oldambient)
380{ 407{
381 int rc; 408 int rc;
382 struct netlbl_audit audit_info; 409 struct netlbl_audit nai;
383 410
384 audit_info.loginuid = audit_get_loginuid(current); 411 smk_netlabel_audit_set(&nai);
385 audit_info.sessionid = audit_get_sessionid(current);
386 audit_info.secid = smack_to_secid(current_security());
387 412
388 if (oldambient != NULL) { 413 if (oldambient != NULL) {
389 rc = netlbl_cfg_map_del(oldambient, &audit_info); 414 rc = netlbl_cfg_map_del(oldambient, PF_INET, NULL, NULL, &nai);
390 if (rc != 0) 415 if (rc != 0)
391 printk(KERN_WARNING "%s:%d remove rc = %d\n", 416 printk(KERN_WARNING "%s:%d remove rc = %d\n",
392 __func__, __LINE__, rc); 417 __func__, __LINE__, rc);
393 } 418 }
394 419
395 rc = netlbl_cfg_unlbl_add_map(smack_net_ambient, &audit_info); 420 rc = netlbl_cfg_unlbl_map_add(smack_net_ambient, PF_INET,
421 NULL, NULL, &nai);
396 if (rc != 0) 422 if (rc != 0)
397 printk(KERN_WARNING "%s:%d add rc = %d\n", 423 printk(KERN_WARNING "%s:%d add rc = %d\n",
398 __func__, __LINE__, rc); 424 __func__, __LINE__, rc);
@@ -603,6 +629,201 @@ static const struct file_operations smk_cipso_ops = {
603 .release = seq_release, 629 .release = seq_release,
604}; 630};
605 631
632/*
633 * Seq_file read operations for /smack/netlabel
634 */
635
636static void *netlbladdr_seq_start(struct seq_file *s, loff_t *pos)
637{
638 if (*pos == SEQ_READ_FINISHED)
639 return NULL;
640
641 return smack_netlbladdrs;
642}
643
644static void *netlbladdr_seq_next(struct seq_file *s, void *v, loff_t *pos)
645{
646 struct smk_netlbladdr *skp = ((struct smk_netlbladdr *) v)->smk_next;
647
648 if (skp == NULL)
649 *pos = SEQ_READ_FINISHED;
650
651 return skp;
652}
653/*
654#define BEMASK 0x80000000
655*/
656#define BEMASK 0x00000001
657#define BEBITS (sizeof(__be32) * 8)
658
659/*
660 * Print host/label pairs
661 */
662static int netlbladdr_seq_show(struct seq_file *s, void *v)
663{
664 struct smk_netlbladdr *skp = (struct smk_netlbladdr *) v;
665 unsigned char *hp = (char *) &skp->smk_host.sin_addr.s_addr;
666 __be32 bebits;
667 int maskn = 0;
668
669 for (bebits = BEMASK; bebits != 0; maskn++, bebits <<= 1)
670 if ((skp->smk_mask.s_addr & bebits) == 0)
671 break;
672
673 seq_printf(s, "%u.%u.%u.%u/%d %s\n",
674 hp[0], hp[1], hp[2], hp[3], maskn, skp->smk_label);
675
676 return 0;
677}
678
679static void netlbladdr_seq_stop(struct seq_file *s, void *v)
680{
681 /* No-op */
682}
683
684static struct seq_operations netlbladdr_seq_ops = {
685 .start = netlbladdr_seq_start,
686 .stop = netlbladdr_seq_stop,
687 .next = netlbladdr_seq_next,
688 .show = netlbladdr_seq_show,
689};
690
691/**
692 * smk_open_netlbladdr - open() for /smack/netlabel
693 * @inode: inode structure representing file
694 * @file: "netlabel" file pointer
695 *
696 * Connect our netlbladdr_seq_* operations with /smack/netlabel
697 * file_operations
698 */
699static int smk_open_netlbladdr(struct inode *inode, struct file *file)
700{
701 return seq_open(file, &netlbladdr_seq_ops);
702}
703
704/**
705 * smk_write_netlbladdr - write() for /smack/netlabel
706 * @filp: file pointer, not actually used
707 * @buf: where to get the data from
708 * @count: bytes sent
709 * @ppos: where to start
710 *
711 * Accepts only one netlbladdr per write call.
712 * Returns number of bytes written or error code, as appropriate
713 */
714static ssize_t smk_write_netlbladdr(struct file *file, const char __user *buf,
715 size_t count, loff_t *ppos)
716{
717 struct smk_netlbladdr *skp;
718 struct sockaddr_in newname;
719 char smack[SMK_LABELLEN];
720 char *sp;
721 char data[SMK_NETLBLADDRMAX];
722 char *host = (char *)&newname.sin_addr.s_addr;
723 int rc;
724 struct netlbl_audit audit_info;
725 struct in_addr mask;
726 unsigned int m;
727 __be32 bebits = BEMASK;
728 __be32 nsa;
729
730 /*
731 * Must have privilege.
732 * No partial writes.
733 * Enough data must be present.
734 * "<addr/mask, as a.b.c.d/e><space><label>"
735 * "<addr, as a.b.c.d><space><label>"
736 */
737 if (!capable(CAP_MAC_ADMIN))
738 return -EPERM;
739 if (*ppos != 0)
740 return -EINVAL;
741 if (count < SMK_NETLBLADDRMIN || count > SMK_NETLBLADDRMAX)
742 return -EINVAL;
743 if (copy_from_user(data, buf, count) != 0)
744 return -EFAULT;
745
746 data[count] = '\0';
747
748 rc = sscanf(data, "%hhd.%hhd.%hhd.%hhd/%d %s",
749 &host[0], &host[1], &host[2], &host[3], &m, smack);
750 if (rc != 6) {
751 rc = sscanf(data, "%hhd.%hhd.%hhd.%hhd %s",
752 &host[0], &host[1], &host[2], &host[3], smack);
753 if (rc != 5)
754 return -EINVAL;
755 m = BEBITS;
756 }
757 if (m > BEBITS)
758 return -EINVAL;
759
760 sp = smk_import(smack, 0);
761 if (sp == NULL)
762 return -EINVAL;
763
764 for (mask.s_addr = 0; m > 0; m--) {
765 mask.s_addr |= bebits;
766 bebits <<= 1;
767 }
768 /*
769 * Only allow one writer at a time. Writes should be
770 * quite rare and small in any case.
771 */
772 mutex_lock(&smk_netlbladdr_lock);
773
774 nsa = newname.sin_addr.s_addr;
775 for (skp = smack_netlbladdrs; skp != NULL; skp = skp->smk_next)
776 if (skp->smk_host.sin_addr.s_addr == nsa &&
777 skp->smk_mask.s_addr == mask.s_addr)
778 break;
779
780 smk_netlabel_audit_set(&audit_info);
781
782 if (skp == NULL) {
783 skp = kzalloc(sizeof(*skp), GFP_KERNEL);
784 if (skp == NULL)
785 rc = -ENOMEM;
786 else {
787 rc = 0;
788 skp->smk_host.sin_addr.s_addr = newname.sin_addr.s_addr;
789 skp->smk_mask.s_addr = mask.s_addr;
790 skp->smk_next = smack_netlbladdrs;
791 skp->smk_label = sp;
792 smack_netlbladdrs = skp;
793 }
794 } else {
795 rc = netlbl_cfg_unlbl_static_del(&init_net, NULL,
796 &skp->smk_host.sin_addr, &skp->smk_mask,
797 PF_INET, &audit_info);
798 skp->smk_label = sp;
799 }
800
801 /*
802 * Now tell netlabel about the single label nature of
803 * this host so that incoming packets get labeled.
804 */
805
806 if (rc == 0)
807 rc = netlbl_cfg_unlbl_static_add(&init_net, NULL,
808 &skp->smk_host.sin_addr, &skp->smk_mask, PF_INET,
809 smack_to_secid(skp->smk_label), &audit_info);
810
811 if (rc == 0)
812 rc = count;
813
814 mutex_unlock(&smk_netlbladdr_lock);
815
816 return rc;
817}
818
819static const struct file_operations smk_netlbladdr_ops = {
820 .open = smk_open_netlbladdr,
821 .read = seq_read,
822 .llseek = seq_lseek,
823 .write = smk_write_netlbladdr,
824 .release = seq_release,
825};
826
606/** 827/**
607 * smk_read_doi - read() for /smack/doi 828 * smk_read_doi - read() for /smack/doi
608 * @filp: file pointer, not actually used 829 * @filp: file pointer, not actually used
@@ -891,110 +1112,6 @@ static const struct file_operations smk_onlycap_ops = {
891 .write = smk_write_onlycap, 1112 .write = smk_write_onlycap,
892}; 1113};
893 1114
894struct option_names {
895 int o_number;
896 char *o_name;
897 char *o_alias;
898};
899
900static struct option_names netlbl_choices[] = {
901 { NETLBL_NLTYPE_RIPSO,
902 NETLBL_NLTYPE_RIPSO_NAME, "ripso" },
903 { NETLBL_NLTYPE_CIPSOV4,
904 NETLBL_NLTYPE_CIPSOV4_NAME, "cipsov4" },
905 { NETLBL_NLTYPE_CIPSOV4,
906 NETLBL_NLTYPE_CIPSOV4_NAME, "cipso" },
907 { NETLBL_NLTYPE_CIPSOV6,
908 NETLBL_NLTYPE_CIPSOV6_NAME, "cipsov6" },
909 { NETLBL_NLTYPE_UNLABELED,
910 NETLBL_NLTYPE_UNLABELED_NAME, "unlabeled" },
911};
912
913/**
914 * smk_read_nltype - read() for /smack/nltype
915 * @filp: file pointer, not actually used
916 * @buf: where to put the result
917 * @count: maximum to send along
918 * @ppos: where to start
919 *
920 * Returns number of bytes read or error code, as appropriate
921 */
922static ssize_t smk_read_nltype(struct file *filp, char __user *buf,
923 size_t count, loff_t *ppos)
924{
925 char bound[40];
926 ssize_t rc;
927 int i;
928
929 if (count < SMK_LABELLEN)
930 return -EINVAL;
931
932 if (*ppos != 0)
933 return 0;
934
935 sprintf(bound, "unknown");
936
937 for (i = 0; i < ARRAY_SIZE(netlbl_choices); i++)
938 if (smack_net_nltype == netlbl_choices[i].o_number) {
939 sprintf(bound, "%s", netlbl_choices[i].o_name);
940 break;
941 }
942
943 rc = simple_read_from_buffer(buf, count, ppos, bound, strlen(bound));
944
945 return rc;
946}
947
948/**
949 * smk_write_nltype - write() for /smack/nltype
950 * @filp: file pointer, not actually used
951 * @buf: where to get the data from
952 * @count: bytes sent
953 * @ppos: where to start
954 *
955 * Returns number of bytes written or error code, as appropriate
956 */
957static ssize_t smk_write_nltype(struct file *file, const char __user *buf,
958 size_t count, loff_t *ppos)
959{
960 char bound[40];
961 char *cp;
962 int i;
963
964 if (!capable(CAP_MAC_ADMIN))
965 return -EPERM;
966
967 if (count >= 40)
968 return -EINVAL;
969
970 if (copy_from_user(bound, buf, count) != 0)
971 return -EFAULT;
972
973 bound[count] = '\0';
974 cp = strchr(bound, ' ');
975 if (cp != NULL)
976 *cp = '\0';
977 cp = strchr(bound, '\n');
978 if (cp != NULL)
979 *cp = '\0';
980
981 for (i = 0; i < ARRAY_SIZE(netlbl_choices); i++)
982 if (strcmp(bound, netlbl_choices[i].o_name) == 0 ||
983 strcmp(bound, netlbl_choices[i].o_alias) == 0) {
984 smack_net_nltype = netlbl_choices[i].o_number;
985 return count;
986 }
987 /*
988 * Not a valid choice.
989 */
990 return -EINVAL;
991}
992
993static const struct file_operations smk_nltype_ops = {
994 .read = smk_read_nltype,
995 .write = smk_write_nltype,
996};
997
998/** 1115/**
999 * smk_fill_super - fill the /smackfs superblock 1116 * smk_fill_super - fill the /smackfs superblock
1000 * @sb: the empty superblock 1117 * @sb: the empty superblock
@@ -1021,8 +1138,8 @@ static int smk_fill_super(struct super_block *sb, void *data, int silent)
1021 {"direct", &smk_direct_ops, S_IRUGO|S_IWUSR}, 1138 {"direct", &smk_direct_ops, S_IRUGO|S_IWUSR},
1022 [SMK_AMBIENT] = 1139 [SMK_AMBIENT] =
1023 {"ambient", &smk_ambient_ops, S_IRUGO|S_IWUSR}, 1140 {"ambient", &smk_ambient_ops, S_IRUGO|S_IWUSR},
1024 [SMK_NLTYPE] = 1141 [SMK_NETLBLADDR] =
1025 {"nltype", &smk_nltype_ops, S_IRUGO|S_IWUSR}, 1142 {"netlabel", &smk_netlbladdr_ops, S_IRUGO|S_IWUSR},
1026 [SMK_ONLYCAP] = 1143 [SMK_ONLYCAP] =
1027 {"onlycap", &smk_onlycap_ops, S_IRUGO|S_IWUSR}, 1144 {"onlycap", &smk_onlycap_ops, S_IRUGO|S_IWUSR},
1028 /* last one */ {""} 1145 /* last one */ {""}