netlabel.c (16307B)
1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * SELinux NetLabel Support 4 * 5 * This file provides the necessary glue to tie NetLabel into the SELinux 6 * subsystem. 7 * 8 * Author: Paul Moore <paul@paul-moore.com> 9 */ 10 11/* 12 * (c) Copyright Hewlett-Packard Development Company, L.P., 2007, 2008 13 */ 14 15#include <linux/spinlock.h> 16#include <linux/rcupdate.h> 17#include <linux/gfp.h> 18#include <linux/ip.h> 19#include <linux/ipv6.h> 20#include <net/sock.h> 21#include <net/netlabel.h> 22#include <net/ip.h> 23#include <net/ipv6.h> 24 25#include "objsec.h" 26#include "security.h" 27#include "netlabel.h" 28 29/** 30 * selinux_netlbl_sidlookup_cached - Cache a SID lookup 31 * @skb: the packet 32 * @family: the packet's address family 33 * @secattr: the NetLabel security attributes 34 * @sid: the SID 35 * 36 * Description: 37 * Query the SELinux security server to lookup the correct SID for the given 38 * security attributes. If the query is successful, cache the result to speed 39 * up future lookups. Returns zero on success, negative values on failure. 40 * 41 */ 42static int selinux_netlbl_sidlookup_cached(struct sk_buff *skb, 43 u16 family, 44 struct netlbl_lsm_secattr *secattr, 45 u32 *sid) 46{ 47 int rc; 48 49 rc = security_netlbl_secattr_to_sid(&selinux_state, secattr, sid); 50 if (rc == 0 && 51 (secattr->flags & NETLBL_SECATTR_CACHEABLE) && 52 (secattr->flags & NETLBL_SECATTR_CACHE)) 53 netlbl_cache_add(skb, family, secattr); 54 55 return rc; 56} 57 58/** 59 * selinux_netlbl_sock_genattr - Generate the NetLabel socket secattr 60 * @sk: the socket 61 * 62 * Description: 63 * Generate the NetLabel security attributes for a socket, making full use of 64 * the socket's attribute cache. Returns a pointer to the security attributes 65 * on success, NULL on failure. 66 * 67 */ 68static struct netlbl_lsm_secattr *selinux_netlbl_sock_genattr(struct sock *sk) 69{ 70 int rc; 71 struct sk_security_struct *sksec = sk->sk_security; 72 struct netlbl_lsm_secattr *secattr; 73 74 if (sksec->nlbl_secattr != NULL) 75 return sksec->nlbl_secattr; 76 77 secattr = netlbl_secattr_alloc(GFP_ATOMIC); 78 if (secattr == NULL) 79 return NULL; 80 rc = security_netlbl_sid_to_secattr(&selinux_state, sksec->sid, 81 secattr); 82 if (rc != 0) { 83 netlbl_secattr_free(secattr); 84 return NULL; 85 } 86 sksec->nlbl_secattr = secattr; 87 88 return secattr; 89} 90 91/** 92 * selinux_netlbl_sock_getattr - Get the cached NetLabel secattr 93 * @sk: the socket 94 * @sid: the SID 95 * 96 * Query the socket's cached secattr and if the SID matches the cached value 97 * return the cache, otherwise return NULL. 98 * 99 */ 100static struct netlbl_lsm_secattr *selinux_netlbl_sock_getattr( 101 const struct sock *sk, 102 u32 sid) 103{ 104 struct sk_security_struct *sksec = sk->sk_security; 105 struct netlbl_lsm_secattr *secattr = sksec->nlbl_secattr; 106 107 if (secattr == NULL) 108 return NULL; 109 110 if ((secattr->flags & NETLBL_SECATTR_SECID) && 111 (secattr->attr.secid == sid)) 112 return secattr; 113 114 return NULL; 115} 116 117/** 118 * selinux_netlbl_cache_invalidate - Invalidate the NetLabel cache 119 * 120 * Description: 121 * Invalidate the NetLabel security attribute mapping cache. 122 * 123 */ 124void selinux_netlbl_cache_invalidate(void) 125{ 126 netlbl_cache_invalidate(); 127} 128 129/** 130 * selinux_netlbl_err - Handle a NetLabel packet error 131 * @skb: the packet 132 * @family: the packet's address family 133 * @error: the error code 134 * @gateway: true if host is acting as a gateway, false otherwise 135 * 136 * Description: 137 * When a packet is dropped due to a call to avc_has_perm() pass the error 138 * code to the NetLabel subsystem so any protocol specific processing can be 139 * done. This is safe to call even if you are unsure if NetLabel labeling is 140 * present on the packet, NetLabel is smart enough to only act when it should. 141 * 142 */ 143void selinux_netlbl_err(struct sk_buff *skb, u16 family, int error, int gateway) 144{ 145 netlbl_skbuff_err(skb, family, error, gateway); 146} 147 148/** 149 * selinux_netlbl_sk_security_free - Free the NetLabel fields 150 * @sksec: the sk_security_struct 151 * 152 * Description: 153 * Free all of the memory in the NetLabel fields of a sk_security_struct. 154 * 155 */ 156void selinux_netlbl_sk_security_free(struct sk_security_struct *sksec) 157{ 158 if (sksec->nlbl_secattr != NULL) 159 netlbl_secattr_free(sksec->nlbl_secattr); 160} 161 162/** 163 * selinux_netlbl_sk_security_reset - Reset the NetLabel fields 164 * @sksec: the sk_security_struct 165 * 166 * Description: 167 * Called when the NetLabel state of a sk_security_struct needs to be reset. 168 * The caller is responsible for all the NetLabel sk_security_struct locking. 169 * 170 */ 171void selinux_netlbl_sk_security_reset(struct sk_security_struct *sksec) 172{ 173 sksec->nlbl_state = NLBL_UNSET; 174} 175 176/** 177 * selinux_netlbl_skbuff_getsid - Get the sid of a packet using NetLabel 178 * @skb: the packet 179 * @family: protocol family 180 * @type: NetLabel labeling protocol type 181 * @sid: the SID 182 * 183 * Description: 184 * Call the NetLabel mechanism to get the security attributes of the given 185 * packet and use those attributes to determine the correct context/SID to 186 * assign to the packet. Returns zero on success, negative values on failure. 187 * 188 */ 189int selinux_netlbl_skbuff_getsid(struct sk_buff *skb, 190 u16 family, 191 u32 *type, 192 u32 *sid) 193{ 194 int rc; 195 struct netlbl_lsm_secattr secattr; 196 197 if (!netlbl_enabled()) { 198 *sid = SECSID_NULL; 199 return 0; 200 } 201 202 netlbl_secattr_init(&secattr); 203 rc = netlbl_skbuff_getattr(skb, family, &secattr); 204 if (rc == 0 && secattr.flags != NETLBL_SECATTR_NONE) 205 rc = selinux_netlbl_sidlookup_cached(skb, family, 206 &secattr, sid); 207 else 208 *sid = SECSID_NULL; 209 *type = secattr.type; 210 netlbl_secattr_destroy(&secattr); 211 212 return rc; 213} 214 215/** 216 * selinux_netlbl_skbuff_setsid - Set the NetLabel on a packet given a sid 217 * @skb: the packet 218 * @family: protocol family 219 * @sid: the SID 220 * 221 * Description 222 * Call the NetLabel mechanism to set the label of a packet using @sid. 223 * Returns zero on success, negative values on failure. 224 * 225 */ 226int selinux_netlbl_skbuff_setsid(struct sk_buff *skb, 227 u16 family, 228 u32 sid) 229{ 230 int rc; 231 struct netlbl_lsm_secattr secattr_storage; 232 struct netlbl_lsm_secattr *secattr = NULL; 233 struct sock *sk; 234 235 /* if this is a locally generated packet check to see if it is already 236 * being labeled by it's parent socket, if it is just exit */ 237 sk = skb_to_full_sk(skb); 238 if (sk != NULL) { 239 struct sk_security_struct *sksec = sk->sk_security; 240 241 if (sksec->nlbl_state != NLBL_REQSKB) 242 return 0; 243 secattr = selinux_netlbl_sock_getattr(sk, sid); 244 } 245 if (secattr == NULL) { 246 secattr = &secattr_storage; 247 netlbl_secattr_init(secattr); 248 rc = security_netlbl_sid_to_secattr(&selinux_state, sid, 249 secattr); 250 if (rc != 0) 251 goto skbuff_setsid_return; 252 } 253 254 rc = netlbl_skbuff_setattr(skb, family, secattr); 255 256skbuff_setsid_return: 257 if (secattr == &secattr_storage) 258 netlbl_secattr_destroy(secattr); 259 return rc; 260} 261 262/** 263 * selinux_netlbl_sctp_assoc_request - Label an incoming sctp association. 264 * @asoc: incoming association. 265 * @skb: the packet. 266 * 267 * Description: 268 * A new incoming connection is represented by @asoc, ...... 269 * Returns zero on success, negative values on failure. 270 * 271 */ 272int selinux_netlbl_sctp_assoc_request(struct sctp_association *asoc, 273 struct sk_buff *skb) 274{ 275 int rc; 276 struct netlbl_lsm_secattr secattr; 277 struct sk_security_struct *sksec = asoc->base.sk->sk_security; 278 struct sockaddr_in addr4; 279 struct sockaddr_in6 addr6; 280 281 if (asoc->base.sk->sk_family != PF_INET && 282 asoc->base.sk->sk_family != PF_INET6) 283 return 0; 284 285 netlbl_secattr_init(&secattr); 286 rc = security_netlbl_sid_to_secattr(&selinux_state, 287 asoc->secid, &secattr); 288 if (rc != 0) 289 goto assoc_request_return; 290 291 /* Move skb hdr address info to a struct sockaddr and then call 292 * netlbl_conn_setattr(). 293 */ 294 if (ip_hdr(skb)->version == 4) { 295 addr4.sin_family = AF_INET; 296 addr4.sin_addr.s_addr = ip_hdr(skb)->saddr; 297 rc = netlbl_conn_setattr(asoc->base.sk, (void *)&addr4, &secattr); 298 } else if (IS_ENABLED(CONFIG_IPV6) && ip_hdr(skb)->version == 6) { 299 addr6.sin6_family = AF_INET6; 300 addr6.sin6_addr = ipv6_hdr(skb)->saddr; 301 rc = netlbl_conn_setattr(asoc->base.sk, (void *)&addr6, &secattr); 302 } else { 303 rc = -EAFNOSUPPORT; 304 } 305 306 if (rc == 0) 307 sksec->nlbl_state = NLBL_LABELED; 308 309assoc_request_return: 310 netlbl_secattr_destroy(&secattr); 311 return rc; 312} 313 314/** 315 * selinux_netlbl_inet_conn_request - Label an incoming stream connection 316 * @req: incoming connection request socket 317 * @family: the request socket's address family 318 * 319 * Description: 320 * A new incoming connection request is represented by @req, we need to label 321 * the new request_sock here and the stack will ensure the on-the-wire label 322 * will get preserved when a full sock is created once the connection handshake 323 * is complete. Returns zero on success, negative values on failure. 324 * 325 */ 326int selinux_netlbl_inet_conn_request(struct request_sock *req, u16 family) 327{ 328 int rc; 329 struct netlbl_lsm_secattr secattr; 330 331 if (family != PF_INET && family != PF_INET6) 332 return 0; 333 334 netlbl_secattr_init(&secattr); 335 rc = security_netlbl_sid_to_secattr(&selinux_state, req->secid, 336 &secattr); 337 if (rc != 0) 338 goto inet_conn_request_return; 339 rc = netlbl_req_setattr(req, &secattr); 340inet_conn_request_return: 341 netlbl_secattr_destroy(&secattr); 342 return rc; 343} 344 345/** 346 * selinux_netlbl_inet_csk_clone - Initialize the newly created sock 347 * @sk: the new sock 348 * @family: the sock's address family 349 * 350 * Description: 351 * A new connection has been established using @sk, we've already labeled the 352 * socket via the request_sock struct in selinux_netlbl_inet_conn_request() but 353 * we need to set the NetLabel state here since we now have a sock structure. 354 * 355 */ 356void selinux_netlbl_inet_csk_clone(struct sock *sk, u16 family) 357{ 358 struct sk_security_struct *sksec = sk->sk_security; 359 360 if (family == PF_INET) 361 sksec->nlbl_state = NLBL_LABELED; 362 else 363 sksec->nlbl_state = NLBL_UNSET; 364} 365 366/** 367 * selinux_netlbl_sctp_sk_clone - Copy state to the newly created sock 368 * @sk: current sock 369 * @newsk: the new sock 370 * 371 * Description: 372 * Called whenever a new socket is created by accept(2) or sctp_peeloff(3). 373 */ 374void selinux_netlbl_sctp_sk_clone(struct sock *sk, struct sock *newsk) 375{ 376 struct sk_security_struct *sksec = sk->sk_security; 377 struct sk_security_struct *newsksec = newsk->sk_security; 378 379 newsksec->nlbl_state = sksec->nlbl_state; 380} 381 382/** 383 * selinux_netlbl_socket_post_create - Label a socket using NetLabel 384 * @sk: the sock to label 385 * @family: protocol family 386 * 387 * Description: 388 * Attempt to label a socket using the NetLabel mechanism using the given 389 * SID. Returns zero values on success, negative values on failure. 390 * 391 */ 392int selinux_netlbl_socket_post_create(struct sock *sk, u16 family) 393{ 394 int rc; 395 struct sk_security_struct *sksec = sk->sk_security; 396 struct netlbl_lsm_secattr *secattr; 397 398 if (family != PF_INET && family != PF_INET6) 399 return 0; 400 401 secattr = selinux_netlbl_sock_genattr(sk); 402 if (secattr == NULL) 403 return -ENOMEM; 404 rc = netlbl_sock_setattr(sk, family, secattr); 405 switch (rc) { 406 case 0: 407 sksec->nlbl_state = NLBL_LABELED; 408 break; 409 case -EDESTADDRREQ: 410 sksec->nlbl_state = NLBL_REQSKB; 411 rc = 0; 412 break; 413 } 414 415 return rc; 416} 417 418/** 419 * selinux_netlbl_sock_rcv_skb - Do an inbound access check using NetLabel 420 * @sksec: the sock's sk_security_struct 421 * @skb: the packet 422 * @family: protocol family 423 * @ad: the audit data 424 * 425 * Description: 426 * Fetch the NetLabel security attributes from @skb and perform an access check 427 * against the receiving socket. Returns zero on success, negative values on 428 * error. 429 * 430 */ 431int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec, 432 struct sk_buff *skb, 433 u16 family, 434 struct common_audit_data *ad) 435{ 436 int rc; 437 u32 nlbl_sid; 438 u32 perm; 439 struct netlbl_lsm_secattr secattr; 440 441 if (!netlbl_enabled()) 442 return 0; 443 444 netlbl_secattr_init(&secattr); 445 rc = netlbl_skbuff_getattr(skb, family, &secattr); 446 if (rc == 0 && secattr.flags != NETLBL_SECATTR_NONE) 447 rc = selinux_netlbl_sidlookup_cached(skb, family, 448 &secattr, &nlbl_sid); 449 else 450 nlbl_sid = SECINITSID_UNLABELED; 451 netlbl_secattr_destroy(&secattr); 452 if (rc != 0) 453 return rc; 454 455 switch (sksec->sclass) { 456 case SECCLASS_UDP_SOCKET: 457 perm = UDP_SOCKET__RECVFROM; 458 break; 459 case SECCLASS_TCP_SOCKET: 460 perm = TCP_SOCKET__RECVFROM; 461 break; 462 default: 463 perm = RAWIP_SOCKET__RECVFROM; 464 } 465 466 rc = avc_has_perm(&selinux_state, 467 sksec->sid, nlbl_sid, sksec->sclass, perm, ad); 468 if (rc == 0) 469 return 0; 470 471 if (nlbl_sid != SECINITSID_UNLABELED) 472 netlbl_skbuff_err(skb, family, rc, 0); 473 return rc; 474} 475 476/** 477 * selinux_netlbl_option - Is this a NetLabel option 478 * @level: the socket level or protocol 479 * @optname: the socket option name 480 * 481 * Description: 482 * Returns true if @level and @optname refer to a NetLabel option. 483 * Helper for selinux_netlbl_socket_setsockopt(). 484 */ 485static inline int selinux_netlbl_option(int level, int optname) 486{ 487 return (level == IPPROTO_IP && optname == IP_OPTIONS) || 488 (level == IPPROTO_IPV6 && optname == IPV6_HOPOPTS); 489} 490 491/** 492 * selinux_netlbl_socket_setsockopt - Do not allow users to remove a NetLabel 493 * @sock: the socket 494 * @level: the socket level or protocol 495 * @optname: the socket option name 496 * 497 * Description: 498 * Check the setsockopt() call and if the user is trying to replace the IP 499 * options on a socket and a NetLabel is in place for the socket deny the 500 * access; otherwise allow the access. Returns zero when the access is 501 * allowed, -EACCES when denied, and other negative values on error. 502 * 503 */ 504int selinux_netlbl_socket_setsockopt(struct socket *sock, 505 int level, 506 int optname) 507{ 508 int rc = 0; 509 struct sock *sk = sock->sk; 510 struct sk_security_struct *sksec = sk->sk_security; 511 struct netlbl_lsm_secattr secattr; 512 513 if (selinux_netlbl_option(level, optname) && 514 (sksec->nlbl_state == NLBL_LABELED || 515 sksec->nlbl_state == NLBL_CONNLABELED)) { 516 netlbl_secattr_init(&secattr); 517 lock_sock(sk); 518 /* call the netlabel function directly as we want to see the 519 * on-the-wire label that is assigned via the socket's options 520 * and not the cached netlabel/lsm attributes */ 521 rc = netlbl_sock_getattr(sk, &secattr); 522 release_sock(sk); 523 if (rc == 0) 524 rc = -EACCES; 525 else if (rc == -ENOMSG) 526 rc = 0; 527 netlbl_secattr_destroy(&secattr); 528 } 529 530 return rc; 531} 532 533/** 534 * selinux_netlbl_socket_connect_helper - Help label a client-side socket on 535 * connect 536 * @sk: the socket to label 537 * @addr: the destination address 538 * 539 * Description: 540 * Attempt to label a connected socket with NetLabel using the given address. 541 * Returns zero values on success, negative values on failure. 542 * 543 */ 544static int selinux_netlbl_socket_connect_helper(struct sock *sk, 545 struct sockaddr *addr) 546{ 547 int rc; 548 struct sk_security_struct *sksec = sk->sk_security; 549 struct netlbl_lsm_secattr *secattr; 550 551 /* connected sockets are allowed to disconnect when the address family 552 * is set to AF_UNSPEC, if that is what is happening we want to reset 553 * the socket */ 554 if (addr->sa_family == AF_UNSPEC) { 555 netlbl_sock_delattr(sk); 556 sksec->nlbl_state = NLBL_REQSKB; 557 rc = 0; 558 return rc; 559 } 560 secattr = selinux_netlbl_sock_genattr(sk); 561 if (secattr == NULL) { 562 rc = -ENOMEM; 563 return rc; 564 } 565 rc = netlbl_conn_setattr(sk, addr, secattr); 566 if (rc == 0) 567 sksec->nlbl_state = NLBL_CONNLABELED; 568 569 return rc; 570} 571 572/** 573 * selinux_netlbl_socket_connect_locked - Label a client-side socket on 574 * connect 575 * @sk: the socket to label 576 * @addr: the destination address 577 * 578 * Description: 579 * Attempt to label a connected socket that already has the socket locked 580 * with NetLabel using the given address. 581 * Returns zero values on success, negative values on failure. 582 * 583 */ 584int selinux_netlbl_socket_connect_locked(struct sock *sk, 585 struct sockaddr *addr) 586{ 587 struct sk_security_struct *sksec = sk->sk_security; 588 589 if (sksec->nlbl_state != NLBL_REQSKB && 590 sksec->nlbl_state != NLBL_CONNLABELED) 591 return 0; 592 593 return selinux_netlbl_socket_connect_helper(sk, addr); 594} 595 596/** 597 * selinux_netlbl_socket_connect - Label a client-side socket on connect 598 * @sk: the socket to label 599 * @addr: the destination address 600 * 601 * Description: 602 * Attempt to label a connected socket with NetLabel using the given address. 603 * Returns zero values on success, negative values on failure. 604 * 605 */ 606int selinux_netlbl_socket_connect(struct sock *sk, struct sockaddr *addr) 607{ 608 int rc; 609 610 lock_sock(sk); 611 rc = selinux_netlbl_socket_connect_locked(sk, addr); 612 release_sock(sk); 613 614 return rc; 615}