linux/security/selinux/netlabel.c
<<
>>
Prefs
   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 */
  55static 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 */
  80static 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 */
 111static 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 */
 144void 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 */
 162void 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 */
 175void 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 */
 191void 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 */
 213int 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 */
 249int 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
 277skbuff_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 */
 292void 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 */
 362int 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 */
 379int 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
 390        sock = SOCKET_I(inode);
 391        sk = sock->sk;
 392        sksec = sk->sk_security;
 393        if (sksec->nlbl_state != NLBL_REQUIRE)
 394                return 0;
 395
 396        local_bh_disable();
 397        bh_lock_sock_nested(sk);
 398        if (likely(sksec->nlbl_state == NLBL_REQUIRE))
 399                rc = selinux_netlbl_sock_setsid(sk);
 400        else
 401                rc = 0;
 402        bh_unlock_sock(sk);
 403        local_bh_enable();
 404
 405        return rc;
 406}
 407
 408/**
 409 * selinux_netlbl_sock_rcv_skb - Do an inbound access check using NetLabel
 410 * @sksec: the sock's sk_security_struct
 411 * @skb: the packet
 412 * @family: protocol family
 413 * @ad: the audit data
 414 *
 415 * Description:
 416 * Fetch the NetLabel security attributes from @skb and perform an access check
 417 * against the receiving socket.  Returns zero on success, negative values on
 418 * error.
 419 *
 420 */
 421int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec,
 422                                struct sk_buff *skb,
 423                                u16 family,
 424                                struct avc_audit_data *ad)
 425{
 426        int rc;
 427        u32 nlbl_sid;
 428        u32 perm;
 429        struct netlbl_lsm_secattr secattr;
 430
 431        if (!netlbl_enabled())
 432                return 0;
 433
 434        netlbl_secattr_init(&secattr);
 435        rc = netlbl_skbuff_getattr(skb, family, &secattr);
 436        if (rc == 0 && secattr.flags != NETLBL_SECATTR_NONE)
 437                rc = selinux_netlbl_sidlookup_cached(skb, &secattr, &nlbl_sid);
 438        else
 439                nlbl_sid = SECINITSID_UNLABELED;
 440        netlbl_secattr_destroy(&secattr);
 441        if (rc != 0)
 442                return rc;
 443
 444        switch (sksec->sclass) {
 445        case SECCLASS_UDP_SOCKET:
 446                perm = UDP_SOCKET__RECVFROM;
 447                break;
 448        case SECCLASS_TCP_SOCKET:
 449                perm = TCP_SOCKET__RECVFROM;
 450                break;
 451        default:
 452                perm = RAWIP_SOCKET__RECVFROM;
 453        }
 454
 455        rc = avc_has_perm(sksec->sid, nlbl_sid, sksec->sclass, perm, ad);
 456        if (rc == 0)
 457                return 0;
 458
 459        if (nlbl_sid != SECINITSID_UNLABELED)
 460                netlbl_skbuff_err(skb, rc, 0);
 461        return rc;
 462}
 463
 464/**
 465 * selinux_netlbl_socket_setsockopt - Do not allow users to remove a NetLabel
 466 * @sock: the socket
 467 * @level: the socket level or protocol
 468 * @optname: the socket option name
 469 *
 470 * Description:
 471 * Check the setsockopt() call and if the user is trying to replace the IP
 472 * options on a socket and a NetLabel is in place for the socket deny the
 473 * access; otherwise allow the access.  Returns zero when the access is
 474 * allowed, -EACCES when denied, and other negative values on error.
 475 *
 476 */
 477int selinux_netlbl_socket_setsockopt(struct socket *sock,
 478                                     int level,
 479                                     int optname)
 480{
 481        int rc = 0;
 482        struct sock *sk = sock->sk;
 483        struct sk_security_struct *sksec = sk->sk_security;
 484        struct netlbl_lsm_secattr secattr;
 485
 486        if (level == IPPROTO_IP && optname == IP_OPTIONS &&
 487            (sksec->nlbl_state == NLBL_LABELED ||
 488             sksec->nlbl_state == NLBL_CONNLABELED)) {
 489                netlbl_secattr_init(&secattr);
 490                lock_sock(sk);
 491                rc = netlbl_sock_getattr(sk, &secattr);
 492                release_sock(sk);
 493                if (rc == 0 && secattr.flags != NETLBL_SECATTR_NONE)
 494                        rc = -EACCES;
 495                netlbl_secattr_destroy(&secattr);
 496        }
 497
 498        return rc;
 499}
 500
 501/**
 502 * selinux_netlbl_socket_connect - Label a client-side socket on connect
 503 * @sk: the socket to label
 504 * @addr: the destination address
 505 *
 506 * Description:
 507 * Attempt to label a connected socket with NetLabel using the given address.
 508 * Returns zero values on success, negative values on failure.
 509 *
 510 */
 511int selinux_netlbl_socket_connect(struct sock *sk, struct sockaddr *addr)
 512{
 513        int rc;
 514        struct sk_security_struct *sksec = sk->sk_security;
 515        struct netlbl_lsm_secattr *secattr;
 516
 517        if (sksec->nlbl_state != NLBL_REQSKB &&
 518            sksec->nlbl_state != NLBL_CONNLABELED)
 519                return 0;
 520
 521        local_bh_disable();
 522        bh_lock_sock_nested(sk);
 523
 524        /* connected sockets are allowed to disconnect when the address family
 525         * is set to AF_UNSPEC, if that is what is happening we want to reset
 526         * the socket */
 527        if (addr->sa_family == AF_UNSPEC) {
 528                netlbl_sock_delattr(sk);
 529                sksec->nlbl_state = NLBL_REQSKB;
 530                rc = 0;
 531                goto socket_connect_return;
 532        }
 533        secattr = selinux_netlbl_sock_genattr(sk);
 534        if (secattr == NULL) {
 535                rc = -ENOMEM;
 536                goto socket_connect_return;
 537        }
 538        rc = netlbl_conn_setattr(sk, addr, secattr);
 539        if (rc == 0)
 540                sksec->nlbl_state = NLBL_CONNLABELED;
 541
 542socket_connect_return:
 543        bh_unlock_sock(sk);
 544        local_bh_enable();
 545        return rc;
 546}
 547