linux/net/netlabel/netlabel_kapi.c
<<
>>
Prefs
   1/*
   2 * NetLabel Kernel API
   3 *
   4 * This file defines the kernel API for the NetLabel system.  The NetLabel
   5 * system manages static and dynamic label mappings for network protocols such
   6 * as CIPSO and RIPSO.
   7 *
   8 * Author: Paul Moore <paul@paul-moore.com>
   9 *
  10 */
  11
  12/*
  13 * (c) Copyright Hewlett-Packard Development Company, L.P., 2006, 2008
  14 *
  15 * This program is free software;  you can redistribute it and/or modify
  16 * it under the terms of the GNU General Public License as published by
  17 * the Free Software Foundation; either version 2 of the License, or
  18 * (at your option) any later version.
  19 *
  20 * This program is distributed in the hope that it will be useful,
  21 * but WITHOUT ANY WARRANTY;  without even the implied warranty of
  22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
  23 * the GNU General Public License for more details.
  24 *
  25 * You should have received a copy of the GNU General Public License
  26 * along with this program;  if not, see <http://www.gnu.org/licenses/>.
  27 *
  28 */
  29
  30#include <linux/init.h>
  31#include <linux/types.h>
  32#include <linux/slab.h>
  33#include <linux/audit.h>
  34#include <linux/in.h>
  35#include <linux/in6.h>
  36#include <net/ip.h>
  37#include <net/ipv6.h>
  38#include <net/netlabel.h>
  39#include <net/cipso_ipv4.h>
  40#include <asm/bug.h>
  41#include <linux/atomic.h>
  42
  43#include "netlabel_domainhash.h"
  44#include "netlabel_unlabeled.h"
  45#include "netlabel_cipso_v4.h"
  46#include "netlabel_user.h"
  47#include "netlabel_mgmt.h"
  48#include "netlabel_addrlist.h"
  49
  50/*
  51 * Configuration Functions
  52 */
  53
  54/**
  55 * netlbl_cfg_map_del - Remove a NetLabel/LSM domain mapping
  56 * @domain: the domain mapping to remove
  57 * @family: address family
  58 * @addr: IP address
  59 * @mask: IP address mask
  60 * @audit_info: NetLabel audit information
  61 *
  62 * Description:
  63 * Removes a NetLabel/LSM domain mapping.  A @domain value of NULL causes the
  64 * default domain mapping to be removed.  Returns zero on success, negative
  65 * values on failure.
  66 *
  67 */
  68int netlbl_cfg_map_del(const char *domain,
  69                       u16 family,
  70                       const void *addr,
  71                       const void *mask,
  72                       struct netlbl_audit *audit_info)
  73{
  74        if (addr == NULL && mask == NULL) {
  75                return netlbl_domhsh_remove(domain, audit_info);
  76        } else if (addr != NULL && mask != NULL) {
  77                switch (family) {
  78                case AF_INET:
  79                        return netlbl_domhsh_remove_af4(domain, addr, mask,
  80                                                        audit_info);
  81                default:
  82                        return -EPFNOSUPPORT;
  83                }
  84        } else
  85                return -EINVAL;
  86}
  87
  88/**
  89 * netlbl_cfg_unlbl_map_add - Add a new unlabeled mapping
  90 * @domain: the domain mapping to add
  91 * @family: address family
  92 * @addr: IP address
  93 * @mask: IP address mask
  94 * @audit_info: NetLabel audit information
  95 *
  96 * Description:
  97 * Adds a new unlabeled NetLabel/LSM domain mapping.  A @domain value of NULL
  98 * causes a new default domain mapping to be added.  Returns zero on success,
  99 * negative values on failure.
 100 *
 101 */
 102int netlbl_cfg_unlbl_map_add(const char *domain,
 103                             u16 family,
 104                             const void *addr,
 105                             const void *mask,
 106                             struct netlbl_audit *audit_info)
 107{
 108        int ret_val = -ENOMEM;
 109        struct netlbl_dom_map *entry;
 110        struct netlbl_domaddr_map *addrmap = NULL;
 111        struct netlbl_domaddr4_map *map4 = NULL;
 112        struct netlbl_domaddr6_map *map6 = NULL;
 113
 114        entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
 115        if (entry == NULL)
 116                return -ENOMEM;
 117        if (domain != NULL) {
 118                entry->domain = kstrdup(domain, GFP_ATOMIC);
 119                if (entry->domain == NULL)
 120                        goto cfg_unlbl_map_add_failure;
 121        }
 122
 123        if (addr == NULL && mask == NULL)
 124                entry->def.type = NETLBL_NLTYPE_UNLABELED;
 125        else if (addr != NULL && mask != NULL) {
 126                addrmap = kzalloc(sizeof(*addrmap), GFP_ATOMIC);
 127                if (addrmap == NULL)
 128                        goto cfg_unlbl_map_add_failure;
 129                INIT_LIST_HEAD(&addrmap->list4);
 130                INIT_LIST_HEAD(&addrmap->list6);
 131
 132                switch (family) {
 133                case AF_INET: {
 134                        const struct in_addr *addr4 = addr;
 135                        const struct in_addr *mask4 = mask;
 136                        map4 = kzalloc(sizeof(*map4), GFP_ATOMIC);
 137                        if (map4 == NULL)
 138                                goto cfg_unlbl_map_add_failure;
 139                        map4->def.type = NETLBL_NLTYPE_UNLABELED;
 140                        map4->list.addr = addr4->s_addr & mask4->s_addr;
 141                        map4->list.mask = mask4->s_addr;
 142                        map4->list.valid = 1;
 143                        ret_val = netlbl_af4list_add(&map4->list,
 144                                                     &addrmap->list4);
 145                        if (ret_val != 0)
 146                                goto cfg_unlbl_map_add_failure;
 147                        break;
 148                        }
 149#if IS_ENABLED(CONFIG_IPV6)
 150                case AF_INET6: {
 151                        const struct in6_addr *addr6 = addr;
 152                        const struct in6_addr *mask6 = mask;
 153                        map6 = kzalloc(sizeof(*map6), GFP_ATOMIC);
 154                        if (map6 == NULL)
 155                                goto cfg_unlbl_map_add_failure;
 156                        map6->def.type = NETLBL_NLTYPE_UNLABELED;
 157                        map6->list.addr = *addr6;
 158                        map6->list.addr.s6_addr32[0] &= mask6->s6_addr32[0];
 159                        map6->list.addr.s6_addr32[1] &= mask6->s6_addr32[1];
 160                        map6->list.addr.s6_addr32[2] &= mask6->s6_addr32[2];
 161                        map6->list.addr.s6_addr32[3] &= mask6->s6_addr32[3];
 162                        map6->list.mask = *mask6;
 163                        map6->list.valid = 1;
 164                        ret_val = netlbl_af6list_add(&map6->list,
 165                                                     &addrmap->list6);
 166                        if (ret_val != 0)
 167                                goto cfg_unlbl_map_add_failure;
 168                        break;
 169                        }
 170#endif /* IPv6 */
 171                default:
 172                        goto cfg_unlbl_map_add_failure;
 173                        break;
 174                }
 175
 176                entry->def.addrsel = addrmap;
 177                entry->def.type = NETLBL_NLTYPE_ADDRSELECT;
 178        } else {
 179                ret_val = -EINVAL;
 180                goto cfg_unlbl_map_add_failure;
 181        }
 182
 183        ret_val = netlbl_domhsh_add(entry, audit_info);
 184        if (ret_val != 0)
 185                goto cfg_unlbl_map_add_failure;
 186
 187        return 0;
 188
 189cfg_unlbl_map_add_failure:
 190        kfree(entry->domain);
 191        kfree(entry);
 192        kfree(addrmap);
 193        kfree(map4);
 194        kfree(map6);
 195        return ret_val;
 196}
 197
 198
 199/**
 200 * netlbl_cfg_unlbl_static_add - Adds a new static label
 201 * @net: network namespace
 202 * @dev_name: interface name
 203 * @addr: IP address in network byte order (struct in[6]_addr)
 204 * @mask: address mask in network byte order (struct in[6]_addr)
 205 * @family: address family
 206 * @secid: LSM secid value for the entry
 207 * @audit_info: NetLabel audit information
 208 *
 209 * Description:
 210 * Adds a new NetLabel static label to be used when protocol provided labels
 211 * are not present on incoming traffic.  If @dev_name is NULL then the default
 212 * interface will be used.  Returns zero on success, negative values on failure.
 213 *
 214 */
 215int netlbl_cfg_unlbl_static_add(struct net *net,
 216                                const char *dev_name,
 217                                const void *addr,
 218                                const void *mask,
 219                                u16 family,
 220                                u32 secid,
 221                                struct netlbl_audit *audit_info)
 222{
 223        u32 addr_len;
 224
 225        switch (family) {
 226        case AF_INET:
 227                addr_len = sizeof(struct in_addr);
 228                break;
 229#if IS_ENABLED(CONFIG_IPV6)
 230        case AF_INET6:
 231                addr_len = sizeof(struct in6_addr);
 232                break;
 233#endif /* IPv6 */
 234        default:
 235                return -EPFNOSUPPORT;
 236        }
 237
 238        return netlbl_unlhsh_add(net,
 239                                 dev_name, addr, mask, addr_len,
 240                                 secid, audit_info);
 241}
 242
 243/**
 244 * netlbl_cfg_unlbl_static_del - Removes an existing static label
 245 * @net: network namespace
 246 * @dev_name: interface name
 247 * @addr: IP address in network byte order (struct in[6]_addr)
 248 * @mask: address mask in network byte order (struct in[6]_addr)
 249 * @family: address family
 250 * @secid: LSM secid value for the entry
 251 * @audit_info: NetLabel audit information
 252 *
 253 * Description:
 254 * Removes an existing NetLabel static label used when protocol provided labels
 255 * are not present on incoming traffic.  If @dev_name is NULL then the default
 256 * interface will be used.  Returns zero on success, negative values on failure.
 257 *
 258 */
 259int netlbl_cfg_unlbl_static_del(struct net *net,
 260                                const char *dev_name,
 261                                const void *addr,
 262                                const void *mask,
 263                                u16 family,
 264                                struct netlbl_audit *audit_info)
 265{
 266        u32 addr_len;
 267
 268        switch (family) {
 269        case AF_INET:
 270                addr_len = sizeof(struct in_addr);
 271                break;
 272#if IS_ENABLED(CONFIG_IPV6)
 273        case AF_INET6:
 274                addr_len = sizeof(struct in6_addr);
 275                break;
 276#endif /* IPv6 */
 277        default:
 278                return -EPFNOSUPPORT;
 279        }
 280
 281        return netlbl_unlhsh_remove(net,
 282                                    dev_name, addr, mask, addr_len,
 283                                    audit_info);
 284}
 285
 286/**
 287 * netlbl_cfg_cipsov4_add - Add a new CIPSOv4 DOI definition
 288 * @doi_def: CIPSO DOI definition
 289 * @audit_info: NetLabel audit information
 290 *
 291 * Description:
 292 * Add a new CIPSO DOI definition as defined by @doi_def.  Returns zero on
 293 * success and negative values on failure.
 294 *
 295 */
 296int netlbl_cfg_cipsov4_add(struct cipso_v4_doi *doi_def,
 297                           struct netlbl_audit *audit_info)
 298{
 299        return cipso_v4_doi_add(doi_def, audit_info);
 300}
 301
 302/**
 303 * netlbl_cfg_cipsov4_del - Remove an existing CIPSOv4 DOI definition
 304 * @doi: CIPSO DOI
 305 * @audit_info: NetLabel audit information
 306 *
 307 * Description:
 308 * Remove an existing CIPSO DOI definition matching @doi.  Returns zero on
 309 * success and negative values on failure.
 310 *
 311 */
 312void netlbl_cfg_cipsov4_del(u32 doi, struct netlbl_audit *audit_info)
 313{
 314        cipso_v4_doi_remove(doi, audit_info);
 315}
 316
 317/**
 318 * netlbl_cfg_cipsov4_map_add - Add a new CIPSOv4 DOI mapping
 319 * @doi: the CIPSO DOI
 320 * @domain: the domain mapping to add
 321 * @addr: IP address
 322 * @mask: IP address mask
 323 * @audit_info: NetLabel audit information
 324 *
 325 * Description:
 326 * Add a new NetLabel/LSM domain mapping for the given CIPSO DOI to the NetLabel
 327 * subsystem.  A @domain value of NULL adds a new default domain mapping.
 328 * Returns zero on success, negative values on failure.
 329 *
 330 */
 331int netlbl_cfg_cipsov4_map_add(u32 doi,
 332                               const char *domain,
 333                               const struct in_addr *addr,
 334                               const struct in_addr *mask,
 335                               struct netlbl_audit *audit_info)
 336{
 337        int ret_val = -ENOMEM;
 338        struct cipso_v4_doi *doi_def;
 339        struct netlbl_dom_map *entry;
 340        struct netlbl_domaddr_map *addrmap = NULL;
 341        struct netlbl_domaddr4_map *addrinfo = NULL;
 342
 343        doi_def = cipso_v4_doi_getdef(doi);
 344        if (doi_def == NULL)
 345                return -ENOENT;
 346
 347        entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
 348        if (entry == NULL)
 349                goto out_entry;
 350        if (domain != NULL) {
 351                entry->domain = kstrdup(domain, GFP_ATOMIC);
 352                if (entry->domain == NULL)
 353                        goto out_domain;
 354        }
 355
 356        if (addr == NULL && mask == NULL) {
 357                entry->def.cipso = doi_def;
 358                entry->def.type = NETLBL_NLTYPE_CIPSOV4;
 359        } else if (addr != NULL && mask != NULL) {
 360                addrmap = kzalloc(sizeof(*addrmap), GFP_ATOMIC);
 361                if (addrmap == NULL)
 362                        goto out_addrmap;
 363                INIT_LIST_HEAD(&addrmap->list4);
 364                INIT_LIST_HEAD(&addrmap->list6);
 365
 366                addrinfo = kzalloc(sizeof(*addrinfo), GFP_ATOMIC);
 367                if (addrinfo == NULL)
 368                        goto out_addrinfo;
 369                addrinfo->def.cipso = doi_def;
 370                addrinfo->def.type = NETLBL_NLTYPE_CIPSOV4;
 371                addrinfo->list.addr = addr->s_addr & mask->s_addr;
 372                addrinfo->list.mask = mask->s_addr;
 373                addrinfo->list.valid = 1;
 374                ret_val = netlbl_af4list_add(&addrinfo->list, &addrmap->list4);
 375                if (ret_val != 0)
 376                        goto cfg_cipsov4_map_add_failure;
 377
 378                entry->def.addrsel = addrmap;
 379                entry->def.type = NETLBL_NLTYPE_ADDRSELECT;
 380        } else {
 381                ret_val = -EINVAL;
 382                goto out_addrmap;
 383        }
 384
 385        ret_val = netlbl_domhsh_add(entry, audit_info);
 386        if (ret_val != 0)
 387                goto cfg_cipsov4_map_add_failure;
 388
 389        return 0;
 390
 391cfg_cipsov4_map_add_failure:
 392        kfree(addrinfo);
 393out_addrinfo:
 394        kfree(addrmap);
 395out_addrmap:
 396        kfree(entry->domain);
 397out_domain:
 398        kfree(entry);
 399out_entry:
 400        cipso_v4_doi_putdef(doi_def);
 401        return ret_val;
 402}
 403
 404/*
 405 * Security Attribute Functions
 406 */
 407
 408/**
 409 * netlbl_secattr_catmap_walk - Walk a LSM secattr catmap looking for a bit
 410 * @catmap: the category bitmap
 411 * @offset: the offset to start searching at, in bits
 412 *
 413 * Description:
 414 * This function walks a LSM secattr category bitmap starting at @offset and
 415 * returns the spot of the first set bit or -ENOENT if no bits are set.
 416 *
 417 */
 418int netlbl_secattr_catmap_walk(struct netlbl_lsm_secattr_catmap *catmap,
 419                               u32 offset)
 420{
 421        struct netlbl_lsm_secattr_catmap *iter = catmap;
 422        u32 node_idx;
 423        u32 node_bit;
 424        NETLBL_CATMAP_MAPTYPE bitmap;
 425
 426        if (offset > iter->startbit) {
 427                while (offset >= (iter->startbit + NETLBL_CATMAP_SIZE)) {
 428                        iter = iter->next;
 429                        if (iter == NULL)
 430                                return -ENOENT;
 431                }
 432                node_idx = (offset - iter->startbit) / NETLBL_CATMAP_MAPSIZE;
 433                node_bit = offset - iter->startbit -
 434                           (NETLBL_CATMAP_MAPSIZE * node_idx);
 435        } else {
 436                node_idx = 0;
 437                node_bit = 0;
 438        }
 439        bitmap = iter->bitmap[node_idx] >> node_bit;
 440
 441        for (;;) {
 442                if (bitmap != 0) {
 443                        while ((bitmap & NETLBL_CATMAP_BIT) == 0) {
 444                                bitmap >>= 1;
 445                                node_bit++;
 446                        }
 447                        return iter->startbit +
 448                                (NETLBL_CATMAP_MAPSIZE * node_idx) + node_bit;
 449                }
 450                if (++node_idx >= NETLBL_CATMAP_MAPCNT) {
 451                        if (iter->next != NULL) {
 452                                iter = iter->next;
 453                                node_idx = 0;
 454                        } else
 455                                return -ENOENT;
 456                }
 457                bitmap = iter->bitmap[node_idx];
 458                node_bit = 0;
 459        }
 460
 461        return -ENOENT;
 462}
 463
 464/**
 465 * netlbl_secattr_catmap_walk_rng - Find the end of a string of set bits
 466 * @catmap: the category bitmap
 467 * @offset: the offset to start searching at, in bits
 468 *
 469 * Description:
 470 * This function walks a LSM secattr category bitmap starting at @offset and
 471 * returns the spot of the first cleared bit or -ENOENT if the offset is past
 472 * the end of the bitmap.
 473 *
 474 */
 475int netlbl_secattr_catmap_walk_rng(struct netlbl_lsm_secattr_catmap *catmap,
 476                                   u32 offset)
 477{
 478        struct netlbl_lsm_secattr_catmap *iter = catmap;
 479        u32 node_idx;
 480        u32 node_bit;
 481        NETLBL_CATMAP_MAPTYPE bitmask;
 482        NETLBL_CATMAP_MAPTYPE bitmap;
 483
 484        if (offset > iter->startbit) {
 485                while (offset >= (iter->startbit + NETLBL_CATMAP_SIZE)) {
 486                        iter = iter->next;
 487                        if (iter == NULL)
 488                                return -ENOENT;
 489                }
 490                node_idx = (offset - iter->startbit) / NETLBL_CATMAP_MAPSIZE;
 491                node_bit = offset - iter->startbit -
 492                           (NETLBL_CATMAP_MAPSIZE * node_idx);
 493        } else {
 494                node_idx = 0;
 495                node_bit = 0;
 496        }
 497        bitmask = NETLBL_CATMAP_BIT << node_bit;
 498
 499        for (;;) {
 500                bitmap = iter->bitmap[node_idx];
 501                while (bitmask != 0 && (bitmap & bitmask) != 0) {
 502                        bitmask <<= 1;
 503                        node_bit++;
 504                }
 505
 506                if (bitmask != 0)
 507                        return iter->startbit +
 508                                (NETLBL_CATMAP_MAPSIZE * node_idx) +
 509                                node_bit - 1;
 510                else if (++node_idx >= NETLBL_CATMAP_MAPCNT) {
 511                        if (iter->next == NULL)
 512                                return iter->startbit + NETLBL_CATMAP_SIZE - 1;
 513                        iter = iter->next;
 514                        node_idx = 0;
 515                }
 516                bitmask = NETLBL_CATMAP_BIT;
 517                node_bit = 0;
 518        }
 519
 520        return -ENOENT;
 521}
 522
 523/**
 524 * netlbl_secattr_catmap_setbit - Set a bit in a LSM secattr catmap
 525 * @catmap: the category bitmap
 526 * @bit: the bit to set
 527 * @flags: memory allocation flags
 528 *
 529 * Description:
 530 * Set the bit specified by @bit in @catmap.  Returns zero on success,
 531 * negative values on failure.
 532 *
 533 */
 534int netlbl_secattr_catmap_setbit(struct netlbl_lsm_secattr_catmap *catmap,
 535                                 u32 bit,
 536                                 gfp_t flags)
 537{
 538        struct netlbl_lsm_secattr_catmap *iter = catmap;
 539        u32 node_bit;
 540        u32 node_idx;
 541
 542        while (iter->next != NULL &&
 543               bit >= (iter->startbit + NETLBL_CATMAP_SIZE))
 544                iter = iter->next;
 545        if (bit >= (iter->startbit + NETLBL_CATMAP_SIZE)) {
 546                iter->next = netlbl_secattr_catmap_alloc(flags);
 547                if (iter->next == NULL)
 548                        return -ENOMEM;
 549                iter = iter->next;
 550                iter->startbit = bit & ~(NETLBL_CATMAP_SIZE - 1);
 551        }
 552
 553        /* gcc always rounds to zero when doing integer division */
 554        node_idx = (bit - iter->startbit) / NETLBL_CATMAP_MAPSIZE;
 555        node_bit = bit - iter->startbit - (NETLBL_CATMAP_MAPSIZE * node_idx);
 556        iter->bitmap[node_idx] |= NETLBL_CATMAP_BIT << node_bit;
 557
 558        return 0;
 559}
 560
 561/**
 562 * netlbl_secattr_catmap_setrng - Set a range of bits in a LSM secattr catmap
 563 * @catmap: the category bitmap
 564 * @start: the starting bit
 565 * @end: the last bit in the string
 566 * @flags: memory allocation flags
 567 *
 568 * Description:
 569 * Set a range of bits, starting at @start and ending with @end.  Returns zero
 570 * on success, negative values on failure.
 571 *
 572 */
 573int netlbl_secattr_catmap_setrng(struct netlbl_lsm_secattr_catmap *catmap,
 574                                 u32 start,
 575                                 u32 end,
 576                                 gfp_t flags)
 577{
 578        int ret_val = 0;
 579        struct netlbl_lsm_secattr_catmap *iter = catmap;
 580        u32 iter_max_spot;
 581        u32 spot;
 582
 583        /* XXX - This could probably be made a bit faster by combining writes
 584         * to the catmap instead of setting a single bit each time, but for
 585         * right now skipping to the start of the range in the catmap should
 586         * be a nice improvement over calling the individual setbit function
 587         * repeatedly from a loop. */
 588
 589        while (iter->next != NULL &&
 590               start >= (iter->startbit + NETLBL_CATMAP_SIZE))
 591                iter = iter->next;
 592        iter_max_spot = iter->startbit + NETLBL_CATMAP_SIZE;
 593
 594        for (spot = start; spot <= end && ret_val == 0; spot++) {
 595                if (spot >= iter_max_spot && iter->next != NULL) {
 596                        iter = iter->next;
 597                        iter_max_spot = iter->startbit + NETLBL_CATMAP_SIZE;
 598                }
 599                ret_val = netlbl_secattr_catmap_setbit(iter, spot, flags);
 600        }
 601
 602        return ret_val;
 603}
 604
 605/*
 606 * LSM Functions
 607 */
 608
 609/**
 610 * netlbl_enabled - Determine if the NetLabel subsystem is enabled
 611 *
 612 * Description:
 613 * The LSM can use this function to determine if it should use NetLabel
 614 * security attributes in it's enforcement mechanism.  Currently, NetLabel is
 615 * considered to be enabled when it's configuration contains a valid setup for
 616 * at least one labeled protocol (i.e. NetLabel can understand incoming
 617 * labeled packets of at least one type); otherwise NetLabel is considered to
 618 * be disabled.
 619 *
 620 */
 621int netlbl_enabled(void)
 622{
 623        /* At some point we probably want to expose this mechanism to the user
 624         * as well so that admins can toggle NetLabel regardless of the
 625         * configuration */
 626        return (atomic_read(&netlabel_mgmt_protocount) > 0);
 627}
 628
 629/**
 630 * netlbl_sock_setattr - Label a socket using the correct protocol
 631 * @sk: the socket to label
 632 * @family: protocol family
 633 * @secattr: the security attributes
 634 *
 635 * Description:
 636 * Attach the correct label to the given socket using the security attributes
 637 * specified in @secattr.  This function requires exclusive access to @sk,
 638 * which means it either needs to be in the process of being created or locked.
 639 * Returns zero on success, -EDESTADDRREQ if the domain is configured to use
 640 * network address selectors (can't blindly label the socket), and negative
 641 * values on all other failures.
 642 *
 643 */
 644int netlbl_sock_setattr(struct sock *sk,
 645                        u16 family,
 646                        const struct netlbl_lsm_secattr *secattr)
 647{
 648        int ret_val;
 649        struct netlbl_dom_map *dom_entry;
 650
 651        rcu_read_lock();
 652        dom_entry = netlbl_domhsh_getentry(secattr->domain);
 653        if (dom_entry == NULL) {
 654                ret_val = -ENOENT;
 655                goto socket_setattr_return;
 656        }
 657        switch (family) {
 658        case AF_INET:
 659                switch (dom_entry->def.type) {
 660                case NETLBL_NLTYPE_ADDRSELECT:
 661                        ret_val = -EDESTADDRREQ;
 662                        break;
 663                case NETLBL_NLTYPE_CIPSOV4:
 664                        ret_val = cipso_v4_sock_setattr(sk,
 665                                                        dom_entry->def.cipso,
 666                                                        secattr);
 667                        break;
 668                case NETLBL_NLTYPE_UNLABELED:
 669                        ret_val = 0;
 670                        break;
 671                default:
 672                        ret_val = -ENOENT;
 673                }
 674                break;
 675#if IS_ENABLED(CONFIG_IPV6)
 676        case AF_INET6:
 677                /* since we don't support any IPv6 labeling protocols right
 678                 * now we can optimize everything away until we do */
 679                ret_val = 0;
 680                break;
 681#endif /* IPv6 */
 682        default:
 683                ret_val = -EPROTONOSUPPORT;
 684        }
 685
 686socket_setattr_return:
 687        rcu_read_unlock();
 688        return ret_val;
 689}
 690
 691/**
 692 * netlbl_sock_delattr - Delete all the NetLabel labels on a socket
 693 * @sk: the socket
 694 *
 695 * Description:
 696 * Remove all the NetLabel labeling from @sk.  The caller is responsible for
 697 * ensuring that @sk is locked.
 698 *
 699 */
 700void netlbl_sock_delattr(struct sock *sk)
 701{
 702        cipso_v4_sock_delattr(sk);
 703}
 704
 705/**
 706 * netlbl_sock_getattr - Determine the security attributes of a sock
 707 * @sk: the sock
 708 * @secattr: the security attributes
 709 *
 710 * Description:
 711 * Examines the given sock to see if any NetLabel style labeling has been
 712 * applied to the sock, if so it parses the socket label and returns the
 713 * security attributes in @secattr.  Returns zero on success, negative values
 714 * on failure.
 715 *
 716 */
 717int netlbl_sock_getattr(struct sock *sk,
 718                        struct netlbl_lsm_secattr *secattr)
 719{
 720        int ret_val;
 721
 722        switch (sk->sk_family) {
 723        case AF_INET:
 724                ret_val = cipso_v4_sock_getattr(sk, secattr);
 725                break;
 726#if IS_ENABLED(CONFIG_IPV6)
 727        case AF_INET6:
 728                ret_val = -ENOMSG;
 729                break;
 730#endif /* IPv6 */
 731        default:
 732                ret_val = -EPROTONOSUPPORT;
 733        }
 734
 735        return ret_val;
 736}
 737
 738/**
 739 * netlbl_conn_setattr - Label a connected socket using the correct protocol
 740 * @sk: the socket to label
 741 * @addr: the destination address
 742 * @secattr: the security attributes
 743 *
 744 * Description:
 745 * Attach the correct label to the given connected socket using the security
 746 * attributes specified in @secattr.  The caller is responsible for ensuring
 747 * that @sk is locked.  Returns zero on success, negative values on failure.
 748 *
 749 */
 750int netlbl_conn_setattr(struct sock *sk,
 751                        struct sockaddr *addr,
 752                        const struct netlbl_lsm_secattr *secattr)
 753{
 754        int ret_val;
 755        struct sockaddr_in *addr4;
 756        struct netlbl_dommap_def *entry;
 757
 758        rcu_read_lock();
 759        switch (addr->sa_family) {
 760        case AF_INET:
 761                addr4 = (struct sockaddr_in *)addr;
 762                entry = netlbl_domhsh_getentry_af4(secattr->domain,
 763                                                   addr4->sin_addr.s_addr);
 764                if (entry == NULL) {
 765                        ret_val = -ENOENT;
 766                        goto conn_setattr_return;
 767                }
 768                switch (entry->type) {
 769                case NETLBL_NLTYPE_CIPSOV4:
 770                        ret_val = cipso_v4_sock_setattr(sk,
 771                                                        entry->cipso, secattr);
 772                        break;
 773                case NETLBL_NLTYPE_UNLABELED:
 774                        /* just delete the protocols we support for right now
 775                         * but we could remove other protocols if needed */
 776                        cipso_v4_sock_delattr(sk);
 777                        ret_val = 0;
 778                        break;
 779                default:
 780                        ret_val = -ENOENT;
 781                }
 782                break;
 783#if IS_ENABLED(CONFIG_IPV6)
 784        case AF_INET6:
 785                /* since we don't support any IPv6 labeling protocols right
 786                 * now we can optimize everything away until we do */
 787                ret_val = 0;
 788                break;
 789#endif /* IPv6 */
 790        default:
 791                ret_val = -EPROTONOSUPPORT;
 792        }
 793
 794conn_setattr_return:
 795        rcu_read_unlock();
 796        return ret_val;
 797}
 798
 799/**
 800 * netlbl_req_setattr - Label a request socket using the correct protocol
 801 * @req: the request socket to label
 802 * @secattr: the security attributes
 803 *
 804 * Description:
 805 * Attach the correct label to the given socket using the security attributes
 806 * specified in @secattr.  Returns zero on success, negative values on failure.
 807 *
 808 */
 809int netlbl_req_setattr(struct request_sock *req,
 810                       const struct netlbl_lsm_secattr *secattr)
 811{
 812        int ret_val;
 813        struct netlbl_dommap_def *entry;
 814
 815        rcu_read_lock();
 816        switch (req->rsk_ops->family) {
 817        case AF_INET:
 818                entry = netlbl_domhsh_getentry_af4(secattr->domain,
 819                                                   inet_rsk(req)->ir_rmt_addr);
 820                if (entry == NULL) {
 821                        ret_val = -ENOENT;
 822                        goto req_setattr_return;
 823                }
 824                switch (entry->type) {
 825                case NETLBL_NLTYPE_CIPSOV4:
 826                        ret_val = cipso_v4_req_setattr(req,
 827                                                       entry->cipso, secattr);
 828                        break;
 829                case NETLBL_NLTYPE_UNLABELED:
 830                        /* just delete the protocols we support for right now
 831                         * but we could remove other protocols if needed */
 832                        cipso_v4_req_delattr(req);
 833                        ret_val = 0;
 834                        break;
 835                default:
 836                        ret_val = -ENOENT;
 837                }
 838                break;
 839#if IS_ENABLED(CONFIG_IPV6)
 840        case AF_INET6:
 841                /* since we don't support any IPv6 labeling protocols right
 842                 * now we can optimize everything away until we do */
 843                ret_val = 0;
 844                break;
 845#endif /* IPv6 */
 846        default:
 847                ret_val = -EPROTONOSUPPORT;
 848        }
 849
 850req_setattr_return:
 851        rcu_read_unlock();
 852        return ret_val;
 853}
 854
 855/**
 856* netlbl_req_delattr - Delete all the NetLabel labels on a socket
 857* @req: the socket
 858*
 859* Description:
 860* Remove all the NetLabel labeling from @req.
 861*
 862*/
 863void netlbl_req_delattr(struct request_sock *req)
 864{
 865        cipso_v4_req_delattr(req);
 866}
 867
 868/**
 869 * netlbl_skbuff_setattr - Label a packet using the correct protocol
 870 * @skb: the packet
 871 * @family: protocol family
 872 * @secattr: the security attributes
 873 *
 874 * Description:
 875 * Attach the correct label to the given packet using the security attributes
 876 * specified in @secattr.  Returns zero on success, negative values on failure.
 877 *
 878 */
 879int netlbl_skbuff_setattr(struct sk_buff *skb,
 880                          u16 family,
 881                          const struct netlbl_lsm_secattr *secattr)
 882{
 883        int ret_val;
 884        struct iphdr *hdr4;
 885        struct netlbl_dommap_def *entry;
 886
 887        rcu_read_lock();
 888        switch (family) {
 889        case AF_INET:
 890                hdr4 = ip_hdr(skb);
 891                entry = netlbl_domhsh_getentry_af4(secattr->domain,hdr4->daddr);
 892                if (entry == NULL) {
 893                        ret_val = -ENOENT;
 894                        goto skbuff_setattr_return;
 895                }
 896                switch (entry->type) {
 897                case NETLBL_NLTYPE_CIPSOV4:
 898                        ret_val = cipso_v4_skbuff_setattr(skb, entry->cipso,
 899                                                          secattr);
 900                        break;
 901                case NETLBL_NLTYPE_UNLABELED:
 902                        /* just delete the protocols we support for right now
 903                         * but we could remove other protocols if needed */
 904                        ret_val = cipso_v4_skbuff_delattr(skb);
 905                        break;
 906                default:
 907                        ret_val = -ENOENT;
 908                }
 909                break;
 910#if IS_ENABLED(CONFIG_IPV6)
 911        case AF_INET6:
 912                /* since we don't support any IPv6 labeling protocols right
 913                 * now we can optimize everything away until we do */
 914                ret_val = 0;
 915                break;
 916#endif /* IPv6 */
 917        default:
 918                ret_val = -EPROTONOSUPPORT;
 919        }
 920
 921skbuff_setattr_return:
 922        rcu_read_unlock();
 923        return ret_val;
 924}
 925
 926/**
 927 * netlbl_skbuff_getattr - Determine the security attributes of a packet
 928 * @skb: the packet
 929 * @family: protocol family
 930 * @secattr: the security attributes
 931 *
 932 * Description:
 933 * Examines the given packet to see if a recognized form of packet labeling
 934 * is present, if so it parses the packet label and returns the security
 935 * attributes in @secattr.  Returns zero on success, negative values on
 936 * failure.
 937 *
 938 */
 939int netlbl_skbuff_getattr(const struct sk_buff *skb,
 940                          u16 family,
 941                          struct netlbl_lsm_secattr *secattr)
 942{
 943        switch (family) {
 944        case AF_INET:
 945                if (CIPSO_V4_OPTEXIST(skb) &&
 946                    cipso_v4_skbuff_getattr(skb, secattr) == 0)
 947                        return 0;
 948                break;
 949#if IS_ENABLED(CONFIG_IPV6)
 950        case AF_INET6:
 951                break;
 952#endif /* IPv6 */
 953        }
 954
 955        return netlbl_unlabel_getattr(skb, family, secattr);
 956}
 957
 958/**
 959 * netlbl_skbuff_err - Handle a LSM error on a sk_buff
 960 * @skb: the packet
 961 * @error: the error code
 962 * @gateway: true if host is acting as a gateway, false otherwise
 963 *
 964 * Description:
 965 * Deal with a LSM problem when handling the packet in @skb, typically this is
 966 * a permission denied problem (-EACCES).  The correct action is determined
 967 * according to the packet's labeling protocol.
 968 *
 969 */
 970void netlbl_skbuff_err(struct sk_buff *skb, int error, int gateway)
 971{
 972        if (CIPSO_V4_OPTEXIST(skb))
 973                cipso_v4_error(skb, error, gateway);
 974}
 975
 976/**
 977 * netlbl_cache_invalidate - Invalidate all of the NetLabel protocol caches
 978 *
 979 * Description:
 980 * For all of the NetLabel protocols that support some form of label mapping
 981 * cache, invalidate the cache.  Returns zero on success, negative values on
 982 * error.
 983 *
 984 */
 985void netlbl_cache_invalidate(void)
 986{
 987        cipso_v4_cache_invalidate();
 988}
 989
 990/**
 991 * netlbl_cache_add - Add an entry to a NetLabel protocol cache
 992 * @skb: the packet
 993 * @secattr: the packet's security attributes
 994 *
 995 * Description:
 996 * Add the LSM security attributes for the given packet to the underlying
 997 * NetLabel protocol's label mapping cache.  Returns zero on success, negative
 998 * values on error.
 999 *
1000 */
1001int netlbl_cache_add(const struct sk_buff *skb,
1002                     const struct netlbl_lsm_secattr *secattr)
1003{
1004        if ((secattr->flags & NETLBL_SECATTR_CACHE) == 0)
1005                return -ENOMSG;
1006
1007        if (CIPSO_V4_OPTEXIST(skb))
1008                return cipso_v4_cache_add(skb, secattr);
1009
1010        return -ENOMSG;
1011}
1012
1013/*
1014 * Protocol Engine Functions
1015 */
1016
1017/**
1018 * netlbl_audit_start - Start an audit message
1019 * @type: audit message type
1020 * @audit_info: NetLabel audit information
1021 *
1022 * Description:
1023 * Start an audit message using the type specified in @type and fill the audit
1024 * message with some fields common to all NetLabel audit messages.  This
1025 * function should only be used by protocol engines, not LSMs.  Returns a
1026 * pointer to the audit buffer on success, NULL on failure.
1027 *
1028 */
1029struct audit_buffer *netlbl_audit_start(int type,
1030                                        struct netlbl_audit *audit_info)
1031{
1032        return netlbl_audit_start_common(type, audit_info);
1033}
1034
1035/*
1036 * Setup Functions
1037 */
1038
1039/**
1040 * netlbl_init - Initialize NetLabel
1041 *
1042 * Description:
1043 * Perform the required NetLabel initialization before first use.
1044 *
1045 */
1046static int __init netlbl_init(void)
1047{
1048        int ret_val;
1049
1050        printk(KERN_INFO "NetLabel: Initializing\n");
1051        printk(KERN_INFO "NetLabel:  domain hash size = %u\n",
1052               (1 << NETLBL_DOMHSH_BITSIZE));
1053        printk(KERN_INFO "NetLabel:  protocols ="
1054               " UNLABELED"
1055               " CIPSOv4"
1056               "\n");
1057
1058        ret_val = netlbl_domhsh_init(NETLBL_DOMHSH_BITSIZE);
1059        if (ret_val != 0)
1060                goto init_failure;
1061
1062        ret_val = netlbl_unlabel_init(NETLBL_UNLHSH_BITSIZE);
1063        if (ret_val != 0)
1064                goto init_failure;
1065
1066        ret_val = netlbl_netlink_init();
1067        if (ret_val != 0)
1068                goto init_failure;
1069
1070        ret_val = netlbl_unlabel_defconf();
1071        if (ret_val != 0)
1072                goto init_failure;
1073        printk(KERN_INFO "NetLabel:  unlabeled traffic allowed by default\n");
1074
1075        return 0;
1076
1077init_failure:
1078        panic("NetLabel: failed to initialize properly (%d)\n", ret_val);
1079}
1080
1081subsys_initcall(netlbl_init);
1082