aboutsummaryrefslogtreecommitdiffstats
path: root/security/selinux/netlabel.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/selinux/netlabel.c')
-rw-r--r--security/selinux/netlabel.c115
1 files changed, 79 insertions, 36 deletions
diff --git a/security/selinux/netlabel.c b/security/selinux/netlabel.c
index b22b7dafa0e3..f58701a7b728 100644
--- a/security/selinux/netlabel.c
+++ b/security/selinux/netlabel.c
@@ -68,6 +68,38 @@ static int selinux_netlbl_sidlookup_cached(struct sk_buff *skb,
68} 68}
69 69
70/** 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/**
71 * selinux_netlbl_sock_setsid - Label a socket using the NetLabel mechanism 103 * selinux_netlbl_sock_setsid - Label a socket using the NetLabel mechanism
72 * @sk: the socket to label 104 * @sk: the socket to label
73 * 105 *
@@ -80,17 +112,15 @@ static int selinux_netlbl_sock_setsid(struct sock *sk)
80{ 112{
81 int rc; 113 int rc;
82 struct sk_security_struct *sksec = sk->sk_security; 114 struct sk_security_struct *sksec = sk->sk_security;
83 struct netlbl_lsm_secattr secattr; 115 struct netlbl_lsm_secattr *secattr;
84 116
85 if (sksec->nlbl_state != NLBL_REQUIRE) 117 if (sksec->nlbl_state != NLBL_REQUIRE)
86 return 0; 118 return 0;
87 119
88 netlbl_secattr_init(&secattr); 120 secattr = selinux_netlbl_sock_genattr(sk);
89 121 if (secattr == NULL)
90 rc = security_netlbl_sid_to_secattr(sksec->sid, &secattr); 122 return -ENOMEM;
91 if (rc != 0) 123 rc = netlbl_sock_setattr(sk, secattr);
92 goto sock_setsid_return;
93 rc = netlbl_sock_setattr(sk, &secattr);
94 switch (rc) { 124 switch (rc) {
95 case 0: 125 case 0:
96 sksec->nlbl_state = NLBL_LABELED; 126 sksec->nlbl_state = NLBL_LABELED;
@@ -101,8 +131,6 @@ static int selinux_netlbl_sock_setsid(struct sock *sk)
101 break; 131 break;
102 } 132 }
103 133
104sock_setsid_return:
105 netlbl_secattr_destroy(&secattr);
106 return rc; 134 return rc;
107} 135}
108 136
@@ -137,6 +165,20 @@ void selinux_netlbl_err(struct sk_buff *skb, int error, int gateway)
137} 165}
138 166
139/** 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/**
140 * selinux_netlbl_sk_security_reset - Reset the NetLabel fields 182 * selinux_netlbl_sk_security_reset - Reset the NetLabel fields
141 * @ssec: the sk_security_struct 183 * @ssec: the sk_security_struct
142 * @family: the socket family 184 * @family: the socket family
@@ -209,7 +251,8 @@ int selinux_netlbl_skbuff_setsid(struct sk_buff *skb,
209 u32 sid) 251 u32 sid)
210{ 252{
211 int rc; 253 int rc;
212 struct netlbl_lsm_secattr secattr; 254 struct netlbl_lsm_secattr secattr_storage;
255 struct netlbl_lsm_secattr *secattr = NULL;
213 struct sock *sk; 256 struct sock *sk;
214 257
215 /* if this is a locally generated packet check to see if it is already 258 /* if this is a locally generated packet check to see if it is already
@@ -219,16 +262,21 @@ int selinux_netlbl_skbuff_setsid(struct sk_buff *skb,
219 struct sk_security_struct *sksec = sk->sk_security; 262 struct sk_security_struct *sksec = sk->sk_security;
220 if (sksec->nlbl_state != NLBL_REQSKB) 263 if (sksec->nlbl_state != NLBL_REQSKB)
221 return 0; 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;
222 } 273 }
223 274
224 netlbl_secattr_init(&secattr); 275 rc = netlbl_skbuff_setattr(skb, family, secattr);
225 rc = security_netlbl_sid_to_secattr(sid, &secattr);
226 if (rc != 0)
227 goto skbuff_setsid_return;
228 rc = netlbl_skbuff_setattr(skb, family, &secattr);
229 276
230skbuff_setsid_return: 277skbuff_setsid_return:
231 netlbl_secattr_destroy(&secattr); 278 if (secattr == &secattr_storage)
279 netlbl_secattr_destroy(secattr);
232 return rc; 280 return rc;
233} 281}
234 282
@@ -245,18 +293,18 @@ void selinux_netlbl_inet_conn_established(struct sock *sk, u16 family)
245{ 293{
246 int rc; 294 int rc;
247 struct sk_security_struct *sksec = sk->sk_security; 295 struct sk_security_struct *sksec = sk->sk_security;
248 struct netlbl_lsm_secattr secattr; 296 struct netlbl_lsm_secattr *secattr;
249 struct inet_sock *sk_inet = inet_sk(sk); 297 struct inet_sock *sk_inet = inet_sk(sk);
250 struct sockaddr_in addr; 298 struct sockaddr_in addr;
251 299
252 if (sksec->nlbl_state != NLBL_REQUIRE) 300 if (sksec->nlbl_state != NLBL_REQUIRE)
253 return; 301 return;
254 302
255 netlbl_secattr_init(&secattr); 303 secattr = selinux_netlbl_sock_genattr(sk);
256 if (security_netlbl_sid_to_secattr(sksec->sid, &secattr) != 0) 304 if (secattr == NULL)
257 goto inet_conn_established_return; 305 return;
258 306
259 rc = netlbl_sock_setattr(sk, &secattr); 307 rc = netlbl_sock_setattr(sk, secattr);
260 switch (rc) { 308 switch (rc) {
261 case 0: 309 case 0:
262 sksec->nlbl_state = NLBL_LABELED; 310 sksec->nlbl_state = NLBL_LABELED;
@@ -266,13 +314,13 @@ void selinux_netlbl_inet_conn_established(struct sock *sk, u16 family)
266 * labeling protocols */ 314 * labeling protocols */
267 if (family != PF_INET) { 315 if (family != PF_INET) {
268 sksec->nlbl_state = NLBL_UNSET; 316 sksec->nlbl_state = NLBL_UNSET;
269 goto inet_conn_established_return; 317 return;
270 } 318 }
271 319
272 addr.sin_family = family; 320 addr.sin_family = family;
273 addr.sin_addr.s_addr = sk_inet->daddr; 321 addr.sin_addr.s_addr = sk_inet->daddr;
274 if (netlbl_conn_setattr(sk, (struct sockaddr *)&addr, 322 if (netlbl_conn_setattr(sk, (struct sockaddr *)&addr,
275 &secattr) != 0) { 323 secattr) != 0) {
276 /* we failed to label the connected socket (could be 324 /* we failed to label the connected socket (could be
277 * for a variety of reasons, the actual "why" isn't 325 * for a variety of reasons, the actual "why" isn't
278 * important here) so we have to go to our backup plan, 326 * important here) so we have to go to our backup plan,
@@ -300,10 +348,6 @@ void selinux_netlbl_inet_conn_established(struct sock *sk, u16 family)
300 * return an error code */ 348 * return an error code */
301 break; 349 break;
302 } 350 }
303
304inet_conn_established_return:
305 netlbl_secattr_destroy(&secattr);
306 return;
307} 351}
308 352
309/** 353/**
@@ -468,13 +512,12 @@ int selinux_netlbl_socket_connect(struct sock *sk, struct sockaddr *addr)
468{ 512{
469 int rc; 513 int rc;
470 struct sk_security_struct *sksec = sk->sk_security; 514 struct sk_security_struct *sksec = sk->sk_security;
471 struct netlbl_lsm_secattr secattr; 515 struct netlbl_lsm_secattr *secattr;
472 516
473 if (sksec->nlbl_state != NLBL_REQSKB && 517 if (sksec->nlbl_state != NLBL_REQSKB &&
474 sksec->nlbl_state != NLBL_CONNLABELED) 518 sksec->nlbl_state != NLBL_CONNLABELED)
475 return 0; 519 return 0;
476 520
477 netlbl_secattr_init(&secattr);
478 local_bh_disable(); 521 local_bh_disable();
479 bh_lock_sock_nested(sk); 522 bh_lock_sock_nested(sk);
480 523
@@ -487,17 +530,17 @@ int selinux_netlbl_socket_connect(struct sock *sk, struct sockaddr *addr)
487 rc = 0; 530 rc = 0;
488 goto socket_connect_return; 531 goto socket_connect_return;
489 } 532 }
490 rc = security_netlbl_sid_to_secattr(sksec->sid, &secattr); 533 secattr = selinux_netlbl_sock_genattr(sk);
491 if (rc != 0) 534 if (secattr == NULL) {
535 rc = -ENOMEM;
492 goto socket_connect_return; 536 goto socket_connect_return;
493 rc = netlbl_conn_setattr(sk, addr, &secattr); 537 }
494 if (rc != 0) 538 rc = netlbl_conn_setattr(sk, addr, secattr);
495 goto socket_connect_return; 539 if (rc == 0)
496 sksec->nlbl_state = NLBL_CONNLABELED; 540 sksec->nlbl_state = NLBL_CONNLABELED;
497 541
498socket_connect_return: 542socket_connect_return:
499 bh_unlock_sock(sk); 543 bh_unlock_sock(sk);
500 local_bh_enable(); 544 local_bh_enable();
501 netlbl_secattr_destroy(&secattr);
502 return rc; 545 return rc;
503} 546}