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