aboutsummaryrefslogtreecommitdiffstats
path: root/security/selinux
diff options
context:
space:
mode:
Diffstat (limited to 'security/selinux')
-rw-r--r--security/selinux/Kconfig3
-rw-r--r--security/selinux/avc.c2
-rw-r--r--security/selinux/hooks.c305
-rw-r--r--security/selinux/include/avc.h4
-rw-r--r--security/selinux/include/netlabel.h44
-rw-r--r--security/selinux/include/objsec.h9
-rw-r--r--security/selinux/include/security.h15
-rw-r--r--security/selinux/netlabel.c280
-rw-r--r--security/selinux/ss/avtab.c8
-rw-r--r--security/selinux/ss/conditional.c18
-rw-r--r--security/selinux/ss/conditional.h2
-rw-r--r--security/selinux/ss/ebitmap.c4
-rw-r--r--security/selinux/ss/hashtab.c6
-rw-r--r--security/selinux/ss/mls.c14
-rw-r--r--security/selinux/ss/policydb.c225
-rw-r--r--security/selinux/ss/policydb.h5
-rw-r--r--security/selinux/ss/services.c210
-rw-r--r--security/selinux/ss/sidtab.c12
18 files changed, 946 insertions, 220 deletions
diff --git a/security/selinux/Kconfig b/security/selinux/Kconfig
index a436d1cfa88b..26301dd651d3 100644
--- a/security/selinux/Kconfig
+++ b/security/selinux/Kconfig
@@ -6,9 +6,6 @@ config SECURITY_SELINUX
6 help 6 help
7 This selects NSA Security-Enhanced Linux (SELinux). 7 This selects NSA Security-Enhanced Linux (SELinux).
8 You will also need a policy configuration and a labeled filesystem. 8 You will also need a policy configuration and a labeled filesystem.
9 You can obtain the policy compiler (checkpolicy), the utility for
10 labeling filesystems (setfiles), and an example policy configuration
11 from <http://www.nsa.gov/selinux/>.
12 If you are unsure how to answer this question, answer N. 9 If you are unsure how to answer this question, answer N.
13 10
14config SECURITY_SELINUX_BOOTPARAM 11config SECURITY_SELINUX_BOOTPARAM
diff --git a/security/selinux/avc.c b/security/selinux/avc.c
index 114b4b4c97b2..cb30c7e350b3 100644
--- a/security/selinux/avc.c
+++ b/security/selinux/avc.c
@@ -136,7 +136,7 @@ static inline int avc_hash(u32 ssid, u32 tsid, u16 tclass)
136 * @tclass: target security class 136 * @tclass: target security class
137 * @av: access vector 137 * @av: access vector
138 */ 138 */
139static void avc_dump_av(struct audit_buffer *ab, u16 tclass, u32 av) 139void avc_dump_av(struct audit_buffer *ab, u16 tclass, u32 av)
140{ 140{
141 const char **common_pts = NULL; 141 const char **common_pts = NULL;
142 u32 common_base = 0; 142 u32 common_base = 0;
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 03fc6a81ae32..3e3fde7c1d2b 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -75,6 +75,7 @@
75#include <linux/string.h> 75#include <linux/string.h>
76#include <linux/selinux.h> 76#include <linux/selinux.h>
77#include <linux/mutex.h> 77#include <linux/mutex.h>
78#include <linux/posix-timers.h>
78 79
79#include "avc.h" 80#include "avc.h"
80#include "objsec.h" 81#include "objsec.h"
@@ -291,6 +292,7 @@ static void sk_free_security(struct sock *sk)
291 struct sk_security_struct *ssec = sk->sk_security; 292 struct sk_security_struct *ssec = sk->sk_security;
292 293
293 sk->sk_security = NULL; 294 sk->sk_security = NULL;
295 selinux_netlbl_sk_security_free(ssec);
294 kfree(ssec); 296 kfree(ssec);
295} 297}
296 298
@@ -324,7 +326,7 @@ enum {
324 Opt_rootcontext = 4, 326 Opt_rootcontext = 4,
325}; 327};
326 328
327static match_table_t tokens = { 329static const match_table_t tokens = {
328 {Opt_context, CONTEXT_STR "%s"}, 330 {Opt_context, CONTEXT_STR "%s"},
329 {Opt_fscontext, FSCONTEXT_STR "%s"}, 331 {Opt_fscontext, FSCONTEXT_STR "%s"},
330 {Opt_defcontext, DEFCONTEXT_STR "%s"}, 332 {Opt_defcontext, DEFCONTEXT_STR "%s"},
@@ -957,7 +959,8 @@ out_err:
957 return rc; 959 return rc;
958} 960}
959 961
960void selinux_write_opts(struct seq_file *m, struct security_mnt_opts *opts) 962static void selinux_write_opts(struct seq_file *m,
963 struct security_mnt_opts *opts)
961{ 964{
962 int i; 965 int i;
963 char *prefix; 966 char *prefix;
@@ -1290,7 +1293,7 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent
1290 /* Default to the fs superblock SID. */ 1293 /* Default to the fs superblock SID. */
1291 isec->sid = sbsec->sid; 1294 isec->sid = sbsec->sid;
1292 1295
1293 if (sbsec->proc) { 1296 if (sbsec->proc && !S_ISLNK(inode->i_mode)) {
1294 struct proc_inode *proci = PROC_I(inode); 1297 struct proc_inode *proci = PROC_I(inode);
1295 if (proci->pde) { 1298 if (proci->pde) {
1296 isec->sclass = inode_mode_to_security_class(inode->i_mode); 1299 isec->sclass = inode_mode_to_security_class(inode->i_mode);
@@ -2120,7 +2123,6 @@ static inline void flush_unauthorized_files(struct files_struct *files)
2120 long j = -1; 2123 long j = -1;
2121 int drop_tty = 0; 2124 int drop_tty = 0;
2122 2125
2123 mutex_lock(&tty_mutex);
2124 tty = get_current_tty(); 2126 tty = get_current_tty();
2125 if (tty) { 2127 if (tty) {
2126 file_list_lock(); 2128 file_list_lock();
@@ -2138,8 +2140,8 @@ static inline void flush_unauthorized_files(struct files_struct *files)
2138 } 2140 }
2139 } 2141 }
2140 file_list_unlock(); 2142 file_list_unlock();
2143 tty_kref_put(tty);
2141 } 2144 }
2142 mutex_unlock(&tty_mutex);
2143 /* Reset controlling tty. */ 2145 /* Reset controlling tty. */
2144 if (drop_tty) 2146 if (drop_tty)
2145 no_tty(); 2147 no_tty();
@@ -2321,13 +2323,7 @@ static void selinux_bprm_post_apply_creds(struct linux_binprm *bprm)
2321 initrlim = init_task.signal->rlim+i; 2323 initrlim = init_task.signal->rlim+i;
2322 rlim->rlim_cur = min(rlim->rlim_max, initrlim->rlim_cur); 2324 rlim->rlim_cur = min(rlim->rlim_max, initrlim->rlim_cur);
2323 } 2325 }
2324 if (current->signal->rlim[RLIMIT_CPU].rlim_cur != RLIM_INFINITY) { 2326 update_rlimit_cpu(rlim->rlim_cur);
2325 /*
2326 * This will cause RLIMIT_CPU calculations
2327 * to be refigured.
2328 */
2329 current->it_prof_expires = jiffies_to_cputime(1);
2330 }
2331 } 2327 }
2332 2328
2333 /* Wake up the parent if it is waiting so that it can 2329 /* Wake up the parent if it is waiting so that it can
@@ -3548,38 +3544,44 @@ out:
3548#endif /* IPV6 */ 3544#endif /* IPV6 */
3549 3545
3550static int selinux_parse_skb(struct sk_buff *skb, struct avc_audit_data *ad, 3546static int selinux_parse_skb(struct sk_buff *skb, struct avc_audit_data *ad,
3551 char **addrp, int src, u8 *proto) 3547 char **_addrp, int src, u8 *proto)
3552{ 3548{
3553 int ret = 0; 3549 char *addrp;
3550 int ret;
3554 3551
3555 switch (ad->u.net.family) { 3552 switch (ad->u.net.family) {
3556 case PF_INET: 3553 case PF_INET:
3557 ret = selinux_parse_skb_ipv4(skb, ad, proto); 3554 ret = selinux_parse_skb_ipv4(skb, ad, proto);
3558 if (ret || !addrp) 3555 if (ret)
3559 break; 3556 goto parse_error;
3560 *addrp = (char *)(src ? &ad->u.net.v4info.saddr : 3557 addrp = (char *)(src ? &ad->u.net.v4info.saddr :
3561 &ad->u.net.v4info.daddr); 3558 &ad->u.net.v4info.daddr);
3562 break; 3559 goto okay;
3563 3560
3564#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) 3561#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
3565 case PF_INET6: 3562 case PF_INET6:
3566 ret = selinux_parse_skb_ipv6(skb, ad, proto); 3563 ret = selinux_parse_skb_ipv6(skb, ad, proto);
3567 if (ret || !addrp) 3564 if (ret)
3568 break; 3565 goto parse_error;
3569 *addrp = (char *)(src ? &ad->u.net.v6info.saddr : 3566 addrp = (char *)(src ? &ad->u.net.v6info.saddr :
3570 &ad->u.net.v6info.daddr); 3567 &ad->u.net.v6info.daddr);
3571 break; 3568 goto okay;
3572#endif /* IPV6 */ 3569#endif /* IPV6 */
3573 default: 3570 default:
3574 break; 3571 addrp = NULL;
3572 goto okay;
3575 } 3573 }
3576 3574
3577 if (unlikely(ret)) 3575parse_error:
3578 printk(KERN_WARNING 3576 printk(KERN_WARNING
3579 "SELinux: failure in selinux_parse_skb()," 3577 "SELinux: failure in selinux_parse_skb(),"
3580 " unable to parse packet\n"); 3578 " unable to parse packet\n");
3581
3582 return ret; 3579 return ret;
3580
3581okay:
3582 if (_addrp)
3583 *_addrp = addrp;
3584 return 0;
3583} 3585}
3584 3586
3585/** 3587/**
@@ -3794,6 +3796,7 @@ out:
3794 3796
3795static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, int addrlen) 3797static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, int addrlen)
3796{ 3798{
3799 struct sock *sk = sock->sk;
3797 struct inode_security_struct *isec; 3800 struct inode_security_struct *isec;
3798 int err; 3801 int err;
3799 3802
@@ -3807,7 +3810,6 @@ static int selinux_socket_connect(struct socket *sock, struct sockaddr *address,
3807 isec = SOCK_INODE(sock)->i_security; 3810 isec = SOCK_INODE(sock)->i_security;
3808 if (isec->sclass == SECCLASS_TCP_SOCKET || 3811 if (isec->sclass == SECCLASS_TCP_SOCKET ||
3809 isec->sclass == SECCLASS_DCCP_SOCKET) { 3812 isec->sclass == SECCLASS_DCCP_SOCKET) {
3810 struct sock *sk = sock->sk;
3811 struct avc_audit_data ad; 3813 struct avc_audit_data ad;
3812 struct sockaddr_in *addr4 = NULL; 3814 struct sockaddr_in *addr4 = NULL;
3813 struct sockaddr_in6 *addr6 = NULL; 3815 struct sockaddr_in6 *addr6 = NULL;
@@ -3841,6 +3843,8 @@ static int selinux_socket_connect(struct socket *sock, struct sockaddr *address,
3841 goto out; 3843 goto out;
3842 } 3844 }
3843 3845
3846 err = selinux_netlbl_socket_connect(sk, address);
3847
3844out: 3848out:
3845 return err; 3849 return err;
3846} 3850}
@@ -4070,20 +4074,28 @@ static int selinux_sock_rcv_skb_iptables_compat(struct sock *sk,
4070} 4074}
4071 4075
4072static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb, 4076static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb,
4073 struct avc_audit_data *ad, 4077 u16 family)
4074 u16 family, char *addrp)
4075{ 4078{
4076 int err; 4079 int err;
4077 struct sk_security_struct *sksec = sk->sk_security; 4080 struct sk_security_struct *sksec = sk->sk_security;
4078 u32 peer_sid; 4081 u32 peer_sid;
4079 u32 sk_sid = sksec->sid; 4082 u32 sk_sid = sksec->sid;
4083 struct avc_audit_data ad;
4084 char *addrp;
4085
4086 AVC_AUDIT_DATA_INIT(&ad, NET);
4087 ad.u.net.netif = skb->iif;
4088 ad.u.net.family = family;
4089 err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL);
4090 if (err)
4091 return err;
4080 4092
4081 if (selinux_compat_net) 4093 if (selinux_compat_net)
4082 err = selinux_sock_rcv_skb_iptables_compat(sk, skb, ad, 4094 err = selinux_sock_rcv_skb_iptables_compat(sk, skb, &ad,
4083 family, addrp); 4095 family, addrp);
4084 else 4096 else
4085 err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET, 4097 err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET,
4086 PACKET__RECV, ad); 4098 PACKET__RECV, &ad);
4087 if (err) 4099 if (err)
4088 return err; 4100 return err;
4089 4101
@@ -4092,12 +4104,14 @@ static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb,
4092 if (err) 4104 if (err)
4093 return err; 4105 return err;
4094 err = avc_has_perm(sk_sid, peer_sid, 4106 err = avc_has_perm(sk_sid, peer_sid,
4095 SECCLASS_PEER, PEER__RECV, ad); 4107 SECCLASS_PEER, PEER__RECV, &ad);
4108 if (err)
4109 selinux_netlbl_err(skb, err, 0);
4096 } else { 4110 } else {
4097 err = selinux_netlbl_sock_rcv_skb(sksec, skb, family, ad); 4111 err = selinux_netlbl_sock_rcv_skb(sksec, skb, family, &ad);
4098 if (err) 4112 if (err)
4099 return err; 4113 return err;
4100 err = selinux_xfrm_sock_rcv_skb(sksec->sid, skb, ad); 4114 err = selinux_xfrm_sock_rcv_skb(sksec->sid, skb, &ad);
4101 } 4115 }
4102 4116
4103 return err; 4117 return err;
@@ -4111,6 +4125,8 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
4111 u32 sk_sid = sksec->sid; 4125 u32 sk_sid = sksec->sid;
4112 struct avc_audit_data ad; 4126 struct avc_audit_data ad;
4113 char *addrp; 4127 char *addrp;
4128 u8 secmark_active;
4129 u8 peerlbl_active;
4114 4130
4115 if (family != PF_INET && family != PF_INET6) 4131 if (family != PF_INET && family != PF_INET6)
4116 return 0; 4132 return 0;
@@ -4119,6 +4135,18 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
4119 if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP)) 4135 if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
4120 family = PF_INET; 4136 family = PF_INET;
4121 4137
4138 /* If any sort of compatibility mode is enabled then handoff processing
4139 * to the selinux_sock_rcv_skb_compat() function to deal with the
4140 * special handling. We do this in an attempt to keep this function
4141 * as fast and as clean as possible. */
4142 if (selinux_compat_net || !selinux_policycap_netpeer)
4143 return selinux_sock_rcv_skb_compat(sk, skb, family);
4144
4145 secmark_active = selinux_secmark_enabled();
4146 peerlbl_active = netlbl_enabled() || selinux_xfrm_enabled();
4147 if (!secmark_active && !peerlbl_active)
4148 return 0;
4149
4122 AVC_AUDIT_DATA_INIT(&ad, NET); 4150 AVC_AUDIT_DATA_INIT(&ad, NET);
4123 ad.u.net.netif = skb->iif; 4151 ad.u.net.netif = skb->iif;
4124 ad.u.net.family = family; 4152 ad.u.net.family = family;
@@ -4126,15 +4154,7 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
4126 if (err) 4154 if (err)
4127 return err; 4155 return err;
4128 4156
4129 /* If any sort of compatibility mode is enabled then handoff processing 4157 if (peerlbl_active) {
4130 * to the selinux_sock_rcv_skb_compat() function to deal with the
4131 * special handling. We do this in an attempt to keep this function
4132 * as fast and as clean as possible. */
4133 if (selinux_compat_net || !selinux_policycap_netpeer)
4134 return selinux_sock_rcv_skb_compat(sk, skb, &ad,
4135 family, addrp);
4136
4137 if (netlbl_enabled() || selinux_xfrm_enabled()) {
4138 u32 peer_sid; 4158 u32 peer_sid;
4139 4159
4140 err = selinux_skb_peerlbl_sid(skb, family, &peer_sid); 4160 err = selinux_skb_peerlbl_sid(skb, family, &peer_sid);
@@ -4142,13 +4162,17 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
4142 return err; 4162 return err;
4143 err = selinux_inet_sys_rcv_skb(skb->iif, addrp, family, 4163 err = selinux_inet_sys_rcv_skb(skb->iif, addrp, family,
4144 peer_sid, &ad); 4164 peer_sid, &ad);
4145 if (err) 4165 if (err) {
4166 selinux_netlbl_err(skb, err, 0);
4146 return err; 4167 return err;
4168 }
4147 err = avc_has_perm(sk_sid, peer_sid, SECCLASS_PEER, 4169 err = avc_has_perm(sk_sid, peer_sid, SECCLASS_PEER,
4148 PEER__RECV, &ad); 4170 PEER__RECV, &ad);
4171 if (err)
4172 selinux_netlbl_err(skb, err, 0);
4149 } 4173 }
4150 4174
4151 if (selinux_secmark_enabled()) { 4175 if (secmark_active) {
4152 err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET, 4176 err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET,
4153 PACKET__RECV, &ad); 4177 PACKET__RECV, &ad);
4154 if (err) 4178 if (err)
@@ -4207,10 +4231,12 @@ static int selinux_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *
4207 u32 peer_secid = SECSID_NULL; 4231 u32 peer_secid = SECSID_NULL;
4208 u16 family; 4232 u16 family;
4209 4233
4210 if (sock) 4234 if (skb && skb->protocol == htons(ETH_P_IP))
4235 family = PF_INET;
4236 else if (skb && skb->protocol == htons(ETH_P_IPV6))
4237 family = PF_INET6;
4238 else if (sock)
4211 family = sock->sk->sk_family; 4239 family = sock->sk->sk_family;
4212 else if (skb && skb->sk)
4213 family = skb->sk->sk_family;
4214 else 4240 else
4215 goto out; 4241 goto out;
4216 4242
@@ -4268,8 +4294,6 @@ static void selinux_sock_graft(struct sock *sk, struct socket *parent)
4268 sk->sk_family == PF_UNIX) 4294 sk->sk_family == PF_UNIX)
4269 isec->sid = sksec->sid; 4295 isec->sid = sksec->sid;
4270 sksec->sclass = isec->sclass; 4296 sksec->sclass = isec->sclass;
4271
4272 selinux_netlbl_sock_graft(sk, parent);
4273} 4297}
4274 4298
4275static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb, 4299static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb,
@@ -4277,10 +4301,15 @@ static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb,
4277{ 4301{
4278 struct sk_security_struct *sksec = sk->sk_security; 4302 struct sk_security_struct *sksec = sk->sk_security;
4279 int err; 4303 int err;
4304 u16 family = sk->sk_family;
4280 u32 newsid; 4305 u32 newsid;
4281 u32 peersid; 4306 u32 peersid;
4282 4307
4283 err = selinux_skb_peerlbl_sid(skb, sk->sk_family, &peersid); 4308 /* handle mapped IPv4 packets arriving via IPv6 sockets */
4309 if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
4310 family = PF_INET;
4311
4312 err = selinux_skb_peerlbl_sid(skb, family, &peersid);
4284 if (err) 4313 if (err)
4285 return err; 4314 return err;
4286 if (peersid == SECSID_NULL) { 4315 if (peersid == SECSID_NULL) {
@@ -4315,12 +4344,18 @@ static void selinux_inet_csk_clone(struct sock *newsk,
4315 selinux_netlbl_sk_security_reset(newsksec, req->rsk_ops->family); 4344 selinux_netlbl_sk_security_reset(newsksec, req->rsk_ops->family);
4316} 4345}
4317 4346
4318static void selinux_inet_conn_established(struct sock *sk, 4347static void selinux_inet_conn_established(struct sock *sk, struct sk_buff *skb)
4319 struct sk_buff *skb)
4320{ 4348{
4349 u16 family = sk->sk_family;
4321 struct sk_security_struct *sksec = sk->sk_security; 4350 struct sk_security_struct *sksec = sk->sk_security;
4322 4351
4323 selinux_skb_peerlbl_sid(skb, sk->sk_family, &sksec->peer_sid); 4352 /* handle mapped IPv4 packets arriving via IPv6 sockets */
4353 if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
4354 family = PF_INET;
4355
4356 selinux_skb_peerlbl_sid(skb, family, &sksec->peer_sid);
4357
4358 selinux_netlbl_inet_conn_established(sk, family);
4324} 4359}
4325 4360
4326static void selinux_req_classify_flow(const struct request_sock *req, 4361static void selinux_req_classify_flow(const struct request_sock *req,
@@ -4370,39 +4405,54 @@ out:
4370static unsigned int selinux_ip_forward(struct sk_buff *skb, int ifindex, 4405static unsigned int selinux_ip_forward(struct sk_buff *skb, int ifindex,
4371 u16 family) 4406 u16 family)
4372{ 4407{
4408 int err;
4373 char *addrp; 4409 char *addrp;
4374 u32 peer_sid; 4410 u32 peer_sid;
4375 struct avc_audit_data ad; 4411 struct avc_audit_data ad;
4376 u8 secmark_active; 4412 u8 secmark_active;
4413 u8 netlbl_active;
4377 u8 peerlbl_active; 4414 u8 peerlbl_active;
4378 4415
4379 if (!selinux_policycap_netpeer) 4416 if (!selinux_policycap_netpeer)
4380 return NF_ACCEPT; 4417 return NF_ACCEPT;
4381 4418
4382 secmark_active = selinux_secmark_enabled(); 4419 secmark_active = selinux_secmark_enabled();
4383 peerlbl_active = netlbl_enabled() || selinux_xfrm_enabled(); 4420 netlbl_active = netlbl_enabled();
4421 peerlbl_active = netlbl_active || selinux_xfrm_enabled();
4384 if (!secmark_active && !peerlbl_active) 4422 if (!secmark_active && !peerlbl_active)
4385 return NF_ACCEPT; 4423 return NF_ACCEPT;
4386 4424
4425 if (selinux_skb_peerlbl_sid(skb, family, &peer_sid) != 0)
4426 return NF_DROP;
4427
4387 AVC_AUDIT_DATA_INIT(&ad, NET); 4428 AVC_AUDIT_DATA_INIT(&ad, NET);
4388 ad.u.net.netif = ifindex; 4429 ad.u.net.netif = ifindex;
4389 ad.u.net.family = family; 4430 ad.u.net.family = family;
4390 if (selinux_parse_skb(skb, &ad, &addrp, 1, NULL) != 0) 4431 if (selinux_parse_skb(skb, &ad, &addrp, 1, NULL) != 0)
4391 return NF_DROP; 4432 return NF_DROP;
4392 4433
4393 if (selinux_skb_peerlbl_sid(skb, family, &peer_sid) != 0) 4434 if (peerlbl_active) {
4394 return NF_DROP; 4435 err = selinux_inet_sys_rcv_skb(ifindex, addrp, family,
4395 4436 peer_sid, &ad);
4396 if (peerlbl_active) 4437 if (err) {
4397 if (selinux_inet_sys_rcv_skb(ifindex, addrp, family, 4438 selinux_netlbl_err(skb, err, 1);
4398 peer_sid, &ad) != 0)
4399 return NF_DROP; 4439 return NF_DROP;
4440 }
4441 }
4400 4442
4401 if (secmark_active) 4443 if (secmark_active)
4402 if (avc_has_perm(peer_sid, skb->secmark, 4444 if (avc_has_perm(peer_sid, skb->secmark,
4403 SECCLASS_PACKET, PACKET__FORWARD_IN, &ad)) 4445 SECCLASS_PACKET, PACKET__FORWARD_IN, &ad))
4404 return NF_DROP; 4446 return NF_DROP;
4405 4447
4448 if (netlbl_active)
4449 /* we do this in the FORWARD path and not the POST_ROUTING
4450 * path because we want to make sure we apply the necessary
4451 * labeling before IPsec is applied so we can leverage AH
4452 * protection */
4453 if (selinux_netlbl_skbuff_setsid(skb, family, peer_sid) != 0)
4454 return NF_DROP;
4455
4406 return NF_ACCEPT; 4456 return NF_ACCEPT;
4407} 4457}
4408 4458
@@ -4426,6 +4476,37 @@ static unsigned int selinux_ipv6_forward(unsigned int hooknum,
4426} 4476}
4427#endif /* IPV6 */ 4477#endif /* IPV6 */
4428 4478
4479static unsigned int selinux_ip_output(struct sk_buff *skb,
4480 u16 family)
4481{
4482 u32 sid;
4483
4484 if (!netlbl_enabled())
4485 return NF_ACCEPT;
4486
4487 /* we do this in the LOCAL_OUT path and not the POST_ROUTING path
4488 * because we want to make sure we apply the necessary labeling
4489 * before IPsec is applied so we can leverage AH protection */
4490 if (skb->sk) {
4491 struct sk_security_struct *sksec = skb->sk->sk_security;
4492 sid = sksec->sid;
4493 } else
4494 sid = SECINITSID_KERNEL;
4495 if (selinux_netlbl_skbuff_setsid(skb, family, sid) != 0)
4496 return NF_DROP;
4497
4498 return NF_ACCEPT;
4499}
4500
4501static unsigned int selinux_ipv4_output(unsigned int hooknum,
4502 struct sk_buff *skb,
4503 const struct net_device *in,
4504 const struct net_device *out,
4505 int (*okfn)(struct sk_buff *))
4506{
4507 return selinux_ip_output(skb, PF_INET);
4508}
4509
4429static int selinux_ip_postroute_iptables_compat(struct sock *sk, 4510static int selinux_ip_postroute_iptables_compat(struct sock *sk,
4430 int ifindex, 4511 int ifindex,
4431 struct avc_audit_data *ad, 4512 struct avc_audit_data *ad,
@@ -4493,30 +4574,36 @@ static int selinux_ip_postroute_iptables_compat(struct sock *sk,
4493 4574
4494static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb, 4575static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb,
4495 int ifindex, 4576 int ifindex,
4496 struct avc_audit_data *ad, 4577 u16 family)
4497 u16 family,
4498 char *addrp,
4499 u8 proto)
4500{ 4578{
4501 struct sock *sk = skb->sk; 4579 struct sock *sk = skb->sk;
4502 struct sk_security_struct *sksec; 4580 struct sk_security_struct *sksec;
4581 struct avc_audit_data ad;
4582 char *addrp;
4583 u8 proto;
4503 4584
4504 if (sk == NULL) 4585 if (sk == NULL)
4505 return NF_ACCEPT; 4586 return NF_ACCEPT;
4506 sksec = sk->sk_security; 4587 sksec = sk->sk_security;
4507 4588
4589 AVC_AUDIT_DATA_INIT(&ad, NET);
4590 ad.u.net.netif = ifindex;
4591 ad.u.net.family = family;
4592 if (selinux_parse_skb(skb, &ad, &addrp, 0, &proto))
4593 return NF_DROP;
4594
4508 if (selinux_compat_net) { 4595 if (selinux_compat_net) {
4509 if (selinux_ip_postroute_iptables_compat(skb->sk, ifindex, 4596 if (selinux_ip_postroute_iptables_compat(skb->sk, ifindex,
4510 ad, family, addrp)) 4597 &ad, family, addrp))
4511 return NF_DROP; 4598 return NF_DROP;
4512 } else { 4599 } else {
4513 if (avc_has_perm(sksec->sid, skb->secmark, 4600 if (avc_has_perm(sksec->sid, skb->secmark,
4514 SECCLASS_PACKET, PACKET__SEND, ad)) 4601 SECCLASS_PACKET, PACKET__SEND, &ad))
4515 return NF_DROP; 4602 return NF_DROP;
4516 } 4603 }
4517 4604
4518 if (selinux_policycap_netpeer) 4605 if (selinux_policycap_netpeer)
4519 if (selinux_xfrm_postroute_last(sksec->sid, skb, ad, proto)) 4606 if (selinux_xfrm_postroute_last(sksec->sid, skb, &ad, proto))
4520 return NF_DROP; 4607 return NF_DROP;
4521 4608
4522 return NF_ACCEPT; 4609 return NF_ACCEPT;
@@ -4530,23 +4617,15 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex,
4530 struct sock *sk; 4617 struct sock *sk;
4531 struct avc_audit_data ad; 4618 struct avc_audit_data ad;
4532 char *addrp; 4619 char *addrp;
4533 u8 proto;
4534 u8 secmark_active; 4620 u8 secmark_active;
4535 u8 peerlbl_active; 4621 u8 peerlbl_active;
4536 4622
4537 AVC_AUDIT_DATA_INIT(&ad, NET);
4538 ad.u.net.netif = ifindex;
4539 ad.u.net.family = family;
4540 if (selinux_parse_skb(skb, &ad, &addrp, 0, &proto))
4541 return NF_DROP;
4542
4543 /* If any sort of compatibility mode is enabled then handoff processing 4623 /* If any sort of compatibility mode is enabled then handoff processing
4544 * to the selinux_ip_postroute_compat() function to deal with the 4624 * to the selinux_ip_postroute_compat() function to deal with the
4545 * special handling. We do this in an attempt to keep this function 4625 * special handling. We do this in an attempt to keep this function
4546 * as fast and as clean as possible. */ 4626 * as fast and as clean as possible. */
4547 if (selinux_compat_net || !selinux_policycap_netpeer) 4627 if (selinux_compat_net || !selinux_policycap_netpeer)
4548 return selinux_ip_postroute_compat(skb, ifindex, &ad, 4628 return selinux_ip_postroute_compat(skb, ifindex, family);
4549 family, addrp, proto);
4550 4629
4551 /* If skb->dst->xfrm is non-NULL then the packet is undergoing an IPsec 4630 /* If skb->dst->xfrm is non-NULL then the packet is undergoing an IPsec
4552 * packet transformation so allow the packet to pass without any checks 4631 * packet transformation so allow the packet to pass without any checks
@@ -4562,21 +4641,45 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex,
4562 if (!secmark_active && !peerlbl_active) 4641 if (!secmark_active && !peerlbl_active)
4563 return NF_ACCEPT; 4642 return NF_ACCEPT;
4564 4643
4565 /* if the packet is locally generated (skb->sk != NULL) then use the 4644 /* if the packet is being forwarded then get the peer label from the
4566 * socket's label as the peer label, otherwise the packet is being 4645 * packet itself; otherwise check to see if it is from a local
4567 * forwarded through this system and we need to fetch the peer label 4646 * application or the kernel, if from an application get the peer label
4568 * directly from the packet */ 4647 * from the sending socket, otherwise use the kernel's sid */
4569 sk = skb->sk; 4648 sk = skb->sk;
4570 if (sk) { 4649 if (sk == NULL) {
4650 switch (family) {
4651 case PF_INET:
4652 if (IPCB(skb)->flags & IPSKB_FORWARDED)
4653 secmark_perm = PACKET__FORWARD_OUT;
4654 else
4655 secmark_perm = PACKET__SEND;
4656 break;
4657 case PF_INET6:
4658 if (IP6CB(skb)->flags & IP6SKB_FORWARDED)
4659 secmark_perm = PACKET__FORWARD_OUT;
4660 else
4661 secmark_perm = PACKET__SEND;
4662 break;
4663 default:
4664 return NF_DROP;
4665 }
4666 if (secmark_perm == PACKET__FORWARD_OUT) {
4667 if (selinux_skb_peerlbl_sid(skb, family, &peer_sid))
4668 return NF_DROP;
4669 } else
4670 peer_sid = SECINITSID_KERNEL;
4671 } else {
4571 struct sk_security_struct *sksec = sk->sk_security; 4672 struct sk_security_struct *sksec = sk->sk_security;
4572 peer_sid = sksec->sid; 4673 peer_sid = sksec->sid;
4573 secmark_perm = PACKET__SEND; 4674 secmark_perm = PACKET__SEND;
4574 } else {
4575 if (selinux_skb_peerlbl_sid(skb, family, &peer_sid))
4576 return NF_DROP;
4577 secmark_perm = PACKET__FORWARD_OUT;
4578 } 4675 }
4579 4676
4677 AVC_AUDIT_DATA_INIT(&ad, NET);
4678 ad.u.net.netif = ifindex;
4679 ad.u.net.family = family;
4680 if (selinux_parse_skb(skb, &ad, &addrp, 0, NULL))
4681 return NF_DROP;
4682
4580 if (secmark_active) 4683 if (secmark_active)
4581 if (avc_has_perm(peer_sid, skb->secmark, 4684 if (avc_has_perm(peer_sid, skb->secmark,
4582 SECCLASS_PACKET, secmark_perm, &ad)) 4685 SECCLASS_PACKET, secmark_perm, &ad))
@@ -5219,8 +5322,12 @@ static int selinux_setprocattr(struct task_struct *p,
5219 5322
5220 if (sid == 0) 5323 if (sid == 0)
5221 return -EINVAL; 5324 return -EINVAL;
5222 5325 /*
5223 /* Only allow single threaded processes to change context */ 5326 * SELinux allows to change context in the following case only.
5327 * - Single threaded processes.
5328 * - Multi threaded processes intend to change its context into
5329 * more restricted domain (defined by TYPEBOUNDS statement).
5330 */
5224 if (atomic_read(&p->mm->mm_users) != 1) { 5331 if (atomic_read(&p->mm->mm_users) != 1) {
5225 struct task_struct *g, *t; 5332 struct task_struct *g, *t;
5226 struct mm_struct *mm = p->mm; 5333 struct mm_struct *mm = p->mm;
@@ -5228,11 +5335,16 @@ static int selinux_setprocattr(struct task_struct *p,
5228 do_each_thread(g, t) { 5335 do_each_thread(g, t) {
5229 if (t->mm == mm && t != p) { 5336 if (t->mm == mm && t != p) {
5230 read_unlock(&tasklist_lock); 5337 read_unlock(&tasklist_lock);
5231 return -EPERM; 5338 error = security_bounded_transition(tsec->sid, sid);
5339 if (!error)
5340 goto boundary_ok;
5341
5342 return error;
5232 } 5343 }
5233 } while_each_thread(g, t); 5344 } while_each_thread(g, t);
5234 read_unlock(&tasklist_lock); 5345 read_unlock(&tasklist_lock);
5235 } 5346 }
5347boundary_ok:
5236 5348
5237 /* Check permissions for the transition. */ 5349 /* Check permissions for the transition. */
5238 error = avc_has_perm(tsec->sid, sid, SECCLASS_PROCESS, 5350 error = avc_has_perm(tsec->sid, sid, SECCLASS_PROCESS,
@@ -5641,6 +5753,13 @@ static struct nf_hook_ops selinux_ipv4_ops[] = {
5641 .pf = PF_INET, 5753 .pf = PF_INET,
5642 .hooknum = NF_INET_FORWARD, 5754 .hooknum = NF_INET_FORWARD,
5643 .priority = NF_IP_PRI_SELINUX_FIRST, 5755 .priority = NF_IP_PRI_SELINUX_FIRST,
5756 },
5757 {
5758 .hook = selinux_ipv4_output,
5759 .owner = THIS_MODULE,
5760 .pf = PF_INET,
5761 .hooknum = NF_INET_LOCAL_OUT,
5762 .priority = NF_IP_PRI_SELINUX_FIRST,
5644 } 5763 }
5645}; 5764};
5646 5765
diff --git a/security/selinux/include/avc.h b/security/selinux/include/avc.h
index 7b9769f5e775..d12ff1a9c0aa 100644
--- a/security/selinux/include/avc.h
+++ b/security/selinux/include/avc.h
@@ -12,6 +12,7 @@
12#include <linux/kdev_t.h> 12#include <linux/kdev_t.h>
13#include <linux/spinlock.h> 13#include <linux/spinlock.h>
14#include <linux/init.h> 14#include <linux/init.h>
15#include <linux/audit.h>
15#include <linux/in6.h> 16#include <linux/in6.h>
16#include <linux/path.h> 17#include <linux/path.h>
17#include <asm/system.h> 18#include <asm/system.h>
@@ -126,6 +127,9 @@ int avc_add_callback(int (*callback)(u32 event, u32 ssid, u32 tsid,
126 u32 events, u32 ssid, u32 tsid, 127 u32 events, u32 ssid, u32 tsid,
127 u16 tclass, u32 perms); 128 u16 tclass, u32 perms);
128 129
130/* Shows permission in human readable form */
131void avc_dump_av(struct audit_buffer *ab, u16 tclass, u32 av);
132
129/* Exported to selinuxfs */ 133/* Exported to selinuxfs */
130int avc_get_hash_stats(char *page); 134int avc_get_hash_stats(char *page);
131extern unsigned int avc_cache_threshold; 135extern unsigned int avc_cache_threshold;
diff --git a/security/selinux/include/netlabel.h b/security/selinux/include/netlabel.h
index 487a7d81fe20..b913c8d06038 100644
--- a/security/selinux/include/netlabel.h
+++ b/security/selinux/include/netlabel.h
@@ -39,6 +39,9 @@
39#ifdef CONFIG_NETLABEL 39#ifdef CONFIG_NETLABEL
40void selinux_netlbl_cache_invalidate(void); 40void selinux_netlbl_cache_invalidate(void);
41 41
42void selinux_netlbl_err(struct sk_buff *skb, int error, int gateway);
43
44void selinux_netlbl_sk_security_free(struct sk_security_struct *ssec);
42void selinux_netlbl_sk_security_reset(struct sk_security_struct *ssec, 45void selinux_netlbl_sk_security_reset(struct sk_security_struct *ssec,
43 int family); 46 int family);
44 47
@@ -46,8 +49,11 @@ int selinux_netlbl_skbuff_getsid(struct sk_buff *skb,
46 u16 family, 49 u16 family,
47 u32 *type, 50 u32 *type,
48 u32 *sid); 51 u32 *sid);
52int selinux_netlbl_skbuff_setsid(struct sk_buff *skb,
53 u16 family,
54 u32 sid);
49 55
50void selinux_netlbl_sock_graft(struct sock *sk, struct socket *sock); 56void selinux_netlbl_inet_conn_established(struct sock *sk, u16 family);
51int selinux_netlbl_socket_post_create(struct socket *sock); 57int selinux_netlbl_socket_post_create(struct socket *sock);
52int selinux_netlbl_inode_permission(struct inode *inode, int mask); 58int selinux_netlbl_inode_permission(struct inode *inode, int mask);
53int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec, 59int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec,
@@ -57,12 +63,27 @@ int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec,
57int selinux_netlbl_socket_setsockopt(struct socket *sock, 63int selinux_netlbl_socket_setsockopt(struct socket *sock,
58 int level, 64 int level,
59 int optname); 65 int optname);
66int selinux_netlbl_socket_connect(struct sock *sk, struct sockaddr *addr);
67
60#else 68#else
61static inline void selinux_netlbl_cache_invalidate(void) 69static inline void selinux_netlbl_cache_invalidate(void)
62{ 70{
63 return; 71 return;
64} 72}
65 73
74static inline void selinux_netlbl_err(struct sk_buff *skb,
75 int error,
76 int gateway)
77{
78 return;
79}
80
81static inline void selinux_netlbl_sk_security_free(
82 struct sk_security_struct *ssec)
83{
84 return;
85}
86
66static inline void selinux_netlbl_sk_security_reset( 87static inline void selinux_netlbl_sk_security_reset(
67 struct sk_security_struct *ssec, 88 struct sk_security_struct *ssec,
68 int family) 89 int family)
@@ -79,9 +100,21 @@ static inline int selinux_netlbl_skbuff_getsid(struct sk_buff *skb,
79 *sid = SECSID_NULL; 100 *sid = SECSID_NULL;
80 return 0; 101 return 0;
81} 102}
103static inline int selinux_netlbl_skbuff_setsid(struct sk_buff *skb,
104 u16 family,
105 u32 sid)
106{
107 return 0;
108}
82 109
83static inline void selinux_netlbl_sock_graft(struct sock *sk, 110static inline int selinux_netlbl_conn_setsid(struct sock *sk,
84 struct socket *sock) 111 struct sockaddr *addr)
112{
113 return 0;
114}
115
116static inline void selinux_netlbl_inet_conn_established(struct sock *sk,
117 u16 family)
85{ 118{
86 return; 119 return;
87} 120}
@@ -107,6 +140,11 @@ static inline int selinux_netlbl_socket_setsockopt(struct socket *sock,
107{ 140{
108 return 0; 141 return 0;
109} 142}
143static inline int selinux_netlbl_socket_connect(struct sock *sk,
144 struct sockaddr *addr)
145{
146 return 0;
147}
110#endif /* CONFIG_NETLABEL */ 148#endif /* CONFIG_NETLABEL */
111 149
112#endif 150#endif
diff --git a/security/selinux/include/objsec.h b/security/selinux/include/objsec.h
index 91070ab874ce..f8be8d7fa26d 100644
--- a/security/selinux/include/objsec.h
+++ b/security/selinux/include/objsec.h
@@ -109,16 +109,19 @@ struct netport_security_struct {
109}; 109};
110 110
111struct sk_security_struct { 111struct sk_security_struct {
112 u32 sid; /* SID of this object */
113 u32 peer_sid; /* SID of peer */
114 u16 sclass; /* sock security class */
115#ifdef CONFIG_NETLABEL 112#ifdef CONFIG_NETLABEL
116 enum { /* NetLabel state */ 113 enum { /* NetLabel state */
117 NLBL_UNSET = 0, 114 NLBL_UNSET = 0,
118 NLBL_REQUIRE, 115 NLBL_REQUIRE,
119 NLBL_LABELED, 116 NLBL_LABELED,
117 NLBL_REQSKB,
118 NLBL_CONNLABELED,
120 } nlbl_state; 119 } nlbl_state;
120 struct netlbl_lsm_secattr *nlbl_secattr; /* NetLabel sec attributes */
121#endif 121#endif
122 u32 sid; /* SID of this object */
123 u32 peer_sid; /* SID of peer */
124 u16 sclass; /* sock security class */
122}; 125};
123 126
124struct key_security_struct { 127struct key_security_struct {
diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h
index 7c543003d653..72447370bc95 100644
--- a/security/selinux/include/security.h
+++ b/security/selinux/include/security.h
@@ -27,13 +27,14 @@
27#define POLICYDB_VERSION_RANGETRANS 21 27#define POLICYDB_VERSION_RANGETRANS 21
28#define POLICYDB_VERSION_POLCAP 22 28#define POLICYDB_VERSION_POLCAP 22
29#define POLICYDB_VERSION_PERMISSIVE 23 29#define POLICYDB_VERSION_PERMISSIVE 23
30#define POLICYDB_VERSION_BOUNDARY 24
30 31
31/* Range of policy versions we understand*/ 32/* Range of policy versions we understand*/
32#define POLICYDB_VERSION_MIN POLICYDB_VERSION_BASE 33#define POLICYDB_VERSION_MIN POLICYDB_VERSION_BASE
33#ifdef CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX 34#ifdef CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX
34#define POLICYDB_VERSION_MAX CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX_VALUE 35#define POLICYDB_VERSION_MAX CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX_VALUE
35#else 36#else
36#define POLICYDB_VERSION_MAX POLICYDB_VERSION_PERMISSIVE 37#define POLICYDB_VERSION_MAX POLICYDB_VERSION_BOUNDARY
37#endif 38#endif
38 39
39#define CONTEXT_MNT 0x01 40#define CONTEXT_MNT 0x01
@@ -62,6 +63,16 @@ enum {
62extern int selinux_policycap_netpeer; 63extern int selinux_policycap_netpeer;
63extern int selinux_policycap_openperm; 64extern int selinux_policycap_openperm;
64 65
66/*
67 * type_datum properties
68 * available at the kernel policy version >= POLICYDB_VERSION_BOUNDARY
69 */
70#define TYPEDATUM_PROPERTY_PRIMARY 0x0001
71#define TYPEDATUM_PROPERTY_ATTRIBUTE 0x0002
72
73/* limitation of boundary depth */
74#define POLICYDB_BOUNDS_MAXDEPTH 4
75
65int security_load_policy(void *data, size_t len); 76int security_load_policy(void *data, size_t len);
66 77
67int security_policycap_supported(unsigned int req_cap); 78int security_policycap_supported(unsigned int req_cap);
@@ -117,6 +128,8 @@ int security_node_sid(u16 domain, void *addr, u32 addrlen,
117int security_validate_transition(u32 oldsid, u32 newsid, u32 tasksid, 128int security_validate_transition(u32 oldsid, u32 newsid, u32 tasksid,
118 u16 tclass); 129 u16 tclass);
119 130
131int security_bounded_transition(u32 oldsid, u32 newsid);
132
120int security_sid_mls_copy(u32 sid, u32 mls_sid, u32 *new_sid); 133int security_sid_mls_copy(u32 sid, u32 mls_sid, u32 *new_sid);
121 134
122int security_net_peersid_resolve(u32 nlbl_sid, u32 nlbl_type, 135int security_net_peersid_resolve(u32 nlbl_sid, u32 nlbl_type,
diff --git a/security/selinux/netlabel.c b/security/selinux/netlabel.c
index 89b418392f11..f58701a7b728 100644
--- a/security/selinux/netlabel.c
+++ b/security/selinux/netlabel.c
@@ -9,7 +9,7 @@
9 */ 9 */
10 10
11/* 11/*
12 * (c) Copyright Hewlett-Packard Development Company, L.P., 2007 12 * (c) Copyright Hewlett-Packard Development Company, L.P., 2007, 2008
13 * 13 *
14 * This program is free software; you can redistribute it and/or modify 14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by 15 * it under the terms of the GNU General Public License as published by
@@ -29,8 +29,12 @@
29 29
30#include <linux/spinlock.h> 30#include <linux/spinlock.h>
31#include <linux/rcupdate.h> 31#include <linux/rcupdate.h>
32#include <linux/ip.h>
33#include <linux/ipv6.h>
32#include <net/sock.h> 34#include <net/sock.h>
33#include <net/netlabel.h> 35#include <net/netlabel.h>
36#include <net/ip.h>
37#include <net/ipv6.h>
34 38
35#include "objsec.h" 39#include "objsec.h"
36#include "security.h" 40#include "security.h"
@@ -64,32 +68,69 @@ static int selinux_netlbl_sidlookup_cached(struct sk_buff *skb,
64} 68}
65 69
66/** 70/**
71 * selinux_netlbl_sock_genattr - Generate the NetLabel socket secattr
72 * @sk: the socket
73 *
74 * Description:
75 * Generate the NetLabel security attributes for a socket, making full use of
76 * the socket's attribute cache. Returns a pointer to the security attributes
77 * on success, NULL on failure.
78 *
79 */
80static struct netlbl_lsm_secattr *selinux_netlbl_sock_genattr(struct sock *sk)
81{
82 int rc;
83 struct sk_security_struct *sksec = sk->sk_security;
84 struct netlbl_lsm_secattr *secattr;
85
86 if (sksec->nlbl_secattr != NULL)
87 return sksec->nlbl_secattr;
88
89 secattr = netlbl_secattr_alloc(GFP_ATOMIC);
90 if (secattr == NULL)
91 return NULL;
92 rc = security_netlbl_sid_to_secattr(sksec->sid, secattr);
93 if (rc != 0) {
94 netlbl_secattr_free(secattr);
95 return NULL;
96 }
97 sksec->nlbl_secattr = secattr;
98
99 return secattr;
100}
101
102/**
67 * selinux_netlbl_sock_setsid - Label a socket using the NetLabel mechanism 103 * selinux_netlbl_sock_setsid - Label a socket using the NetLabel mechanism
68 * @sk: the socket to label 104 * @sk: the socket to label
69 * @sid: the SID to use
70 * 105 *
71 * Description: 106 * Description:
72 * Attempt to label a socket using the NetLabel mechanism using the given 107 * Attempt to label a socket using the NetLabel mechanism. Returns zero values
73 * SID. Returns zero values on success, negative values on failure. 108 * on success, negative values on failure.
74 * 109 *
75 */ 110 */
76static int selinux_netlbl_sock_setsid(struct sock *sk, u32 sid) 111static int selinux_netlbl_sock_setsid(struct sock *sk)
77{ 112{
78 int rc; 113 int rc;
79 struct sk_security_struct *sksec = sk->sk_security; 114 struct sk_security_struct *sksec = sk->sk_security;
80 struct netlbl_lsm_secattr secattr; 115 struct netlbl_lsm_secattr *secattr;
81 116
82 netlbl_secattr_init(&secattr); 117 if (sksec->nlbl_state != NLBL_REQUIRE)
118 return 0;
83 119
84 rc = security_netlbl_sid_to_secattr(sid, &secattr); 120 secattr = selinux_netlbl_sock_genattr(sk);
85 if (rc != 0) 121 if (secattr == NULL)
86 goto sock_setsid_return; 122 return -ENOMEM;
87 rc = netlbl_sock_setattr(sk, &secattr); 123 rc = netlbl_sock_setattr(sk, secattr);
88 if (rc == 0) 124 switch (rc) {
125 case 0:
89 sksec->nlbl_state = NLBL_LABELED; 126 sksec->nlbl_state = NLBL_LABELED;
127 break;
128 case -EDESTADDRREQ:
129 sksec->nlbl_state = NLBL_REQSKB;
130 rc = 0;
131 break;
132 }
90 133
91sock_setsid_return:
92 netlbl_secattr_destroy(&secattr);
93 return rc; 134 return rc;
94} 135}
95 136
@@ -106,6 +147,38 @@ void selinux_netlbl_cache_invalidate(void)
106} 147}
107 148
108/** 149/**
150 * selinux_netlbl_err - Handle a NetLabel packet error
151 * @skb: the packet
152 * @error: the error code
153 * @gateway: true if host is acting as a gateway, false otherwise
154 *
155 * Description:
156 * When a packet is dropped due to a call to avc_has_perm() pass the error
157 * code to the NetLabel subsystem so any protocol specific processing can be
158 * done. This is safe to call even if you are unsure if NetLabel labeling is
159 * present on the packet, NetLabel is smart enough to only act when it should.
160 *
161 */
162void selinux_netlbl_err(struct sk_buff *skb, int error, int gateway)
163{
164 netlbl_skbuff_err(skb, error, gateway);
165}
166
167/**
168 * selinux_netlbl_sk_security_free - Free the NetLabel fields
169 * @sssec: the sk_security_struct
170 *
171 * Description:
172 * Free all of the memory in the NetLabel fields of a sk_security_struct.
173 *
174 */
175void selinux_netlbl_sk_security_free(struct sk_security_struct *ssec)
176{
177 if (ssec->nlbl_secattr != NULL)
178 netlbl_secattr_free(ssec->nlbl_secattr);
179}
180
181/**
109 * selinux_netlbl_sk_security_reset - Reset the NetLabel fields 182 * selinux_netlbl_sk_security_reset - Reset the NetLabel fields
110 * @ssec: the sk_security_struct 183 * @ssec: the sk_security_struct
111 * @family: the socket family 184 * @family: the socket family
@@ -163,35 +236,118 @@ int selinux_netlbl_skbuff_getsid(struct sk_buff *skb,
163} 236}
164 237
165/** 238/**
166 * selinux_netlbl_sock_graft - Netlabel the new socket 239 * selinux_netlbl_skbuff_setsid - Set the NetLabel on a packet given a sid
240 * @skb: the packet
241 * @family: protocol family
242 * @sid: the SID
243 *
244 * Description
245 * Call the NetLabel mechanism to set the label of a packet using @sid.
246 * Returns zero on auccess, negative values on failure.
247 *
248 */
249int selinux_netlbl_skbuff_setsid(struct sk_buff *skb,
250 u16 family,
251 u32 sid)
252{
253 int rc;
254 struct netlbl_lsm_secattr secattr_storage;
255 struct netlbl_lsm_secattr *secattr = NULL;
256 struct sock *sk;
257
258 /* if this is a locally generated packet check to see if it is already
259 * being labeled by it's parent socket, if it is just exit */
260 sk = skb->sk;
261 if (sk != NULL) {
262 struct sk_security_struct *sksec = sk->sk_security;
263 if (sksec->nlbl_state != NLBL_REQSKB)
264 return 0;
265 secattr = sksec->nlbl_secattr;
266 }
267 if (secattr == NULL) {
268 secattr = &secattr_storage;
269 netlbl_secattr_init(secattr);
270 rc = security_netlbl_sid_to_secattr(sid, secattr);
271 if (rc != 0)
272 goto skbuff_setsid_return;
273 }
274
275 rc = netlbl_skbuff_setattr(skb, family, secattr);
276
277skbuff_setsid_return:
278 if (secattr == &secattr_storage)
279 netlbl_secattr_destroy(secattr);
280 return rc;
281}
282
283/**
284 * selinux_netlbl_inet_conn_established - Netlabel the newly accepted connection
167 * @sk: the new connection 285 * @sk: the new connection
168 * @sock: the new socket
169 * 286 *
170 * Description: 287 * Description:
171 * The connection represented by @sk is being grafted onto @sock so set the 288 * A new connection has been established on @sk so make sure it is labeled
172 * socket's NetLabel to match the SID of @sk. 289 * correctly with the NetLabel susbsystem.
173 * 290 *
174 */ 291 */
175void selinux_netlbl_sock_graft(struct sock *sk, struct socket *sock) 292void selinux_netlbl_inet_conn_established(struct sock *sk, u16 family)
176{ 293{
294 int rc;
177 struct sk_security_struct *sksec = sk->sk_security; 295 struct sk_security_struct *sksec = sk->sk_security;
178 struct netlbl_lsm_secattr secattr; 296 struct netlbl_lsm_secattr *secattr;
179 u32 nlbl_peer_sid; 297 struct inet_sock *sk_inet = inet_sk(sk);
298 struct sockaddr_in addr;
180 299
181 if (sksec->nlbl_state != NLBL_REQUIRE) 300 if (sksec->nlbl_state != NLBL_REQUIRE)
182 return; 301 return;
183 302
184 netlbl_secattr_init(&secattr); 303 secattr = selinux_netlbl_sock_genattr(sk);
185 if (netlbl_sock_getattr(sk, &secattr) == 0 && 304 if (secattr == NULL)
186 secattr.flags != NETLBL_SECATTR_NONE && 305 return;
187 security_netlbl_secattr_to_sid(&secattr, &nlbl_peer_sid) == 0)
188 sksec->peer_sid = nlbl_peer_sid;
189 netlbl_secattr_destroy(&secattr);
190 306
191 /* Try to set the NetLabel on the socket to save time later, if we fail 307 rc = netlbl_sock_setattr(sk, secattr);
192 * here we will pick up the pieces in later calls to 308 switch (rc) {
193 * selinux_netlbl_inode_permission(). */ 309 case 0:
194 selinux_netlbl_sock_setsid(sk, sksec->sid); 310 sksec->nlbl_state = NLBL_LABELED;
311 break;
312 case -EDESTADDRREQ:
313 /* no PF_INET6 support yet because we don't support any IPv6
314 * labeling protocols */
315 if (family != PF_INET) {
316 sksec->nlbl_state = NLBL_UNSET;
317 return;
318 }
319
320 addr.sin_family = family;
321 addr.sin_addr.s_addr = sk_inet->daddr;
322 if (netlbl_conn_setattr(sk, (struct sockaddr *)&addr,
323 secattr) != 0) {
324 /* we failed to label the connected socket (could be
325 * for a variety of reasons, the actual "why" isn't
326 * important here) so we have to go to our backup plan,
327 * labeling the packets individually in the netfilter
328 * local output hook. this is okay but we need to
329 * adjust the MSS of the connection to take into
330 * account any labeling overhead, since we don't know
331 * the exact overhead at this point we'll use the worst
332 * case value which is 40 bytes for IPv4 */
333 struct inet_connection_sock *sk_conn = inet_csk(sk);
334 sk_conn->icsk_ext_hdr_len += 40 -
335 (sk_inet->opt ? sk_inet->opt->optlen : 0);
336 sk_conn->icsk_sync_mss(sk, sk_conn->icsk_pmtu_cookie);
337
338 sksec->nlbl_state = NLBL_REQSKB;
339 } else
340 sksec->nlbl_state = NLBL_CONNLABELED;
341 break;
342 default:
343 /* note that we are failing to label the socket which could be
344 * a bad thing since it means traffic could leave the system
345 * without the desired labeling, however, all is not lost as
346 * we have a check in selinux_netlbl_inode_permission() to
347 * pick up the pieces that we might drop here because we can't
348 * return an error code */
349 break;
350 }
195} 351}
196 352
197/** 353/**
@@ -205,13 +361,7 @@ void selinux_netlbl_sock_graft(struct sock *sk, struct socket *sock)
205 */ 361 */
206int selinux_netlbl_socket_post_create(struct socket *sock) 362int selinux_netlbl_socket_post_create(struct socket *sock)
207{ 363{
208 struct sock *sk = sock->sk; 364 return selinux_netlbl_sock_setsid(sock->sk);
209 struct sk_security_struct *sksec = sk->sk_security;
210
211 if (sksec->nlbl_state != NLBL_REQUIRE)
212 return 0;
213
214 return selinux_netlbl_sock_setsid(sk, sksec->sid);
215} 365}
216 366
217/** 367/**
@@ -246,7 +396,7 @@ int selinux_netlbl_inode_permission(struct inode *inode, int mask)
246 local_bh_disable(); 396 local_bh_disable();
247 bh_lock_sock_nested(sk); 397 bh_lock_sock_nested(sk);
248 if (likely(sksec->nlbl_state == NLBL_REQUIRE)) 398 if (likely(sksec->nlbl_state == NLBL_REQUIRE))
249 rc = selinux_netlbl_sock_setsid(sk, sksec->sid); 399 rc = selinux_netlbl_sock_setsid(sk);
250 else 400 else
251 rc = 0; 401 rc = 0;
252 bh_unlock_sock(sk); 402 bh_unlock_sock(sk);
@@ -307,7 +457,7 @@ int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec,
307 return 0; 457 return 0;
308 458
309 if (nlbl_sid != SECINITSID_UNLABELED) 459 if (nlbl_sid != SECINITSID_UNLABELED)
310 netlbl_skbuff_err(skb, rc); 460 netlbl_skbuff_err(skb, rc, 0);
311 return rc; 461 return rc;
312} 462}
313 463
@@ -334,7 +484,8 @@ int selinux_netlbl_socket_setsockopt(struct socket *sock,
334 struct netlbl_lsm_secattr secattr; 484 struct netlbl_lsm_secattr secattr;
335 485
336 if (level == IPPROTO_IP && optname == IP_OPTIONS && 486 if (level == IPPROTO_IP && optname == IP_OPTIONS &&
337 sksec->nlbl_state == NLBL_LABELED) { 487 (sksec->nlbl_state == NLBL_LABELED ||
488 sksec->nlbl_state == NLBL_CONNLABELED)) {
338 netlbl_secattr_init(&secattr); 489 netlbl_secattr_init(&secattr);
339 lock_sock(sk); 490 lock_sock(sk);
340 rc = netlbl_sock_getattr(sk, &secattr); 491 rc = netlbl_sock_getattr(sk, &secattr);
@@ -346,3 +497,50 @@ int selinux_netlbl_socket_setsockopt(struct socket *sock,
346 497
347 return rc; 498 return rc;
348} 499}
500
501/**
502 * selinux_netlbl_socket_connect - Label a client-side socket on connect
503 * @sk: the socket to label
504 * @addr: the destination address
505 *
506 * Description:
507 * Attempt to label a connected socket with NetLabel using the given address.
508 * Returns zero values on success, negative values on failure.
509 *
510 */
511int selinux_netlbl_socket_connect(struct sock *sk, struct sockaddr *addr)
512{
513 int rc;
514 struct sk_security_struct *sksec = sk->sk_security;
515 struct netlbl_lsm_secattr *secattr;
516
517 if (sksec->nlbl_state != NLBL_REQSKB &&
518 sksec->nlbl_state != NLBL_CONNLABELED)
519 return 0;
520
521 local_bh_disable();
522 bh_lock_sock_nested(sk);
523
524 /* connected sockets are allowed to disconnect when the address family
525 * is set to AF_UNSPEC, if that is what is happening we want to reset
526 * the socket */
527 if (addr->sa_family == AF_UNSPEC) {
528 netlbl_sock_delattr(sk);
529 sksec->nlbl_state = NLBL_REQSKB;
530 rc = 0;
531 goto socket_connect_return;
532 }
533 secattr = selinux_netlbl_sock_genattr(sk);
534 if (secattr == NULL) {
535 rc = -ENOMEM;
536 goto socket_connect_return;
537 }
538 rc = netlbl_conn_setattr(sk, addr, secattr);
539 if (rc == 0)
540 sksec->nlbl_state = NLBL_CONNLABELED;
541
542socket_connect_return:
543 bh_unlock_sock(sk);
544 local_bh_enable();
545 return rc;
546}
diff --git a/security/selinux/ss/avtab.c b/security/selinux/ss/avtab.c
index a1be97f8beea..1215b8e47dba 100644
--- a/security/selinux/ss/avtab.c
+++ b/security/selinux/ss/avtab.c
@@ -98,7 +98,7 @@ struct avtab_node *
98avtab_insert_nonunique(struct avtab *h, struct avtab_key *key, struct avtab_datum *datum) 98avtab_insert_nonunique(struct avtab *h, struct avtab_key *key, struct avtab_datum *datum)
99{ 99{
100 int hvalue; 100 int hvalue;
101 struct avtab_node *prev, *cur, *newnode; 101 struct avtab_node *prev, *cur;
102 u16 specified = key->specified & ~(AVTAB_ENABLED|AVTAB_ENABLED_OLD); 102 u16 specified = key->specified & ~(AVTAB_ENABLED|AVTAB_ENABLED_OLD);
103 103
104 if (!h || !h->htable) 104 if (!h || !h->htable)
@@ -122,9 +122,7 @@ avtab_insert_nonunique(struct avtab *h, struct avtab_key *key, struct avtab_datu
122 key->target_class < cur->key.target_class) 122 key->target_class < cur->key.target_class)
123 break; 123 break;
124 } 124 }
125 newnode = avtab_insert_node(h, hvalue, prev, cur, key, datum); 125 return avtab_insert_node(h, hvalue, prev, cur, key, datum);
126
127 return newnode;
128} 126}
129 127
130struct avtab_datum *avtab_search(struct avtab *h, struct avtab_key *key) 128struct avtab_datum *avtab_search(struct avtab *h, struct avtab_key *key)
@@ -231,7 +229,7 @@ void avtab_destroy(struct avtab *h)
231 229
232 for (i = 0; i < h->nslot; i++) { 230 for (i = 0; i < h->nslot; i++) {
233 cur = h->htable[i]; 231 cur = h->htable[i];
234 while (cur != NULL) { 232 while (cur) {
235 temp = cur; 233 temp = cur;
236 cur = cur->next; 234 cur = cur->next;
237 kmem_cache_free(avtab_node_cachep, temp); 235 kmem_cache_free(avtab_node_cachep, temp);
diff --git a/security/selinux/ss/conditional.c b/security/selinux/ss/conditional.c
index fb4efe4f4bc8..4a4e35cac22b 100644
--- a/security/selinux/ss/conditional.c
+++ b/security/selinux/ss/conditional.c
@@ -29,7 +29,7 @@ static int cond_evaluate_expr(struct policydb *p, struct cond_expr *expr)
29 int s[COND_EXPR_MAXDEPTH]; 29 int s[COND_EXPR_MAXDEPTH];
30 int sp = -1; 30 int sp = -1;
31 31
32 for (cur = expr; cur != NULL; cur = cur->next) { 32 for (cur = expr; cur; cur = cur->next) {
33 switch (cur->expr_type) { 33 switch (cur->expr_type) {
34 case COND_BOOL: 34 case COND_BOOL:
35 if (sp == (COND_EXPR_MAXDEPTH - 1)) 35 if (sp == (COND_EXPR_MAXDEPTH - 1))
@@ -97,14 +97,14 @@ int evaluate_cond_node(struct policydb *p, struct cond_node *node)
97 if (new_state == -1) 97 if (new_state == -1)
98 printk(KERN_ERR "SELinux: expression result was undefined - disabling all rules.\n"); 98 printk(KERN_ERR "SELinux: expression result was undefined - disabling all rules.\n");
99 /* turn the rules on or off */ 99 /* turn the rules on or off */
100 for (cur = node->true_list; cur != NULL; cur = cur->next) { 100 for (cur = node->true_list; cur; cur = cur->next) {
101 if (new_state <= 0) 101 if (new_state <= 0)
102 cur->node->key.specified &= ~AVTAB_ENABLED; 102 cur->node->key.specified &= ~AVTAB_ENABLED;
103 else 103 else
104 cur->node->key.specified |= AVTAB_ENABLED; 104 cur->node->key.specified |= AVTAB_ENABLED;
105 } 105 }
106 106
107 for (cur = node->false_list; cur != NULL; cur = cur->next) { 107 for (cur = node->false_list; cur; cur = cur->next) {
108 /* -1 or 1 */ 108 /* -1 or 1 */
109 if (new_state) 109 if (new_state)
110 cur->node->key.specified &= ~AVTAB_ENABLED; 110 cur->node->key.specified &= ~AVTAB_ENABLED;
@@ -128,7 +128,7 @@ int cond_policydb_init(struct policydb *p)
128static void cond_av_list_destroy(struct cond_av_list *list) 128static void cond_av_list_destroy(struct cond_av_list *list)
129{ 129{
130 struct cond_av_list *cur, *next; 130 struct cond_av_list *cur, *next;
131 for (cur = list; cur != NULL; cur = next) { 131 for (cur = list; cur; cur = next) {
132 next = cur->next; 132 next = cur->next;
133 /* the avtab_ptr_t node is destroy by the avtab */ 133 /* the avtab_ptr_t node is destroy by the avtab */
134 kfree(cur); 134 kfree(cur);
@@ -139,7 +139,7 @@ static void cond_node_destroy(struct cond_node *node)
139{ 139{
140 struct cond_expr *cur_expr, *next_expr; 140 struct cond_expr *cur_expr, *next_expr;
141 141
142 for (cur_expr = node->expr; cur_expr != NULL; cur_expr = next_expr) { 142 for (cur_expr = node->expr; cur_expr; cur_expr = next_expr) {
143 next_expr = cur_expr->next; 143 next_expr = cur_expr->next;
144 kfree(cur_expr); 144 kfree(cur_expr);
145 } 145 }
@@ -155,7 +155,7 @@ static void cond_list_destroy(struct cond_node *list)
155 if (list == NULL) 155 if (list == NULL)
156 return; 156 return;
157 157
158 for (cur = list; cur != NULL; cur = next) { 158 for (cur = list; cur; cur = next) {
159 next = cur->next; 159 next = cur->next;
160 cond_node_destroy(cur); 160 cond_node_destroy(cur);
161 } 161 }
@@ -239,7 +239,7 @@ int cond_read_bool(struct policydb *p, struct hashtab *h, void *fp)
239 rc = next_entry(key, fp, len); 239 rc = next_entry(key, fp, len);
240 if (rc < 0) 240 if (rc < 0)
241 goto err; 241 goto err;
242 key[len] = 0; 242 key[len] = '\0';
243 if (hashtab_insert(h, key, booldatum)) 243 if (hashtab_insert(h, key, booldatum))
244 goto err; 244 goto err;
245 245
@@ -291,7 +291,7 @@ static int cond_insertf(struct avtab *a, struct avtab_key *k, struct avtab_datum
291 goto err; 291 goto err;
292 } 292 }
293 found = 0; 293 found = 0;
294 for (cur = other; cur != NULL; cur = cur->next) { 294 for (cur = other; cur; cur = cur->next) {
295 if (cur->node == node_ptr) { 295 if (cur->node == node_ptr) {
296 found = 1; 296 found = 1;
297 break; 297 break;
@@ -485,7 +485,7 @@ void cond_compute_av(struct avtab *ctab, struct avtab_key *key, struct av_decisi
485 if (!ctab || !key || !avd) 485 if (!ctab || !key || !avd)
486 return; 486 return;
487 487
488 for (node = avtab_search_node(ctab, key); node != NULL; 488 for (node = avtab_search_node(ctab, key); node;
489 node = avtab_search_node_next(node, key->specified)) { 489 node = avtab_search_node_next(node, key->specified)) {
490 if ((u16)(AVTAB_ALLOWED|AVTAB_ENABLED) == 490 if ((u16)(AVTAB_ALLOWED|AVTAB_ENABLED) ==
491 (node->key.specified & (AVTAB_ALLOWED|AVTAB_ENABLED))) 491 (node->key.specified & (AVTAB_ALLOWED|AVTAB_ENABLED)))
diff --git a/security/selinux/ss/conditional.h b/security/selinux/ss/conditional.h
index 65b9f8366e9c..53ddb013ae57 100644
--- a/security/selinux/ss/conditional.h
+++ b/security/selinux/ss/conditional.h
@@ -28,7 +28,7 @@ struct cond_expr {
28#define COND_XOR 5 /* bool ^ bool */ 28#define COND_XOR 5 /* bool ^ bool */
29#define COND_EQ 6 /* bool == bool */ 29#define COND_EQ 6 /* bool == bool */
30#define COND_NEQ 7 /* bool != bool */ 30#define COND_NEQ 7 /* bool != bool */
31#define COND_LAST 8 31#define COND_LAST COND_NEQ
32 __u32 expr_type; 32 __u32 expr_type;
33 __u32 bool; 33 __u32 bool;
34 struct cond_expr *next; 34 struct cond_expr *next;
diff --git a/security/selinux/ss/ebitmap.c b/security/selinux/ss/ebitmap.c
index ddc275490af8..68c7348d1acc 100644
--- a/security/selinux/ss/ebitmap.c
+++ b/security/selinux/ss/ebitmap.c
@@ -109,7 +109,7 @@ int ebitmap_netlbl_export(struct ebitmap *ebmap,
109 *catmap = c_iter; 109 *catmap = c_iter;
110 c_iter->startbit = e_iter->startbit & ~(NETLBL_CATMAP_SIZE - 1); 110 c_iter->startbit = e_iter->startbit & ~(NETLBL_CATMAP_SIZE - 1);
111 111
112 while (e_iter != NULL) { 112 while (e_iter) {
113 for (i = 0; i < EBITMAP_UNIT_NUMS; i++) { 113 for (i = 0; i < EBITMAP_UNIT_NUMS; i++) {
114 unsigned int delta, e_startbit, c_endbit; 114 unsigned int delta, e_startbit, c_endbit;
115 115
@@ -197,7 +197,7 @@ int ebitmap_netlbl_import(struct ebitmap *ebmap,
197 } 197 }
198 } 198 }
199 c_iter = c_iter->next; 199 c_iter = c_iter->next;
200 } while (c_iter != NULL); 200 } while (c_iter);
201 if (e_iter != NULL) 201 if (e_iter != NULL)
202 ebmap->highbit = e_iter->startbit + EBITMAP_SIZE; 202 ebmap->highbit = e_iter->startbit + EBITMAP_SIZE;
203 else 203 else
diff --git a/security/selinux/ss/hashtab.c b/security/selinux/ss/hashtab.c
index 2e7788e13213..933e735bb185 100644
--- a/security/selinux/ss/hashtab.c
+++ b/security/selinux/ss/hashtab.c
@@ -81,7 +81,7 @@ void *hashtab_search(struct hashtab *h, const void *key)
81 81
82 hvalue = h->hash_value(h, key); 82 hvalue = h->hash_value(h, key);
83 cur = h->htable[hvalue]; 83 cur = h->htable[hvalue];
84 while (cur != NULL && h->keycmp(h, key, cur->key) > 0) 84 while (cur && h->keycmp(h, key, cur->key) > 0)
85 cur = cur->next; 85 cur = cur->next;
86 86
87 if (cur == NULL || (h->keycmp(h, key, cur->key) != 0)) 87 if (cur == NULL || (h->keycmp(h, key, cur->key) != 0))
@@ -100,7 +100,7 @@ void hashtab_destroy(struct hashtab *h)
100 100
101 for (i = 0; i < h->size; i++) { 101 for (i = 0; i < h->size; i++) {
102 cur = h->htable[i]; 102 cur = h->htable[i];
103 while (cur != NULL) { 103 while (cur) {
104 temp = cur; 104 temp = cur;
105 cur = cur->next; 105 cur = cur->next;
106 kfree(temp); 106 kfree(temp);
@@ -127,7 +127,7 @@ int hashtab_map(struct hashtab *h,
127 127
128 for (i = 0; i < h->size; i++) { 128 for (i = 0; i < h->size; i++) {
129 cur = h->htable[i]; 129 cur = h->htable[i];
130 while (cur != NULL) { 130 while (cur) {
131 ret = apply(cur->key, cur->datum, args); 131 ret = apply(cur->key, cur->datum, args);
132 if (ret) 132 if (ret)
133 return ret; 133 return ret;
diff --git a/security/selinux/ss/mls.c b/security/selinux/ss/mls.c
index 77d745da48bb..b5407f16c2a4 100644
--- a/security/selinux/ss/mls.c
+++ b/security/selinux/ss/mls.c
@@ -283,8 +283,8 @@ int mls_context_to_sid(struct policydb *pol,
283 p++; 283 p++;
284 284
285 delim = *p; 285 delim = *p;
286 if (delim != 0) 286 if (delim != '\0')
287 *p++ = 0; 287 *p++ = '\0';
288 288
289 for (l = 0; l < 2; l++) { 289 for (l = 0; l < 2; l++) {
290 levdatum = hashtab_search(pol->p_levels.table, scontextp); 290 levdatum = hashtab_search(pol->p_levels.table, scontextp);
@@ -302,14 +302,14 @@ int mls_context_to_sid(struct policydb *pol,
302 while (*p && *p != ',' && *p != '-') 302 while (*p && *p != ',' && *p != '-')
303 p++; 303 p++;
304 delim = *p; 304 delim = *p;
305 if (delim != 0) 305 if (delim != '\0')
306 *p++ = 0; 306 *p++ = '\0';
307 307
308 /* Separate into range if exists */ 308 /* Separate into range if exists */
309 rngptr = strchr(scontextp, '.'); 309 rngptr = strchr(scontextp, '.');
310 if (rngptr != NULL) { 310 if (rngptr != NULL) {
311 /* Remove '.' */ 311 /* Remove '.' */
312 *rngptr++ = 0; 312 *rngptr++ = '\0';
313 } 313 }
314 314
315 catdatum = hashtab_search(pol->p_cats.table, 315 catdatum = hashtab_search(pol->p_cats.table,
@@ -357,8 +357,8 @@ int mls_context_to_sid(struct policydb *pol,
357 p++; 357 p++;
358 358
359 delim = *p; 359 delim = *p;
360 if (delim != 0) 360 if (delim != '\0')
361 *p++ = 0; 361 *p++ = '\0';
362 } else 362 } else
363 break; 363 break;
364 } 364 }
diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c
index 2391761ae422..72e4a54973aa 100644
--- a/security/selinux/ss/policydb.c
+++ b/security/selinux/ss/policydb.c
@@ -30,6 +30,7 @@
30#include <linux/slab.h> 30#include <linux/slab.h>
31#include <linux/string.h> 31#include <linux/string.h>
32#include <linux/errno.h> 32#include <linux/errno.h>
33#include <linux/audit.h>
33#include "security.h" 34#include "security.h"
34 35
35#include "policydb.h" 36#include "policydb.h"
@@ -116,7 +117,12 @@ static struct policydb_compat_info policydb_compat[] = {
116 .version = POLICYDB_VERSION_PERMISSIVE, 117 .version = POLICYDB_VERSION_PERMISSIVE,
117 .sym_num = SYM_NUM, 118 .sym_num = SYM_NUM,
118 .ocon_num = OCON_NUM, 119 .ocon_num = OCON_NUM,
119 } 120 },
121 {
122 .version = POLICYDB_VERSION_BOUNDARY,
123 .sym_num = SYM_NUM,
124 .ocon_num = OCON_NUM,
125 },
120}; 126};
121 127
122static struct policydb_compat_info *policydb_lookup_compat(int version) 128static struct policydb_compat_info *policydb_lookup_compat(int version)
@@ -254,7 +260,9 @@ static int role_index(void *key, void *datum, void *datap)
254 260
255 role = datum; 261 role = datum;
256 p = datap; 262 p = datap;
257 if (!role->value || role->value > p->p_roles.nprim) 263 if (!role->value
264 || role->value > p->p_roles.nprim
265 || role->bounds > p->p_roles.nprim)
258 return -EINVAL; 266 return -EINVAL;
259 p->p_role_val_to_name[role->value - 1] = key; 267 p->p_role_val_to_name[role->value - 1] = key;
260 p->role_val_to_struct[role->value - 1] = role; 268 p->role_val_to_struct[role->value - 1] = role;
@@ -270,9 +278,12 @@ static int type_index(void *key, void *datum, void *datap)
270 p = datap; 278 p = datap;
271 279
272 if (typdatum->primary) { 280 if (typdatum->primary) {
273 if (!typdatum->value || typdatum->value > p->p_types.nprim) 281 if (!typdatum->value
282 || typdatum->value > p->p_types.nprim
283 || typdatum->bounds > p->p_types.nprim)
274 return -EINVAL; 284 return -EINVAL;
275 p->p_type_val_to_name[typdatum->value - 1] = key; 285 p->p_type_val_to_name[typdatum->value - 1] = key;
286 p->type_val_to_struct[typdatum->value - 1] = typdatum;
276 } 287 }
277 288
278 return 0; 289 return 0;
@@ -285,7 +296,9 @@ static int user_index(void *key, void *datum, void *datap)
285 296
286 usrdatum = datum; 297 usrdatum = datum;
287 p = datap; 298 p = datap;
288 if (!usrdatum->value || usrdatum->value > p->p_users.nprim) 299 if (!usrdatum->value
300 || usrdatum->value > p->p_users.nprim
301 || usrdatum->bounds > p->p_users.nprim)
289 return -EINVAL; 302 return -EINVAL;
290 p->p_user_val_to_name[usrdatum->value - 1] = key; 303 p->p_user_val_to_name[usrdatum->value - 1] = key;
291 p->user_val_to_struct[usrdatum->value - 1] = usrdatum; 304 p->user_val_to_struct[usrdatum->value - 1] = usrdatum;
@@ -438,6 +451,14 @@ static int policydb_index_others(struct policydb *p)
438 goto out; 451 goto out;
439 } 452 }
440 453
454 p->type_val_to_struct =
455 kmalloc(p->p_types.nprim * sizeof(*(p->type_val_to_struct)),
456 GFP_KERNEL);
457 if (!p->type_val_to_struct) {
458 rc = -ENOMEM;
459 goto out;
460 }
461
441 if (cond_init_bool_indexes(p)) { 462 if (cond_init_bool_indexes(p)) {
442 rc = -ENOMEM; 463 rc = -ENOMEM;
443 goto out; 464 goto out;
@@ -625,6 +646,7 @@ void policydb_destroy(struct policydb *p)
625 kfree(p->class_val_to_struct); 646 kfree(p->class_val_to_struct);
626 kfree(p->role_val_to_struct); 647 kfree(p->role_val_to_struct);
627 kfree(p->user_val_to_struct); 648 kfree(p->user_val_to_struct);
649 kfree(p->type_val_to_struct);
628 650
629 avtab_destroy(&p->te_avtab); 651 avtab_destroy(&p->te_avtab);
630 652
@@ -932,7 +954,7 @@ static int perm_read(struct policydb *p, struct hashtab *h, void *fp)
932 rc = next_entry(key, fp, len); 954 rc = next_entry(key, fp, len);
933 if (rc < 0) 955 if (rc < 0)
934 goto bad; 956 goto bad;
935 key[len] = 0; 957 key[len] = '\0';
936 958
937 rc = hashtab_insert(h, key, perdatum); 959 rc = hashtab_insert(h, key, perdatum);
938 if (rc) 960 if (rc)
@@ -979,7 +1001,7 @@ static int common_read(struct policydb *p, struct hashtab *h, void *fp)
979 rc = next_entry(key, fp, len); 1001 rc = next_entry(key, fp, len);
980 if (rc < 0) 1002 if (rc < 0)
981 goto bad; 1003 goto bad;
982 key[len] = 0; 1004 key[len] = '\0';
983 1005
984 for (i = 0; i < nel; i++) { 1006 for (i = 0; i < nel; i++) {
985 rc = perm_read(p, comdatum->permissions.table, fp); 1007 rc = perm_read(p, comdatum->permissions.table, fp);
@@ -1117,7 +1139,7 @@ static int class_read(struct policydb *p, struct hashtab *h, void *fp)
1117 rc = next_entry(key, fp, len); 1139 rc = next_entry(key, fp, len);
1118 if (rc < 0) 1140 if (rc < 0)
1119 goto bad; 1141 goto bad;
1120 key[len] = 0; 1142 key[len] = '\0';
1121 1143
1122 if (len2) { 1144 if (len2) {
1123 cladatum->comkey = kmalloc(len2 + 1, GFP_KERNEL); 1145 cladatum->comkey = kmalloc(len2 + 1, GFP_KERNEL);
@@ -1128,7 +1150,7 @@ static int class_read(struct policydb *p, struct hashtab *h, void *fp)
1128 rc = next_entry(cladatum->comkey, fp, len2); 1150 rc = next_entry(cladatum->comkey, fp, len2);
1129 if (rc < 0) 1151 if (rc < 0)
1130 goto bad; 1152 goto bad;
1131 cladatum->comkey[len2] = 0; 1153 cladatum->comkey[len2] = '\0';
1132 1154
1133 cladatum->comdatum = hashtab_search(p->p_commons.table, 1155 cladatum->comdatum = hashtab_search(p->p_commons.table,
1134 cladatum->comkey); 1156 cladatum->comkey);
@@ -1176,8 +1198,8 @@ static int role_read(struct policydb *p, struct hashtab *h, void *fp)
1176{ 1198{
1177 char *key = NULL; 1199 char *key = NULL;
1178 struct role_datum *role; 1200 struct role_datum *role;
1179 int rc; 1201 int rc, to_read = 2;
1180 __le32 buf[2]; 1202 __le32 buf[3];
1181 u32 len; 1203 u32 len;
1182 1204
1183 role = kzalloc(sizeof(*role), GFP_KERNEL); 1205 role = kzalloc(sizeof(*role), GFP_KERNEL);
@@ -1186,12 +1208,17 @@ static int role_read(struct policydb *p, struct hashtab *h, void *fp)
1186 goto out; 1208 goto out;
1187 } 1209 }
1188 1210
1189 rc = next_entry(buf, fp, sizeof buf); 1211 if (p->policyvers >= POLICYDB_VERSION_BOUNDARY)
1212 to_read = 3;
1213
1214 rc = next_entry(buf, fp, sizeof(buf[0]) * to_read);
1190 if (rc < 0) 1215 if (rc < 0)
1191 goto bad; 1216 goto bad;
1192 1217
1193 len = le32_to_cpu(buf[0]); 1218 len = le32_to_cpu(buf[0]);
1194 role->value = le32_to_cpu(buf[1]); 1219 role->value = le32_to_cpu(buf[1]);
1220 if (p->policyvers >= POLICYDB_VERSION_BOUNDARY)
1221 role->bounds = le32_to_cpu(buf[2]);
1195 1222
1196 key = kmalloc(len + 1, GFP_KERNEL); 1223 key = kmalloc(len + 1, GFP_KERNEL);
1197 if (!key) { 1224 if (!key) {
@@ -1201,7 +1228,7 @@ static int role_read(struct policydb *p, struct hashtab *h, void *fp)
1201 rc = next_entry(key, fp, len); 1228 rc = next_entry(key, fp, len);
1202 if (rc < 0) 1229 if (rc < 0)
1203 goto bad; 1230 goto bad;
1204 key[len] = 0; 1231 key[len] = '\0';
1205 1232
1206 rc = ebitmap_read(&role->dominates, fp); 1233 rc = ebitmap_read(&role->dominates, fp);
1207 if (rc) 1234 if (rc)
@@ -1236,8 +1263,8 @@ static int type_read(struct policydb *p, struct hashtab *h, void *fp)
1236{ 1263{
1237 char *key = NULL; 1264 char *key = NULL;
1238 struct type_datum *typdatum; 1265 struct type_datum *typdatum;
1239 int rc; 1266 int rc, to_read = 3;
1240 __le32 buf[3]; 1267 __le32 buf[4];
1241 u32 len; 1268 u32 len;
1242 1269
1243 typdatum = kzalloc(sizeof(*typdatum), GFP_KERNEL); 1270 typdatum = kzalloc(sizeof(*typdatum), GFP_KERNEL);
@@ -1246,13 +1273,27 @@ static int type_read(struct policydb *p, struct hashtab *h, void *fp)
1246 return rc; 1273 return rc;
1247 } 1274 }
1248 1275
1249 rc = next_entry(buf, fp, sizeof buf); 1276 if (p->policyvers >= POLICYDB_VERSION_BOUNDARY)
1277 to_read = 4;
1278
1279 rc = next_entry(buf, fp, sizeof(buf[0]) * to_read);
1250 if (rc < 0) 1280 if (rc < 0)
1251 goto bad; 1281 goto bad;
1252 1282
1253 len = le32_to_cpu(buf[0]); 1283 len = le32_to_cpu(buf[0]);
1254 typdatum->value = le32_to_cpu(buf[1]); 1284 typdatum->value = le32_to_cpu(buf[1]);
1255 typdatum->primary = le32_to_cpu(buf[2]); 1285 if (p->policyvers >= POLICYDB_VERSION_BOUNDARY) {
1286 u32 prop = le32_to_cpu(buf[2]);
1287
1288 if (prop & TYPEDATUM_PROPERTY_PRIMARY)
1289 typdatum->primary = 1;
1290 if (prop & TYPEDATUM_PROPERTY_ATTRIBUTE)
1291 typdatum->attribute = 1;
1292
1293 typdatum->bounds = le32_to_cpu(buf[3]);
1294 } else {
1295 typdatum->primary = le32_to_cpu(buf[2]);
1296 }
1256 1297
1257 key = kmalloc(len + 1, GFP_KERNEL); 1298 key = kmalloc(len + 1, GFP_KERNEL);
1258 if (!key) { 1299 if (!key) {
@@ -1262,7 +1303,7 @@ static int type_read(struct policydb *p, struct hashtab *h, void *fp)
1262 rc = next_entry(key, fp, len); 1303 rc = next_entry(key, fp, len);
1263 if (rc < 0) 1304 if (rc < 0)
1264 goto bad; 1305 goto bad;
1265 key[len] = 0; 1306 key[len] = '\0';
1266 1307
1267 rc = hashtab_insert(h, key, typdatum); 1308 rc = hashtab_insert(h, key, typdatum);
1268 if (rc) 1309 if (rc)
@@ -1309,8 +1350,8 @@ static int user_read(struct policydb *p, struct hashtab *h, void *fp)
1309{ 1350{
1310 char *key = NULL; 1351 char *key = NULL;
1311 struct user_datum *usrdatum; 1352 struct user_datum *usrdatum;
1312 int rc; 1353 int rc, to_read = 2;
1313 __le32 buf[2]; 1354 __le32 buf[3];
1314 u32 len; 1355 u32 len;
1315 1356
1316 usrdatum = kzalloc(sizeof(*usrdatum), GFP_KERNEL); 1357 usrdatum = kzalloc(sizeof(*usrdatum), GFP_KERNEL);
@@ -1319,12 +1360,17 @@ static int user_read(struct policydb *p, struct hashtab *h, void *fp)
1319 goto out; 1360 goto out;
1320 } 1361 }
1321 1362
1322 rc = next_entry(buf, fp, sizeof buf); 1363 if (p->policyvers >= POLICYDB_VERSION_BOUNDARY)
1364 to_read = 3;
1365
1366 rc = next_entry(buf, fp, sizeof(buf[0]) * to_read);
1323 if (rc < 0) 1367 if (rc < 0)
1324 goto bad; 1368 goto bad;
1325 1369
1326 len = le32_to_cpu(buf[0]); 1370 len = le32_to_cpu(buf[0]);
1327 usrdatum->value = le32_to_cpu(buf[1]); 1371 usrdatum->value = le32_to_cpu(buf[1]);
1372 if (p->policyvers >= POLICYDB_VERSION_BOUNDARY)
1373 usrdatum->bounds = le32_to_cpu(buf[2]);
1328 1374
1329 key = kmalloc(len + 1, GFP_KERNEL); 1375 key = kmalloc(len + 1, GFP_KERNEL);
1330 if (!key) { 1376 if (!key) {
@@ -1334,7 +1380,7 @@ static int user_read(struct policydb *p, struct hashtab *h, void *fp)
1334 rc = next_entry(key, fp, len); 1380 rc = next_entry(key, fp, len);
1335 if (rc < 0) 1381 if (rc < 0)
1336 goto bad; 1382 goto bad;
1337 key[len] = 0; 1383 key[len] = '\0';
1338 1384
1339 rc = ebitmap_read(&usrdatum->roles, fp); 1385 rc = ebitmap_read(&usrdatum->roles, fp);
1340 if (rc) 1386 if (rc)
@@ -1388,7 +1434,7 @@ static int sens_read(struct policydb *p, struct hashtab *h, void *fp)
1388 rc = next_entry(key, fp, len); 1434 rc = next_entry(key, fp, len);
1389 if (rc < 0) 1435 if (rc < 0)
1390 goto bad; 1436 goto bad;
1391 key[len] = 0; 1437 key[len] = '\0';
1392 1438
1393 levdatum->level = kmalloc(sizeof(struct mls_level), GFP_ATOMIC); 1439 levdatum->level = kmalloc(sizeof(struct mls_level), GFP_ATOMIC);
1394 if (!levdatum->level) { 1440 if (!levdatum->level) {
@@ -1440,7 +1486,7 @@ static int cat_read(struct policydb *p, struct hashtab *h, void *fp)
1440 rc = next_entry(key, fp, len); 1486 rc = next_entry(key, fp, len);
1441 if (rc < 0) 1487 if (rc < 0)
1442 goto bad; 1488 goto bad;
1443 key[len] = 0; 1489 key[len] = '\0';
1444 1490
1445 rc = hashtab_insert(h, key, catdatum); 1491 rc = hashtab_insert(h, key, catdatum);
1446 if (rc) 1492 if (rc)
@@ -1465,6 +1511,133 @@ static int (*read_f[SYM_NUM]) (struct policydb *p, struct hashtab *h, void *fp)
1465 cat_read, 1511 cat_read,
1466}; 1512};
1467 1513
1514static int user_bounds_sanity_check(void *key, void *datum, void *datap)
1515{
1516 struct user_datum *upper, *user;
1517 struct policydb *p = datap;
1518 int depth = 0;
1519
1520 upper = user = datum;
1521 while (upper->bounds) {
1522 struct ebitmap_node *node;
1523 unsigned long bit;
1524
1525 if (++depth == POLICYDB_BOUNDS_MAXDEPTH) {
1526 printk(KERN_ERR "SELinux: user %s: "
1527 "too deep or looped boundary",
1528 (char *) key);
1529 return -EINVAL;
1530 }
1531
1532 upper = p->user_val_to_struct[upper->bounds - 1];
1533 ebitmap_for_each_positive_bit(&user->roles, node, bit) {
1534 if (ebitmap_get_bit(&upper->roles, bit))
1535 continue;
1536
1537 printk(KERN_ERR
1538 "SELinux: boundary violated policy: "
1539 "user=%s role=%s bounds=%s\n",
1540 p->p_user_val_to_name[user->value - 1],
1541 p->p_role_val_to_name[bit],
1542 p->p_user_val_to_name[upper->value - 1]);
1543
1544 return -EINVAL;
1545 }
1546 }
1547
1548 return 0;
1549}
1550
1551static int role_bounds_sanity_check(void *key, void *datum, void *datap)
1552{
1553 struct role_datum *upper, *role;
1554 struct policydb *p = datap;
1555 int depth = 0;
1556
1557 upper = role = datum;
1558 while (upper->bounds) {
1559 struct ebitmap_node *node;
1560 unsigned long bit;
1561
1562 if (++depth == POLICYDB_BOUNDS_MAXDEPTH) {
1563 printk(KERN_ERR "SELinux: role %s: "
1564 "too deep or looped bounds\n",
1565 (char *) key);
1566 return -EINVAL;
1567 }
1568
1569 upper = p->role_val_to_struct[upper->bounds - 1];
1570 ebitmap_for_each_positive_bit(&role->types, node, bit) {
1571 if (ebitmap_get_bit(&upper->types, bit))
1572 continue;
1573
1574 printk(KERN_ERR
1575 "SELinux: boundary violated policy: "
1576 "role=%s type=%s bounds=%s\n",
1577 p->p_role_val_to_name[role->value - 1],
1578 p->p_type_val_to_name[bit],
1579 p->p_role_val_to_name[upper->value - 1]);
1580
1581 return -EINVAL;
1582 }
1583 }
1584
1585 return 0;
1586}
1587
1588static int type_bounds_sanity_check(void *key, void *datum, void *datap)
1589{
1590 struct type_datum *upper, *type;
1591 struct policydb *p = datap;
1592 int depth = 0;
1593
1594 upper = type = datum;
1595 while (upper->bounds) {
1596 if (++depth == POLICYDB_BOUNDS_MAXDEPTH) {
1597 printk(KERN_ERR "SELinux: type %s: "
1598 "too deep or looped boundary\n",
1599 (char *) key);
1600 return -EINVAL;
1601 }
1602
1603 upper = p->type_val_to_struct[upper->bounds - 1];
1604 if (upper->attribute) {
1605 printk(KERN_ERR "SELinux: type %s: "
1606 "bounded by attribute %s",
1607 (char *) key,
1608 p->p_type_val_to_name[upper->value - 1]);
1609 return -EINVAL;
1610 }
1611 }
1612
1613 return 0;
1614}
1615
1616static int policydb_bounds_sanity_check(struct policydb *p)
1617{
1618 int rc;
1619
1620 if (p->policyvers < POLICYDB_VERSION_BOUNDARY)
1621 return 0;
1622
1623 rc = hashtab_map(p->p_users.table,
1624 user_bounds_sanity_check, p);
1625 if (rc)
1626 return rc;
1627
1628 rc = hashtab_map(p->p_roles.table,
1629 role_bounds_sanity_check, p);
1630 if (rc)
1631 return rc;
1632
1633 rc = hashtab_map(p->p_types.table,
1634 type_bounds_sanity_check, p);
1635 if (rc)
1636 return rc;
1637
1638 return 0;
1639}
1640
1468extern int ss_initialized; 1641extern int ss_initialized;
1469 1642
1470/* 1643/*
@@ -1523,7 +1696,7 @@ int policydb_read(struct policydb *p, void *fp)
1523 kfree(policydb_str); 1696 kfree(policydb_str);
1524 goto bad; 1697 goto bad;
1525 } 1698 }
1526 policydb_str[len] = 0; 1699 policydb_str[len] = '\0';
1527 if (strcmp(policydb_str, POLICYDB_STRING)) { 1700 if (strcmp(policydb_str, POLICYDB_STRING)) {
1528 printk(KERN_ERR "SELinux: policydb string %s does not match " 1701 printk(KERN_ERR "SELinux: policydb string %s does not match "
1529 "my string %s\n", policydb_str, POLICYDB_STRING); 1702 "my string %s\n", policydb_str, POLICYDB_STRING);
@@ -1961,6 +2134,10 @@ int policydb_read(struct policydb *p, void *fp)
1961 goto bad; 2134 goto bad;
1962 } 2135 }
1963 2136
2137 rc = policydb_bounds_sanity_check(p);
2138 if (rc)
2139 goto bad;
2140
1964 rc = 0; 2141 rc = 0;
1965out: 2142out:
1966 return rc; 2143 return rc;
diff --git a/security/selinux/ss/policydb.h b/security/selinux/ss/policydb.h
index 4253370fda6a..55152d498b53 100644
--- a/security/selinux/ss/policydb.h
+++ b/security/selinux/ss/policydb.h
@@ -61,6 +61,7 @@ struct class_datum {
61/* Role attributes */ 61/* Role attributes */
62struct role_datum { 62struct role_datum {
63 u32 value; /* internal role value */ 63 u32 value; /* internal role value */
64 u32 bounds; /* boundary of role */
64 struct ebitmap dominates; /* set of roles dominated by this role */ 65 struct ebitmap dominates; /* set of roles dominated by this role */
65 struct ebitmap types; /* set of authorized types for role */ 66 struct ebitmap types; /* set of authorized types for role */
66}; 67};
@@ -81,12 +82,15 @@ struct role_allow {
81/* Type attributes */ 82/* Type attributes */
82struct type_datum { 83struct type_datum {
83 u32 value; /* internal type value */ 84 u32 value; /* internal type value */
85 u32 bounds; /* boundary of type */
84 unsigned char primary; /* primary name? */ 86 unsigned char primary; /* primary name? */
87 unsigned char attribute;/* attribute ?*/
85}; 88};
86 89
87/* User attributes */ 90/* User attributes */
88struct user_datum { 91struct user_datum {
89 u32 value; /* internal user value */ 92 u32 value; /* internal user value */
93 u32 bounds; /* bounds of user */
90 struct ebitmap roles; /* set of authorized roles for user */ 94 struct ebitmap roles; /* set of authorized roles for user */
91 struct mls_range range; /* MLS range (min - max) for user */ 95 struct mls_range range; /* MLS range (min - max) for user */
92 struct mls_level dfltlevel; /* default login MLS level for user */ 96 struct mls_level dfltlevel; /* default login MLS level for user */
@@ -209,6 +213,7 @@ struct policydb {
209 struct class_datum **class_val_to_struct; 213 struct class_datum **class_val_to_struct;
210 struct role_datum **role_val_to_struct; 214 struct role_datum **role_val_to_struct;
211 struct user_datum **user_val_to_struct; 215 struct user_datum **user_val_to_struct;
216 struct type_datum **type_val_to_struct;
212 217
213 /* type enforcement access vectors and transitions */ 218 /* type enforcement access vectors and transitions */
214 struct avtab te_avtab; 219 struct avtab te_avtab;
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index b52f923ce680..343c8ab14af0 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -88,6 +88,11 @@ static u32 latest_granting;
88static int context_struct_to_string(struct context *context, char **scontext, 88static int context_struct_to_string(struct context *context, char **scontext,
89 u32 *scontext_len); 89 u32 *scontext_len);
90 90
91static int context_struct_compute_av(struct context *scontext,
92 struct context *tcontext,
93 u16 tclass,
94 u32 requested,
95 struct av_decision *avd);
91/* 96/*
92 * Return the boolean value of a constraint expression 97 * Return the boolean value of a constraint expression
93 * when it is applied to the specified source and target 98 * when it is applied to the specified source and target
@@ -274,6 +279,100 @@ mls_ops:
274} 279}
275 280
276/* 281/*
282 * security_boundary_permission - drops violated permissions
283 * on boundary constraint.
284 */
285static void type_attribute_bounds_av(struct context *scontext,
286 struct context *tcontext,
287 u16 tclass,
288 u32 requested,
289 struct av_decision *avd)
290{
291 struct context lo_scontext;
292 struct context lo_tcontext;
293 struct av_decision lo_avd;
294 struct type_datum *source
295 = policydb.type_val_to_struct[scontext->type - 1];
296 struct type_datum *target
297 = policydb.type_val_to_struct[tcontext->type - 1];
298 u32 masked = 0;
299
300 if (source->bounds) {
301 memset(&lo_avd, 0, sizeof(lo_avd));
302
303 memcpy(&lo_scontext, scontext, sizeof(lo_scontext));
304 lo_scontext.type = source->bounds;
305
306 context_struct_compute_av(&lo_scontext,
307 tcontext,
308 tclass,
309 requested,
310 &lo_avd);
311 if ((lo_avd.allowed & avd->allowed) == avd->allowed)
312 return; /* no masked permission */
313 masked = ~lo_avd.allowed & avd->allowed;
314 }
315
316 if (target->bounds) {
317 memset(&lo_avd, 0, sizeof(lo_avd));
318
319 memcpy(&lo_tcontext, tcontext, sizeof(lo_tcontext));
320 lo_tcontext.type = target->bounds;
321
322 context_struct_compute_av(scontext,
323 &lo_tcontext,
324 tclass,
325 requested,
326 &lo_avd);
327 if ((lo_avd.allowed & avd->allowed) == avd->allowed)
328 return; /* no masked permission */
329 masked = ~lo_avd.allowed & avd->allowed;
330 }
331
332 if (source->bounds && target->bounds) {
333 memset(&lo_avd, 0, sizeof(lo_avd));
334 /*
335 * lo_scontext and lo_tcontext are already
336 * set up.
337 */
338
339 context_struct_compute_av(&lo_scontext,
340 &lo_tcontext,
341 tclass,
342 requested,
343 &lo_avd);
344 if ((lo_avd.allowed & avd->allowed) == avd->allowed)
345 return; /* no masked permission */
346 masked = ~lo_avd.allowed & avd->allowed;
347 }
348
349 if (masked) {
350 struct audit_buffer *ab;
351 char *stype_name
352 = policydb.p_type_val_to_name[source->value - 1];
353 char *ttype_name
354 = policydb.p_type_val_to_name[target->value - 1];
355 char *tclass_name
356 = policydb.p_class_val_to_name[tclass - 1];
357
358 /* mask violated permissions */
359 avd->allowed &= ~masked;
360
361 /* notice to userspace via audit message */
362 ab = audit_log_start(current->audit_context,
363 GFP_ATOMIC, AUDIT_SELINUX_ERR);
364 if (!ab)
365 return;
366
367 audit_log_format(ab, "av boundary violation: "
368 "source=%s target=%s tclass=%s",
369 stype_name, ttype_name, tclass_name);
370 avc_dump_av(ab, tclass, masked);
371 audit_log_end(ab);
372 }
373}
374
375/*
277 * Compute access vectors based on a context structure pair for 376 * Compute access vectors based on a context structure pair for
278 * the permissions in a particular class. 377 * the permissions in a particular class.
279 */ 378 */
@@ -356,7 +455,7 @@ static int context_struct_compute_av(struct context *scontext,
356 avkey.source_type = i + 1; 455 avkey.source_type = i + 1;
357 avkey.target_type = j + 1; 456 avkey.target_type = j + 1;
358 for (node = avtab_search_node(&policydb.te_avtab, &avkey); 457 for (node = avtab_search_node(&policydb.te_avtab, &avkey);
359 node != NULL; 458 node;
360 node = avtab_search_node_next(node, avkey.specified)) { 459 node = avtab_search_node_next(node, avkey.specified)) {
361 if (node->key.specified == AVTAB_ALLOWED) 460 if (node->key.specified == AVTAB_ALLOWED)
362 avd->allowed |= node->datum.data; 461 avd->allowed |= node->datum.data;
@@ -404,6 +503,14 @@ static int context_struct_compute_av(struct context *scontext,
404 PROCESS__DYNTRANSITION); 503 PROCESS__DYNTRANSITION);
405 } 504 }
406 505
506 /*
507 * If the given source and target types have boundary
508 * constraint, lazy checks have to mask any violated
509 * permission and notice it to userspace via audit.
510 */
511 type_attribute_bounds_av(scontext, tcontext,
512 tclass, requested, avd);
513
407 return 0; 514 return 0;
408 515
409inval_class: 516inval_class:
@@ -549,6 +656,69 @@ out:
549 return rc; 656 return rc;
550} 657}
551 658
659/*
660 * security_bounded_transition - check whether the given
661 * transition is directed to bounded, or not.
662 * It returns 0, if @newsid is bounded by @oldsid.
663 * Otherwise, it returns error code.
664 *
665 * @oldsid : current security identifier
666 * @newsid : destinated security identifier
667 */
668int security_bounded_transition(u32 old_sid, u32 new_sid)
669{
670 struct context *old_context, *new_context;
671 struct type_datum *type;
672 int index;
673 int rc = -EINVAL;
674
675 read_lock(&policy_rwlock);
676
677 old_context = sidtab_search(&sidtab, old_sid);
678 if (!old_context) {
679 printk(KERN_ERR "SELinux: %s: unrecognized SID %u\n",
680 __func__, old_sid);
681 goto out;
682 }
683
684 new_context = sidtab_search(&sidtab, new_sid);
685 if (!new_context) {
686 printk(KERN_ERR "SELinux: %s: unrecognized SID %u\n",
687 __func__, new_sid);
688 goto out;
689 }
690
691 /* type/domain unchaned */
692 if (old_context->type == new_context->type) {
693 rc = 0;
694 goto out;
695 }
696
697 index = new_context->type;
698 while (true) {
699 type = policydb.type_val_to_struct[index - 1];
700 BUG_ON(!type);
701
702 /* not bounded anymore */
703 if (!type->bounds) {
704 rc = -EPERM;
705 break;
706 }
707
708 /* @newsid is bounded by @oldsid */
709 if (type->bounds == old_context->type) {
710 rc = 0;
711 break;
712 }
713 index = type->bounds;
714 }
715out:
716 read_unlock(&policy_rwlock);
717
718 return rc;
719}
720
721
552/** 722/**
553 * security_compute_av - Compute access vector decisions. 723 * security_compute_av - Compute access vector decisions.
554 * @ssid: source security identifier 724 * @ssid: source security identifier
@@ -794,7 +964,7 @@ static int string_to_context_struct(struct policydb *pol,
794 *p++ = 0; 964 *p++ = 0;
795 965
796 typdatum = hashtab_search(pol->p_types.table, scontextp); 966 typdatum = hashtab_search(pol->p_types.table, scontextp);
797 if (!typdatum) 967 if (!typdatum || typdatum->attribute)
798 goto out; 968 goto out;
799 969
800 ctx->type = typdatum->value; 970 ctx->type = typdatum->value;
@@ -811,11 +981,12 @@ static int string_to_context_struct(struct policydb *pol,
811 /* Check the validity of the new context. */ 981 /* Check the validity of the new context. */
812 if (!policydb_context_isvalid(pol, ctx)) { 982 if (!policydb_context_isvalid(pol, ctx)) {
813 rc = -EINVAL; 983 rc = -EINVAL;
814 context_destroy(ctx);
815 goto out; 984 goto out;
816 } 985 }
817 rc = 0; 986 rc = 0;
818out: 987out:
988 if (rc)
989 context_destroy(ctx);
819 return rc; 990 return rc;
820} 991}
821 992
@@ -868,8 +1039,7 @@ static int security_context_to_sid_core(const char *scontext, u32 scontext_len,
868 } else if (rc) 1039 } else if (rc)
869 goto out; 1040 goto out;
870 rc = sidtab_context_to_sid(&sidtab, &context, sid); 1041 rc = sidtab_context_to_sid(&sidtab, &context, sid);
871 if (rc) 1042 context_destroy(&context);
872 context_destroy(&context);
873out: 1043out:
874 read_unlock(&policy_rwlock); 1044 read_unlock(&policy_rwlock);
875 kfree(scontext2); 1045 kfree(scontext2);
@@ -1037,7 +1207,7 @@ static int security_compute_sid(u32 ssid,
1037 /* If no permanent rule, also check for enabled conditional rules */ 1207 /* If no permanent rule, also check for enabled conditional rules */
1038 if (!avdatum) { 1208 if (!avdatum) {
1039 node = avtab_search_node(&policydb.te_cond_avtab, &avkey); 1209 node = avtab_search_node(&policydb.te_cond_avtab, &avkey);
1040 for (; node != NULL; node = avtab_search_node_next(node, specified)) { 1210 for (; node; node = avtab_search_node_next(node, specified)) {
1041 if (node->key.specified & AVTAB_ENABLED) { 1211 if (node->key.specified & AVTAB_ENABLED) {
1042 avdatum = &node->datum; 1212 avdatum = &node->datum;
1043 break; 1213 break;
@@ -2050,7 +2220,7 @@ int security_set_bools(int len, int *values)
2050 policydb.bool_val_to_struct[i]->state = 0; 2220 policydb.bool_val_to_struct[i]->state = 0;
2051 } 2221 }
2052 2222
2053 for (cur = policydb.cond_list; cur != NULL; cur = cur->next) { 2223 for (cur = policydb.cond_list; cur; cur = cur->next) {
2054 rc = evaluate_cond_node(&policydb, cur); 2224 rc = evaluate_cond_node(&policydb, cur);
2055 if (rc) 2225 if (rc)
2056 goto out; 2226 goto out;
@@ -2102,7 +2272,7 @@ static int security_preserve_bools(struct policydb *p)
2102 if (booldatum) 2272 if (booldatum)
2103 booldatum->state = bvalues[i]; 2273 booldatum->state = bvalues[i];
2104 } 2274 }
2105 for (cur = p->cond_list; cur != NULL; cur = cur->next) { 2275 for (cur = p->cond_list; cur; cur = cur->next) {
2106 rc = evaluate_cond_node(p, cur); 2276 rc = evaluate_cond_node(p, cur);
2107 if (rc) 2277 if (rc)
2108 goto out; 2278 goto out;
@@ -2737,6 +2907,7 @@ int security_netlbl_secattr_to_sid(struct netlbl_lsm_secattr *secattr,
2737 if (ctx == NULL) 2907 if (ctx == NULL)
2738 goto netlbl_secattr_to_sid_return; 2908 goto netlbl_secattr_to_sid_return;
2739 2909
2910 context_init(&ctx_new);
2740 ctx_new.user = ctx->user; 2911 ctx_new.user = ctx->user;
2741 ctx_new.role = ctx->role; 2912 ctx_new.role = ctx->role;
2742 ctx_new.type = ctx->type; 2913 ctx_new.type = ctx->type;
@@ -2745,13 +2916,9 @@ int security_netlbl_secattr_to_sid(struct netlbl_lsm_secattr *secattr,
2745 if (ebitmap_netlbl_import(&ctx_new.range.level[0].cat, 2916 if (ebitmap_netlbl_import(&ctx_new.range.level[0].cat,
2746 secattr->attr.mls.cat) != 0) 2917 secattr->attr.mls.cat) != 0)
2747 goto netlbl_secattr_to_sid_return; 2918 goto netlbl_secattr_to_sid_return;
2748 ctx_new.range.level[1].cat.highbit = 2919 memcpy(&ctx_new.range.level[1].cat,
2749 ctx_new.range.level[0].cat.highbit; 2920 &ctx_new.range.level[0].cat,
2750 ctx_new.range.level[1].cat.node = 2921 sizeof(ctx_new.range.level[0].cat));
2751 ctx_new.range.level[0].cat.node;
2752 } else {
2753 ebitmap_init(&ctx_new.range.level[0].cat);
2754 ebitmap_init(&ctx_new.range.level[1].cat);
2755 } 2922 }
2756 if (mls_context_isvalid(&policydb, &ctx_new) != 1) 2923 if (mls_context_isvalid(&policydb, &ctx_new) != 1)
2757 goto netlbl_secattr_to_sid_return_cleanup; 2924 goto netlbl_secattr_to_sid_return_cleanup;
@@ -2788,7 +2955,7 @@ netlbl_secattr_to_sid_return_cleanup:
2788 */ 2955 */
2789int security_netlbl_sid_to_secattr(u32 sid, struct netlbl_lsm_secattr *secattr) 2956int security_netlbl_sid_to_secattr(u32 sid, struct netlbl_lsm_secattr *secattr)
2790{ 2957{
2791 int rc = -ENOENT; 2958 int rc;
2792 struct context *ctx; 2959 struct context *ctx;
2793 2960
2794 if (!ss_initialized) 2961 if (!ss_initialized)
@@ -2796,11 +2963,18 @@ int security_netlbl_sid_to_secattr(u32 sid, struct netlbl_lsm_secattr *secattr)
2796 2963
2797 read_lock(&policy_rwlock); 2964 read_lock(&policy_rwlock);
2798 ctx = sidtab_search(&sidtab, sid); 2965 ctx = sidtab_search(&sidtab, sid);
2799 if (ctx == NULL) 2966 if (ctx == NULL) {
2967 rc = -ENOENT;
2800 goto netlbl_sid_to_secattr_failure; 2968 goto netlbl_sid_to_secattr_failure;
2969 }
2801 secattr->domain = kstrdup(policydb.p_type_val_to_name[ctx->type - 1], 2970 secattr->domain = kstrdup(policydb.p_type_val_to_name[ctx->type - 1],
2802 GFP_ATOMIC); 2971 GFP_ATOMIC);
2803 secattr->flags |= NETLBL_SECATTR_DOMAIN_CPY; 2972 if (secattr->domain == NULL) {
2973 rc = -ENOMEM;
2974 goto netlbl_sid_to_secattr_failure;
2975 }
2976 secattr->attr.secid = sid;
2977 secattr->flags |= NETLBL_SECATTR_DOMAIN_CPY | NETLBL_SECATTR_SECID;
2804 mls_export_netlbl_lvl(ctx, secattr); 2978 mls_export_netlbl_lvl(ctx, secattr);
2805 rc = mls_export_netlbl_cat(ctx, secattr); 2979 rc = mls_export_netlbl_cat(ctx, secattr);
2806 if (rc != 0) 2980 if (rc != 0)
diff --git a/security/selinux/ss/sidtab.c b/security/selinux/ss/sidtab.c
index a81ded104129..e817989764cd 100644
--- a/security/selinux/ss/sidtab.c
+++ b/security/selinux/ss/sidtab.c
@@ -43,7 +43,7 @@ int sidtab_insert(struct sidtab *s, u32 sid, struct context *context)
43 hvalue = SIDTAB_HASH(sid); 43 hvalue = SIDTAB_HASH(sid);
44 prev = NULL; 44 prev = NULL;
45 cur = s->htable[hvalue]; 45 cur = s->htable[hvalue];
46 while (cur != NULL && sid > cur->sid) { 46 while (cur && sid > cur->sid) {
47 prev = cur; 47 prev = cur;
48 cur = cur->next; 48 cur = cur->next;
49 } 49 }
@@ -92,7 +92,7 @@ static struct context *sidtab_search_core(struct sidtab *s, u32 sid, int force)
92 92
93 hvalue = SIDTAB_HASH(sid); 93 hvalue = SIDTAB_HASH(sid);
94 cur = s->htable[hvalue]; 94 cur = s->htable[hvalue];
95 while (cur != NULL && sid > cur->sid) 95 while (cur && sid > cur->sid)
96 cur = cur->next; 96 cur = cur->next;
97 97
98 if (force && cur && sid == cur->sid && cur->context.len) 98 if (force && cur && sid == cur->sid && cur->context.len)
@@ -103,7 +103,7 @@ static struct context *sidtab_search_core(struct sidtab *s, u32 sid, int force)
103 sid = SECINITSID_UNLABELED; 103 sid = SECINITSID_UNLABELED;
104 hvalue = SIDTAB_HASH(sid); 104 hvalue = SIDTAB_HASH(sid);
105 cur = s->htable[hvalue]; 105 cur = s->htable[hvalue];
106 while (cur != NULL && sid > cur->sid) 106 while (cur && sid > cur->sid)
107 cur = cur->next; 107 cur = cur->next;
108 if (!cur || sid != cur->sid) 108 if (!cur || sid != cur->sid)
109 return NULL; 109 return NULL;
@@ -136,7 +136,7 @@ int sidtab_map(struct sidtab *s,
136 136
137 for (i = 0; i < SIDTAB_SIZE; i++) { 137 for (i = 0; i < SIDTAB_SIZE; i++) {
138 cur = s->htable[i]; 138 cur = s->htable[i];
139 while (cur != NULL) { 139 while (cur) {
140 rc = apply(cur->sid, &cur->context, args); 140 rc = apply(cur->sid, &cur->context, args);
141 if (rc) 141 if (rc)
142 goto out; 142 goto out;
@@ -155,7 +155,7 @@ static inline u32 sidtab_search_context(struct sidtab *s,
155 155
156 for (i = 0; i < SIDTAB_SIZE; i++) { 156 for (i = 0; i < SIDTAB_SIZE; i++) {
157 cur = s->htable[i]; 157 cur = s->htable[i];
158 while (cur != NULL) { 158 while (cur) {
159 if (context_cmp(&cur->context, context)) 159 if (context_cmp(&cur->context, context))
160 return cur->sid; 160 return cur->sid;
161 cur = cur->next; 161 cur = cur->next;
@@ -242,7 +242,7 @@ void sidtab_destroy(struct sidtab *s)
242 242
243 for (i = 0; i < SIDTAB_SIZE; i++) { 243 for (i = 0; i < SIDTAB_SIZE; i++) {
244 cur = s->htable[i]; 244 cur = s->htable[i];
245 while (cur != NULL) { 245 while (cur) {
246 temp = cur; 246 temp = cur;
247 cur = cur->next; 247 cur = cur->next;
248 context_destroy(&temp->context); 248 context_destroy(&temp->context);