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(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(sksec->sid, secattr); 94 if (rc != 0) { 95 netlbl_secattr_free(secattr); 96 return NULL; 97 } 98 sksec->nlbl_secattr = secattr; 99 100 return secattr; 101 } 102 103 /** 104 * selinux_netlbl_sock_getattr - Get the cached NetLabel secattr 105 * @sk: the socket 106 * @sid: the SID 107 * 108 * Query the socket's cached secattr and if the SID matches the cached value 109 * return the cache, otherwise return NULL. 110 * 111 */ 112 static struct netlbl_lsm_secattr *selinux_netlbl_sock_getattr( 113 const struct sock *sk, 114 u32 sid) 115 { 116 struct sk_security_struct *sksec = sk->sk_security; 117 struct netlbl_lsm_secattr *secattr = sksec->nlbl_secattr; 118 119 if (secattr == NULL) 120 return NULL; 121 122 if ((secattr->flags & NETLBL_SECATTR_SECID) && 123 (secattr->attr.secid == sid)) 124 return secattr; 125 126 return NULL; 127 } 128 129 /** 130 * selinux_netlbl_cache_invalidate - Invalidate the NetLabel cache 131 * 132 * Description: 133 * Invalidate the NetLabel security attribute mapping cache. 134 * 135 */ 136 void selinux_netlbl_cache_invalidate(void) 137 { 138 netlbl_cache_invalidate(); 139 } 140 141 /** 142 * selinux_netlbl_err - Handle a NetLabel packet error 143 * @skb: the packet 144 * @error: the error code 145 * @gateway: true if host is acting as a gateway, false otherwise 146 * 147 * Description: 148 * When a packet is dropped due to a call to avc_has_perm() pass the error 149 * code to the NetLabel subsystem so any protocol specific processing can be 150 * done. This is safe to call even if you are unsure if NetLabel labeling is 151 * present on the packet, NetLabel is smart enough to only act when it should. 152 * 153 */ 154 void selinux_netlbl_err(struct sk_buff *skb, u16 family, int error, int gateway) 155 { 156 netlbl_skbuff_err(skb, family, error, gateway); 157 } 158 159 /** 160 * selinux_netlbl_sk_security_free - Free the NetLabel fields 161 * @sksec: the sk_security_struct 162 * 163 * Description: 164 * Free all of the memory in the NetLabel fields of a sk_security_struct. 165 * 166 */ 167 void selinux_netlbl_sk_security_free(struct sk_security_struct *sksec) 168 { 169 if (sksec->nlbl_secattr != NULL) 170 netlbl_secattr_free(sksec->nlbl_secattr); 171 } 172 173 /** 174 * selinux_netlbl_sk_security_reset - Reset the NetLabel fields 175 * @sksec: the sk_security_struct 176 * @family: the socket family 177 * 178 * Description: 179 * Called when the NetLabel state of a sk_security_struct needs to be reset. 180 * The caller is responsible for all the NetLabel sk_security_struct locking. 181 * 182 */ 183 void selinux_netlbl_sk_security_reset(struct sk_security_struct *sksec) 184 { 185 sksec->nlbl_state = NLBL_UNSET; 186 } 187 188 /** 189 * selinux_netlbl_skbuff_getsid - Get the sid of a packet using NetLabel 190 * @skb: the packet 191 * @family: protocol family 192 * @type: NetLabel labeling protocol type 193 * @sid: the SID 194 * 195 * Description: 196 * Call the NetLabel mechanism to get the security attributes of the given 197 * packet and use those attributes to determine the correct context/SID to 198 * assign to the packet. Returns zero on success, negative values on failure. 199 * 200 */ 201 int selinux_netlbl_skbuff_getsid(struct sk_buff *skb, 202 u16 family, 203 u32 *type, 204 u32 *sid) 205 { 206 int rc; 207 struct netlbl_lsm_secattr secattr; 208 209 if (!netlbl_enabled()) { 210 *sid = SECSID_NULL; 211 return 0; 212 } 213 214 netlbl_secattr_init(&secattr); 215 rc = netlbl_skbuff_getattr(skb, family, &secattr); 216 if (rc == 0 && secattr.flags != NETLBL_SECATTR_NONE) 217 rc = selinux_netlbl_sidlookup_cached(skb, family, 218 &secattr, sid); 219 else 220 *sid = SECSID_NULL; 221 *type = secattr.type; 222 netlbl_secattr_destroy(&secattr); 223 224 return rc; 225 } 226 227 /** 228 * selinux_netlbl_skbuff_setsid - Set the NetLabel on a packet given a sid 229 * @skb: the packet 230 * @family: protocol family 231 * @sid: the SID 232 * 233 * Description 234 * Call the NetLabel mechanism to set the label of a packet using @sid. 235 * Returns zero on success, negative values on failure. 236 * 237 */ 238 int selinux_netlbl_skbuff_setsid(struct sk_buff *skb, 239 u16 family, 240 u32 sid) 241 { 242 int rc; 243 struct netlbl_lsm_secattr secattr_storage; 244 struct netlbl_lsm_secattr *secattr = NULL; 245 struct sock *sk; 246 247 /* if this is a locally generated packet check to see if it is already 248 * being labeled by it's parent socket, if it is just exit */ 249 sk = skb_to_full_sk(skb); 250 if (sk != NULL) { 251 struct sk_security_struct *sksec = sk->sk_security; 252 if (sksec->nlbl_state != NLBL_REQSKB) 253 return 0; 254 secattr = selinux_netlbl_sock_getattr(sk, sid); 255 } 256 if (secattr == NULL) { 257 secattr = &secattr_storage; 258 netlbl_secattr_init(secattr); 259 rc = security_netlbl_sid_to_secattr(sid, secattr); 260 if (rc != 0) 261 goto skbuff_setsid_return; 262 } 263 264 rc = netlbl_skbuff_setattr(skb, family, secattr); 265 266 skbuff_setsid_return: 267 if (secattr == &secattr_storage) 268 netlbl_secattr_destroy(secattr); 269 return rc; 270 } 271 272 /** 273 * selinux_netlbl_inet_conn_request - Label an incoming stream connection 274 * @req: incoming connection request socket 275 * 276 * Description: 277 * A new incoming connection request is represented by @req, we need to label 278 * the new request_sock here and the stack will ensure the on-the-wire label 279 * will get preserved when a full sock is created once the connection handshake 280 * is complete. Returns zero on success, negative values on failure. 281 * 282 */ 283 int selinux_netlbl_inet_conn_request(struct request_sock *req, u16 family) 284 { 285 int rc; 286 struct netlbl_lsm_secattr secattr; 287 288 if (family != PF_INET && family != PF_INET6) 289 return 0; 290 291 netlbl_secattr_init(&secattr); 292 rc = security_netlbl_sid_to_secattr(req->secid, &secattr); 293 if (rc != 0) 294 goto inet_conn_request_return; 295 rc = netlbl_req_setattr(req, &secattr); 296 inet_conn_request_return: 297 netlbl_secattr_destroy(&secattr); 298 return rc; 299 } 300 301 /** 302 * selinux_netlbl_inet_csk_clone - Initialize the newly created sock 303 * @sk: the new sock 304 * 305 * Description: 306 * A new connection has been established using @sk, we've already labeled the 307 * socket via the request_sock struct in selinux_netlbl_inet_conn_request() but 308 * we need to set the NetLabel state here since we now have a sock structure. 309 * 310 */ 311 void selinux_netlbl_inet_csk_clone(struct sock *sk, u16 family) 312 { 313 struct sk_security_struct *sksec = sk->sk_security; 314 315 if (family == PF_INET) 316 sksec->nlbl_state = NLBL_LABELED; 317 else 318 sksec->nlbl_state = NLBL_UNSET; 319 } 320 321 /** 322 * selinux_netlbl_socket_post_create - Label a socket using NetLabel 323 * @sock: the socket to label 324 * @family: protocol family 325 * 326 * Description: 327 * Attempt to label a socket using the NetLabel mechanism using the given 328 * SID. Returns zero values on success, negative values on failure. 329 * 330 */ 331 int selinux_netlbl_socket_post_create(struct sock *sk, u16 family) 332 { 333 int rc; 334 struct sk_security_struct *sksec = sk->sk_security; 335 struct netlbl_lsm_secattr *secattr; 336 337 if (family != PF_INET && family != PF_INET6) 338 return 0; 339 340 secattr = selinux_netlbl_sock_genattr(sk); 341 if (secattr == NULL) 342 return -ENOMEM; 343 rc = netlbl_sock_setattr(sk, family, secattr); 344 switch (rc) { 345 case 0: 346 sksec->nlbl_state = NLBL_LABELED; 347 break; 348 case -EDESTADDRREQ: 349 sksec->nlbl_state = NLBL_REQSKB; 350 rc = 0; 351 break; 352 } 353 354 return rc; 355 } 356 357 /** 358 * selinux_netlbl_sock_rcv_skb - Do an inbound access check using NetLabel 359 * @sksec: the sock's sk_security_struct 360 * @skb: the packet 361 * @family: protocol family 362 * @ad: the audit data 363 * 364 * Description: 365 * Fetch the NetLabel security attributes from @skb and perform an access check 366 * against the receiving socket. Returns zero on success, negative values on 367 * error. 368 * 369 */ 370 int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec, 371 struct sk_buff *skb, 372 u16 family, 373 struct common_audit_data *ad) 374 { 375 int rc; 376 u32 nlbl_sid; 377 u32 perm; 378 struct netlbl_lsm_secattr secattr; 379 380 if (!netlbl_enabled()) 381 return 0; 382 383 netlbl_secattr_init(&secattr); 384 rc = netlbl_skbuff_getattr(skb, family, &secattr); 385 if (rc == 0 && secattr.flags != NETLBL_SECATTR_NONE) 386 rc = selinux_netlbl_sidlookup_cached(skb, family, 387 &secattr, &nlbl_sid); 388 else 389 nlbl_sid = SECINITSID_UNLABELED; 390 netlbl_secattr_destroy(&secattr); 391 if (rc != 0) 392 return rc; 393 394 switch (sksec->sclass) { 395 case SECCLASS_UDP_SOCKET: 396 perm = UDP_SOCKET__RECVFROM; 397 break; 398 case SECCLASS_TCP_SOCKET: 399 perm = TCP_SOCKET__RECVFROM; 400 break; 401 default: 402 perm = RAWIP_SOCKET__RECVFROM; 403 } 404 405 rc = avc_has_perm(sksec->sid, nlbl_sid, sksec->sclass, perm, ad); 406 if (rc == 0) 407 return 0; 408 409 if (nlbl_sid != SECINITSID_UNLABELED) 410 netlbl_skbuff_err(skb, family, rc, 0); 411 return rc; 412 } 413 414 /** 415 * selinux_netlbl_option - Is this a NetLabel option 416 * @level: the socket level or protocol 417 * @optname: the socket option name 418 * 419 * Description: 420 * Returns true if @level and @optname refer to a NetLabel option. 421 * Helper for selinux_netlbl_socket_setsockopt(). 422 */ 423 static inline int selinux_netlbl_option(int level, int optname) 424 { 425 return (level == IPPROTO_IP && optname == IP_OPTIONS) || 426 (level == IPPROTO_IPV6 && optname == IPV6_HOPOPTS); 427 } 428 429 /** 430 * selinux_netlbl_socket_setsockopt - Do not allow users to remove a NetLabel 431 * @sock: the socket 432 * @level: the socket level or protocol 433 * @optname: the socket option name 434 * 435 * Description: 436 * Check the setsockopt() call and if the user is trying to replace the IP 437 * options on a socket and a NetLabel is in place for the socket deny the 438 * access; otherwise allow the access. Returns zero when the access is 439 * allowed, -EACCES when denied, and other negative values on error. 440 * 441 */ 442 int selinux_netlbl_socket_setsockopt(struct socket *sock, 443 int level, 444 int optname) 445 { 446 int rc = 0; 447 struct sock *sk = sock->sk; 448 struct sk_security_struct *sksec = sk->sk_security; 449 struct netlbl_lsm_secattr secattr; 450 451 if (selinux_netlbl_option(level, optname) && 452 (sksec->nlbl_state == NLBL_LABELED || 453 sksec->nlbl_state == NLBL_CONNLABELED)) { 454 netlbl_secattr_init(&secattr); 455 lock_sock(sk); 456 /* call the netlabel function directly as we want to see the 457 * on-the-wire label that is assigned via the socket's options 458 * and not the cached netlabel/lsm attributes */ 459 rc = netlbl_sock_getattr(sk, &secattr); 460 release_sock(sk); 461 if (rc == 0) 462 rc = -EACCES; 463 else if (rc == -ENOMSG) 464 rc = 0; 465 netlbl_secattr_destroy(&secattr); 466 } 467 468 return rc; 469 } 470 471 /** 472 * selinux_netlbl_socket_connect - Label a client-side socket on connect 473 * @sk: the socket to label 474 * @addr: the destination address 475 * 476 * Description: 477 * Attempt to label a connected socket with NetLabel using the given address. 478 * Returns zero values on success, negative values on failure. 479 * 480 */ 481 int selinux_netlbl_socket_connect(struct sock *sk, struct sockaddr *addr) 482 { 483 int rc; 484 struct sk_security_struct *sksec = sk->sk_security; 485 struct netlbl_lsm_secattr *secattr; 486 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 494 * is set to AF_UNSPEC, if that is what is happening we want to reset 495 * the socket */ 496 if (addr->sa_family == AF_UNSPEC) { 497 netlbl_sock_delattr(sk); 498 sksec->nlbl_state = NLBL_REQSKB; 499 rc = 0; 500 goto socket_connect_return; 501 } 502 secattr = selinux_netlbl_sock_genattr(sk); 503 if (secattr == NULL) { 504 rc = -ENOMEM; 505 goto socket_connect_return; 506 } 507 rc = netlbl_conn_setattr(sk, addr, secattr); 508 if (rc == 0) 509 sksec->nlbl_state = NLBL_CONNLABELED; 510 511 socket_connect_return: 512 release_sock(sk); 513 return rc; 514 } 515