^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * NetLabel Domain Hash Table
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * This file manages the domain hash table that NetLabel uses to determine
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * which network labeling protocol to use for a given domain. The NetLabel
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * system manages static and dynamic label mappings for network protocols such
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * as CIPSO and RIPSO.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * Author: Paul Moore <paul@paul-moore.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * (c) Copyright Hewlett-Packard Development Company, L.P., 2006, 2008
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/rculist.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/skbuff.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/spinlock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/audit.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <net/netlabel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <net/cipso_ipv4.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <net/calipso.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <asm/bug.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include "netlabel_mgmt.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include "netlabel_addrlist.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #include "netlabel_calipso.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #include "netlabel_domainhash.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #include "netlabel_user.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) struct netlbl_domhsh_tbl {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) struct list_head *tbl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) u32 size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) /* Domain hash table */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) /* updates should be so rare that having one spinlock for the entire hash table
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) * should be okay */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) static DEFINE_SPINLOCK(netlbl_domhsh_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #define netlbl_domhsh_rcu_deref(p) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) rcu_dereference_check(p, lockdep_is_held(&netlbl_domhsh_lock))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) static struct netlbl_domhsh_tbl __rcu *netlbl_domhsh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) static struct netlbl_dom_map __rcu *netlbl_domhsh_def_ipv4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) static struct netlbl_dom_map __rcu *netlbl_domhsh_def_ipv6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) * Domain Hash Table Helper Functions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) * netlbl_domhsh_free_entry - Frees a domain hash table entry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) * @entry: the entry's RCU field
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) * Description:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) * This function is designed to be used as a callback to the call_rcu()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) * function so that the memory allocated to a hash table entry can be released
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) * safely.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) static void netlbl_domhsh_free_entry(struct rcu_head *entry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) struct netlbl_dom_map *ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) struct netlbl_af4list *iter4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) struct netlbl_af4list *tmp4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) #if IS_ENABLED(CONFIG_IPV6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) struct netlbl_af6list *iter6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) struct netlbl_af6list *tmp6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) #endif /* IPv6 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) ptr = container_of(entry, struct netlbl_dom_map, rcu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) if (ptr->def.type == NETLBL_NLTYPE_ADDRSELECT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) netlbl_af4list_foreach_safe(iter4, tmp4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) &ptr->def.addrsel->list4) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) netlbl_af4list_remove_entry(iter4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) kfree(netlbl_domhsh_addr4_entry(iter4));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) #if IS_ENABLED(CONFIG_IPV6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) netlbl_af6list_foreach_safe(iter6, tmp6,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) &ptr->def.addrsel->list6) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) netlbl_af6list_remove_entry(iter6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) kfree(netlbl_domhsh_addr6_entry(iter6));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) #endif /* IPv6 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) kfree(ptr->def.addrsel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) kfree(ptr->domain);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) kfree(ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) * netlbl_domhsh_hash - Hashing function for the domain hash table
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) * @key: the domain name to hash
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) * Description:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) * This is the hashing function for the domain hash table, it returns the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) * correct bucket number for the domain. The caller is responsible for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) * ensuring that the hash table is protected with either a RCU read lock or the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) * hash table lock.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) static u32 netlbl_domhsh_hash(const char *key)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) u32 iter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) u32 len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) /* This is taken (with slight modification) from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) * security/selinux/ss/symtab.c:symhash() */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) for (iter = 0, val = 0, len = strlen(key); iter < len; iter++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) val = (val << 4 | (val >> (8 * sizeof(u32) - 4))) ^ key[iter];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) return val & (netlbl_domhsh_rcu_deref(netlbl_domhsh)->size - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) static bool netlbl_family_match(u16 f1, u16 f2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) return (f1 == f2) || (f1 == AF_UNSPEC) || (f2 == AF_UNSPEC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) * netlbl_domhsh_search - Search for a domain entry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) * @domain: the domain
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) * @family: the address family
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) * Description:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) * Searches the domain hash table and returns a pointer to the hash table
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) * entry if found, otherwise NULL is returned. @family may be %AF_UNSPEC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) * which matches any address family entries. The caller is responsible for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) * ensuring that the hash table is protected with either a RCU read lock or the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) * hash table lock.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) static struct netlbl_dom_map *netlbl_domhsh_search(const char *domain,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) u16 family)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) u32 bkt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) struct list_head *bkt_list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) struct netlbl_dom_map *iter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) if (domain != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) bkt = netlbl_domhsh_hash(domain);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) bkt_list = &netlbl_domhsh_rcu_deref(netlbl_domhsh)->tbl[bkt];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) list_for_each_entry_rcu(iter, bkt_list, list,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) lockdep_is_held(&netlbl_domhsh_lock))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) if (iter->valid &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) netlbl_family_match(iter->family, family) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) strcmp(iter->domain, domain) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) return iter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) * netlbl_domhsh_search_def - Search for a domain entry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) * @domain: the domain
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) * @family: the address family
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) * Description:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) * Searches the domain hash table and returns a pointer to the hash table
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) * entry if an exact match is found, if an exact match is not present in the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) * hash table then the default entry is returned if valid otherwise NULL is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) * returned. @family may be %AF_UNSPEC which matches any address family
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) * entries. The caller is responsible ensuring that the hash table is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) * protected with either a RCU read lock or the hash table lock.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) static struct netlbl_dom_map *netlbl_domhsh_search_def(const char *domain,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) u16 family)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) struct netlbl_dom_map *entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) entry = netlbl_domhsh_search(domain, family);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) if (entry != NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) return entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) if (family == AF_INET || family == AF_UNSPEC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) entry = netlbl_domhsh_rcu_deref(netlbl_domhsh_def_ipv4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) if (entry != NULL && entry->valid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) return entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) if (family == AF_INET6 || family == AF_UNSPEC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) entry = netlbl_domhsh_rcu_deref(netlbl_domhsh_def_ipv6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) if (entry != NULL && entry->valid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) return entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) * netlbl_domhsh_audit_add - Generate an audit entry for an add event
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) * @entry: the entry being added
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) * @addr4: the IPv4 address information
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) * @addr6: the IPv6 address information
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) * @result: the result code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) * @audit_info: NetLabel audit information
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) * Description:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) * Generate an audit record for adding a new NetLabel/LSM mapping entry with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) * the given information. Caller is responsible for holding the necessary
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) * locks.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) static void netlbl_domhsh_audit_add(struct netlbl_dom_map *entry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) struct netlbl_af4list *addr4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) struct netlbl_af6list *addr6,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) int result,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) struct netlbl_audit *audit_info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) struct audit_buffer *audit_buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) struct cipso_v4_doi *cipsov4 = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) struct calipso_doi *calipso = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) u32 type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) audit_buf = netlbl_audit_start_common(AUDIT_MAC_MAP_ADD, audit_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) if (audit_buf != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) audit_log_format(audit_buf, " nlbl_domain=%s",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) entry->domain ? entry->domain : "(default)");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) if (addr4 != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) struct netlbl_domaddr4_map *map4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) map4 = netlbl_domhsh_addr4_entry(addr4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) type = map4->def.type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) cipsov4 = map4->def.cipso;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) netlbl_af4list_audit_addr(audit_buf, 0, NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) addr4->addr, addr4->mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) #if IS_ENABLED(CONFIG_IPV6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) } else if (addr6 != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) struct netlbl_domaddr6_map *map6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) map6 = netlbl_domhsh_addr6_entry(addr6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) type = map6->def.type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) calipso = map6->def.calipso;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) netlbl_af6list_audit_addr(audit_buf, 0, NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) &addr6->addr, &addr6->mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) #endif /* IPv6 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) type = entry->def.type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) cipsov4 = entry->def.cipso;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) calipso = entry->def.calipso;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) switch (type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) case NETLBL_NLTYPE_UNLABELED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) audit_log_format(audit_buf, " nlbl_protocol=unlbl");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) case NETLBL_NLTYPE_CIPSOV4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) BUG_ON(cipsov4 == NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) audit_log_format(audit_buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) " nlbl_protocol=cipsov4 cipso_doi=%u",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) cipsov4->doi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) case NETLBL_NLTYPE_CALIPSO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) BUG_ON(calipso == NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) audit_log_format(audit_buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) " nlbl_protocol=calipso calipso_doi=%u",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) calipso->doi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) audit_log_format(audit_buf, " res=%u", result == 0 ? 1 : 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) audit_log_end(audit_buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) * netlbl_domhsh_validate - Validate a new domain mapping entry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) * @entry: the entry to validate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) * This function validates the new domain mapping entry to ensure that it is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) * a valid entry. Returns zero on success, negative values on failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) static int netlbl_domhsh_validate(const struct netlbl_dom_map *entry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) struct netlbl_af4list *iter4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) struct netlbl_domaddr4_map *map4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) #if IS_ENABLED(CONFIG_IPV6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) struct netlbl_af6list *iter6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) struct netlbl_domaddr6_map *map6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) #endif /* IPv6 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) if (entry == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) if (entry->family != AF_INET && entry->family != AF_INET6 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) (entry->family != AF_UNSPEC ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) entry->def.type != NETLBL_NLTYPE_UNLABELED))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) switch (entry->def.type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) case NETLBL_NLTYPE_UNLABELED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) if (entry->def.cipso != NULL || entry->def.calipso != NULL ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) entry->def.addrsel != NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) case NETLBL_NLTYPE_CIPSOV4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) if (entry->family != AF_INET ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) entry->def.cipso == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) case NETLBL_NLTYPE_CALIPSO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) if (entry->family != AF_INET6 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) entry->def.calipso == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) case NETLBL_NLTYPE_ADDRSELECT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) netlbl_af4list_foreach(iter4, &entry->def.addrsel->list4) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) map4 = netlbl_domhsh_addr4_entry(iter4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) switch (map4->def.type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) case NETLBL_NLTYPE_UNLABELED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) if (map4->def.cipso != NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) case NETLBL_NLTYPE_CIPSOV4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) if (map4->def.cipso == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) #if IS_ENABLED(CONFIG_IPV6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) netlbl_af6list_foreach(iter6, &entry->def.addrsel->list6) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) map6 = netlbl_domhsh_addr6_entry(iter6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) switch (map6->def.type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) case NETLBL_NLTYPE_UNLABELED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) if (map6->def.calipso != NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) case NETLBL_NLTYPE_CALIPSO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) if (map6->def.calipso == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) #endif /* IPv6 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) * Domain Hash Table Functions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) * netlbl_domhsh_init - Init for the domain hash
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) * @size: the number of bits to use for the hash buckets
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) * Description:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) * Initializes the domain hash table, should be called only by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) * netlbl_user_init() during initialization. Returns zero on success, non-zero
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) * values on error.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) int __init netlbl_domhsh_init(u32 size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) u32 iter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) struct netlbl_domhsh_tbl *hsh_tbl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) if (size == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) hsh_tbl = kmalloc(sizeof(*hsh_tbl), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) if (hsh_tbl == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) hsh_tbl->size = 1 << size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) hsh_tbl->tbl = kcalloc(hsh_tbl->size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) sizeof(struct list_head),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) if (hsh_tbl->tbl == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) kfree(hsh_tbl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) for (iter = 0; iter < hsh_tbl->size; iter++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) INIT_LIST_HEAD(&hsh_tbl->tbl[iter]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) spin_lock(&netlbl_domhsh_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) rcu_assign_pointer(netlbl_domhsh, hsh_tbl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) spin_unlock(&netlbl_domhsh_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) * netlbl_domhsh_add - Adds a entry to the domain hash table
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) * @entry: the entry to add
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) * @audit_info: NetLabel audit information
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) * Description:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) * Adds a new entry to the domain hash table and handles any updates to the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) * lower level protocol handler (i.e. CIPSO). @entry->family may be set to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) * %AF_UNSPEC which will add an entry that matches all address families. This
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) * is only useful for the unlabelled type and will only succeed if there is no
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) * existing entry for any address family with the same domain. Returns zero
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) * on success, negative on failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) int netlbl_domhsh_add(struct netlbl_dom_map *entry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) struct netlbl_audit *audit_info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) int ret_val = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) struct netlbl_dom_map *entry_old, *entry_b;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) struct netlbl_af4list *iter4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) struct netlbl_af4list *tmp4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) #if IS_ENABLED(CONFIG_IPV6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) struct netlbl_af6list *iter6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) struct netlbl_af6list *tmp6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) #endif /* IPv6 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) ret_val = netlbl_domhsh_validate(entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) if (ret_val != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) return ret_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) /* XXX - we can remove this RCU read lock as the spinlock protects the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) * entire function, but before we do we need to fixup the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) * netlbl_af[4,6]list RCU functions to do "the right thing" with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) * respect to rcu_dereference() when only a spinlock is held. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) spin_lock(&netlbl_domhsh_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) if (entry->domain != NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) entry_old = netlbl_domhsh_search(entry->domain, entry->family);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) entry_old = netlbl_domhsh_search_def(entry->domain,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) entry->family);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) if (entry_old == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) entry->valid = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) if (entry->domain != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) u32 bkt = netlbl_domhsh_hash(entry->domain);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) list_add_tail_rcu(&entry->list,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) &rcu_dereference(netlbl_domhsh)->tbl[bkt]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) INIT_LIST_HEAD(&entry->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) switch (entry->family) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) case AF_INET:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) rcu_assign_pointer(netlbl_domhsh_def_ipv4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) case AF_INET6:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) rcu_assign_pointer(netlbl_domhsh_def_ipv6,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) case AF_UNSPEC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) if (entry->def.type !=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) NETLBL_NLTYPE_UNLABELED) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) ret_val = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) goto add_return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) entry_b = kzalloc(sizeof(*entry_b), GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) if (entry_b == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) ret_val = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) goto add_return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) entry_b->family = AF_INET6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) entry_b->def.type = NETLBL_NLTYPE_UNLABELED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) entry_b->valid = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) entry->family = AF_INET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) rcu_assign_pointer(netlbl_domhsh_def_ipv4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) rcu_assign_pointer(netlbl_domhsh_def_ipv6,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) entry_b);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) /* Already checked in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) * netlbl_domhsh_validate(). */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) ret_val = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) goto add_return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) if (entry->def.type == NETLBL_NLTYPE_ADDRSELECT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) netlbl_af4list_foreach_rcu(iter4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) &entry->def.addrsel->list4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) netlbl_domhsh_audit_add(entry, iter4, NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) ret_val, audit_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) #if IS_ENABLED(CONFIG_IPV6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) netlbl_af6list_foreach_rcu(iter6,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) &entry->def.addrsel->list6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) netlbl_domhsh_audit_add(entry, NULL, iter6,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) ret_val, audit_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) #endif /* IPv6 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) netlbl_domhsh_audit_add(entry, NULL, NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) ret_val, audit_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) } else if (entry_old->def.type == NETLBL_NLTYPE_ADDRSELECT &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) entry->def.type == NETLBL_NLTYPE_ADDRSELECT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) struct list_head *old_list4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) struct list_head *old_list6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) old_list4 = &entry_old->def.addrsel->list4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) old_list6 = &entry_old->def.addrsel->list6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) /* we only allow the addition of address selectors if all of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) * the selectors do not exist in the existing domain map */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) netlbl_af4list_foreach_rcu(iter4, &entry->def.addrsel->list4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) if (netlbl_af4list_search_exact(iter4->addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) iter4->mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) old_list4)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) ret_val = -EEXIST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) goto add_return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) #if IS_ENABLED(CONFIG_IPV6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) netlbl_af6list_foreach_rcu(iter6, &entry->def.addrsel->list6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) if (netlbl_af6list_search_exact(&iter6->addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) &iter6->mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) old_list6)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) ret_val = -EEXIST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) goto add_return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) #endif /* IPv6 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) netlbl_af4list_foreach_safe(iter4, tmp4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) &entry->def.addrsel->list4) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) netlbl_af4list_remove_entry(iter4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) iter4->valid = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) ret_val = netlbl_af4list_add(iter4, old_list4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) netlbl_domhsh_audit_add(entry_old, iter4, NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) ret_val, audit_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) if (ret_val != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) goto add_return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) #if IS_ENABLED(CONFIG_IPV6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) netlbl_af6list_foreach_safe(iter6, tmp6,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) &entry->def.addrsel->list6) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) netlbl_af6list_remove_entry(iter6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) iter6->valid = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) ret_val = netlbl_af6list_add(iter6, old_list6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) netlbl_domhsh_audit_add(entry_old, NULL, iter6,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) ret_val, audit_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) if (ret_val != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) goto add_return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) #endif /* IPv6 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) /* cleanup the new entry since we've moved everything over */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) netlbl_domhsh_free_entry(&entry->rcu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) ret_val = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) add_return:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) spin_unlock(&netlbl_domhsh_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) return ret_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) * netlbl_domhsh_add_default - Adds the default entry to the domain hash table
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) * @entry: the entry to add
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) * @audit_info: NetLabel audit information
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) * Description:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) * Adds a new default entry to the domain hash table and handles any updates
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) * to the lower level protocol handler (i.e. CIPSO). Returns zero on success,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) * negative on failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) int netlbl_domhsh_add_default(struct netlbl_dom_map *entry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) struct netlbl_audit *audit_info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) return netlbl_domhsh_add(entry, audit_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) * netlbl_domhsh_remove_entry - Removes a given entry from the domain table
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) * @entry: the entry to remove
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) * @audit_info: NetLabel audit information
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) * Description:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) * Removes an entry from the domain hash table and handles any updates to the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) * lower level protocol handler (i.e. CIPSO). Caller is responsible for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) * ensuring that the RCU read lock is held. Returns zero on success, negative
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) * on failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) int netlbl_domhsh_remove_entry(struct netlbl_dom_map *entry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) struct netlbl_audit *audit_info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) int ret_val = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) struct audit_buffer *audit_buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) struct netlbl_af4list *iter4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) struct netlbl_domaddr4_map *map4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) #if IS_ENABLED(CONFIG_IPV6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) struct netlbl_af6list *iter6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) struct netlbl_domaddr6_map *map6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) #endif /* IPv6 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) if (entry == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) spin_lock(&netlbl_domhsh_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) if (entry->valid) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) entry->valid = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) if (entry == rcu_dereference(netlbl_domhsh_def_ipv4))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) RCU_INIT_POINTER(netlbl_domhsh_def_ipv4, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) else if (entry == rcu_dereference(netlbl_domhsh_def_ipv6))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) RCU_INIT_POINTER(netlbl_domhsh_def_ipv6, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) list_del_rcu(&entry->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) ret_val = -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) spin_unlock(&netlbl_domhsh_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) if (ret_val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) return ret_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) audit_buf = netlbl_audit_start_common(AUDIT_MAC_MAP_DEL, audit_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) if (audit_buf != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) audit_log_format(audit_buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) " nlbl_domain=%s res=1",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) entry->domain ? entry->domain : "(default)");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) audit_log_end(audit_buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) switch (entry->def.type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) case NETLBL_NLTYPE_ADDRSELECT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) netlbl_af4list_foreach_rcu(iter4, &entry->def.addrsel->list4) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) map4 = netlbl_domhsh_addr4_entry(iter4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) cipso_v4_doi_putdef(map4->def.cipso);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) #if IS_ENABLED(CONFIG_IPV6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) netlbl_af6list_foreach_rcu(iter6, &entry->def.addrsel->list6) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) map6 = netlbl_domhsh_addr6_entry(iter6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) calipso_doi_putdef(map6->def.calipso);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) #endif /* IPv6 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) case NETLBL_NLTYPE_CIPSOV4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) cipso_v4_doi_putdef(entry->def.cipso);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) #if IS_ENABLED(CONFIG_IPV6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) case NETLBL_NLTYPE_CALIPSO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) calipso_doi_putdef(entry->def.calipso);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) #endif /* IPv6 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) call_rcu(&entry->rcu, netlbl_domhsh_free_entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) return ret_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) * netlbl_domhsh_remove_af4 - Removes an address selector entry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) * @domain: the domain
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) * @addr: IPv4 address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) * @mask: IPv4 address mask
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) * @audit_info: NetLabel audit information
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) * Description:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) * Removes an individual address selector from a domain mapping and potentially
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) * the entire mapping if it is empty. Returns zero on success, negative values
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) * on failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) int netlbl_domhsh_remove_af4(const char *domain,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) const struct in_addr *addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) const struct in_addr *mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) struct netlbl_audit *audit_info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) struct netlbl_dom_map *entry_map;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) struct netlbl_af4list *entry_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) struct netlbl_af4list *iter4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) #if IS_ENABLED(CONFIG_IPV6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) struct netlbl_af6list *iter6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) #endif /* IPv6 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) struct netlbl_domaddr4_map *entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) if (domain)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) entry_map = netlbl_domhsh_search(domain, AF_INET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) entry_map = netlbl_domhsh_search_def(domain, AF_INET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) if (entry_map == NULL ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) entry_map->def.type != NETLBL_NLTYPE_ADDRSELECT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) goto remove_af4_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) spin_lock(&netlbl_domhsh_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) entry_addr = netlbl_af4list_remove(addr->s_addr, mask->s_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) &entry_map->def.addrsel->list4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) spin_unlock(&netlbl_domhsh_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) if (entry_addr == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) goto remove_af4_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) netlbl_af4list_foreach_rcu(iter4, &entry_map->def.addrsel->list4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) goto remove_af4_single_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) #if IS_ENABLED(CONFIG_IPV6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) netlbl_af6list_foreach_rcu(iter6, &entry_map->def.addrsel->list6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) goto remove_af4_single_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) #endif /* IPv6 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) /* the domain mapping is empty so remove it from the mapping table */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) netlbl_domhsh_remove_entry(entry_map, audit_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) remove_af4_single_addr:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) /* yick, we can't use call_rcu here because we don't have a rcu head
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) * pointer but hopefully this should be a rare case so the pause
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) * shouldn't be a problem */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) synchronize_rcu();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) entry = netlbl_domhsh_addr4_entry(entry_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) cipso_v4_doi_putdef(entry->def.cipso);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) kfree(entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) remove_af4_failure:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) #if IS_ENABLED(CONFIG_IPV6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) * netlbl_domhsh_remove_af6 - Removes an address selector entry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) * @domain: the domain
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) * @addr: IPv6 address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) * @mask: IPv6 address mask
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) * @audit_info: NetLabel audit information
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) * Description:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) * Removes an individual address selector from a domain mapping and potentially
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) * the entire mapping if it is empty. Returns zero on success, negative values
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) * on failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) int netlbl_domhsh_remove_af6(const char *domain,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) const struct in6_addr *addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) const struct in6_addr *mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) struct netlbl_audit *audit_info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) struct netlbl_dom_map *entry_map;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) struct netlbl_af6list *entry_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) struct netlbl_af4list *iter4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) struct netlbl_af6list *iter6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) struct netlbl_domaddr6_map *entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) if (domain)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) entry_map = netlbl_domhsh_search(domain, AF_INET6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) entry_map = netlbl_domhsh_search_def(domain, AF_INET6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) if (entry_map == NULL ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) entry_map->def.type != NETLBL_NLTYPE_ADDRSELECT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) goto remove_af6_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) spin_lock(&netlbl_domhsh_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) entry_addr = netlbl_af6list_remove(addr, mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) &entry_map->def.addrsel->list6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) spin_unlock(&netlbl_domhsh_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) if (entry_addr == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) goto remove_af6_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) netlbl_af4list_foreach_rcu(iter4, &entry_map->def.addrsel->list4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) goto remove_af6_single_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) netlbl_af6list_foreach_rcu(iter6, &entry_map->def.addrsel->list6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) goto remove_af6_single_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) /* the domain mapping is empty so remove it from the mapping table */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) netlbl_domhsh_remove_entry(entry_map, audit_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) remove_af6_single_addr:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) /* yick, we can't use call_rcu here because we don't have a rcu head
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) * pointer but hopefully this should be a rare case so the pause
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) * shouldn't be a problem */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) synchronize_rcu();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) entry = netlbl_domhsh_addr6_entry(entry_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) calipso_doi_putdef(entry->def.calipso);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) kfree(entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) remove_af6_failure:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) #endif /* IPv6 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) * netlbl_domhsh_remove - Removes an entry from the domain hash table
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) * @domain: the domain to remove
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) * @family: address family
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) * @audit_info: NetLabel audit information
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) * Description:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) * Removes an entry from the domain hash table and handles any updates to the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) * lower level protocol handler (i.e. CIPSO). @family may be %AF_UNSPEC which
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) * removes all address family entries. Returns zero on success, negative on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) * failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) int netlbl_domhsh_remove(const char *domain, u16 family,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) struct netlbl_audit *audit_info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) int ret_val = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) struct netlbl_dom_map *entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) if (family == AF_INET || family == AF_UNSPEC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) if (domain)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) entry = netlbl_domhsh_search(domain, AF_INET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) entry = netlbl_domhsh_search_def(domain, AF_INET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) ret_val = netlbl_domhsh_remove_entry(entry, audit_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) if (ret_val && ret_val != -ENOENT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) if (family == AF_INET6 || family == AF_UNSPEC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) int ret_val2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) if (domain)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) entry = netlbl_domhsh_search(domain, AF_INET6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) entry = netlbl_domhsh_search_def(domain, AF_INET6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) ret_val2 = netlbl_domhsh_remove_entry(entry, audit_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) if (ret_val2 != -ENOENT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) ret_val = ret_val2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) done:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) return ret_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) * netlbl_domhsh_remove_default - Removes the default entry from the table
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) * @family: address family
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) * @audit_info: NetLabel audit information
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) * Description:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) * Removes/resets the default entry corresponding to @family from the domain
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) * hash table and handles any updates to the lower level protocol handler
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) * (i.e. CIPSO). @family may be %AF_UNSPEC which removes all address family
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) * entries. Returns zero on success, negative on failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) int netlbl_domhsh_remove_default(u16 family, struct netlbl_audit *audit_info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) return netlbl_domhsh_remove(NULL, family, audit_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) * netlbl_domhsh_getentry - Get an entry from the domain hash table
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) * @domain: the domain name to search for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) * @family: address family
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) * Description:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) * Look through the domain hash table searching for an entry to match @domain,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) * with address family @family, return a pointer to a copy of the entry or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) * NULL. The caller is responsible for ensuring that rcu_read_[un]lock() is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) * called.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) struct netlbl_dom_map *netlbl_domhsh_getentry(const char *domain, u16 family)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) if (family == AF_UNSPEC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) return netlbl_domhsh_search_def(domain, family);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) * netlbl_domhsh_getentry_af4 - Get an entry from the domain hash table
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) * @domain: the domain name to search for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) * @addr: the IP address to search for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) * Description:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) * Look through the domain hash table searching for an entry to match @domain
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) * and @addr, return a pointer to a copy of the entry or NULL. The caller is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) * responsible for ensuring that rcu_read_[un]lock() is called.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) struct netlbl_dommap_def *netlbl_domhsh_getentry_af4(const char *domain,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) __be32 addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) struct netlbl_dom_map *dom_iter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) struct netlbl_af4list *addr_iter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) dom_iter = netlbl_domhsh_search_def(domain, AF_INET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) if (dom_iter == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) if (dom_iter->def.type != NETLBL_NLTYPE_ADDRSELECT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) return &dom_iter->def;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) addr_iter = netlbl_af4list_search(addr, &dom_iter->def.addrsel->list4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) if (addr_iter == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) return &(netlbl_domhsh_addr4_entry(addr_iter)->def);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) #if IS_ENABLED(CONFIG_IPV6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) * netlbl_domhsh_getentry_af6 - Get an entry from the domain hash table
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) * @domain: the domain name to search for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) * @addr: the IP address to search for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) * Description:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) * Look through the domain hash table searching for an entry to match @domain
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) * and @addr, return a pointer to a copy of the entry or NULL. The caller is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) * responsible for ensuring that rcu_read_[un]lock() is called.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) struct netlbl_dommap_def *netlbl_domhsh_getentry_af6(const char *domain,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) const struct in6_addr *addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) struct netlbl_dom_map *dom_iter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) struct netlbl_af6list *addr_iter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) dom_iter = netlbl_domhsh_search_def(domain, AF_INET6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) if (dom_iter == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) if (dom_iter->def.type != NETLBL_NLTYPE_ADDRSELECT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) return &dom_iter->def;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) addr_iter = netlbl_af6list_search(addr, &dom_iter->def.addrsel->list6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) if (addr_iter == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) return &(netlbl_domhsh_addr6_entry(addr_iter)->def);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) #endif /* IPv6 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) * netlbl_domhsh_walk - Iterate through the domain mapping hash table
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) * @skip_bkt: the number of buckets to skip at the start
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) * @skip_chain: the number of entries to skip in the first iterated bucket
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) * @callback: callback for each entry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) * @cb_arg: argument for the callback function
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) * Description:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) * Interate over the domain mapping hash table, skipping the first @skip_bkt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) * buckets and @skip_chain entries. For each entry in the table call
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) * @callback, if @callback returns a negative value stop 'walking' through the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) * table and return. Updates the values in @skip_bkt and @skip_chain on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) * return. Returns zero on success, negative values on failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) int netlbl_domhsh_walk(u32 *skip_bkt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) u32 *skip_chain,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) int (*callback) (struct netlbl_dom_map *entry, void *arg),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) void *cb_arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) int ret_val = -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) u32 iter_bkt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) struct list_head *iter_list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) struct netlbl_dom_map *iter_entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) u32 chain_cnt = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) for (iter_bkt = *skip_bkt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) iter_bkt < rcu_dereference(netlbl_domhsh)->size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) iter_bkt++, chain_cnt = 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) iter_list = &rcu_dereference(netlbl_domhsh)->tbl[iter_bkt];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) list_for_each_entry_rcu(iter_entry, iter_list, list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) if (iter_entry->valid) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) if (chain_cnt++ < *skip_chain)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) ret_val = callback(iter_entry, cb_arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) if (ret_val < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) chain_cnt--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) goto walk_return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) walk_return:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) *skip_bkt = iter_bkt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) *skip_chain = chain_cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) return ret_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) }