linux/net/netlabel/netlabel_unlabeled.c
<<
>>
Prefs
   1/*
   2 * NetLabel Unlabeled Support
   3 *
   4 * This file defines functions for dealing with unlabeled packets for the
   5 * NetLabel system.  The NetLabel system manages static and dynamic label
   6 * mappings for network protocols such 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/types.h>
  31#include <linux/rcupdate.h>
  32#include <linux/list.h>
  33#include <linux/spinlock.h>
  34#include <linux/socket.h>
  35#include <linux/string.h>
  36#include <linux/skbuff.h>
  37#include <linux/audit.h>
  38#include <linux/in.h>
  39#include <linux/in6.h>
  40#include <linux/ip.h>
  41#include <linux/ipv6.h>
  42#include <linux/notifier.h>
  43#include <linux/netdevice.h>
  44#include <linux/security.h>
  45#include <linux/slab.h>
  46#include <net/sock.h>
  47#include <net/netlink.h>
  48#include <net/genetlink.h>
  49#include <net/ip.h>
  50#include <net/ipv6.h>
  51#include <net/net_namespace.h>
  52#include <net/netlabel.h>
  53#include <asm/bug.h>
  54#include <linux/atomic.h>
  55
  56#include "netlabel_user.h"
  57#include "netlabel_addrlist.h"
  58#include "netlabel_domainhash.h"
  59#include "netlabel_unlabeled.h"
  60#include "netlabel_mgmt.h"
  61
  62/* NOTE: at present we always use init's network namespace since we don't
  63 *       presently support different namespaces even though the majority of
  64 *       the functions in this file are "namespace safe" */
  65
  66/* The unlabeled connection hash table which we use to map network interfaces
  67 * and addresses of unlabeled packets to a user specified secid value for the
  68 * LSM.  The hash table is used to lookup the network interface entry
  69 * (struct netlbl_unlhsh_iface) and then the interface entry is used to
  70 * lookup an IP address match from an ordered list.  If a network interface
  71 * match can not be found in the hash table then the default entry
  72 * (netlbl_unlhsh_def) is used.  The IP address entry list
  73 * (struct netlbl_unlhsh_addr) is ordered such that the entries with a
  74 * larger netmask come first.
  75 */
  76struct netlbl_unlhsh_tbl {
  77        struct list_head *tbl;
  78        u32 size;
  79};
  80#define netlbl_unlhsh_addr4_entry(iter) \
  81        container_of(iter, struct netlbl_unlhsh_addr4, list)
  82struct netlbl_unlhsh_addr4 {
  83        u32 secid;
  84
  85        struct netlbl_af4list list;
  86        struct rcu_head rcu;
  87};
  88#define netlbl_unlhsh_addr6_entry(iter) \
  89        container_of(iter, struct netlbl_unlhsh_addr6, list)
  90struct netlbl_unlhsh_addr6 {
  91        u32 secid;
  92
  93        struct netlbl_af6list list;
  94        struct rcu_head rcu;
  95};
  96struct netlbl_unlhsh_iface {
  97        int ifindex;
  98        struct list_head addr4_list;
  99        struct list_head addr6_list;
 100
 101        u32 valid;
 102        struct list_head list;
 103        struct rcu_head rcu;
 104};
 105
 106/* Argument struct for netlbl_unlhsh_walk() */
 107struct netlbl_unlhsh_walk_arg {
 108        struct netlink_callback *nl_cb;
 109        struct sk_buff *skb;
 110        u32 seq;
 111};
 112
 113/* Unlabeled connection hash table */
 114/* updates should be so rare that having one spinlock for the entire
 115 * hash table should be okay */
 116static DEFINE_SPINLOCK(netlbl_unlhsh_lock);
 117#define netlbl_unlhsh_rcu_deref(p) \
 118        rcu_dereference_check(p, lockdep_is_held(&netlbl_unlhsh_lock))
 119static struct netlbl_unlhsh_tbl __rcu *netlbl_unlhsh;
 120static struct netlbl_unlhsh_iface __rcu *netlbl_unlhsh_def;
 121
 122/* Accept unlabeled packets flag */
 123static u8 netlabel_unlabel_acceptflg;
 124
 125/* NetLabel Generic NETLINK unlabeled family */
 126static struct genl_family netlbl_unlabel_gnl_family;
 127
 128/* NetLabel Netlink attribute policy */
 129static const struct nla_policy netlbl_unlabel_genl_policy[NLBL_UNLABEL_A_MAX + 1] = {
 130        [NLBL_UNLABEL_A_ACPTFLG] = { .type = NLA_U8 },
 131        [NLBL_UNLABEL_A_IPV6ADDR] = { .type = NLA_BINARY,
 132                                      .len = sizeof(struct in6_addr) },
 133        [NLBL_UNLABEL_A_IPV6MASK] = { .type = NLA_BINARY,
 134                                      .len = sizeof(struct in6_addr) },
 135        [NLBL_UNLABEL_A_IPV4ADDR] = { .type = NLA_BINARY,
 136                                      .len = sizeof(struct in_addr) },
 137        [NLBL_UNLABEL_A_IPV4MASK] = { .type = NLA_BINARY,
 138                                      .len = sizeof(struct in_addr) },
 139        [NLBL_UNLABEL_A_IFACE] = { .type = NLA_NUL_STRING,
 140                                   .len = IFNAMSIZ - 1 },
 141        [NLBL_UNLABEL_A_SECCTX] = { .type = NLA_BINARY }
 142};
 143
 144/*
 145 * Unlabeled Connection Hash Table Functions
 146 */
 147
 148/**
 149 * netlbl_unlhsh_free_iface - Frees an interface entry from the hash table
 150 * @entry: the entry's RCU field
 151 *
 152 * Description:
 153 * This function is designed to be used as a callback to the call_rcu()
 154 * function so that memory allocated to a hash table interface entry can be
 155 * released safely.  It is important to note that this function does not free
 156 * the IPv4 and IPv6 address lists contained as part of an interface entry.  It
 157 * is up to the rest of the code to make sure an interface entry is only freed
 158 * once it's address lists are empty.
 159 *
 160 */
 161static void netlbl_unlhsh_free_iface(struct rcu_head *entry)
 162{
 163        struct netlbl_unlhsh_iface *iface;
 164        struct netlbl_af4list *iter4;
 165        struct netlbl_af4list *tmp4;
 166#if IS_ENABLED(CONFIG_IPV6)
 167        struct netlbl_af6list *iter6;
 168        struct netlbl_af6list *tmp6;
 169#endif /* IPv6 */
 170
 171        iface = container_of(entry, struct netlbl_unlhsh_iface, rcu);
 172
 173        /* no need for locks here since we are the only one with access to this
 174         * structure */
 175
 176        netlbl_af4list_foreach_safe(iter4, tmp4, &iface->addr4_list) {
 177                netlbl_af4list_remove_entry(iter4);
 178                kfree(netlbl_unlhsh_addr4_entry(iter4));
 179        }
 180#if IS_ENABLED(CONFIG_IPV6)
 181        netlbl_af6list_foreach_safe(iter6, tmp6, &iface->addr6_list) {
 182                netlbl_af6list_remove_entry(iter6);
 183                kfree(netlbl_unlhsh_addr6_entry(iter6));
 184        }
 185#endif /* IPv6 */
 186        kfree(iface);
 187}
 188
 189/**
 190 * netlbl_unlhsh_hash - Hashing function for the hash table
 191 * @ifindex: the network interface/device to hash
 192 *
 193 * Description:
 194 * This is the hashing function for the unlabeled hash table, it returns the
 195 * bucket number for the given device/interface.  The caller is responsible for
 196 * ensuring that the hash table is protected with either a RCU read lock or
 197 * the hash table lock.
 198 *
 199 */
 200static u32 netlbl_unlhsh_hash(int ifindex)
 201{
 202        return ifindex & (netlbl_unlhsh_rcu_deref(netlbl_unlhsh)->size - 1);
 203}
 204
 205/**
 206 * netlbl_unlhsh_search_iface - Search for a matching interface entry
 207 * @ifindex: the network interface
 208 *
 209 * Description:
 210 * Searches the unlabeled connection hash table and returns a pointer to the
 211 * interface entry which matches @ifindex, otherwise NULL is returned.  The
 212 * caller is responsible for ensuring that the hash table is protected with
 213 * either a RCU read lock or the hash table lock.
 214 *
 215 */
 216static struct netlbl_unlhsh_iface *netlbl_unlhsh_search_iface(int ifindex)
 217{
 218        u32 bkt;
 219        struct list_head *bkt_list;
 220        struct netlbl_unlhsh_iface *iter;
 221
 222        bkt = netlbl_unlhsh_hash(ifindex);
 223        bkt_list = &netlbl_unlhsh_rcu_deref(netlbl_unlhsh)->tbl[bkt];
 224        list_for_each_entry_rcu(iter, bkt_list, list)
 225                if (iter->valid && iter->ifindex == ifindex)
 226                        return iter;
 227
 228        return NULL;
 229}
 230
 231/**
 232 * netlbl_unlhsh_add_addr4 - Add a new IPv4 address entry to the hash table
 233 * @iface: the associated interface entry
 234 * @addr: IPv4 address in network byte order
 235 * @mask: IPv4 address mask in network byte order
 236 * @secid: LSM secid value for entry
 237 *
 238 * Description:
 239 * Add a new address entry into the unlabeled connection hash table using the
 240 * interface entry specified by @iface.  On success zero is returned, otherwise
 241 * a negative value is returned.
 242 *
 243 */
 244static int netlbl_unlhsh_add_addr4(struct netlbl_unlhsh_iface *iface,
 245                                   const struct in_addr *addr,
 246                                   const struct in_addr *mask,
 247                                   u32 secid)
 248{
 249        int ret_val;
 250        struct netlbl_unlhsh_addr4 *entry;
 251
 252        entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
 253        if (entry == NULL)
 254                return -ENOMEM;
 255
 256        entry->list.addr = addr->s_addr & mask->s_addr;
 257        entry->list.mask = mask->s_addr;
 258        entry->list.valid = 1;
 259        entry->secid = secid;
 260
 261        spin_lock(&netlbl_unlhsh_lock);
 262        ret_val = netlbl_af4list_add(&entry->list, &iface->addr4_list);
 263        spin_unlock(&netlbl_unlhsh_lock);
 264
 265        if (ret_val != 0)
 266                kfree(entry);
 267        return ret_val;
 268}
 269
 270#if IS_ENABLED(CONFIG_IPV6)
 271/**
 272 * netlbl_unlhsh_add_addr6 - Add a new IPv6 address entry to the hash table
 273 * @iface: the associated interface entry
 274 * @addr: IPv6 address in network byte order
 275 * @mask: IPv6 address mask in network byte order
 276 * @secid: LSM secid value for entry
 277 *
 278 * Description:
 279 * Add a new address entry into the unlabeled connection hash table using the
 280 * interface entry specified by @iface.  On success zero is returned, otherwise
 281 * a negative value is returned.
 282 *
 283 */
 284static int netlbl_unlhsh_add_addr6(struct netlbl_unlhsh_iface *iface,
 285                                   const struct in6_addr *addr,
 286                                   const struct in6_addr *mask,
 287                                   u32 secid)
 288{
 289        int ret_val;
 290        struct netlbl_unlhsh_addr6 *entry;
 291
 292        entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
 293        if (entry == NULL)
 294                return -ENOMEM;
 295
 296        entry->list.addr = *addr;
 297        entry->list.addr.s6_addr32[0] &= mask->s6_addr32[0];
 298        entry->list.addr.s6_addr32[1] &= mask->s6_addr32[1];
 299        entry->list.addr.s6_addr32[2] &= mask->s6_addr32[2];
 300        entry->list.addr.s6_addr32[3] &= mask->s6_addr32[3];
 301        entry->list.mask = *mask;
 302        entry->list.valid = 1;
 303        entry->secid = secid;
 304
 305        spin_lock(&netlbl_unlhsh_lock);
 306        ret_val = netlbl_af6list_add(&entry->list, &iface->addr6_list);
 307        spin_unlock(&netlbl_unlhsh_lock);
 308
 309        if (ret_val != 0)
 310                kfree(entry);
 311        return 0;
 312}
 313#endif /* IPv6 */
 314
 315/**
 316 * netlbl_unlhsh_add_iface - Adds a new interface entry to the hash table
 317 * @ifindex: network interface
 318 *
 319 * Description:
 320 * Add a new, empty, interface entry into the unlabeled connection hash table.
 321 * On success a pointer to the new interface entry is returned, on failure NULL
 322 * is returned.
 323 *
 324 */
 325static struct netlbl_unlhsh_iface *netlbl_unlhsh_add_iface(int ifindex)
 326{
 327        u32 bkt;
 328        struct netlbl_unlhsh_iface *iface;
 329
 330        iface = kzalloc(sizeof(*iface), GFP_ATOMIC);
 331        if (iface == NULL)
 332                return NULL;
 333
 334        iface->ifindex = ifindex;
 335        INIT_LIST_HEAD(&iface->addr4_list);
 336        INIT_LIST_HEAD(&iface->addr6_list);
 337        iface->valid = 1;
 338
 339        spin_lock(&netlbl_unlhsh_lock);
 340        if (ifindex > 0) {
 341                bkt = netlbl_unlhsh_hash(ifindex);
 342                if (netlbl_unlhsh_search_iface(ifindex) != NULL)
 343                        goto add_iface_failure;
 344                list_add_tail_rcu(&iface->list,
 345                             &netlbl_unlhsh_rcu_deref(netlbl_unlhsh)->tbl[bkt]);
 346        } else {
 347                INIT_LIST_HEAD(&iface->list);
 348                if (netlbl_unlhsh_rcu_deref(netlbl_unlhsh_def) != NULL)
 349                        goto add_iface_failure;
 350                rcu_assign_pointer(netlbl_unlhsh_def, iface);
 351        }
 352        spin_unlock(&netlbl_unlhsh_lock);
 353
 354        return iface;
 355
 356add_iface_failure:
 357        spin_unlock(&netlbl_unlhsh_lock);
 358        kfree(iface);
 359        return NULL;
 360}
 361
 362/**
 363 * netlbl_unlhsh_add - Adds a new entry to the unlabeled connection hash table
 364 * @net: network namespace
 365 * @dev_name: interface name
 366 * @addr: IP address in network byte order
 367 * @mask: address mask in network byte order
 368 * @addr_len: length of address/mask (4 for IPv4, 16 for IPv6)
 369 * @secid: LSM secid value for the entry
 370 * @audit_info: NetLabel audit information
 371 *
 372 * Description:
 373 * Adds a new entry to the unlabeled connection hash table.  Returns zero on
 374 * success, negative values on failure.
 375 *
 376 */
 377int netlbl_unlhsh_add(struct net *net,
 378                      const char *dev_name,
 379                      const void *addr,
 380                      const void *mask,
 381                      u32 addr_len,
 382                      u32 secid,
 383                      struct netlbl_audit *audit_info)
 384{
 385        int ret_val;
 386        int ifindex;
 387        struct net_device *dev;
 388        struct netlbl_unlhsh_iface *iface;
 389        struct audit_buffer *audit_buf = NULL;
 390        char *secctx = NULL;
 391        u32 secctx_len;
 392
 393        if (addr_len != sizeof(struct in_addr) &&
 394            addr_len != sizeof(struct in6_addr))
 395                return -EINVAL;
 396
 397        rcu_read_lock();
 398        if (dev_name != NULL) {
 399                dev = dev_get_by_name_rcu(net, dev_name);
 400                if (dev == NULL) {
 401                        ret_val = -ENODEV;
 402                        goto unlhsh_add_return;
 403                }
 404                ifindex = dev->ifindex;
 405                iface = netlbl_unlhsh_search_iface(ifindex);
 406        } else {
 407                ifindex = 0;
 408                iface = rcu_dereference(netlbl_unlhsh_def);
 409        }
 410        if (iface == NULL) {
 411                iface = netlbl_unlhsh_add_iface(ifindex);
 412                if (iface == NULL) {
 413                        ret_val = -ENOMEM;
 414                        goto unlhsh_add_return;
 415                }
 416        }
 417        audit_buf = netlbl_audit_start_common(AUDIT_MAC_UNLBL_STCADD,
 418                                              audit_info);
 419        switch (addr_len) {
 420        case sizeof(struct in_addr): {
 421                const struct in_addr *addr4 = addr;
 422                const struct in_addr *mask4 = mask;
 423
 424                ret_val = netlbl_unlhsh_add_addr4(iface, addr4, mask4, secid);
 425                if (audit_buf != NULL)
 426                        netlbl_af4list_audit_addr(audit_buf, 1,
 427                                                  dev_name,
 428                                                  addr4->s_addr,
 429                                                  mask4->s_addr);
 430                break;
 431        }
 432#if IS_ENABLED(CONFIG_IPV6)
 433        case sizeof(struct in6_addr): {
 434                const struct in6_addr *addr6 = addr;
 435                const struct in6_addr *mask6 = mask;
 436
 437                ret_val = netlbl_unlhsh_add_addr6(iface, addr6, mask6, secid);
 438                if (audit_buf != NULL)
 439                        netlbl_af6list_audit_addr(audit_buf, 1,
 440                                                  dev_name,
 441                                                  addr6, mask6);
 442                break;
 443        }
 444#endif /* IPv6 */
 445        default:
 446                ret_val = -EINVAL;
 447        }
 448        if (ret_val == 0)
 449                atomic_inc(&netlabel_mgmt_protocount);
 450
 451unlhsh_add_return:
 452        rcu_read_unlock();
 453        if (audit_buf != NULL) {
 454                if (security_secid_to_secctx(secid,
 455                                             &secctx,
 456                                             &secctx_len) == 0) {
 457                        audit_log_format(audit_buf, " sec_obj=%s", secctx);
 458                        security_release_secctx(secctx, secctx_len);
 459                }
 460                audit_log_format(audit_buf, " res=%u", ret_val == 0 ? 1 : 0);
 461                audit_log_end(audit_buf);
 462        }
 463        return ret_val;
 464}
 465
 466/**
 467 * netlbl_unlhsh_remove_addr4 - Remove an IPv4 address entry
 468 * @net: network namespace
 469 * @iface: interface entry
 470 * @addr: IP address
 471 * @mask: IP address mask
 472 * @audit_info: NetLabel audit information
 473 *
 474 * Description:
 475 * Remove an IP address entry from the unlabeled connection hash table.
 476 * Returns zero on success, negative values on failure.
 477 *
 478 */
 479static int netlbl_unlhsh_remove_addr4(struct net *net,
 480                                      struct netlbl_unlhsh_iface *iface,
 481                                      const struct in_addr *addr,
 482                                      const struct in_addr *mask,
 483                                      struct netlbl_audit *audit_info)
 484{
 485        struct netlbl_af4list *list_entry;
 486        struct netlbl_unlhsh_addr4 *entry;
 487        struct audit_buffer *audit_buf;
 488        struct net_device *dev;
 489        char *secctx;
 490        u32 secctx_len;
 491
 492        spin_lock(&netlbl_unlhsh_lock);
 493        list_entry = netlbl_af4list_remove(addr->s_addr, mask->s_addr,
 494                                           &iface->addr4_list);
 495        spin_unlock(&netlbl_unlhsh_lock);
 496        if (list_entry != NULL)
 497                entry = netlbl_unlhsh_addr4_entry(list_entry);
 498        else
 499                entry = NULL;
 500
 501        audit_buf = netlbl_audit_start_common(AUDIT_MAC_UNLBL_STCDEL,
 502                                              audit_info);
 503        if (audit_buf != NULL) {
 504                dev = dev_get_by_index(net, iface->ifindex);
 505                netlbl_af4list_audit_addr(audit_buf, 1,
 506                                          (dev != NULL ? dev->name : NULL),
 507                                          addr->s_addr, mask->s_addr);
 508                if (dev != NULL)
 509                        dev_put(dev);
 510                if (entry != NULL &&
 511                    security_secid_to_secctx(entry->secid,
 512                                             &secctx, &secctx_len) == 0) {
 513                        audit_log_format(audit_buf, " sec_obj=%s", secctx);
 514                        security_release_secctx(secctx, secctx_len);
 515                }
 516                audit_log_format(audit_buf, " res=%u", entry != NULL ? 1 : 0);
 517                audit_log_end(audit_buf);
 518        }
 519
 520        if (entry == NULL)
 521                return -ENOENT;
 522
 523        kfree_rcu(entry, rcu);
 524        return 0;
 525}
 526
 527#if IS_ENABLED(CONFIG_IPV6)
 528/**
 529 * netlbl_unlhsh_remove_addr6 - Remove an IPv6 address entry
 530 * @net: network namespace
 531 * @iface: interface entry
 532 * @addr: IP address
 533 * @mask: IP address mask
 534 * @audit_info: NetLabel audit information
 535 *
 536 * Description:
 537 * Remove an IP address entry from the unlabeled connection hash table.
 538 * Returns zero on success, negative values on failure.
 539 *
 540 */
 541static int netlbl_unlhsh_remove_addr6(struct net *net,
 542                                      struct netlbl_unlhsh_iface *iface,
 543                                      const struct in6_addr *addr,
 544                                      const struct in6_addr *mask,
 545                                      struct netlbl_audit *audit_info)
 546{
 547        struct netlbl_af6list *list_entry;
 548        struct netlbl_unlhsh_addr6 *entry;
 549        struct audit_buffer *audit_buf;
 550        struct net_device *dev;
 551        char *secctx;
 552        u32 secctx_len;
 553
 554        spin_lock(&netlbl_unlhsh_lock);
 555        list_entry = netlbl_af6list_remove(addr, mask, &iface->addr6_list);
 556        spin_unlock(&netlbl_unlhsh_lock);
 557        if (list_entry != NULL)
 558                entry = netlbl_unlhsh_addr6_entry(list_entry);
 559        else
 560                entry = NULL;
 561
 562        audit_buf = netlbl_audit_start_common(AUDIT_MAC_UNLBL_STCDEL,
 563                                              audit_info);
 564        if (audit_buf != NULL) {
 565                dev = dev_get_by_index(net, iface->ifindex);
 566                netlbl_af6list_audit_addr(audit_buf, 1,
 567                                          (dev != NULL ? dev->name : NULL),
 568                                          addr, mask);
 569                if (dev != NULL)
 570                        dev_put(dev);
 571                if (entry != NULL &&
 572                    security_secid_to_secctx(entry->secid,
 573                                             &secctx, &secctx_len) == 0) {
 574                        audit_log_format(audit_buf, " sec_obj=%s", secctx);
 575                        security_release_secctx(secctx, secctx_len);
 576                }
 577                audit_log_format(audit_buf, " res=%u", entry != NULL ? 1 : 0);
 578                audit_log_end(audit_buf);
 579        }
 580
 581        if (entry == NULL)
 582                return -ENOENT;
 583
 584        kfree_rcu(entry, rcu);
 585        return 0;
 586}
 587#endif /* IPv6 */
 588
 589/**
 590 * netlbl_unlhsh_condremove_iface - Remove an interface entry
 591 * @iface: the interface entry
 592 *
 593 * Description:
 594 * Remove an interface entry from the unlabeled connection hash table if it is
 595 * empty.  An interface entry is considered to be empty if there are no
 596 * address entries assigned to it.
 597 *
 598 */
 599static void netlbl_unlhsh_condremove_iface(struct netlbl_unlhsh_iface *iface)
 600{
 601        struct netlbl_af4list *iter4;
 602#if IS_ENABLED(CONFIG_IPV6)
 603        struct netlbl_af6list *iter6;
 604#endif /* IPv6 */
 605
 606        spin_lock(&netlbl_unlhsh_lock);
 607        netlbl_af4list_foreach_rcu(iter4, &iface->addr4_list)
 608                goto unlhsh_condremove_failure;
 609#if IS_ENABLED(CONFIG_IPV6)
 610        netlbl_af6list_foreach_rcu(iter6, &iface->addr6_list)
 611                goto unlhsh_condremove_failure;
 612#endif /* IPv6 */
 613        iface->valid = 0;
 614        if (iface->ifindex > 0)
 615                list_del_rcu(&iface->list);
 616        else
 617                RCU_INIT_POINTER(netlbl_unlhsh_def, NULL);
 618        spin_unlock(&netlbl_unlhsh_lock);
 619
 620        call_rcu(&iface->rcu, netlbl_unlhsh_free_iface);
 621        return;
 622
 623unlhsh_condremove_failure:
 624        spin_unlock(&netlbl_unlhsh_lock);
 625}
 626
 627/**
 628 * netlbl_unlhsh_remove - Remove an entry from the unlabeled hash table
 629 * @net: network namespace
 630 * @dev_name: interface name
 631 * @addr: IP address in network byte order
 632 * @mask: address mask in network byte order
 633 * @addr_len: length of address/mask (4 for IPv4, 16 for IPv6)
 634 * @audit_info: NetLabel audit information
 635 *
 636 * Description:
 637 * Removes and existing entry from the unlabeled connection hash table.
 638 * Returns zero on success, negative values on failure.
 639 *
 640 */
 641int netlbl_unlhsh_remove(struct net *net,
 642                         const char *dev_name,
 643                         const void *addr,
 644                         const void *mask,
 645                         u32 addr_len,
 646                         struct netlbl_audit *audit_info)
 647{
 648        int ret_val;
 649        struct net_device *dev;
 650        struct netlbl_unlhsh_iface *iface;
 651
 652        if (addr_len != sizeof(struct in_addr) &&
 653            addr_len != sizeof(struct in6_addr))
 654                return -EINVAL;
 655
 656        rcu_read_lock();
 657        if (dev_name != NULL) {
 658                dev = dev_get_by_name_rcu(net, dev_name);
 659                if (dev == NULL) {
 660                        ret_val = -ENODEV;
 661                        goto unlhsh_remove_return;
 662                }
 663                iface = netlbl_unlhsh_search_iface(dev->ifindex);
 664        } else
 665                iface = rcu_dereference(netlbl_unlhsh_def);
 666        if (iface == NULL) {
 667                ret_val = -ENOENT;
 668                goto unlhsh_remove_return;
 669        }
 670        switch (addr_len) {
 671        case sizeof(struct in_addr):
 672                ret_val = netlbl_unlhsh_remove_addr4(net,
 673                                                     iface, addr, mask,
 674                                                     audit_info);
 675                break;
 676#if IS_ENABLED(CONFIG_IPV6)
 677        case sizeof(struct in6_addr):
 678                ret_val = netlbl_unlhsh_remove_addr6(net,
 679                                                     iface, addr, mask,
 680                                                     audit_info);
 681                break;
 682#endif /* IPv6 */
 683        default:
 684                ret_val = -EINVAL;
 685        }
 686        if (ret_val == 0) {
 687                netlbl_unlhsh_condremove_iface(iface);
 688                atomic_dec(&netlabel_mgmt_protocount);
 689        }
 690
 691unlhsh_remove_return:
 692        rcu_read_unlock();
 693        return ret_val;
 694}
 695
 696/*
 697 * General Helper Functions
 698 */
 699
 700/**
 701 * netlbl_unlhsh_netdev_handler - Network device notification handler
 702 * @this: notifier block
 703 * @event: the event
 704 * @ptr: the netdevice notifier info (cast to void)
 705 *
 706 * Description:
 707 * Handle network device events, although at present all we care about is a
 708 * network device going away.  In the case of a device going away we clear any
 709 * related entries from the unlabeled connection hash table.
 710 *
 711 */
 712static int netlbl_unlhsh_netdev_handler(struct notifier_block *this,
 713                                        unsigned long event, void *ptr)
 714{
 715        struct net_device *dev = netdev_notifier_info_to_dev(ptr);
 716        struct netlbl_unlhsh_iface *iface = NULL;
 717
 718        if (!net_eq(dev_net(dev), &init_net))
 719                return NOTIFY_DONE;
 720
 721        /* XXX - should this be a check for NETDEV_DOWN or _UNREGISTER? */
 722        if (event == NETDEV_DOWN) {
 723                spin_lock(&netlbl_unlhsh_lock);
 724                iface = netlbl_unlhsh_search_iface(dev->ifindex);
 725                if (iface != NULL && iface->valid) {
 726                        iface->valid = 0;
 727                        list_del_rcu(&iface->list);
 728                } else
 729                        iface = NULL;
 730                spin_unlock(&netlbl_unlhsh_lock);
 731        }
 732
 733        if (iface != NULL)
 734                call_rcu(&iface->rcu, netlbl_unlhsh_free_iface);
 735
 736        return NOTIFY_DONE;
 737}
 738
 739/**
 740 * netlbl_unlabel_acceptflg_set - Set the unlabeled accept flag
 741 * @value: desired value
 742 * @audit_info: NetLabel audit information
 743 *
 744 * Description:
 745 * Set the value of the unlabeled accept flag to @value.
 746 *
 747 */
 748static void netlbl_unlabel_acceptflg_set(u8 value,
 749                                         struct netlbl_audit *audit_info)
 750{
 751        struct audit_buffer *audit_buf;
 752        u8 old_val;
 753
 754        old_val = netlabel_unlabel_acceptflg;
 755        netlabel_unlabel_acceptflg = value;
 756        audit_buf = netlbl_audit_start_common(AUDIT_MAC_UNLBL_ALLOW,
 757                                              audit_info);
 758        if (audit_buf != NULL) {
 759                audit_log_format(audit_buf,
 760                                 " unlbl_accept=%u old=%u", value, old_val);
 761                audit_log_end(audit_buf);
 762        }
 763}
 764
 765/**
 766 * netlbl_unlabel_addrinfo_get - Get the IPv4/6 address information
 767 * @info: the Generic NETLINK info block
 768 * @addr: the IP address
 769 * @mask: the IP address mask
 770 * @len: the address length
 771 *
 772 * Description:
 773 * Examine the Generic NETLINK message and extract the IP address information.
 774 * Returns zero on success, negative values on failure.
 775 *
 776 */
 777static int netlbl_unlabel_addrinfo_get(struct genl_info *info,
 778                                       void **addr,
 779                                       void **mask,
 780                                       u32 *len)
 781{
 782        u32 addr_len;
 783
 784        if (info->attrs[NLBL_UNLABEL_A_IPV4ADDR]) {
 785                addr_len = nla_len(info->attrs[NLBL_UNLABEL_A_IPV4ADDR]);
 786                if (addr_len != sizeof(struct in_addr) &&
 787                    addr_len != nla_len(info->attrs[NLBL_UNLABEL_A_IPV4MASK]))
 788                        return -EINVAL;
 789                *len = addr_len;
 790                *addr = nla_data(info->attrs[NLBL_UNLABEL_A_IPV4ADDR]);
 791                *mask = nla_data(info->attrs[NLBL_UNLABEL_A_IPV4MASK]);
 792                return 0;
 793        } else if (info->attrs[NLBL_UNLABEL_A_IPV6ADDR]) {
 794                addr_len = nla_len(info->attrs[NLBL_UNLABEL_A_IPV6ADDR]);
 795                if (addr_len != sizeof(struct in6_addr) &&
 796                    addr_len != nla_len(info->attrs[NLBL_UNLABEL_A_IPV6MASK]))
 797                        return -EINVAL;
 798                *len = addr_len;
 799                *addr = nla_data(info->attrs[NLBL_UNLABEL_A_IPV6ADDR]);
 800                *mask = nla_data(info->attrs[NLBL_UNLABEL_A_IPV6MASK]);
 801                return 0;
 802        }
 803
 804        return -EINVAL;
 805}
 806
 807/*
 808 * NetLabel Command Handlers
 809 */
 810
 811/**
 812 * netlbl_unlabel_accept - Handle an ACCEPT message
 813 * @skb: the NETLINK buffer
 814 * @info: the Generic NETLINK info block
 815 *
 816 * Description:
 817 * Process a user generated ACCEPT message and set the accept flag accordingly.
 818 * Returns zero on success, negative values on failure.
 819 *
 820 */
 821static int netlbl_unlabel_accept(struct sk_buff *skb, struct genl_info *info)
 822{
 823        u8 value;
 824        struct netlbl_audit audit_info;
 825
 826        if (info->attrs[NLBL_UNLABEL_A_ACPTFLG]) {
 827                value = nla_get_u8(info->attrs[NLBL_UNLABEL_A_ACPTFLG]);
 828                if (value == 1 || value == 0) {
 829                        netlbl_netlink_auditinfo(skb, &audit_info);
 830                        netlbl_unlabel_acceptflg_set(value, &audit_info);
 831                        return 0;
 832                }
 833        }
 834
 835        return -EINVAL;
 836}
 837
 838/**
 839 * netlbl_unlabel_list - Handle a LIST message
 840 * @skb: the NETLINK buffer
 841 * @info: the Generic NETLINK info block
 842 *
 843 * Description:
 844 * Process a user generated LIST message and respond with the current status.
 845 * Returns zero on success, negative values on failure.
 846 *
 847 */
 848static int netlbl_unlabel_list(struct sk_buff *skb, struct genl_info *info)
 849{
 850        int ret_val = -EINVAL;
 851        struct sk_buff *ans_skb;
 852        void *data;
 853
 854        ans_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
 855        if (ans_skb == NULL)
 856                goto list_failure;
 857        data = genlmsg_put_reply(ans_skb, info, &netlbl_unlabel_gnl_family,
 858                                 0, NLBL_UNLABEL_C_LIST);
 859        if (data == NULL) {
 860                ret_val = -ENOMEM;
 861                goto list_failure;
 862        }
 863
 864        ret_val = nla_put_u8(ans_skb,
 865                             NLBL_UNLABEL_A_ACPTFLG,
 866                             netlabel_unlabel_acceptflg);
 867        if (ret_val != 0)
 868                goto list_failure;
 869
 870        genlmsg_end(ans_skb, data);
 871        return genlmsg_reply(ans_skb, info);
 872
 873list_failure:
 874        kfree_skb(ans_skb);
 875        return ret_val;
 876}
 877
 878/**
 879 * netlbl_unlabel_staticadd - Handle a STATICADD message
 880 * @skb: the NETLINK buffer
 881 * @info: the Generic NETLINK info block
 882 *
 883 * Description:
 884 * Process a user generated STATICADD message and add a new unlabeled
 885 * connection entry to the hash table.  Returns zero on success, negative
 886 * values on failure.
 887 *
 888 */
 889static int netlbl_unlabel_staticadd(struct sk_buff *skb,
 890                                    struct genl_info *info)
 891{
 892        int ret_val;
 893        char *dev_name;
 894        void *addr;
 895        void *mask;
 896        u32 addr_len;
 897        u32 secid;
 898        struct netlbl_audit audit_info;
 899
 900        /* Don't allow users to add both IPv4 and IPv6 addresses for a
 901         * single entry.  However, allow users to create two entries, one each
 902         * for IPv4 and IPv4, with the same LSM security context which should
 903         * achieve the same result. */
 904        if (!info->attrs[NLBL_UNLABEL_A_SECCTX] ||
 905            !info->attrs[NLBL_UNLABEL_A_IFACE] ||
 906            !((!info->attrs[NLBL_UNLABEL_A_IPV4ADDR] ||
 907               !info->attrs[NLBL_UNLABEL_A_IPV4MASK]) ^
 908              (!info->attrs[NLBL_UNLABEL_A_IPV6ADDR] ||
 909               !info->attrs[NLBL_UNLABEL_A_IPV6MASK])))
 910                return -EINVAL;
 911
 912        netlbl_netlink_auditinfo(skb, &audit_info);
 913
 914        ret_val = netlbl_unlabel_addrinfo_get(info, &addr, &mask, &addr_len);
 915        if (ret_val != 0)
 916                return ret_val;
 917        dev_name = nla_data(info->attrs[NLBL_UNLABEL_A_IFACE]);
 918        ret_val = security_secctx_to_secid(
 919                                  nla_data(info->attrs[NLBL_UNLABEL_A_SECCTX]),
 920                                  nla_len(info->attrs[NLBL_UNLABEL_A_SECCTX]),
 921                                  &secid);
 922        if (ret_val != 0)
 923                return ret_val;
 924
 925        return netlbl_unlhsh_add(&init_net,
 926                                 dev_name, addr, mask, addr_len, secid,
 927                                 &audit_info);
 928}
 929
 930/**
 931 * netlbl_unlabel_staticadddef - Handle a STATICADDDEF message
 932 * @skb: the NETLINK buffer
 933 * @info: the Generic NETLINK info block
 934 *
 935 * Description:
 936 * Process a user generated STATICADDDEF message and add a new default
 937 * unlabeled connection entry.  Returns zero on success, negative values on
 938 * failure.
 939 *
 940 */
 941static int netlbl_unlabel_staticadddef(struct sk_buff *skb,
 942                                       struct genl_info *info)
 943{
 944        int ret_val;
 945        void *addr;
 946        void *mask;
 947        u32 addr_len;
 948        u32 secid;
 949        struct netlbl_audit audit_info;
 950
 951        /* Don't allow users to add both IPv4 and IPv6 addresses for a
 952         * single entry.  However, allow users to create two entries, one each
 953         * for IPv4 and IPv6, with the same LSM security context which should
 954         * achieve the same result. */
 955        if (!info->attrs[NLBL_UNLABEL_A_SECCTX] ||
 956            !((!info->attrs[NLBL_UNLABEL_A_IPV4ADDR] ||
 957               !info->attrs[NLBL_UNLABEL_A_IPV4MASK]) ^
 958              (!info->attrs[NLBL_UNLABEL_A_IPV6ADDR] ||
 959               !info->attrs[NLBL_UNLABEL_A_IPV6MASK])))
 960                return -EINVAL;
 961
 962        netlbl_netlink_auditinfo(skb, &audit_info);
 963
 964        ret_val = netlbl_unlabel_addrinfo_get(info, &addr, &mask, &addr_len);
 965        if (ret_val != 0)
 966                return ret_val;
 967        ret_val = security_secctx_to_secid(
 968                                  nla_data(info->attrs[NLBL_UNLABEL_A_SECCTX]),
 969                                  nla_len(info->attrs[NLBL_UNLABEL_A_SECCTX]),
 970                                  &secid);
 971        if (ret_val != 0)
 972                return ret_val;
 973
 974        return netlbl_unlhsh_add(&init_net,
 975                                 NULL, addr, mask, addr_len, secid,
 976                                 &audit_info);
 977}
 978
 979/**
 980 * netlbl_unlabel_staticremove - Handle a STATICREMOVE message
 981 * @skb: the NETLINK buffer
 982 * @info: the Generic NETLINK info block
 983 *
 984 * Description:
 985 * Process a user generated STATICREMOVE message and remove the specified
 986 * unlabeled connection entry.  Returns zero on success, negative values on
 987 * failure.
 988 *
 989 */
 990static int netlbl_unlabel_staticremove(struct sk_buff *skb,
 991                                       struct genl_info *info)
 992{
 993        int ret_val;
 994        char *dev_name;
 995        void *addr;
 996        void *mask;
 997        u32 addr_len;
 998        struct netlbl_audit audit_info;
 999
1000        /* See the note in netlbl_unlabel_staticadd() about not allowing both
1001         * IPv4 and IPv6 in the same entry. */
1002        if (!info->attrs[NLBL_UNLABEL_A_IFACE] ||
1003            !((!info->attrs[NLBL_UNLABEL_A_IPV4ADDR] ||
1004               !info->attrs[NLBL_UNLABEL_A_IPV4MASK]) ^
1005              (!info->attrs[NLBL_UNLABEL_A_IPV6ADDR] ||
1006               !info->attrs[NLBL_UNLABEL_A_IPV6MASK])))
1007                return -EINVAL;
1008
1009        netlbl_netlink_auditinfo(skb, &audit_info);
1010
1011        ret_val = netlbl_unlabel_addrinfo_get(info, &addr, &mask, &addr_len);
1012        if (ret_val != 0)
1013                return ret_val;
1014        dev_name = nla_data(info->attrs[NLBL_UNLABEL_A_IFACE]);
1015
1016        return netlbl_unlhsh_remove(&init_net,
1017                                    dev_name, addr, mask, addr_len,
1018                                    &audit_info);
1019}
1020
1021/**
1022 * netlbl_unlabel_staticremovedef - Handle a STATICREMOVEDEF message
1023 * @skb: the NETLINK buffer
1024 * @info: the Generic NETLINK info block
1025 *
1026 * Description:
1027 * Process a user generated STATICREMOVEDEF message and remove the default
1028 * unlabeled connection entry.  Returns zero on success, negative values on
1029 * failure.
1030 *
1031 */
1032static int netlbl_unlabel_staticremovedef(struct sk_buff *skb,
1033                                          struct genl_info *info)
1034{
1035        int ret_val;
1036        void *addr;
1037        void *mask;
1038        u32 addr_len;
1039        struct netlbl_audit audit_info;
1040
1041        /* See the note in netlbl_unlabel_staticadd() about not allowing both
1042         * IPv4 and IPv6 in the same entry. */
1043        if (!((!info->attrs[NLBL_UNLABEL_A_IPV4ADDR] ||
1044               !info->attrs[NLBL_UNLABEL_A_IPV4MASK]) ^
1045              (!info->attrs[NLBL_UNLABEL_A_IPV6ADDR] ||
1046               !info->attrs[NLBL_UNLABEL_A_IPV6MASK])))
1047                return -EINVAL;
1048
1049        netlbl_netlink_auditinfo(skb, &audit_info);
1050
1051        ret_val = netlbl_unlabel_addrinfo_get(info, &addr, &mask, &addr_len);
1052        if (ret_val != 0)
1053                return ret_val;
1054
1055        return netlbl_unlhsh_remove(&init_net,
1056                                    NULL, addr, mask, addr_len,
1057                                    &audit_info);
1058}
1059
1060
1061/**
1062 * netlbl_unlabel_staticlist_gen - Generate messages for STATICLIST[DEF]
1063 * @cmd: command/message
1064 * @iface: the interface entry
1065 * @addr4: the IPv4 address entry
1066 * @addr6: the IPv6 address entry
1067 * @arg: the netlbl_unlhsh_walk_arg structure
1068 *
1069 * Description:
1070 * This function is designed to be used to generate a response for a
1071 * STATICLIST or STATICLISTDEF message.  When called either @addr4 or @addr6
1072 * can be specified, not both, the other unspecified entry should be set to
1073 * NULL by the caller.  Returns the size of the message on success, negative
1074 * values on failure.
1075 *
1076 */
1077static int netlbl_unlabel_staticlist_gen(u32 cmd,
1078                                       const struct netlbl_unlhsh_iface *iface,
1079                                       const struct netlbl_unlhsh_addr4 *addr4,
1080                                       const struct netlbl_unlhsh_addr6 *addr6,
1081                                       void *arg)
1082{
1083        int ret_val = -ENOMEM;
1084        struct netlbl_unlhsh_walk_arg *cb_arg = arg;
1085        struct net_device *dev;
1086        void *data;
1087        u32 secid;
1088        char *secctx;
1089        u32 secctx_len;
1090
1091        data = genlmsg_put(cb_arg->skb, NETLINK_CB(cb_arg->nl_cb->skb).portid,
1092                           cb_arg->seq, &netlbl_unlabel_gnl_family,
1093                           NLM_F_MULTI, cmd);
1094        if (data == NULL)
1095                goto list_cb_failure;
1096
1097        if (iface->ifindex > 0) {
1098                dev = dev_get_by_index(&init_net, iface->ifindex);
1099                if (!dev) {
1100                        ret_val = -ENODEV;
1101                        goto list_cb_failure;
1102                }
1103                ret_val = nla_put_string(cb_arg->skb,
1104                                         NLBL_UNLABEL_A_IFACE, dev->name);
1105                dev_put(dev);
1106                if (ret_val != 0)
1107                        goto list_cb_failure;
1108        }
1109
1110        if (addr4) {
1111                struct in_addr addr_struct;
1112
1113                addr_struct.s_addr = addr4->list.addr;
1114                ret_val = nla_put_in_addr(cb_arg->skb,
1115                                          NLBL_UNLABEL_A_IPV4ADDR,
1116                                          addr_struct.s_addr);
1117                if (ret_val != 0)
1118                        goto list_cb_failure;
1119
1120                addr_struct.s_addr = addr4->list.mask;
1121                ret_val = nla_put_in_addr(cb_arg->skb,
1122                                          NLBL_UNLABEL_A_IPV4MASK,
1123                                          addr_struct.s_addr);
1124                if (ret_val != 0)
1125                        goto list_cb_failure;
1126
1127                secid = addr4->secid;
1128        } else {
1129                ret_val = nla_put_in6_addr(cb_arg->skb,
1130                                           NLBL_UNLABEL_A_IPV6ADDR,
1131                                           &addr6->list.addr);
1132                if (ret_val != 0)
1133                        goto list_cb_failure;
1134
1135                ret_val = nla_put_in6_addr(cb_arg->skb,
1136                                           NLBL_UNLABEL_A_IPV6MASK,
1137                                           &addr6->list.mask);
1138                if (ret_val != 0)
1139                        goto list_cb_failure;
1140
1141                secid = addr6->secid;
1142        }
1143
1144        ret_val = security_secid_to_secctx(secid, &secctx, &secctx_len);
1145        if (ret_val != 0)
1146                goto list_cb_failure;
1147        ret_val = nla_put(cb_arg->skb,
1148                          NLBL_UNLABEL_A_SECCTX,
1149                          secctx_len,
1150                          secctx);
1151        security_release_secctx(secctx, secctx_len);
1152        if (ret_val != 0)
1153                goto list_cb_failure;
1154
1155        cb_arg->seq++;
1156        genlmsg_end(cb_arg->skb, data);
1157        return 0;
1158
1159list_cb_failure:
1160        genlmsg_cancel(cb_arg->skb, data);
1161        return ret_val;
1162}
1163
1164/**
1165 * netlbl_unlabel_staticlist - Handle a STATICLIST message
1166 * @skb: the NETLINK buffer
1167 * @cb: the NETLINK callback
1168 *
1169 * Description:
1170 * Process a user generated STATICLIST message and dump the unlabeled
1171 * connection hash table in a form suitable for use in a kernel generated
1172 * STATICLIST message.  Returns the length of @skb.
1173 *
1174 */
1175static int netlbl_unlabel_staticlist(struct sk_buff *skb,
1176                                     struct netlink_callback *cb)
1177{
1178        struct netlbl_unlhsh_walk_arg cb_arg;
1179        u32 skip_bkt = cb->args[0];
1180        u32 skip_chain = cb->args[1];
1181        u32 iter_bkt;
1182        u32 iter_chain = 0, iter_addr4 = 0, iter_addr6 = 0;
1183        struct netlbl_unlhsh_iface *iface;
1184        struct list_head *iter_list;
1185        struct netlbl_af4list *addr4;
1186#if IS_ENABLED(CONFIG_IPV6)
1187        struct netlbl_af6list *addr6;
1188#endif
1189
1190        cb_arg.nl_cb = cb;
1191        cb_arg.skb = skb;
1192        cb_arg.seq = cb->nlh->nlmsg_seq;
1193
1194        rcu_read_lock();
1195        for (iter_bkt = skip_bkt;
1196             iter_bkt < rcu_dereference(netlbl_unlhsh)->size;
1197             iter_bkt++, iter_chain = 0, iter_addr4 = 0, iter_addr6 = 0) {
1198                iter_list = &rcu_dereference(netlbl_unlhsh)->tbl[iter_bkt];
1199                list_for_each_entry_rcu(iface, iter_list, list) {
1200                        if (!iface->valid ||
1201                            iter_chain++ < skip_chain)
1202                                continue;
1203                        netlbl_af4list_foreach_rcu(addr4,
1204                                                   &iface->addr4_list) {
1205                                if (iter_addr4++ < cb->args[2])
1206                                        continue;
1207                                if (netlbl_unlabel_staticlist_gen(
1208                                              NLBL_UNLABEL_C_STATICLIST,
1209                                              iface,
1210                                              netlbl_unlhsh_addr4_entry(addr4),
1211                                              NULL,
1212                                              &cb_arg) < 0) {
1213                                        iter_addr4--;
1214                                        iter_chain--;
1215                                        goto unlabel_staticlist_return;
1216                                }
1217                        }
1218#if IS_ENABLED(CONFIG_IPV6)
1219                        netlbl_af6list_foreach_rcu(addr6,
1220                                                   &iface->addr6_list) {
1221                                if (iter_addr6++ < cb->args[3])
1222                                        continue;
1223                                if (netlbl_unlabel_staticlist_gen(
1224                                              NLBL_UNLABEL_C_STATICLIST,
1225                                              iface,
1226                                              NULL,
1227                                              netlbl_unlhsh_addr6_entry(addr6),
1228                                              &cb_arg) < 0) {
1229                                        iter_addr6--;
1230                                        iter_chain--;
1231                                        goto unlabel_staticlist_return;
1232                                }
1233                        }
1234#endif /* IPv6 */
1235                }
1236        }
1237
1238unlabel_staticlist_return:
1239        rcu_read_unlock();
1240        cb->args[0] = iter_bkt;
1241        cb->args[1] = iter_chain;
1242        cb->args[2] = iter_addr4;
1243        cb->args[3] = iter_addr6;
1244        return skb->len;
1245}
1246
1247/**
1248 * netlbl_unlabel_staticlistdef - Handle a STATICLISTDEF message
1249 * @skb: the NETLINK buffer
1250 * @cb: the NETLINK callback
1251 *
1252 * Description:
1253 * Process a user generated STATICLISTDEF message and dump the default
1254 * unlabeled connection entry in a form suitable for use in a kernel generated
1255 * STATICLISTDEF message.  Returns the length of @skb.
1256 *
1257 */
1258static int netlbl_unlabel_staticlistdef(struct sk_buff *skb,
1259                                        struct netlink_callback *cb)
1260{
1261        struct netlbl_unlhsh_walk_arg cb_arg;
1262        struct netlbl_unlhsh_iface *iface;
1263        u32 iter_addr4 = 0, iter_addr6 = 0;
1264        struct netlbl_af4list *addr4;
1265#if IS_ENABLED(CONFIG_IPV6)
1266        struct netlbl_af6list *addr6;
1267#endif
1268
1269        cb_arg.nl_cb = cb;
1270        cb_arg.skb = skb;
1271        cb_arg.seq = cb->nlh->nlmsg_seq;
1272
1273        rcu_read_lock();
1274        iface = rcu_dereference(netlbl_unlhsh_def);
1275        if (iface == NULL || !iface->valid)
1276                goto unlabel_staticlistdef_return;
1277
1278        netlbl_af4list_foreach_rcu(addr4, &iface->addr4_list) {
1279                if (iter_addr4++ < cb->args[0])
1280                        continue;
1281                if (netlbl_unlabel_staticlist_gen(NLBL_UNLABEL_C_STATICLISTDEF,
1282                                              iface,
1283                                              netlbl_unlhsh_addr4_entry(addr4),
1284                                              NULL,
1285                                              &cb_arg) < 0) {
1286                        iter_addr4--;
1287                        goto unlabel_staticlistdef_return;
1288                }
1289        }
1290#if IS_ENABLED(CONFIG_IPV6)
1291        netlbl_af6list_foreach_rcu(addr6, &iface->addr6_list) {
1292                if (iter_addr6++ < cb->args[1])
1293                        continue;
1294                if (netlbl_unlabel_staticlist_gen(NLBL_UNLABEL_C_STATICLISTDEF,
1295                                              iface,
1296                                              NULL,
1297                                              netlbl_unlhsh_addr6_entry(addr6),
1298                                              &cb_arg) < 0) {
1299                        iter_addr6--;
1300                        goto unlabel_staticlistdef_return;
1301                }
1302        }
1303#endif /* IPv6 */
1304
1305unlabel_staticlistdef_return:
1306        rcu_read_unlock();
1307        cb->args[0] = iter_addr4;
1308        cb->args[1] = iter_addr6;
1309        return skb->len;
1310}
1311
1312/*
1313 * NetLabel Generic NETLINK Command Definitions
1314 */
1315
1316static const struct genl_ops netlbl_unlabel_genl_ops[] = {
1317        {
1318        .cmd = NLBL_UNLABEL_C_STATICADD,
1319        .flags = GENL_ADMIN_PERM,
1320        .policy = netlbl_unlabel_genl_policy,
1321        .doit = netlbl_unlabel_staticadd,
1322        .dumpit = NULL,
1323        },
1324        {
1325        .cmd = NLBL_UNLABEL_C_STATICREMOVE,
1326        .flags = GENL_ADMIN_PERM,
1327        .policy = netlbl_unlabel_genl_policy,
1328        .doit = netlbl_unlabel_staticremove,
1329        .dumpit = NULL,
1330        },
1331        {
1332        .cmd = NLBL_UNLABEL_C_STATICLIST,
1333        .flags = 0,
1334        .policy = netlbl_unlabel_genl_policy,
1335        .doit = NULL,
1336        .dumpit = netlbl_unlabel_staticlist,
1337        },
1338        {
1339        .cmd = NLBL_UNLABEL_C_STATICADDDEF,
1340        .flags = GENL_ADMIN_PERM,
1341        .policy = netlbl_unlabel_genl_policy,
1342        .doit = netlbl_unlabel_staticadddef,
1343        .dumpit = NULL,
1344        },
1345        {
1346        .cmd = NLBL_UNLABEL_C_STATICREMOVEDEF,
1347        .flags = GENL_ADMIN_PERM,
1348        .policy = netlbl_unlabel_genl_policy,
1349        .doit = netlbl_unlabel_staticremovedef,
1350        .dumpit = NULL,
1351        },
1352        {
1353        .cmd = NLBL_UNLABEL_C_STATICLISTDEF,
1354        .flags = 0,
1355        .policy = netlbl_unlabel_genl_policy,
1356        .doit = NULL,
1357        .dumpit = netlbl_unlabel_staticlistdef,
1358        },
1359        {
1360        .cmd = NLBL_UNLABEL_C_ACCEPT,
1361        .flags = GENL_ADMIN_PERM,
1362        .policy = netlbl_unlabel_genl_policy,
1363        .doit = netlbl_unlabel_accept,
1364        .dumpit = NULL,
1365        },
1366        {
1367        .cmd = NLBL_UNLABEL_C_LIST,
1368        .flags = 0,
1369        .policy = netlbl_unlabel_genl_policy,
1370        .doit = netlbl_unlabel_list,
1371        .dumpit = NULL,
1372        },
1373};
1374
1375static struct genl_family netlbl_unlabel_gnl_family __ro_after_init = {
1376        .hdrsize = 0,
1377        .name = NETLBL_NLTYPE_UNLABELED_NAME,
1378        .version = NETLBL_PROTO_VERSION,
1379        .maxattr = NLBL_UNLABEL_A_MAX,
1380        .module = THIS_MODULE,
1381        .ops = netlbl_unlabel_genl_ops,
1382        .n_ops = ARRAY_SIZE(netlbl_unlabel_genl_ops),
1383};
1384
1385/*
1386 * NetLabel Generic NETLINK Protocol Functions
1387 */
1388
1389/**
1390 * netlbl_unlabel_genl_init - Register the Unlabeled NetLabel component
1391 *
1392 * Description:
1393 * Register the unlabeled packet NetLabel component with the Generic NETLINK
1394 * mechanism.  Returns zero on success, negative values on failure.
1395 *
1396 */
1397int __init netlbl_unlabel_genl_init(void)
1398{
1399        return genl_register_family(&netlbl_unlabel_gnl_family);
1400}
1401
1402/*
1403 * NetLabel KAPI Hooks
1404 */
1405
1406static struct notifier_block netlbl_unlhsh_netdev_notifier = {
1407        .notifier_call = netlbl_unlhsh_netdev_handler,
1408};
1409
1410/**
1411 * netlbl_unlabel_init - Initialize the unlabeled connection hash table
1412 * @size: the number of bits to use for the hash buckets
1413 *
1414 * Description:
1415 * Initializes the unlabeled connection hash table and registers a network
1416 * device notification handler.  This function should only be called by the
1417 * NetLabel subsystem itself during initialization.  Returns zero on success,
1418 * non-zero values on error.
1419 *
1420 */
1421int __init netlbl_unlabel_init(u32 size)
1422{
1423        u32 iter;
1424        struct netlbl_unlhsh_tbl *hsh_tbl;
1425
1426        if (size == 0)
1427                return -EINVAL;
1428
1429        hsh_tbl = kmalloc(sizeof(*hsh_tbl), GFP_KERNEL);
1430        if (hsh_tbl == NULL)
1431                return -ENOMEM;
1432        hsh_tbl->size = 1 << size;
1433        hsh_tbl->tbl = kcalloc(hsh_tbl->size,
1434                               sizeof(struct list_head),
1435                               GFP_KERNEL);
1436        if (hsh_tbl->tbl == NULL) {
1437                kfree(hsh_tbl);
1438                return -ENOMEM;
1439        }
1440        for (iter = 0; iter < hsh_tbl->size; iter++)
1441                INIT_LIST_HEAD(&hsh_tbl->tbl[iter]);
1442
1443        spin_lock(&netlbl_unlhsh_lock);
1444        rcu_assign_pointer(netlbl_unlhsh, hsh_tbl);
1445        spin_unlock(&netlbl_unlhsh_lock);
1446
1447        register_netdevice_notifier(&netlbl_unlhsh_netdev_notifier);
1448
1449        return 0;
1450}
1451
1452/**
1453 * netlbl_unlabel_getattr - Get the security attributes for an unlabled packet
1454 * @skb: the packet
1455 * @family: protocol family
1456 * @secattr: the security attributes
1457 *
1458 * Description:
1459 * Determine the security attributes, if any, for an unlabled packet and return
1460 * them in @secattr.  Returns zero on success and negative values on failure.
1461 *
1462 */
1463int netlbl_unlabel_getattr(const struct sk_buff *skb,
1464                           u16 family,
1465                           struct netlbl_lsm_secattr *secattr)
1466{
1467        struct netlbl_unlhsh_iface *iface;
1468
1469        rcu_read_lock();
1470        iface = netlbl_unlhsh_search_iface(skb->skb_iif);
1471        if (iface == NULL)
1472                iface = rcu_dereference(netlbl_unlhsh_def);
1473        if (iface == NULL || !iface->valid)
1474                goto unlabel_getattr_nolabel;
1475        switch (family) {
1476        case PF_INET: {
1477                struct iphdr *hdr4;
1478                struct netlbl_af4list *addr4;
1479
1480                hdr4 = ip_hdr(skb);
1481                addr4 = netlbl_af4list_search(hdr4->saddr,
1482                                              &iface->addr4_list);
1483                if (addr4 == NULL)
1484                        goto unlabel_getattr_nolabel;
1485                secattr->attr.secid = netlbl_unlhsh_addr4_entry(addr4)->secid;
1486                break;
1487        }
1488#if IS_ENABLED(CONFIG_IPV6)
1489        case PF_INET6: {
1490                struct ipv6hdr *hdr6;
1491                struct netlbl_af6list *addr6;
1492
1493                hdr6 = ipv6_hdr(skb);
1494                addr6 = netlbl_af6list_search(&hdr6->saddr,
1495                                              &iface->addr6_list);
1496                if (addr6 == NULL)
1497                        goto unlabel_getattr_nolabel;
1498                secattr->attr.secid = netlbl_unlhsh_addr6_entry(addr6)->secid;
1499                break;
1500        }
1501#endif /* IPv6 */
1502        default:
1503                goto unlabel_getattr_nolabel;
1504        }
1505        rcu_read_unlock();
1506
1507        secattr->flags |= NETLBL_SECATTR_SECID;
1508        secattr->type = NETLBL_NLTYPE_UNLABELED;
1509        return 0;
1510
1511unlabel_getattr_nolabel:
1512        rcu_read_unlock();
1513        if (netlabel_unlabel_acceptflg == 0)
1514                return -ENOMSG;
1515        secattr->type = NETLBL_NLTYPE_UNLABELED;
1516        return 0;
1517}
1518
1519/**
1520 * netlbl_unlabel_defconf - Set the default config to allow unlabeled packets
1521 *
1522 * Description:
1523 * Set the default NetLabel configuration to allow incoming unlabeled packets
1524 * and to send unlabeled network traffic by default.
1525 *
1526 */
1527int __init netlbl_unlabel_defconf(void)
1528{
1529        int ret_val;
1530        struct netlbl_dom_map *entry;
1531        struct netlbl_audit audit_info;
1532
1533        /* Only the kernel is allowed to call this function and the only time
1534         * it is called is at bootup before the audit subsystem is reporting
1535         * messages so don't worry to much about these values. */
1536        security_task_getsecid(current, &audit_info.secid);
1537        audit_info.loginuid = GLOBAL_ROOT_UID;
1538        audit_info.sessionid = 0;
1539
1540        entry = kzalloc(sizeof(*entry), GFP_KERNEL);
1541        if (entry == NULL)
1542                return -ENOMEM;
1543        entry->family = AF_UNSPEC;
1544        entry->def.type = NETLBL_NLTYPE_UNLABELED;
1545        ret_val = netlbl_domhsh_add_default(entry, &audit_info);
1546        if (ret_val != 0)
1547                return ret_val;
1548
1549        netlbl_unlabel_acceptflg_set(1, &audit_info);
1550
1551        return 0;
1552}
1553