summaryrefslogtreecommitdiffstats
path: root/security/selinux/netlabel.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/selinux/netlabel.c')
-rw-r--r--security/selinux/netlabel.c148
1 files changed, 132 insertions, 16 deletions
diff --git a/security/selinux/netlabel.c b/security/selinux/netlabel.c
index 2c297b995b16..186e727b737b 100644
--- a/security/selinux/netlabel.c
+++ b/security/selinux/netlabel.c
@@ -59,7 +59,7 @@ static int selinux_netlbl_sidlookup_cached(struct sk_buff *skb,
59{ 59{
60 int rc; 60 int rc;
61 61
62 rc = security_netlbl_secattr_to_sid(secattr, sid); 62 rc = security_netlbl_secattr_to_sid(&selinux_state, secattr, sid);
63 if (rc == 0 && 63 if (rc == 0 &&
64 (secattr->flags & NETLBL_SECATTR_CACHEABLE) && 64 (secattr->flags & NETLBL_SECATTR_CACHEABLE) &&
65 (secattr->flags & NETLBL_SECATTR_CACHE)) 65 (secattr->flags & NETLBL_SECATTR_CACHE))
@@ -90,7 +90,8 @@ static struct netlbl_lsm_secattr *selinux_netlbl_sock_genattr(struct sock *sk)
90 secattr = netlbl_secattr_alloc(GFP_ATOMIC); 90 secattr = netlbl_secattr_alloc(GFP_ATOMIC);
91 if (secattr == NULL) 91 if (secattr == NULL)
92 return NULL; 92 return NULL;
93 rc = security_netlbl_sid_to_secattr(sksec->sid, secattr); 93 rc = security_netlbl_sid_to_secattr(&selinux_state, sksec->sid,
94 secattr);
94 if (rc != 0) { 95 if (rc != 0) {
95 netlbl_secattr_free(secattr); 96 netlbl_secattr_free(secattr);
96 return NULL; 97 return NULL;
@@ -249,6 +250,7 @@ int selinux_netlbl_skbuff_setsid(struct sk_buff *skb,
249 sk = skb_to_full_sk(skb); 250 sk = skb_to_full_sk(skb);
250 if (sk != NULL) { 251 if (sk != NULL) {
251 struct sk_security_struct *sksec = sk->sk_security; 252 struct sk_security_struct *sksec = sk->sk_security;
253
252 if (sksec->nlbl_state != NLBL_REQSKB) 254 if (sksec->nlbl_state != NLBL_REQSKB)
253 return 0; 255 return 0;
254 secattr = selinux_netlbl_sock_getattr(sk, sid); 256 secattr = selinux_netlbl_sock_getattr(sk, sid);
@@ -256,7 +258,8 @@ int selinux_netlbl_skbuff_setsid(struct sk_buff *skb,
256 if (secattr == NULL) { 258 if (secattr == NULL) {
257 secattr = &secattr_storage; 259 secattr = &secattr_storage;
258 netlbl_secattr_init(secattr); 260 netlbl_secattr_init(secattr);
259 rc = security_netlbl_sid_to_secattr(sid, secattr); 261 rc = security_netlbl_sid_to_secattr(&selinux_state, sid,
262 secattr);
260 if (rc != 0) 263 if (rc != 0)
261 goto skbuff_setsid_return; 264 goto skbuff_setsid_return;
262 } 265 }
@@ -270,6 +273,62 @@ skbuff_setsid_return:
270} 273}
271 274
272/** 275/**
276 * selinux_netlbl_sctp_assoc_request - Label an incoming sctp association.
277 * @ep: incoming association endpoint.
278 * @skb: the packet.
279 *
280 * Description:
281 * A new incoming connection is represented by @ep, ......
282 * Returns zero on success, negative values on failure.
283 *
284 */
285int selinux_netlbl_sctp_assoc_request(struct sctp_endpoint *ep,
286 struct sk_buff *skb)
287{
288 int rc;
289 struct netlbl_lsm_secattr secattr;
290 struct sk_security_struct *sksec = ep->base.sk->sk_security;
291 struct sockaddr *addr;
292 struct sockaddr_in addr4;
293#if IS_ENABLED(CONFIG_IPV6)
294 struct sockaddr_in6 addr6;
295#endif
296
297 if (ep->base.sk->sk_family != PF_INET &&
298 ep->base.sk->sk_family != PF_INET6)
299 return 0;
300
301 netlbl_secattr_init(&secattr);
302 rc = security_netlbl_sid_to_secattr(&selinux_state,
303 ep->secid, &secattr);
304 if (rc != 0)
305 goto assoc_request_return;
306
307 /* Move skb hdr address info to a struct sockaddr and then call
308 * netlbl_conn_setattr().
309 */
310 if (ip_hdr(skb)->version == 4) {
311 addr4.sin_family = AF_INET;
312 addr4.sin_addr.s_addr = ip_hdr(skb)->saddr;
313 addr = (struct sockaddr *)&addr4;
314#if IS_ENABLED(CONFIG_IPV6)
315 } else {
316 addr6.sin6_family = AF_INET6;
317 addr6.sin6_addr = ipv6_hdr(skb)->saddr;
318 addr = (struct sockaddr *)&addr6;
319#endif
320 }
321
322 rc = netlbl_conn_setattr(ep->base.sk, addr, &secattr);
323 if (rc == 0)
324 sksec->nlbl_state = NLBL_LABELED;
325
326assoc_request_return:
327 netlbl_secattr_destroy(&secattr);
328 return rc;
329}
330
331/**
273 * selinux_netlbl_inet_conn_request - Label an incoming stream connection 332 * selinux_netlbl_inet_conn_request - Label an incoming stream connection
274 * @req: incoming connection request socket 333 * @req: incoming connection request socket
275 * 334 *
@@ -289,7 +348,8 @@ int selinux_netlbl_inet_conn_request(struct request_sock *req, u16 family)
289 return 0; 348 return 0;
290 349
291 netlbl_secattr_init(&secattr); 350 netlbl_secattr_init(&secattr);
292 rc = security_netlbl_sid_to_secattr(req->secid, &secattr); 351 rc = security_netlbl_sid_to_secattr(&selinux_state, req->secid,
352 &secattr);
293 if (rc != 0) 353 if (rc != 0)
294 goto inet_conn_request_return; 354 goto inet_conn_request_return;
295 rc = netlbl_req_setattr(req, &secattr); 355 rc = netlbl_req_setattr(req, &secattr);
@@ -319,6 +379,22 @@ void selinux_netlbl_inet_csk_clone(struct sock *sk, u16 family)
319} 379}
320 380
321/** 381/**
382 * selinux_netlbl_sctp_sk_clone - Copy state to the newly created sock
383 * @sk: current sock
384 * @newsk: the new sock
385 *
386 * Description:
387 * Called whenever a new socket is created by accept(2) or sctp_peeloff(3).
388 */
389void selinux_netlbl_sctp_sk_clone(struct sock *sk, struct sock *newsk)
390{
391 struct sk_security_struct *sksec = sk->sk_security;
392 struct sk_security_struct *newsksec = newsk->sk_security;
393
394 newsksec->nlbl_state = sksec->nlbl_state;
395}
396
397/**
322 * selinux_netlbl_socket_post_create - Label a socket using NetLabel 398 * selinux_netlbl_socket_post_create - Label a socket using NetLabel
323 * @sock: the socket to label 399 * @sock: the socket to label
324 * @family: protocol family 400 * @family: protocol family
@@ -402,7 +478,8 @@ int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec,
402 perm = RAWIP_SOCKET__RECVFROM; 478 perm = RAWIP_SOCKET__RECVFROM;
403 } 479 }
404 480
405 rc = avc_has_perm(sksec->sid, nlbl_sid, sksec->sclass, perm, ad); 481 rc = avc_has_perm(&selinux_state,
482 sksec->sid, nlbl_sid, sksec->sclass, perm, ad);
406 if (rc == 0) 483 if (rc == 0)
407 return 0; 484 return 0;
408 485
@@ -469,7 +546,8 @@ int selinux_netlbl_socket_setsockopt(struct socket *sock,
469} 546}
470 547
471/** 548/**
472 * selinux_netlbl_socket_connect - Label a client-side socket on connect 549 * selinux_netlbl_socket_connect_helper - Help label a client-side socket on
550 * connect
473 * @sk: the socket to label 551 * @sk: the socket to label
474 * @addr: the destination address 552 * @addr: the destination address
475 * 553 *
@@ -478,18 +556,13 @@ int selinux_netlbl_socket_setsockopt(struct socket *sock,
478 * Returns zero values on success, negative values on failure. 556 * Returns zero values on success, negative values on failure.
479 * 557 *
480 */ 558 */
481int selinux_netlbl_socket_connect(struct sock *sk, struct sockaddr *addr) 559static int selinux_netlbl_socket_connect_helper(struct sock *sk,
560 struct sockaddr *addr)
482{ 561{
483 int rc; 562 int rc;
484 struct sk_security_struct *sksec = sk->sk_security; 563 struct sk_security_struct *sksec = sk->sk_security;
485 struct netlbl_lsm_secattr *secattr; 564 struct netlbl_lsm_secattr *secattr;
486 565
487 if (sksec->nlbl_state != NLBL_REQSKB &&
488 sksec->nlbl_state != NLBL_CONNLABELED)
489 return 0;
490
491 lock_sock(sk);
492
493 /* connected sockets are allowed to disconnect when the address family 566 /* connected sockets are allowed to disconnect when the address family
494 * is set to AF_UNSPEC, if that is what is happening we want to reset 567 * is set to AF_UNSPEC, if that is what is happening we want to reset
495 * the socket */ 568 * the socket */
@@ -497,18 +570,61 @@ int selinux_netlbl_socket_connect(struct sock *sk, struct sockaddr *addr)
497 netlbl_sock_delattr(sk); 570 netlbl_sock_delattr(sk);
498 sksec->nlbl_state = NLBL_REQSKB; 571 sksec->nlbl_state = NLBL_REQSKB;
499 rc = 0; 572 rc = 0;
500 goto socket_connect_return; 573 return rc;
501 } 574 }
502 secattr = selinux_netlbl_sock_genattr(sk); 575 secattr = selinux_netlbl_sock_genattr(sk);
503 if (secattr == NULL) { 576 if (secattr == NULL) {
504 rc = -ENOMEM; 577 rc = -ENOMEM;
505 goto socket_connect_return; 578 return rc;
506 } 579 }
507 rc = netlbl_conn_setattr(sk, addr, secattr); 580 rc = netlbl_conn_setattr(sk, addr, secattr);
508 if (rc == 0) 581 if (rc == 0)
509 sksec->nlbl_state = NLBL_CONNLABELED; 582 sksec->nlbl_state = NLBL_CONNLABELED;
510 583
511socket_connect_return: 584 return rc;
585}
586
587/**
588 * selinux_netlbl_socket_connect_locked - Label a client-side socket on
589 * connect
590 * @sk: the socket to label
591 * @addr: the destination address
592 *
593 * Description:
594 * Attempt to label a connected socket that already has the socket locked
595 * with NetLabel using the given address.
596 * Returns zero values on success, negative values on failure.
597 *
598 */
599int selinux_netlbl_socket_connect_locked(struct sock *sk,
600 struct sockaddr *addr)
601{
602 struct sk_security_struct *sksec = sk->sk_security;
603
604 if (sksec->nlbl_state != NLBL_REQSKB &&
605 sksec->nlbl_state != NLBL_CONNLABELED)
606 return 0;
607
608 return selinux_netlbl_socket_connect_helper(sk, addr);
609}
610
611/**
612 * selinux_netlbl_socket_connect - Label a client-side socket on connect
613 * @sk: the socket to label
614 * @addr: the destination address
615 *
616 * Description:
617 * Attempt to label a connected socket with NetLabel using the given address.
618 * Returns zero values on success, negative values on failure.
619 *
620 */
621int selinux_netlbl_socket_connect(struct sock *sk, struct sockaddr *addr)
622{
623 int rc;
624
625 lock_sock(sk);
626 rc = selinux_netlbl_socket_connect_locked(sk, addr);
512 release_sock(sk); 627 release_sock(sk);
628
513 return rc; 629 return rc;
514} 630}