aboutsummaryrefslogtreecommitdiffstats
path: root/security
diff options
context:
space:
mode:
authorPaul Moore <paul.moore@hp.com>2008-10-10 10:16:32 -0400
committerPaul Moore <paul.moore@hp.com>2008-10-10 10:16:32 -0400
commit948bf85c1bc9a84754786a9d5dd99b7ecc46451e (patch)
treea4706be1f4a5a37408774ef3c4cab8cf2e7775b5 /security
parent63c41688743760631188cf0f4ae986a6793ccb0a (diff)
netlabel: Add functionality to set the security attributes of a packet
This patch builds upon the new NetLabel address selector functionality by providing the NetLabel KAPI and CIPSO engine support needed to enable the new packet-based labeling. The only new addition to the NetLabel KAPI at this point is shown below: * int netlbl_skbuff_setattr(skb, family, secattr) ... and is designed to be called from a Netfilter hook after the packet's IP header has been populated such as in the FORWARD or LOCAL_OUT hooks. This patch also provides the necessary SELinux hooks to support this new functionality. Smack support is not currently included due to uncertainty regarding the permissions needed to expand the Smack network access controls. Signed-off-by: Paul Moore <paul.moore@hp.com> Reviewed-by: James Morris <jmorris@namei.org>
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