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