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