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.moore@hp.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, write to the Free Software 26 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 27 * 28 */ 29 30 #include <linux/spinlock.h> 31 #include <linux/rcupdate.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 struct netlbl_lsm_secattr *secattr, 57 u32 *sid) 58 { 59 int rc; 60 61 rc = security_netlbl_secattr_to_sid(secattr, sid); 62 if (rc == 0 && 63 (secattr->flags & NETLBL_SECATTR_CACHEABLE) && 64 (secattr->flags & NETLBL_SECATTR_CACHE)) 65 netlbl_cache_add(skb, secattr); 66 67 return rc; 68 } 69 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 */ 80 static 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 /** 103 * selinux_netlbl_sock_setsid - Label a socket using the NetLabel mechanism 104 * @sk: the socket to label 105 * 106 * Description: 107 * Attempt to label a socket using the NetLabel mechanism. Returns zero values 108 * on success, negative values on failure. 109 * 110 */ 111 static int selinux_netlbl_sock_setsid(struct sock *sk) 112 { 113 int rc; 114 struct sk_security_struct *sksec = sk->sk_security; 115 struct netlbl_lsm_secattr *secattr; 116 117 if (sksec->nlbl_state != NLBL_REQUIRE) 118 return 0; 119 120 secattr = selinux_netlbl_sock_genattr(sk); 121 if (secattr == NULL) 122 return -ENOMEM; 123 rc = netlbl_sock_setattr(sk, secattr); 124 switch (rc) { 125 case 0: 126 sksec->nlbl_state = NLBL_LABELED; 127 break; 128 case -EDESTADDRREQ: 129 sksec->nlbl_state = NLBL_REQSKB; 130 rc = 0; 131 break; 132 } 133 134 return rc; 135 } 136 137 /** 138 * selinux_netlbl_cache_invalidate - Invalidate the NetLabel cache 139 * 140 * Description: 141 * Invalidate the NetLabel security attribute mapping cache. 142 * 143 */ 144 void selinux_netlbl_cache_invalidate(void) 145 { 146 netlbl_cache_invalidate(); 147 } 148 149 /** 150 * selinux_netlbl_err - Handle a NetLabel packet error 151 * @skb: the packet 152 * @error: the error code 153 * @gateway: true if host is acting as a gateway, false otherwise 154 * 155 * Description: 156 * When a packet is dropped due to a call to avc_has_perm() pass the error 157 * code to the NetLabel subsystem so any protocol specific processing can be 158 * done. This is safe to call even if you are unsure if NetLabel labeling is 159 * present on the packet, NetLabel is smart enough to only act when it should. 160 * 161 */ 162 void selinux_netlbl_err(struct sk_buff *skb, int error, int gateway) 163 { 164 netlbl_skbuff_err(skb, error, gateway); 165 } 166 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 */ 175 void 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 /** 182 * selinux_netlbl_sk_security_reset - Reset the NetLabel fields 183 * @ssec: the sk_security_struct 184 * @family: the socket family 185 * 186 * Description: 187 * Called when the NetLabel state of a sk_security_struct needs to be reset. 188 * The caller is responsibile for all the NetLabel sk_security_struct locking. 189 * 190 */ 191 void selinux_netlbl_sk_security_reset(struct sk_security_struct *ssec, 192 int family) 193 { 194 if (family == PF_INET) 195 ssec->nlbl_state = NLBL_REQUIRE; 196 else 197 ssec->nlbl_state = NLBL_UNSET; 198 } 199 200 /** 201 * selinux_netlbl_skbuff_getsid - Get the sid of a packet using NetLabel 202 * @skb: the packet 203 * @family: protocol family 204 * @type: NetLabel labeling protocol type 205 * @sid: the SID 206 * 207 * Description: 208 * Call the NetLabel mechanism to get the security attributes of the given 209 * packet and use those attributes to determine the correct context/SID to 210 * assign to the packet. Returns zero on success, negative values on failure. 211 * 212 */ 213 int selinux_netlbl_skbuff_getsid(struct sk_buff *skb, 214 u16 family, 215 u32 *type, 216 u32 *sid) 217 { 218 int rc; 219 struct netlbl_lsm_secattr secattr; 220 221 if (!netlbl_enabled()) { 222 *sid = SECSID_NULL; 223 return 0; 224 } 225 226 netlbl_secattr_init(&secattr); 227 rc = netlbl_skbuff_getattr(skb, family, &secattr); 228 if (rc == 0 && secattr.flags != NETLBL_SECATTR_NONE) 229 rc = selinux_netlbl_sidlookup_cached(skb, &secattr, sid); 230 else 231 *sid = SECSID_NULL; 232 *type = secattr.type; 233 netlbl_secattr_destroy(&secattr); 234 235 return rc; 236 } 237 238 /** 239 * selinux_netlbl_skbuff_setsid - Set the NetLabel on a packet given a sid 240 * @skb: the packet 241 * @family: protocol family 242 * @sid: the SID 243 * 244 * Description 245 * Call the NetLabel mechanism to set the label of a packet using @sid. 246 * Returns zero on auccess, negative values on failure. 247 * 248 */ 249 int selinux_netlbl_skbuff_setsid(struct sk_buff *skb, 250 u16 family, 251 u32 sid) 252 { 253 int rc; 254 struct netlbl_lsm_secattr secattr_storage; 255 struct netlbl_lsm_secattr *secattr = NULL; 256 struct sock *sk; 257 258 /* if this is a locally generated packet check to see if it is already 259 * being labeled by it's parent socket, if it is just exit */ 260 sk = skb->sk; 261 if (sk != NULL) { 262 struct sk_security_struct *sksec = sk->sk_security; 263 if (sksec->nlbl_state != NLBL_REQSKB) 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; 273 } 274 275 rc = netlbl_skbuff_setattr(skb, family, secattr); 276 277 skbuff_setsid_return: 278 if (secattr == &secattr_storage) 279 netlbl_secattr_destroy(secattr); 280 return rc; 281 } 282 283 /** 284 * selinux_netlbl_inet_conn_established - Netlabel the newly accepted connection 285 * @sk: the new connection 286 * 287 * Description: 288 * A new connection has been established on @sk so make sure it is labeled 289 * correctly with the NetLabel susbsystem. 290 * 291 */ 292 void selinux_netlbl_inet_conn_established(struct sock *sk, u16 family) 293 { 294 int rc; 295 struct sk_security_struct *sksec = sk->sk_security; 296 struct netlbl_lsm_secattr *secattr; 297 struct inet_sock *sk_inet = inet_sk(sk); 298 struct sockaddr_in addr; 299 300 if (sksec->nlbl_state != NLBL_REQUIRE) 301 return; 302 303 secattr = selinux_netlbl_sock_genattr(sk); 304 if (secattr == NULL) 305 return; 306 307 rc = netlbl_sock_setattr(sk, secattr); 308 switch (rc) { 309 case 0: 310 sksec->nlbl_state = NLBL_LABELED; 311 break; 312 case -EDESTADDRREQ: 313 /* no PF_INET6 support yet because we don't support any IPv6 314 * labeling protocols */ 315 if (family != PF_INET) { 316 sksec->nlbl_state = NLBL_UNSET; 317 return; 318 } 319 320 addr.sin_family = family; 321 addr.sin_addr.s_addr = sk_inet->daddr; 322 if (netlbl_conn_setattr(sk, (struct sockaddr *)&addr, 323 secattr) != 0) { 324 /* we failed to label the connected socket (could be 325 * for a variety of reasons, the actual "why" isn't 326 * important here) so we have to go to our backup plan, 327 * labeling the packets individually in the netfilter 328 * local output hook. this is okay but we need to 329 * adjust the MSS of the connection to take into 330 * account any labeling overhead, since we don't know 331 * the exact overhead at this point we'll use the worst 332 * case value which is 40 bytes for IPv4 */ 333 struct inet_connection_sock *sk_conn = inet_csk(sk); 334 sk_conn->icsk_ext_hdr_len += 40 - 335 (sk_inet->opt ? sk_inet->opt->optlen : 0); 336 sk_conn->icsk_sync_mss(sk, sk_conn->icsk_pmtu_cookie); 337 338 sksec->nlbl_state = NLBL_REQSKB; 339 } else 340 sksec->nlbl_state = NLBL_CONNLABELED; 341 break; 342 default: 343 /* note that we are failing to label the socket which could be 344 * a bad thing since it means traffic could leave the system 345 * without the desired labeling, however, all is not lost as 346 * we have a check in selinux_netlbl_inode_permission() to 347 * pick up the pieces that we might drop here because we can't 348 * return an error code */ 349 break; 350 } 351 } 352 353 /** 354 * selinux_netlbl_socket_post_create - Label a socket using NetLabel 355 * @sock: the socket to label 356 * 357 * Description: 358 * Attempt to label a socket using the NetLabel mechanism using the given 359 * SID. Returns zero values on success, negative values on failure. 360 * 361 */ 362 int selinux_netlbl_socket_post_create(struct socket *sock) 363 { 364 return selinux_netlbl_sock_setsid(sock->sk); 365 } 366 367 /** 368 * selinux_netlbl_inode_permission - Verify the socket is NetLabel labeled 369 * @inode: the file descriptor's inode 370 * @mask: the permission mask 371 * 372 * Description: 373 * Looks at a file's inode and if it is marked as a socket protected by 374 * NetLabel then verify that the socket has been labeled, if not try to label 375 * the socket now with the inode's SID. Returns zero on success, negative 376 * values on failure. 377 * 378 */ 379 int selinux_netlbl_inode_permission(struct inode *inode, int mask) 380 { 381 int rc; 382 struct sock *sk; 383 struct socket *sock; 384 struct sk_security_struct *sksec; 385 386 if (!S_ISSOCK(inode->i_mode) || 387 ((mask & (MAY_WRITE | MAY_APPEND)) == 0)) 388 return 0; 389 sock = SOCKET_I(inode); 390 sk = sock->sk; 391 if (sk == NULL) 392 return 0; 393 sksec = sk->sk_security; 394 if (sksec == NULL || sksec->nlbl_state != NLBL_REQUIRE) 395 return 0; 396 397 local_bh_disable(); 398 bh_lock_sock_nested(sk); 399 if (likely(sksec->nlbl_state == NLBL_REQUIRE)) 400 rc = selinux_netlbl_sock_setsid(sk); 401 else 402 rc = 0; 403 bh_unlock_sock(sk); 404 local_bh_enable(); 405 406 return rc; 407 } 408 409 /** 410 * selinux_netlbl_sock_rcv_skb - Do an inbound access check using NetLabel 411 * @sksec: the sock's sk_security_struct 412 * @skb: the packet 413 * @family: protocol family 414 * @ad: the audit data 415 * 416 * Description: 417 * Fetch the NetLabel security attributes from @skb and perform an access check 418 * against the receiving socket. Returns zero on success, negative values on 419 * error. 420 * 421 */ 422 int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec, 423 struct sk_buff *skb, 424 u16 family, 425 struct avc_audit_data *ad) 426 { 427 int rc; 428 u32 nlbl_sid; 429 u32 perm; 430 struct netlbl_lsm_secattr secattr; 431 432 if (!netlbl_enabled()) 433 return 0; 434 435 netlbl_secattr_init(&secattr); 436 rc = netlbl_skbuff_getattr(skb, family, &secattr); 437 if (rc == 0 && secattr.flags != NETLBL_SECATTR_NONE) 438 rc = selinux_netlbl_sidlookup_cached(skb, &secattr, &nlbl_sid); 439 else 440 nlbl_sid = SECINITSID_UNLABELED; 441 netlbl_secattr_destroy(&secattr); 442 if (rc != 0) 443 return rc; 444 445 switch (sksec->sclass) { 446 case SECCLASS_UDP_SOCKET: 447 perm = UDP_SOCKET__RECVFROM; 448 break; 449 case SECCLASS_TCP_SOCKET: 450 perm = TCP_SOCKET__RECVFROM; 451 break; 452 default: 453 perm = RAWIP_SOCKET__RECVFROM; 454 } 455 456 rc = avc_has_perm(sksec->sid, nlbl_sid, sksec->sclass, perm, ad); 457 if (rc == 0) 458 return 0; 459 460 if (nlbl_sid != SECINITSID_UNLABELED) 461 netlbl_skbuff_err(skb, rc, 0); 462 return rc; 463 } 464 465 /** 466 * selinux_netlbl_socket_setsockopt - Do not allow users to remove a NetLabel 467 * @sock: the socket 468 * @level: the socket level or protocol 469 * @optname: the socket option name 470 * 471 * Description: 472 * Check the setsockopt() call and if the user is trying to replace the IP 473 * options on a socket and a NetLabel is in place for the socket deny the 474 * access; otherwise allow the access. Returns zero when the access is 475 * allowed, -EACCES when denied, and other negative values on error. 476 * 477 */ 478 int selinux_netlbl_socket_setsockopt(struct socket *sock, 479 int level, 480 int optname) 481 { 482 int rc = 0; 483 struct sock *sk = sock->sk; 484 struct sk_security_struct *sksec = sk->sk_security; 485 struct netlbl_lsm_secattr secattr; 486 487 if (level == IPPROTO_IP && optname == IP_OPTIONS && 488 (sksec->nlbl_state == NLBL_LABELED || 489 sksec->nlbl_state == NLBL_CONNLABELED)) { 490 netlbl_secattr_init(&secattr); 491 lock_sock(sk); 492 rc = netlbl_sock_getattr(sk, &secattr); 493 release_sock(sk); 494 if (rc == 0) 495 rc = -EACCES; 496 else if (rc == -ENOMSG) 497 rc = 0; 498 netlbl_secattr_destroy(&secattr); 499 } 500 501 return rc; 502 } 503 504 /** 505 * selinux_netlbl_socket_connect - Label a client-side socket on connect 506 * @sk: the socket to label 507 * @addr: the destination address 508 * 509 * Description: 510 * Attempt to label a connected socket with NetLabel using the given address. 511 * Returns zero values on success, negative values on failure. 512 * 513 */ 514 int selinux_netlbl_socket_connect(struct sock *sk, struct sockaddr *addr) 515 { 516 int rc; 517 struct sk_security_struct *sksec = sk->sk_security; 518 struct netlbl_lsm_secattr *secattr; 519 520 if (sksec->nlbl_state != NLBL_REQSKB && 521 sksec->nlbl_state != NLBL_CONNLABELED) 522 return 0; 523 524 local_bh_disable(); 525 bh_lock_sock_nested(sk); 526 527 /* connected sockets are allowed to disconnect when the address family 528 * is set to AF_UNSPEC, if that is what is happening we want to reset 529 * the socket */ 530 if (addr->sa_family == AF_UNSPEC) { 531 netlbl_sock_delattr(sk); 532 sksec->nlbl_state = NLBL_REQSKB; 533 rc = 0; 534 goto socket_connect_return; 535 } 536 secattr = selinux_netlbl_sock_genattr(sk); 537 if (secattr == NULL) { 538 rc = -ENOMEM; 539 goto socket_connect_return; 540 } 541 rc = netlbl_conn_setattr(sk, addr, secattr); 542 if (rc == 0) 543 sksec->nlbl_state = NLBL_CONNLABELED; 544 545 socket_connect_return: 546 bh_unlock_sock(sk); 547 local_bh_enable(); 548 return rc; 549 } 550