aboutsummaryrefslogtreecommitdiffstats
path: root/security
diff options
context:
space:
mode:
Diffstat (limited to 'security')
-rw-r--r--security/selinux/hooks.c50
-rw-r--r--security/selinux/include/netlabel.h9
-rw-r--r--security/selinux/include/objsec.h1
-rw-r--r--security/selinux/netlabel.c68
4 files changed, 125 insertions, 3 deletions
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index a91146a6b37d..7432bdd5d367 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -4407,13 +4407,15 @@ static unsigned int selinux_ip_forward(struct sk_buff *skb, int ifindex,
4407 u32 peer_sid; 4407 u32 peer_sid;
4408 struct avc_audit_data ad; 4408 struct avc_audit_data ad;
4409 u8 secmark_active; 4409 u8 secmark_active;
4410 u8 netlbl_active;
4410 u8 peerlbl_active; 4411 u8 peerlbl_active;
4411 4412
4412 if (!selinux_policycap_netpeer) 4413 if (!selinux_policycap_netpeer)
4413 return NF_ACCEPT; 4414 return NF_ACCEPT;
4414 4415
4415 secmark_active = selinux_secmark_enabled(); 4416 secmark_active = selinux_secmark_enabled();
4416 peerlbl_active = netlbl_enabled() || selinux_xfrm_enabled(); 4417 netlbl_active = netlbl_enabled();
4418 peerlbl_active = netlbl_active || selinux_xfrm_enabled();
4417 if (!secmark_active && !peerlbl_active) 4419 if (!secmark_active && !peerlbl_active)
4418 return NF_ACCEPT; 4420 return NF_ACCEPT;
4419 4421
@@ -4440,6 +4442,14 @@ static unsigned int selinux_ip_forward(struct sk_buff *skb, int ifindex,
4440 SECCLASS_PACKET, PACKET__FORWARD_IN, &ad)) 4442 SECCLASS_PACKET, PACKET__FORWARD_IN, &ad))
4441 return NF_DROP; 4443 return NF_DROP;
4442 4444
4445 if (netlbl_active)
4446 /* we do this in the FORWARD path and not the POST_ROUTING
4447 * path because we want to make sure we apply the necessary
4448 * labeling before IPsec is applied so we can leverage AH
4449 * protection */
4450 if (selinux_netlbl_skbuff_setsid(skb, family, peer_sid) != 0)
4451 return NF_DROP;
4452
4443 return NF_ACCEPT; 4453 return NF_ACCEPT;
4444} 4454}
4445 4455
@@ -4463,6 +4473,37 @@ static unsigned int selinux_ipv6_forward(unsigned int hooknum,
4463} 4473}
4464#endif /* IPV6 */ 4474#endif /* IPV6 */
4465 4475
4476static unsigned int selinux_ip_output(struct sk_buff *skb,
4477 u16 family)
4478{
4479 u32 sid;
4480
4481 if (!netlbl_enabled())
4482 return NF_ACCEPT;
4483
4484 /* we do this in the LOCAL_OUT path and not the POST_ROUTING path
4485 * because we want to make sure we apply the necessary labeling
4486 * before IPsec is applied so we can leverage AH protection */
4487 if (skb->sk) {
4488 struct sk_security_struct *sksec = skb->sk->sk_security;
4489 sid = sksec->sid;
4490 } else
4491 sid = SECINITSID_KERNEL;
4492 if (selinux_netlbl_skbuff_setsid(skb, family, sid) != 0)
4493 return NF_DROP;
4494
4495 return NF_ACCEPT;
4496}
4497
4498static unsigned int selinux_ipv4_output(unsigned int hooknum,
4499 struct sk_buff *skb,
4500 const struct net_device *in,
4501 const struct net_device *out,
4502 int (*okfn)(struct sk_buff *))
4503{
4504 return selinux_ip_output(skb, PF_INET);
4505}
4506
4466static int selinux_ip_postroute_iptables_compat(struct sock *sk, 4507static int selinux_ip_postroute_iptables_compat(struct sock *sk,
4467 int ifindex, 4508 int ifindex,
4468 struct avc_audit_data *ad, 4509 struct avc_audit_data *ad,
@@ -5700,6 +5741,13 @@ static struct nf_hook_ops selinux_ipv4_ops[] = {
5700 .pf = PF_INET, 5741 .pf = PF_INET,
5701 .hooknum = NF_INET_FORWARD, 5742 .hooknum = NF_INET_FORWARD,
5702 .priority = NF_IP_PRI_SELINUX_FIRST, 5743 .priority = NF_IP_PRI_SELINUX_FIRST,
5744 },
5745 {
5746 .hook = selinux_ipv4_output,
5747 .owner = THIS_MODULE,
5748 .pf = PF_INET,
5749 .hooknum = NF_INET_LOCAL_OUT,
5750 .priority = NF_IP_PRI_SELINUX_FIRST,
5703 } 5751 }
5704}; 5752};
5705 5753
diff --git a/security/selinux/include/netlabel.h b/security/selinux/include/netlabel.h
index d4e3ac8a7fbf..b3e6ae071fc3 100644
--- a/security/selinux/include/netlabel.h
+++ b/security/selinux/include/netlabel.h
@@ -48,6 +48,9 @@ int selinux_netlbl_skbuff_getsid(struct sk_buff *skb,
48 u16 family, 48 u16 family,
49 u32 *type, 49 u32 *type,
50 u32 *sid); 50 u32 *sid);
51int selinux_netlbl_skbuff_setsid(struct sk_buff *skb,
52 u16 family,
53 u32 sid);
51 54
52void selinux_netlbl_sock_graft(struct sock *sk, struct socket *sock); 55void selinux_netlbl_sock_graft(struct sock *sk, struct socket *sock);
53int selinux_netlbl_socket_post_create(struct socket *sock); 56int selinux_netlbl_socket_post_create(struct socket *sock);
@@ -88,6 +91,12 @@ static inline int selinux_netlbl_skbuff_getsid(struct sk_buff *skb,
88 *sid = SECSID_NULL; 91 *sid = SECSID_NULL;
89 return 0; 92 return 0;
90} 93}
94static inline int selinux_netlbl_skbuff_setsid(struct sk_buff *skb,
95 u16 family,
96 u32 sid)
97{
98 return 0;
99}
91 100
92static inline void selinux_netlbl_sock_graft(struct sock *sk, 101static inline void selinux_netlbl_sock_graft(struct sock *sk,
93 struct socket *sock) 102 struct socket *sock)
diff --git a/security/selinux/include/objsec.h b/security/selinux/include/objsec.h
index 91070ab874ce..f46dd1c3d01c 100644
--- a/security/selinux/include/objsec.h
+++ b/security/selinux/include/objsec.h
@@ -117,6 +117,7 @@ struct sk_security_struct {
117 NLBL_UNSET = 0, 117 NLBL_UNSET = 0,
118 NLBL_REQUIRE, 118 NLBL_REQUIRE,
119 NLBL_LABELED, 119 NLBL_LABELED,
120 NLBL_REQSKB,
120 } nlbl_state; 121 } nlbl_state;
121#endif 122#endif
122}; 123};
diff --git a/security/selinux/netlabel.c b/security/selinux/netlabel.c
index 4053f7fc95fb..090404d6e512 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
@@ -31,6 +31,8 @@
31#include <linux/rcupdate.h> 31#include <linux/rcupdate.h>
32#include <net/sock.h> 32#include <net/sock.h>
33#include <net/netlabel.h> 33#include <net/netlabel.h>
34#include <net/inet_sock.h>
35#include <net/inet_connection_sock.h>
34 36
35#include "objsec.h" 37#include "objsec.h"
36#include "security.h" 38#include "security.h"
@@ -77,6 +79,8 @@ static int selinux_netlbl_sock_setsid(struct sock *sk)
77 int rc; 79 int rc;
78 struct sk_security_struct *sksec = sk->sk_security; 80 struct sk_security_struct *sksec = sk->sk_security;
79 struct netlbl_lsm_secattr secattr; 81 struct netlbl_lsm_secattr secattr;
82 struct inet_sock *sk_inet;
83 struct inet_connection_sock *sk_conn;
80 84
81 if (sksec->nlbl_state != NLBL_REQUIRE) 85 if (sksec->nlbl_state != NLBL_REQUIRE)
82 return 0; 86 return 0;
@@ -87,8 +91,29 @@ static int selinux_netlbl_sock_setsid(struct sock *sk)
87 if (rc != 0) 91 if (rc != 0)
88 goto sock_setsid_return; 92 goto sock_setsid_return;
89 rc = netlbl_sock_setattr(sk, &secattr); 93 rc = netlbl_sock_setattr(sk, &secattr);
90 if (rc == 0) 94 switch (rc) {
95 case 0:
91 sksec->nlbl_state = NLBL_LABELED; 96 sksec->nlbl_state = NLBL_LABELED;
97 break;
98 case -EDESTADDRREQ:
99 /* we are going to possibly end up labeling the individual
100 * packets later which is problematic for stream sockets
101 * because of the additional IP header size, our solution is to
102 * allow for the maximum IP header length (40 bytes for IPv4,
103 * we don't have to worry about IPv6 yet) just in case */
104 sk_inet = inet_sk(sk);
105 if (sk_inet->is_icsk) {
106 sk_conn = inet_csk(sk);
107 if (sk_inet->opt)
108 sk_conn->icsk_ext_hdr_len -=
109 sk_inet->opt->optlen;
110 sk_conn->icsk_ext_hdr_len += 40;
111 sk_conn->icsk_sync_mss(sk, sk_conn->icsk_pmtu_cookie);
112 }
113 sksec->nlbl_state = NLBL_REQSKB;
114 rc = 0;
115 break;
116 }
92 117
93sock_setsid_return: 118sock_setsid_return:
94 netlbl_secattr_destroy(&secattr); 119 netlbl_secattr_destroy(&secattr);
@@ -183,6 +208,45 @@ int selinux_netlbl_skbuff_getsid(struct sk_buff *skb,
183} 208}
184 209
185/** 210/**
211 * selinux_netlbl_skbuff_setsid - Set the NetLabel on a packet given a sid
212 * @skb: the packet
213 * @family: protocol family
214 * @sid: the SID
215 *
216 * Description
217 * Call the NetLabel mechanism to set the label of a packet using @sid.
218 * Returns zero on auccess, negative values on failure.
219 *
220 */
221int selinux_netlbl_skbuff_setsid(struct sk_buff *skb,
222 u16 family,
223 u32 sid)
224{
225 int rc;
226 struct netlbl_lsm_secattr secattr;
227 struct sock *sk;
228
229 /* if this is a locally generated packet check to see if it is already
230 * being labeled by it's parent socket, if it is just exit */
231 sk = skb->sk;
232 if (sk != NULL) {
233 struct sk_security_struct *sksec = sk->sk_security;
234 if (sksec->nlbl_state != NLBL_REQSKB)
235 return 0;
236 }
237
238 netlbl_secattr_init(&secattr);
239 rc = security_netlbl_sid_to_secattr(sid, &secattr);
240 if (rc != 0)
241 goto skbuff_setsid_return;
242 rc = netlbl_skbuff_setattr(skb, family, &secattr);
243
244skbuff_setsid_return:
245 netlbl_secattr_destroy(&secattr);
246 return rc;
247}
248
249/**
186 * selinux_netlbl_sock_graft - Netlabel the new socket 250 * selinux_netlbl_sock_graft - Netlabel the new socket
187 * @sk: the new connection 251 * @sk: the new connection
188 * @sock: the new socket 252 * @sock: the new socket