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