diff options
Diffstat (limited to 'security/selinux/netlabel.c')
-rw-r--r-- | security/selinux/netlabel.c | 68 |
1 files changed, 66 insertions, 2 deletions
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 | ||
93 | sock_setsid_return: | 118 | sock_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 | */ | ||
221 | int 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 | |||
244 | skbuff_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 |