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, 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/gfp.h> 33 #include <linux/ip.h> 34 #include <linux/ipv6.h> 35 #include <net/sock.h> 36 #include <net/netlabel.h> 37 #include <net/ip.h> 38 #include <net/ipv6.h> 39 40 #include "objsec.h" 41 #include "security.h" 42 #include "netlabel.h" 43 44 /** 45 * selinux_netlbl_sidlookup_cached - Cache a SID lookup 46 * @skb: the packet 47 * @secattr: the NetLabel security attributes 48 * @sid: the SID 49 * 50 * Description: 51 * Query the SELinux security server to lookup the correct SID for the given 52 * security attributes. If the query is successful, cache the result to speed 53 * up future lookups. Returns zero on success, negative values on failure. 54 * 55 */ 56 static int selinux_netlbl_sidlookup_cached(struct sk_buff *skb, 57 u16 family, 58 struct netlbl_lsm_secattr *secattr, 59 u32 *sid) 60 { 61 int rc; 62 63 rc = security_netlbl_secattr_to_sid(secattr, sid); 64 if (rc == 0 && 65 (secattr->flags & NETLBL_SECATTR_CACHEABLE) && 66 (secattr->flags & NETLBL_SECATTR_CACHE)) 67 netlbl_cache_add(skb, family, secattr); 68 69 return rc; 70 } 71 72 /** 73 * selinux_netlbl_sock_genattr - Generate the NetLabel socket secattr 74 * @sk: the socket 75 * 76 * Description: 77 * Generate the NetLabel security attributes for a socket, making full use of 78 * the socket's attribute cache. Returns a pointer to the security attributes 79 * on success, NULL on failure. 80 * 81 */ 82 static struct netlbl_lsm_secattr *selinux_netlbl_sock_genattr(struct sock *sk) 83 { 84 int rc; 85 struct sk_security_struct *sksec = sk->sk_security; 86 struct netlbl_lsm_secattr *secattr; 87 88 if (sksec->nlbl_secattr != NULL) 89 return sksec->nlbl_secattr; 90 91 secattr = netlbl_secattr_alloc(GFP_ATOMIC); 92 if (secattr == NULL) 93 return NULL; 94 rc = security_netlbl_sid_to_secattr(sksec->sid, 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 if (sksec->nlbl_state != NLBL_REQSKB) 254 return 0; 255 secattr = selinux_netlbl_sock_getattr(sk, sid); 256 } 257 if (secattr == NULL) { 258 secattr = &secattr_storage; 259 netlbl_secattr_init(secattr); 260 rc = security_netlbl_sid_to_secattr(sid, secattr); 261 if (rc != 0) 262 goto skbuff_setsid_return; 263 } 264 265 rc = netlbl_skbuff_setattr(skb, family, secattr); 266 267 skbuff_setsid_return: 268 if (secattr == &secattr_storage) 269 netlbl_secattr_destroy(secattr); 270 return rc; 271 } 272 273 /** 274 * selinux_netlbl_inet_conn_request - Label an incoming stream connection 275 * @req: incoming connection request socket 276 * 277 * Description: 278 * A new incoming connection request is represented by @req, we need to label 279 * the new request_sock here and the stack will ensure the on-the-wire label 280 * will get preserved when a full sock is created once the connection handshake 281 * is complete. Returns zero on success, negative values on failure. 282 * 283 */ 284 int selinux_netlbl_inet_conn_request(struct request_sock *req, u16 family) 285 { 286 int rc; 287 struct netlbl_lsm_secattr secattr; 288 289 if (family != PF_INET && family != PF_INET6) 290 return 0; 291 292 netlbl_secattr_init(&secattr); 293 rc = security_netlbl_sid_to_secattr(req->secid, &secattr); 294 if (rc != 0) 295 goto inet_conn_request_return; 296 rc = netlbl_req_setattr(req, &secattr); 297 inet_conn_request_return: 298 netlbl_secattr_destroy(&secattr); 299 return rc; 300 } 301 302 /** 303 * selinux_netlbl_inet_csk_clone - Initialize the newly created sock 304 * @sk: the new sock 305 * 306 * Description: 307 * A new connection has been established using @sk, we've already labeled the 308 * socket via the request_sock struct in selinux_netlbl_inet_conn_request() but 309 * we need to set the NetLabel state here since we now have a sock structure. 310 * 311 */ 312 void selinux_netlbl_inet_csk_clone(struct sock *sk, u16 family) 313 { 314 struct sk_security_struct *sksec = sk->sk_security; 315 316 if (family == PF_INET) 317 sksec->nlbl_state = NLBL_LABELED; 318 else 319 sksec->nlbl_state = NLBL_UNSET; 320 } 321 322 /** 323 * selinux_netlbl_socket_post_create - Label a socket using NetLabel 324 * @sock: the socket to label 325 * @family: protocol family 326 * 327 * Description: 328 * Attempt to label a socket using the NetLabel mechanism using the given 329 * SID. Returns zero values on success, negative values on failure. 330 * 331 */ 332 int selinux_netlbl_socket_post_create(struct sock *sk, u16 family) 333 { 334 int rc; 335 struct sk_security_struct *sksec = sk->sk_security; 336 struct netlbl_lsm_secattr *secattr; 337 338 if (family != PF_INET && family != PF_INET6) 339 return 0; 340 341 secattr = selinux_netlbl_sock_genattr(sk); 342 if (secattr == NULL) 343 return -ENOMEM; 344 rc = netlbl_sock_setattr(sk, family, secattr); 345 switch (rc) { 346 case 0: 347 sksec->nlbl_state = NLBL_LABELED; 348 break; 349 case -EDESTADDRREQ: 350 sksec->nlbl_state = NLBL_REQSKB; 351 rc = 0; 352 break; 353 } 354 355 return rc; 356 } 357 358 /** 359 * selinux_netlbl_sock_rcv_skb - Do an inbound access check using NetLabel 360 * @sksec: the sock's sk_security_struct 361 * @skb: the packet 362 * @family: protocol family 363 * @ad: the audit data 364 * 365 * Description: 366 * Fetch the NetLabel security attributes from @skb and perform an access check 367 * against the receiving socket. Returns zero on success, negative values on 368 * error. 369 * 370 */ 371 int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec, 372 struct sk_buff *skb, 373 u16 family, 374 struct common_audit_data *ad) 375 { 376 int rc; 377 u32 nlbl_sid; 378 u32 perm; 379 struct netlbl_lsm_secattr secattr; 380 381 if (!netlbl_enabled()) 382 return 0; 383 384 netlbl_secattr_init(&secattr); 385 rc = netlbl_skbuff_getattr(skb, family, &secattr); 386 if (rc == 0 && secattr.flags != NETLBL_SECATTR_NONE) 387 rc = selinux_netlbl_sidlookup_cached(skb, family, 388 &secattr, &nlbl_sid); 389 else 390 nlbl_sid = SECINITSID_UNLABELED; 391 netlbl_secattr_destroy(&secattr); 392 if (rc != 0) 393 return rc; 394 395 switch (sksec->sclass) { 396 case SECCLASS_UDP_SOCKET: 397 perm = UDP_SOCKET__RECVFROM; 398 break; 399 case SECCLASS_TCP_SOCKET: 400 perm = TCP_SOCKET__RECVFROM; 401 break; 402 default: 403 perm = RAWIP_SOCKET__RECVFROM; 404 } 405 406 rc = avc_has_perm(sksec->sid, nlbl_sid, sksec->sclass, perm, ad); 407 if (rc == 0) 408 return 0; 409 410 if (nlbl_sid != SECINITSID_UNLABELED) 411 netlbl_skbuff_err(skb, family, rc, 0); 412 return rc; 413 } 414 415 /** 416 * selinux_netlbl_option - Is this a NetLabel option 417 * @level: the socket level or protocol 418 * @optname: the socket option name 419 * 420 * Description: 421 * Returns true if @level and @optname refer to a NetLabel option. 422 * Helper for selinux_netlbl_socket_setsockopt(). 423 */ 424 static inline int selinux_netlbl_option(int level, int optname) 425 { 426 return (level == IPPROTO_IP && optname == IP_OPTIONS) || 427 (level == IPPROTO_IPV6 && optname == IPV6_HOPOPTS); 428 } 429 430 /** 431 * selinux_netlbl_socket_setsockopt - Do not allow users to remove a NetLabel 432 * @sock: the socket 433 * @level: the socket level or protocol 434 * @optname: the socket option name 435 * 436 * Description: 437 * Check the setsockopt() call and if the user is trying to replace the IP 438 * options on a socket and a NetLabel is in place for the socket deny the 439 * access; otherwise allow the access. Returns zero when the access is 440 * allowed, -EACCES when denied, and other negative values on error. 441 * 442 */ 443 int selinux_netlbl_socket_setsockopt(struct socket *sock, 444 int level, 445 int optname) 446 { 447 int rc = 0; 448 struct sock *sk = sock->sk; 449 struct sk_security_struct *sksec = sk->sk_security; 450 struct netlbl_lsm_secattr secattr; 451 452 if (selinux_netlbl_option(level, optname) && 453 (sksec->nlbl_state == NLBL_LABELED || 454 sksec->nlbl_state == NLBL_CONNLABELED)) { 455 netlbl_secattr_init(&secattr); 456 lock_sock(sk); 457 /* call the netlabel function directly as we want to see the 458 * on-the-wire label that is assigned via the socket's options 459 * and not the cached netlabel/lsm attributes */ 460 rc = netlbl_sock_getattr(sk, &secattr); 461 release_sock(sk); 462 if (rc == 0) 463 rc = -EACCES; 464 else if (rc == -ENOMSG) 465 rc = 0; 466 netlbl_secattr_destroy(&secattr); 467 } 468 469 return rc; 470 } 471 472 /** 473 * selinux_netlbl_socket_connect - Label a client-side socket on connect 474 * @sk: the socket to label 475 * @addr: the destination address 476 * 477 * Description: 478 * Attempt to label a connected socket with NetLabel using the given address. 479 * Returns zero values on success, negative values on failure. 480 * 481 */ 482 int selinux_netlbl_socket_connect(struct sock *sk, struct sockaddr *addr) 483 { 484 int rc; 485 struct sk_security_struct *sksec = sk->sk_security; 486 struct netlbl_lsm_secattr *secattr; 487 488 if (sksec->nlbl_state != NLBL_REQSKB && 489 sksec->nlbl_state != NLBL_CONNLABELED) 490 return 0; 491 492 lock_sock(sk); 493 494 /* connected sockets are allowed to disconnect when the address family 495 * is set to AF_UNSPEC, if that is what is happening we want to reset 496 * the socket */ 497 if (addr->sa_family == AF_UNSPEC) { 498 netlbl_sock_delattr(sk); 499 sksec->nlbl_state = NLBL_REQSKB; 500 rc = 0; 501 goto socket_connect_return; 502 } 503 secattr = selinux_netlbl_sock_genattr(sk); 504 if (secattr == NULL) { 505 rc = -ENOMEM; 506 goto socket_connect_return; 507 } 508 rc = netlbl_conn_setattr(sk, addr, secattr); 509 if (rc == 0) 510 sksec->nlbl_state = NLBL_CONNLABELED; 511 512 socket_connect_return: 513 release_sock(sk); 514 return rc; 515 } 516