Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^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)  * CALIPSO - Common Architecture Label IPv6 Security Option
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    4)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    5)  * This is an implementation of the CALIPSO protocol as specified in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    6)  * RFC 5570.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    7)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    8)  * Authors: Paul Moore <paul.moore@hp.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    9)  *          Huw Davies <huw@codeweavers.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   10)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   11) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   12) /* (c) Copyright Hewlett-Packard Development Company, L.P., 2006, 2008
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   13)  * (c) Copyright Huw Davies <huw@codeweavers.com>, 2015
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   14)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   15) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   16) #include <linux/init.h>
^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/rcupdate.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   19) #include <linux/list.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/jhash.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   23) #include <linux/audit.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   24) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   25) #include <net/ip.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   26) #include <net/icmp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   27) #include <net/tcp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   28) #include <net/netlabel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   29) #include <net/calipso.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   30) #include <linux/atomic.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   31) #include <linux/bug.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   32) #include <asm/unaligned.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   33) #include <linux/crc-ccitt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   34) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   35) /* Maximium size of the calipso option including
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   36)  * the two-byte TLV header.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   37)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   38) #define CALIPSO_OPT_LEN_MAX (2 + 252)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   39) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   40) /* Size of the minimum calipso option including
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   41)  * the two-byte TLV header.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   42)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   43) #define CALIPSO_HDR_LEN (2 + 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   44) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   45) /* Maximium size of the calipso option including
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   46)  * the two-byte TLV header and upto 3 bytes of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   47)  * leading pad and 7 bytes of trailing pad.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   48)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   49) #define CALIPSO_OPT_LEN_MAX_WITH_PAD (3 + CALIPSO_OPT_LEN_MAX + 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   50) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   51)  /* Maximium size of u32 aligned buffer required to hold calipso
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   52)   * option.  Max of 3 initial pad bytes starting from buffer + 3.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   53)   * i.e. the worst case is when the previous tlv finishes on 4n + 3.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   54)   */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   55) #define CALIPSO_MAX_BUFFER (6 + CALIPSO_OPT_LEN_MAX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   56) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   57) /* List of available DOI definitions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   58) static DEFINE_SPINLOCK(calipso_doi_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   59) static LIST_HEAD(calipso_doi_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   60) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   61) /* Label mapping cache */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   62) int calipso_cache_enabled = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   63) int calipso_cache_bucketsize = 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   64) #define CALIPSO_CACHE_BUCKETBITS     7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   65) #define CALIPSO_CACHE_BUCKETS        BIT(CALIPSO_CACHE_BUCKETBITS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   66) #define CALIPSO_CACHE_REORDERLIMIT   10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   67) struct calipso_map_cache_bkt {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   68) 	spinlock_t lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   69) 	u32 size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   70) 	struct list_head list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   71) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   72) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   73) struct calipso_map_cache_entry {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   74) 	u32 hash;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   75) 	unsigned char *key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   76) 	size_t key_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   77) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   78) 	struct netlbl_lsm_cache *lsm_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   79) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   80) 	u32 activity;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   81) 	struct list_head list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   82) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   83) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   84) static struct calipso_map_cache_bkt *calipso_cache;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   85) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   86) static void calipso_cache_invalidate(void);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   87) static void calipso_doi_putdef(struct calipso_doi *doi_def);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   88) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   89) /* Label Mapping Cache Functions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   90)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   91) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   92) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   93)  * calipso_cache_entry_free - Frees a cache entry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   94)  * @entry: the entry to free
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   95)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   96)  * Description:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   97)  * This function frees the memory associated with a cache entry including the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   98)  * LSM cache data if there are no longer any users, i.e. reference count == 0.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   99)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  100)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  101) static void calipso_cache_entry_free(struct calipso_map_cache_entry *entry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  102) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  103) 	if (entry->lsm_data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  104) 		netlbl_secattr_cache_free(entry->lsm_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  105) 	kfree(entry->key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  106) 	kfree(entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  107) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  108) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  109) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  110)  * calipso_map_cache_hash - Hashing function for the CALIPSO cache
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  111)  * @key: the hash key
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  112)  * @key_len: the length of the key in bytes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  113)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  114)  * Description:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  115)  * The CALIPSO tag hashing function.  Returns a 32-bit hash value.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  116)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  117)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  118) static u32 calipso_map_cache_hash(const unsigned char *key, u32 key_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  119) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  120) 	return jhash(key, key_len, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  121) }
^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)  * calipso_cache_init - Initialize the CALIPSO cache
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  125)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  126)  * Description:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  127)  * Initializes the CALIPSO label mapping cache, this function should be called
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  128)  * before any of the other functions defined in this file.  Returns zero on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  129)  * success, negative values on error.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  130)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  131)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  132) static int __init calipso_cache_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  133) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  134) 	u32 iter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  135) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  136) 	calipso_cache = kcalloc(CALIPSO_CACHE_BUCKETS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  137) 				sizeof(struct calipso_map_cache_bkt),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  138) 				GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  139) 	if (!calipso_cache)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  140) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  141) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  142) 	for (iter = 0; iter < CALIPSO_CACHE_BUCKETS; iter++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  143) 		spin_lock_init(&calipso_cache[iter].lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  144) 		calipso_cache[iter].size = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  145) 		INIT_LIST_HEAD(&calipso_cache[iter].list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  146) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  147) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  148) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  149) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  150) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  151) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  152)  * calipso_cache_invalidate - Invalidates the current CALIPSO cache
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  153)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  154)  * Description:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  155)  * Invalidates and frees any entries in the CALIPSO cache.  Returns zero on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  156)  * success and negative values on failure.
^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) static void calipso_cache_invalidate(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  160) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  161) 	struct calipso_map_cache_entry *entry, *tmp_entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  162) 	u32 iter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  163) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  164) 	for (iter = 0; iter < CALIPSO_CACHE_BUCKETS; iter++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  165) 		spin_lock_bh(&calipso_cache[iter].lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  166) 		list_for_each_entry_safe(entry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  167) 					 tmp_entry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  168) 					 &calipso_cache[iter].list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  169) 			list_del(&entry->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  170) 			calipso_cache_entry_free(entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  171) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  172) 		calipso_cache[iter].size = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  173) 		spin_unlock_bh(&calipso_cache[iter].lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  174) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  175) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  176) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  177) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  178)  * calipso_cache_check - Check the CALIPSO cache for a label mapping
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  179)  * @key: the buffer to check
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  180)  * @key_len: buffer length in bytes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  181)  * @secattr: the security attribute struct to use
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  182)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  183)  * Description:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  184)  * This function checks the cache to see if a label mapping already exists for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  185)  * the given key.  If there is a match then the cache is adjusted and the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  186)  * @secattr struct is populated with the correct LSM security attributes.  The
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  187)  * cache is adjusted in the following manner if the entry is not already the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  188)  * first in the cache bucket:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  189)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  190)  *  1. The cache entry's activity counter is incremented
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  191)  *  2. The previous (higher ranking) entry's activity counter is decremented
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  192)  *  3. If the difference between the two activity counters is geater than
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  193)  *     CALIPSO_CACHE_REORDERLIMIT the two entries are swapped
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  194)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  195)  * Returns zero on success, -ENOENT for a cache miss, and other negative values
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  196)  * on error.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  197)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  198)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  199) static int calipso_cache_check(const unsigned char *key,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  200) 			       u32 key_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  201) 			       struct netlbl_lsm_secattr *secattr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  202) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  203) 	u32 bkt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  204) 	struct calipso_map_cache_entry *entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  205) 	struct calipso_map_cache_entry *prev_entry = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  206) 	u32 hash;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  207) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  208) 	if (!calipso_cache_enabled)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  209) 		return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  210) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  211) 	hash = calipso_map_cache_hash(key, key_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  212) 	bkt = hash & (CALIPSO_CACHE_BUCKETS - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  213) 	spin_lock_bh(&calipso_cache[bkt].lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  214) 	list_for_each_entry(entry, &calipso_cache[bkt].list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  215) 		if (entry->hash == hash &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  216) 		    entry->key_len == key_len &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  217) 		    memcmp(entry->key, key, key_len) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  218) 			entry->activity += 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  219) 			refcount_inc(&entry->lsm_data->refcount);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  220) 			secattr->cache = entry->lsm_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  221) 			secattr->flags |= NETLBL_SECATTR_CACHE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  222) 			secattr->type = NETLBL_NLTYPE_CALIPSO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  223) 			if (!prev_entry) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  224) 				spin_unlock_bh(&calipso_cache[bkt].lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  225) 				return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  226) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  227) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  228) 			if (prev_entry->activity > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  229) 				prev_entry->activity -= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  230) 			if (entry->activity > prev_entry->activity &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  231) 			    entry->activity - prev_entry->activity >
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  232) 			    CALIPSO_CACHE_REORDERLIMIT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  233) 				__list_del(entry->list.prev, entry->list.next);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  234) 				__list_add(&entry->list,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  235) 					   prev_entry->list.prev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  236) 					   &prev_entry->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  237) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  238) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  239) 			spin_unlock_bh(&calipso_cache[bkt].lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  240) 			return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  241) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  242) 		prev_entry = entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  243) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  244) 	spin_unlock_bh(&calipso_cache[bkt].lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  245) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  246) 	return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  247) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  248) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  249) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  250)  * calipso_cache_add - Add an entry to the CALIPSO cache
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  251)  * @calipso_ptr: the CALIPSO option
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  252)  * @secattr: the packet's security attributes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  253)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  254)  * Description:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  255)  * Add a new entry into the CALIPSO label mapping cache.  Add the new entry to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  256)  * head of the cache bucket's list, if the cache bucket is out of room remove
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  257)  * the last entry in the list first.  It is important to note that there is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  258)  * currently no checking for duplicate keys.  Returns zero on success,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  259)  * negative values on failure.  The key stored starts at calipso_ptr + 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  260)  * i.e. the type and length bytes are not stored, this corresponds to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  261)  * calipso_ptr[1] bytes of data.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  262)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  263)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  264) static int calipso_cache_add(const unsigned char *calipso_ptr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  265) 			     const struct netlbl_lsm_secattr *secattr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  266) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  267) 	int ret_val = -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  268) 	u32 bkt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  269) 	struct calipso_map_cache_entry *entry = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  270) 	struct calipso_map_cache_entry *old_entry = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  271) 	u32 calipso_ptr_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  272) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  273) 	if (!calipso_cache_enabled || calipso_cache_bucketsize <= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  274) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  275) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  276) 	calipso_ptr_len = calipso_ptr[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  277) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  278) 	entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  279) 	if (!entry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  280) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  281) 	entry->key = kmemdup(calipso_ptr + 2, calipso_ptr_len, GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  282) 	if (!entry->key) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  283) 		ret_val = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  284) 		goto cache_add_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  285) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  286) 	entry->key_len = calipso_ptr_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  287) 	entry->hash = calipso_map_cache_hash(calipso_ptr, calipso_ptr_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  288) 	refcount_inc(&secattr->cache->refcount);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  289) 	entry->lsm_data = secattr->cache;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  290) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  291) 	bkt = entry->hash & (CALIPSO_CACHE_BUCKETS - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  292) 	spin_lock_bh(&calipso_cache[bkt].lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  293) 	if (calipso_cache[bkt].size < calipso_cache_bucketsize) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  294) 		list_add(&entry->list, &calipso_cache[bkt].list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  295) 		calipso_cache[bkt].size += 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  296) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  297) 		old_entry = list_entry(calipso_cache[bkt].list.prev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  298) 				       struct calipso_map_cache_entry, list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  299) 		list_del(&old_entry->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  300) 		list_add(&entry->list, &calipso_cache[bkt].list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  301) 		calipso_cache_entry_free(old_entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  302) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  303) 	spin_unlock_bh(&calipso_cache[bkt].lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  304) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  305) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  306) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  307) cache_add_failure:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  308) 	if (entry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  309) 		calipso_cache_entry_free(entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  310) 	return ret_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  311) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  312) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  313) /* DOI List Functions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  314)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  315) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  316) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  317)  * calipso_doi_search - Searches for a DOI definition
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  318)  * @doi: the DOI to search for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  319)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  320)  * Description:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  321)  * Search the DOI definition list for a DOI definition with a DOI value that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  322)  * matches @doi.  The caller is responsible for calling rcu_read_[un]lock().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  323)  * Returns a pointer to the DOI definition on success and NULL on failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  324)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  325) static struct calipso_doi *calipso_doi_search(u32 doi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  326) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  327) 	struct calipso_doi *iter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  328) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  329) 	list_for_each_entry_rcu(iter, &calipso_doi_list, list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  330) 		if (iter->doi == doi && refcount_read(&iter->refcount))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  331) 			return iter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  332) 	return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  333) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  334) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  335) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  336)  * calipso_doi_add - Add a new DOI to the CALIPSO protocol engine
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  337)  * @doi_def: the DOI structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  338)  * @audit_info: NetLabel audit information
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  339)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  340)  * Description:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  341)  * The caller defines a new DOI for use by the CALIPSO engine and calls this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  342)  * function to add it to the list of acceptable domains.  The caller must
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  343)  * ensure that the mapping table specified in @doi_def->map meets all of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  344)  * requirements of the mapping type (see calipso.h for details).  Returns
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  345)  * zero on success and non-zero on failure.
^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) static int calipso_doi_add(struct calipso_doi *doi_def,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  349) 			   struct netlbl_audit *audit_info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  350) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  351) 	int ret_val = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  352) 	u32 doi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  353) 	u32 doi_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  354) 	struct audit_buffer *audit_buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  355) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  356) 	doi = doi_def->doi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  357) 	doi_type = doi_def->type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  358) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  359) 	if (doi_def->doi == CALIPSO_DOI_UNKNOWN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  360) 		goto doi_add_return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  361) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  362) 	refcount_set(&doi_def->refcount, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  363) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  364) 	spin_lock(&calipso_doi_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  365) 	if (calipso_doi_search(doi_def->doi)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  366) 		spin_unlock(&calipso_doi_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  367) 		ret_val = -EEXIST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  368) 		goto doi_add_return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  369) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  370) 	list_add_tail_rcu(&doi_def->list, &calipso_doi_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  371) 	spin_unlock(&calipso_doi_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  372) 	ret_val = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  373) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  374) doi_add_return:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  375) 	audit_buf = netlbl_audit_start(AUDIT_MAC_CALIPSO_ADD, audit_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  376) 	if (audit_buf) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  377) 		const char *type_str;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  378) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  379) 		switch (doi_type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  380) 		case CALIPSO_MAP_PASS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  381) 			type_str = "pass";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  382) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  383) 		default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  384) 			type_str = "(unknown)";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  385) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  386) 		audit_log_format(audit_buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  387) 				 " calipso_doi=%u calipso_type=%s res=%u",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  388) 				 doi, type_str, ret_val == 0 ? 1 : 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  389) 		audit_log_end(audit_buf);
^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) 	return ret_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  393) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  394) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  395) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  396)  * calipso_doi_free - Frees a DOI definition
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  397)  * @doi_def: the DOI definition
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  398)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  399)  * Description:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  400)  * This function frees all of the memory associated with a DOI definition.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  401)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  402)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  403) static void calipso_doi_free(struct calipso_doi *doi_def)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  404) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  405) 	kfree(doi_def);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  406) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  407) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  408) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  409)  * calipso_doi_free_rcu - Frees a DOI definition via the RCU pointer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  410)  * @entry: the entry's RCU field
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  411)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  412)  * Description:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  413)  * This function is designed to be used as a callback to the call_rcu()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  414)  * function so that the memory allocated to the DOI definition can be released
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  415)  * safely.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  416)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  417)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  418) static void calipso_doi_free_rcu(struct rcu_head *entry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  419) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  420) 	struct calipso_doi *doi_def;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  421) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  422) 	doi_def = container_of(entry, struct calipso_doi, rcu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  423) 	calipso_doi_free(doi_def);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  424) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  425) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  426) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  427)  * calipso_doi_remove - Remove an existing DOI from the CALIPSO protocol engine
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  428)  * @doi: the DOI value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  429)  * @audit_secid: the LSM secid to use in the audit message
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  430)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  431)  * Description:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  432)  * Removes a DOI definition from the CALIPSO engine.  The NetLabel routines will
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  433)  * be called to release their own LSM domain mappings as well as our own
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  434)  * domain list.  Returns zero on success and negative values on failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  435)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  436)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  437) static int calipso_doi_remove(u32 doi, struct netlbl_audit *audit_info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  438) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  439) 	int ret_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  440) 	struct calipso_doi *doi_def;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  441) 	struct audit_buffer *audit_buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  442) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  443) 	spin_lock(&calipso_doi_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  444) 	doi_def = calipso_doi_search(doi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  445) 	if (!doi_def) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  446) 		spin_unlock(&calipso_doi_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  447) 		ret_val = -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  448) 		goto doi_remove_return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  449) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  450) 	list_del_rcu(&doi_def->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  451) 	spin_unlock(&calipso_doi_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  452) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  453) 	calipso_doi_putdef(doi_def);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  454) 	ret_val = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  455) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  456) doi_remove_return:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  457) 	audit_buf = netlbl_audit_start(AUDIT_MAC_CALIPSO_DEL, audit_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  458) 	if (audit_buf) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  459) 		audit_log_format(audit_buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  460) 				 " calipso_doi=%u res=%u",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  461) 				 doi, ret_val == 0 ? 1 : 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  462) 		audit_log_end(audit_buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  463) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  464) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  465) 	return ret_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  466) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  467) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  468) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  469)  * calipso_doi_getdef - Returns a reference to a valid DOI definition
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  470)  * @doi: the DOI value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  471)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  472)  * Description:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  473)  * Searches for a valid DOI definition and if one is found it is returned to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  474)  * the caller.  Otherwise NULL is returned.  The caller must ensure that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  475)  * calipso_doi_putdef() is called when the caller is done.
^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) static struct calipso_doi *calipso_doi_getdef(u32 doi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  479) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  480) 	struct calipso_doi *doi_def;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  481) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  482) 	rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  483) 	doi_def = calipso_doi_search(doi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  484) 	if (!doi_def)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  485) 		goto doi_getdef_return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  486) 	if (!refcount_inc_not_zero(&doi_def->refcount))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  487) 		doi_def = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  488) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  489) doi_getdef_return:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  490) 	rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  491) 	return doi_def;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  492) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  493) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  494) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  495)  * calipso_doi_putdef - Releases a reference for the given DOI definition
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  496)  * @doi_def: the DOI definition
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  497)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  498)  * Description:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  499)  * Releases a DOI definition reference obtained from calipso_doi_getdef().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  500)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  501)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  502) static void calipso_doi_putdef(struct calipso_doi *doi_def)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  503) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  504) 	if (!doi_def)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  505) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  506) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  507) 	if (!refcount_dec_and_test(&doi_def->refcount))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  508) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  509) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  510) 	calipso_cache_invalidate();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  511) 	call_rcu(&doi_def->rcu, calipso_doi_free_rcu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  512) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  513) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  514) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  515)  * calipso_doi_walk - Iterate through the DOI definitions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  516)  * @skip_cnt: skip past this number of DOI definitions, updated
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  517)  * @callback: callback for each DOI definition
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  518)  * @cb_arg: argument for the callback function
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  519)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  520)  * Description:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  521)  * Iterate over the DOI definition list, skipping the first @skip_cnt entries.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  522)  * For each entry call @callback, if @callback returns a negative value stop
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  523)  * 'walking' through the list and return.  Updates the value in @skip_cnt upon
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  524)  * return.  Returns zero on success, negative values on failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  525)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  526)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  527) static int calipso_doi_walk(u32 *skip_cnt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  528) 			    int (*callback)(struct calipso_doi *doi_def,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  529) 					    void *arg),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  530) 			    void *cb_arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  531) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  532) 	int ret_val = -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  533) 	u32 doi_cnt = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  534) 	struct calipso_doi *iter_doi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  535) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  536) 	rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  537) 	list_for_each_entry_rcu(iter_doi, &calipso_doi_list, list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  538) 		if (refcount_read(&iter_doi->refcount) > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  539) 			if (doi_cnt++ < *skip_cnt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  540) 				continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  541) 			ret_val = callback(iter_doi, cb_arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  542) 			if (ret_val < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  543) 				doi_cnt--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  544) 				goto doi_walk_return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  545) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  546) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  547) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  548) doi_walk_return:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  549) 	rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  550) 	*skip_cnt = doi_cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  551) 	return ret_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  552) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  553) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  554) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  555)  * calipso_validate - Validate a CALIPSO option
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  556)  * @skb: the packet
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  557)  * @option: the start of the option
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  558)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  559)  * Description:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  560)  * This routine is called to validate a CALIPSO option.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  561)  * If the option is valid then %true is returned, otherwise
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  562)  * %false is returned.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  563)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  564)  * The caller should have already checked that the length of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  565)  * option (including the TLV header) is >= 10 and that the catmap
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  566)  * length is consistent with the option length.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  567)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  568)  * We leave checks on the level and categories to the socket layer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  569)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  570) bool calipso_validate(const struct sk_buff *skb, const unsigned char *option)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  571) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  572) 	struct calipso_doi *doi_def;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  573) 	bool ret_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  574) 	u16 crc, len = option[1] + 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  575) 	static const u8 zero[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  576) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  577) 	/* The original CRC runs over the option including the TLV header
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  578) 	 * with the CRC-16 field (at offset 8) zeroed out. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  579) 	crc = crc_ccitt(0xffff, option, 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  580) 	crc = crc_ccitt(crc, zero, sizeof(zero));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  581) 	if (len > 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  582) 		crc = crc_ccitt(crc, option + 10, len - 10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  583) 	crc = ~crc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  584) 	if (option[8] != (crc & 0xff) || option[9] != ((crc >> 8) & 0xff))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  585) 		return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  586) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  587) 	rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  588) 	doi_def = calipso_doi_search(get_unaligned_be32(option + 2));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  589) 	ret_val = !!doi_def;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  590) 	rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  591) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  592) 	return ret_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  593) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  594) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  595) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  596)  * calipso_map_cat_hton - Perform a category mapping from host to network
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  597)  * @doi_def: the DOI definition
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  598)  * @secattr: the security attributes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  599)  * @net_cat: the zero'd out category bitmap in network/CALIPSO format
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  600)  * @net_cat_len: the length of the CALIPSO bitmap in bytes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  601)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  602)  * Description:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  603)  * Perform a label mapping to translate a local MLS category bitmap to the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  604)  * correct CALIPSO bitmap using the given DOI definition.  Returns the minimum
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  605)  * size in bytes of the network bitmap on success, negative values otherwise.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  606)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  607)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  608) static int calipso_map_cat_hton(const struct calipso_doi *doi_def,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  609) 				const struct netlbl_lsm_secattr *secattr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  610) 				unsigned char *net_cat,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  611) 				u32 net_cat_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  612) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  613) 	int spot = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  614) 	u32 net_spot_max = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  615) 	u32 net_clen_bits = net_cat_len * 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  616) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  617) 	for (;;) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  618) 		spot = netlbl_catmap_walk(secattr->attr.mls.cat,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  619) 					  spot + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  620) 		if (spot < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  621) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  622) 		if (spot >= net_clen_bits)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  623) 			return -ENOSPC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  624) 		netlbl_bitmap_setbit(net_cat, spot, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  625) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  626) 		if (spot > net_spot_max)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  627) 			net_spot_max = spot;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  628) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  629) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  630) 	return (net_spot_max / 32 + 1) * 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  631) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  632) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  633) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  634)  * calipso_map_cat_ntoh - Perform a category mapping from network to host
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  635)  * @doi_def: the DOI definition
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  636)  * @net_cat: the category bitmap in network/CALIPSO format
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  637)  * @net_cat_len: the length of the CALIPSO bitmap in bytes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  638)  * @secattr: the security attributes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  639)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  640)  * Description:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  641)  * Perform a label mapping to translate a CALIPSO bitmap to the correct local
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  642)  * MLS category bitmap using the given DOI definition.  Returns zero on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  643)  * success, negative values on failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  644)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  645)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  646) static int calipso_map_cat_ntoh(const struct calipso_doi *doi_def,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  647) 				const unsigned char *net_cat,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  648) 				u32 net_cat_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  649) 				struct netlbl_lsm_secattr *secattr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  650) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  651) 	int ret_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  652) 	int spot = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  653) 	u32 net_clen_bits = net_cat_len * 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  654) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  655) 	for (;;) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  656) 		spot = netlbl_bitmap_walk(net_cat,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  657) 					  net_clen_bits,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  658) 					  spot + 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  659) 					  1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  660) 		if (spot < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  661) 			if (spot == -2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  662) 				return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  663) 			return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  664) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  665) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  666) 		ret_val = netlbl_catmap_setbit(&secattr->attr.mls.cat,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  667) 					       spot,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  668) 					       GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  669) 		if (ret_val != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  670) 			return ret_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  671) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  672) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  673) 	return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  674) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  675) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  676) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  677)  * calipso_pad_write - Writes pad bytes in TLV format
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  678)  * @buf: the buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  679)  * @offset: offset from start of buffer to write padding
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  680)  * @count: number of pad bytes to write
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  681)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  682)  * Description:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  683)  * Write @count bytes of TLV padding into @buffer starting at offset @offset.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  684)  * @count should be less than 8 - see RFC 4942.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  685)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  686)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  687) static int calipso_pad_write(unsigned char *buf, unsigned int offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  688) 			     unsigned int count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  689) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  690) 	if (WARN_ON_ONCE(count >= 8))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  691) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  692) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  693) 	switch (count) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  694) 	case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  695) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  696) 	case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  697) 		buf[offset] = IPV6_TLV_PAD1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  698) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  699) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  700) 		buf[offset] = IPV6_TLV_PADN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  701) 		buf[offset + 1] = count - 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  702) 		if (count > 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  703) 			memset(buf + offset + 2, 0, count - 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  704) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  705) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  706) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  707) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  708) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  709) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  710)  * calipso_genopt - Generate a CALIPSO option
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  711)  * @buf: the option buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  712)  * @start: offset from which to write
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  713)  * @buf_len: the size of opt_buf
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  714)  * @doi_def: the CALIPSO DOI to use
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  715)  * @secattr: the security attributes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  716)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  717)  * Description:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  718)  * Generate a CALIPSO option using the DOI definition and security attributes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  719)  * passed to the function. This also generates upto three bytes of leading
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  720)  * padding that ensures that the option is 4n + 2 aligned.  It returns the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  721)  * number of bytes written (including any initial padding).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  722)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  723) static int calipso_genopt(unsigned char *buf, u32 start, u32 buf_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  724) 			  const struct calipso_doi *doi_def,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  725) 			  const struct netlbl_lsm_secattr *secattr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  726) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  727) 	int ret_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  728) 	u32 len, pad;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  729) 	u16 crc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  730) 	static const unsigned char padding[4] = {2, 1, 0, 3};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  731) 	unsigned char *calipso;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  732) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  733) 	/* CALIPSO has 4n + 2 alignment */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  734) 	pad = padding[start & 3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  735) 	if (buf_len <= start + pad + CALIPSO_HDR_LEN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  736) 		return -ENOSPC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  737) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  738) 	if ((secattr->flags & NETLBL_SECATTR_MLS_LVL) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  739) 		return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  740) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  741) 	len = CALIPSO_HDR_LEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  742) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  743) 	if (secattr->flags & NETLBL_SECATTR_MLS_CAT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  744) 		ret_val = calipso_map_cat_hton(doi_def,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  745) 					       secattr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  746) 					       buf + start + pad + len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  747) 					       buf_len - start - pad - len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  748) 		if (ret_val < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  749) 			return ret_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  750) 		len += ret_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  751) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  752) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  753) 	calipso_pad_write(buf, start, pad);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  754) 	calipso = buf + start + pad;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  755) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  756) 	calipso[0] = IPV6_TLV_CALIPSO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  757) 	calipso[1] = len - 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  758) 	*(__be32 *)(calipso + 2) = htonl(doi_def->doi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  759) 	calipso[6] = (len - CALIPSO_HDR_LEN) / 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  760) 	calipso[7] = secattr->attr.mls.lvl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  761) 	crc = ~crc_ccitt(0xffff, calipso, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  762) 	calipso[8] = crc & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  763) 	calipso[9] = (crc >> 8) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  764) 	return pad + len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  765) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  766) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  767) /* Hop-by-hop hdr helper functions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  768)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  769) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  770) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  771)  * calipso_opt_update - Replaces socket's hop options with a new set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  772)  * @sk: the socket
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  773)  * @hop: new hop options
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  774)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  775)  * Description:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  776)  * Replaces @sk's hop options with @hop.  @hop may be NULL to leave
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  777)  * the socket with no hop options.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  778)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  779)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  780) static int calipso_opt_update(struct sock *sk, struct ipv6_opt_hdr *hop)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  781) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  782) 	struct ipv6_txoptions *old = txopt_get(inet6_sk(sk)), *txopts;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  783) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  784) 	txopts = ipv6_renew_options(sk, old, IPV6_HOPOPTS, hop);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  785) 	txopt_put(old);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  786) 	if (IS_ERR(txopts))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  787) 		return PTR_ERR(txopts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  788) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  789) 	txopts = ipv6_update_options(sk, txopts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  790) 	if (txopts) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  791) 		atomic_sub(txopts->tot_len, &sk->sk_omem_alloc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  792) 		txopt_put(txopts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  793) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  794) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  795) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  796) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  797) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  798) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  799)  * calipso_tlv_len - Returns the length of the TLV
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  800)  * @opt: the option header
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  801)  * @offset: offset of the TLV within the header
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  802)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  803)  * Description:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  804)  * Returns the length of the TLV option at offset @offset within
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  805)  * the option header @opt.  Checks that the entire TLV fits inside
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  806)  * the option header, returns a negative value if this is not the case.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  807)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  808) static int calipso_tlv_len(struct ipv6_opt_hdr *opt, unsigned int offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  809) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  810) 	unsigned char *tlv = (unsigned char *)opt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  811) 	unsigned int opt_len = ipv6_optlen(opt), tlv_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  812) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  813) 	if (offset < sizeof(*opt) || offset >= opt_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  814) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  815) 	if (tlv[offset] == IPV6_TLV_PAD1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  816) 		return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  817) 	if (offset + 1 >= opt_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  818) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  819) 	tlv_len = tlv[offset + 1] + 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  820) 	if (offset + tlv_len > opt_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  821) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  822) 	return tlv_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  823) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  824) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  825) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  826)  * calipso_opt_find - Finds the CALIPSO option in an IPv6 hop options header
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  827)  * @hop: the hop options header
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  828)  * @start: on return holds the offset of any leading padding
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  829)  * @end: on return holds the offset of the first non-pad TLV after CALIPSO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  830)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  831)  * Description:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  832)  * Finds the space occupied by a CALIPSO option (including any leading and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  833)  * trailing padding).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  834)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  835)  * If a CALIPSO option exists set @start and @end to the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  836)  * offsets within @hop of the start of padding before the first
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  837)  * CALIPSO option and the end of padding after the first CALIPSO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  838)  * option.  In this case the function returns 0.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  839)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  840)  * In the absence of a CALIPSO option, @start and @end will be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  841)  * set to the start and end of any trailing padding in the header.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  842)  * This is useful when appending a new option, as the caller may want
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  843)  * to overwrite some of this padding.  In this case the function will
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  844)  * return -ENOENT.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  845)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  846) static int calipso_opt_find(struct ipv6_opt_hdr *hop, unsigned int *start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  847) 			    unsigned int *end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  848) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  849) 	int ret_val = -ENOENT, tlv_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  850) 	unsigned int opt_len, offset, offset_s = 0, offset_e = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  851) 	unsigned char *opt = (unsigned char *)hop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  852) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  853) 	opt_len = ipv6_optlen(hop);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  854) 	offset = sizeof(*hop);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  855) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  856) 	while (offset < opt_len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  857) 		tlv_len = calipso_tlv_len(hop, offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  858) 		if (tlv_len < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  859) 			return tlv_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  860) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  861) 		switch (opt[offset]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  862) 		case IPV6_TLV_PAD1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  863) 		case IPV6_TLV_PADN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  864) 			if (offset_e)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  865) 				offset_e = offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  866) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  867) 		case IPV6_TLV_CALIPSO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  868) 			ret_val = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  869) 			offset_e = offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  870) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  871) 		default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  872) 			if (offset_e == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  873) 				offset_s = offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  874) 			else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  875) 				goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  876) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  877) 		offset += tlv_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  878) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  879) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  880) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  881) 	if (offset_s)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  882) 		*start = offset_s + calipso_tlv_len(hop, offset_s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  883) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  884) 		*start = sizeof(*hop);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  885) 	if (offset_e)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  886) 		*end = offset_e + calipso_tlv_len(hop, offset_e);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  887) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  888) 		*end = opt_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  889) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  890) 	return ret_val;
^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) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  894)  * calipso_opt_insert - Inserts a CALIPSO option into an IPv6 hop opt hdr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  895)  * @hop: the original hop options header
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  896)  * @doi_def: the CALIPSO DOI to use
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  897)  * @secattr: the specific security attributes of the socket
^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)  * Creates a new hop options header based on @hop with a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  901)  * CALIPSO option added to it.  If @hop already contains a CALIPSO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  902)  * option this is overwritten, otherwise the new option is appended
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  903)  * after any existing options.  If @hop is NULL then the new header
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  904)  * will contain just the CALIPSO option and any needed padding.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  905)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  906)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  907) static struct ipv6_opt_hdr *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  908) calipso_opt_insert(struct ipv6_opt_hdr *hop,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  909) 		   const struct calipso_doi *doi_def,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  910) 		   const struct netlbl_lsm_secattr *secattr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  911) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  912) 	unsigned int start, end, buf_len, pad, hop_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  913) 	struct ipv6_opt_hdr *new;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  914) 	int ret_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  915) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  916) 	if (hop) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  917) 		hop_len = ipv6_optlen(hop);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  918) 		ret_val = calipso_opt_find(hop, &start, &end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  919) 		if (ret_val && ret_val != -ENOENT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  920) 			return ERR_PTR(ret_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  921) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  922) 		hop_len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  923) 		start = sizeof(*hop);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  924) 		end = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  925) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  926) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  927) 	buf_len = hop_len + start - end + CALIPSO_OPT_LEN_MAX_WITH_PAD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  928) 	new = kzalloc(buf_len, GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  929) 	if (!new)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  930) 		return ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  931) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  932) 	if (start > sizeof(*hop))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  933) 		memcpy(new, hop, start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  934) 	ret_val = calipso_genopt((unsigned char *)new, start, buf_len, doi_def,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  935) 				 secattr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  936) 	if (ret_val < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  937) 		kfree(new);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  938) 		return ERR_PTR(ret_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  939) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  940) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  941) 	buf_len = start + ret_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  942) 	/* At this point buf_len aligns to 4n, so (buf_len & 4) pads to 8n */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  943) 	pad = ((buf_len & 4) + (end & 7)) & 7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  944) 	calipso_pad_write((unsigned char *)new, buf_len, pad);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  945) 	buf_len += pad;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  946) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  947) 	if (end != hop_len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  948) 		memcpy((char *)new + buf_len, (char *)hop + end, hop_len - end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  949) 		buf_len += hop_len - end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  950) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  951) 	new->nexthdr = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  952) 	new->hdrlen = buf_len / 8 - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  953) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  954) 	return new;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  955) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  956) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  957) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  958)  * calipso_opt_del - Removes the CALIPSO option from an option header
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  959)  * @hop: the original header
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  960)  * @new: the new header
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  961)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  962)  * Description:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  963)  * Creates a new header based on @hop without any CALIPSO option.  If @hop
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  964)  * doesn't contain a CALIPSO option it returns -ENOENT.  If @hop contains
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  965)  * no other non-padding options, it returns zero with @new set to NULL.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  966)  * Otherwise it returns zero, creates a new header without the CALIPSO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  967)  * option (and removing as much padding as possible) and returns with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  968)  * @new set to that header.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  969)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  970)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  971) static int calipso_opt_del(struct ipv6_opt_hdr *hop,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  972) 			   struct ipv6_opt_hdr **new)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  973) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  974) 	int ret_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  975) 	unsigned int start, end, delta, pad, hop_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  976) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  977) 	ret_val = calipso_opt_find(hop, &start, &end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  978) 	if (ret_val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  979) 		return ret_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  980) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  981) 	hop_len = ipv6_optlen(hop);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  982) 	if (start == sizeof(*hop) && end == hop_len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  983) 		/* There's no other option in the header so return NULL */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  984) 		*new = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  985) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  986) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  987) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  988) 	delta = (end - start) & ~7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  989) 	*new = kzalloc(hop_len - delta, GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  990) 	if (!*new)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  991) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  992) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  993) 	memcpy(*new, hop, start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  994) 	(*new)->hdrlen -= delta / 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  995) 	pad = (end - start) & 7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  996) 	calipso_pad_write((unsigned char *)*new, start, pad);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  997) 	if (end != hop_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  998) 		memcpy((char *)*new + start + pad, (char *)hop + end,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  999) 		       hop_len - end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005)  * calipso_opt_getattr - Get the security attributes from a memory block
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006)  * @calipso: the CALIPSO option
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007)  * @secattr: the security attributes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009)  * Description:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010)  * Inspect @calipso and return the security attributes in @secattr.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011)  * Returns zero on success and negative values on failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) static int calipso_opt_getattr(const unsigned char *calipso,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) 			       struct netlbl_lsm_secattr *secattr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) 	int ret_val = -ENOMSG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) 	u32 doi, len = calipso[1], cat_len = calipso[6] * 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) 	struct calipso_doi *doi_def;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) 	if (cat_len + 8 > len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) 	if (calipso_cache_check(calipso + 2, calipso[1], secattr) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) 	doi = get_unaligned_be32(calipso + 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) 	rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) 	doi_def = calipso_doi_search(doi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) 	if (!doi_def)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) 		goto getattr_return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) 	secattr->attr.mls.lvl = calipso[7];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) 	secattr->flags |= NETLBL_SECATTR_MLS_LVL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) 	if (cat_len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) 		ret_val = calipso_map_cat_ntoh(doi_def,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) 					       calipso + 10,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) 					       cat_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) 					       secattr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) 		if (ret_val != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) 			netlbl_catmap_free(secattr->attr.mls.cat);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) 			goto getattr_return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) 		if (secattr->attr.mls.cat)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) 			secattr->flags |= NETLBL_SECATTR_MLS_CAT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) 	secattr->type = NETLBL_NLTYPE_CALIPSO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) getattr_return:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) 	rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) 	return ret_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) /* sock functions.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061)  * calipso_sock_getattr - Get the security attributes from a sock
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062)  * @sk: the sock
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063)  * @secattr: the security attributes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065)  * Description:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066)  * Query @sk to see if there is a CALIPSO option attached to the sock and if
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067)  * there is return the CALIPSO security attributes in @secattr.  This function
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068)  * requires that @sk be locked, or privately held, but it does not do any
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069)  * locking itself.  Returns zero on success and negative values on failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) static int calipso_sock_getattr(struct sock *sk,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) 				struct netlbl_lsm_secattr *secattr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) 	struct ipv6_opt_hdr *hop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) 	int opt_len, len, ret_val = -ENOMSG, offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) 	unsigned char *opt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) 	struct ipv6_txoptions *txopts = txopt_get(inet6_sk(sk));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) 	if (!txopts || !txopts->hopopt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) 		goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) 	hop = txopts->hopopt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) 	opt = (unsigned char *)hop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) 	opt_len = ipv6_optlen(hop);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) 	offset = sizeof(*hop);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) 	while (offset < opt_len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) 		len = calipso_tlv_len(hop, offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) 		if (len < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) 			ret_val = len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) 			goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) 		switch (opt[offset]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) 		case IPV6_TLV_CALIPSO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) 			if (len < CALIPSO_HDR_LEN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) 				ret_val = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) 			else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) 				ret_val = calipso_opt_getattr(&opt[offset],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) 							      secattr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) 			goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) 		default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) 			offset += len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) done:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) 	txopt_put(txopts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) 	return ret_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112)  * calipso_sock_setattr - Add a CALIPSO option to a socket
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113)  * @sk: the socket
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114)  * @doi_def: the CALIPSO DOI to use
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115)  * @secattr: the specific security attributes of the socket
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117)  * Description:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118)  * Set the CALIPSO option on the given socket using the DOI definition and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119)  * security attributes passed to the function.  This function requires
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120)  * exclusive access to @sk, which means it either needs to be in the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121)  * process of being created or locked.  Returns zero on success and negative
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122)  * values on failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) static int calipso_sock_setattr(struct sock *sk,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) 				const struct calipso_doi *doi_def,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) 				const struct netlbl_lsm_secattr *secattr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) 	int ret_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) 	struct ipv6_opt_hdr *old, *new;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) 	struct ipv6_txoptions *txopts = txopt_get(inet6_sk(sk));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) 	old = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) 	if (txopts)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) 		old = txopts->hopopt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) 	new = calipso_opt_insert(old, doi_def, secattr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) 	txopt_put(txopts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) 	if (IS_ERR(new))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) 		return PTR_ERR(new);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) 	ret_val = calipso_opt_update(sk, new);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) 	kfree(new);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) 	return ret_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149)  * calipso_sock_delattr - Delete the CALIPSO option from a socket
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150)  * @sk: the socket
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152)  * Description:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153)  * Removes the CALIPSO option from a socket, if present.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) static void calipso_sock_delattr(struct sock *sk)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) 	struct ipv6_opt_hdr *new_hop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) 	struct ipv6_txoptions *txopts = txopt_get(inet6_sk(sk));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) 	if (!txopts || !txopts->hopopt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) 		goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) 	if (calipso_opt_del(txopts->hopopt, &new_hop))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) 		goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) 	calipso_opt_update(sk, new_hop);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) 	kfree(new_hop);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) done:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) 	txopt_put(txopts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) /* request sock functions.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178)  * calipso_req_setattr - Add a CALIPSO option to a connection request socket
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179)  * @req: the connection request socket
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180)  * @doi_def: the CALIPSO DOI to use
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181)  * @secattr: the specific security attributes of the socket
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183)  * Description:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184)  * Set the CALIPSO option on the given socket using the DOI definition and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185)  * security attributes passed to the function.  Returns zero on success and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186)  * negative values on failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) static int calipso_req_setattr(struct request_sock *req,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) 			       const struct calipso_doi *doi_def,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) 			       const struct netlbl_lsm_secattr *secattr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) 	struct ipv6_txoptions *txopts;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) 	struct inet_request_sock *req_inet = inet_rsk(req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) 	struct ipv6_opt_hdr *old, *new;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) 	struct sock *sk = sk_to_full_sk(req_to_sk(req));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) 	if (req_inet->ipv6_opt && req_inet->ipv6_opt->hopopt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) 		old = req_inet->ipv6_opt->hopopt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) 		old = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) 	new = calipso_opt_insert(old, doi_def, secattr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) 	if (IS_ERR(new))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) 		return PTR_ERR(new);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) 	txopts = ipv6_renew_options(sk, req_inet->ipv6_opt, IPV6_HOPOPTS, new);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) 	kfree(new);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) 	if (IS_ERR(txopts))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) 		return PTR_ERR(txopts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) 	txopts = xchg(&req_inet->ipv6_opt, txopts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) 	if (txopts) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) 		atomic_sub(txopts->tot_len, &sk->sk_omem_alloc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) 		txopt_put(txopts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224)  * calipso_req_delattr - Delete the CALIPSO option from a request socket
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225)  * @reg: the request socket
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227)  * Description:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228)  * Removes the CALIPSO option from a request socket, if present.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) static void calipso_req_delattr(struct request_sock *req)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) 	struct inet_request_sock *req_inet = inet_rsk(req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) 	struct ipv6_opt_hdr *new;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) 	struct ipv6_txoptions *txopts;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) 	struct sock *sk = sk_to_full_sk(req_to_sk(req));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) 	if (!req_inet->ipv6_opt || !req_inet->ipv6_opt->hopopt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) 	if (calipso_opt_del(req_inet->ipv6_opt->hopopt, &new))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) 		return; /* Nothing to do */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) 	txopts = ipv6_renew_options(sk, req_inet->ipv6_opt, IPV6_HOPOPTS, new);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) 	if (!IS_ERR(txopts)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) 		txopts = xchg(&req_inet->ipv6_opt, txopts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) 		if (txopts) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) 			atomic_sub(txopts->tot_len, &sk->sk_omem_alloc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) 			txopt_put(txopts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) 	kfree(new);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) /* skbuff functions.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260)  * calipso_skbuff_optptr - Find the CALIPSO option in the packet
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261)  * @skb: the packet
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263)  * Description:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264)  * Parse the packet's IP header looking for a CALIPSO option.  Returns a pointer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265)  * to the start of the CALIPSO option on success, NULL if one if not found.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) static unsigned char *calipso_skbuff_optptr(const struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) 	const struct ipv6hdr *ip6_hdr = ipv6_hdr(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) 	int offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) 	if (ip6_hdr->nexthdr != NEXTHDR_HOP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) 		return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) 	offset = ipv6_find_tlv(skb, sizeof(*ip6_hdr), IPV6_TLV_CALIPSO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) 	if (offset >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) 		return (unsigned char *)ip6_hdr + offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) 	return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284)  * calipso_skbuff_setattr - Set the CALIPSO option on a packet
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285)  * @skb: the packet
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286)  * @doi_def: the CALIPSO DOI to use
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287)  * @secattr: the security attributes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289)  * Description:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290)  * Set the CALIPSO option on the given packet based on the security attributes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291)  * Returns a pointer to the IP header on success and NULL on failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) static int calipso_skbuff_setattr(struct sk_buff *skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) 				  const struct calipso_doi *doi_def,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) 				  const struct netlbl_lsm_secattr *secattr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) 	int ret_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) 	struct ipv6hdr *ip6_hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) 	struct ipv6_opt_hdr *hop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) 	unsigned char buf[CALIPSO_MAX_BUFFER];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) 	int len_delta, new_end, pad, payload;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) 	unsigned int start, end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) 	ip6_hdr = ipv6_hdr(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) 	if (ip6_hdr->nexthdr == NEXTHDR_HOP) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) 		hop = (struct ipv6_opt_hdr *)(ip6_hdr + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) 		ret_val = calipso_opt_find(hop, &start, &end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) 		if (ret_val && ret_val != -ENOENT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) 			return ret_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) 		start = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) 		end = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) 	memset(buf, 0, sizeof(buf));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) 	ret_val = calipso_genopt(buf, start & 3, sizeof(buf), doi_def, secattr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) 	if (ret_val < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) 		return ret_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) 	new_end = start + ret_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) 	/* At this point new_end aligns to 4n, so (new_end & 4) pads to 8n */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) 	pad = ((new_end & 4) + (end & 7)) & 7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) 	len_delta = new_end - (int)end + pad;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) 	ret_val = skb_cow(skb, skb_headroom(skb) + len_delta);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) 	if (ret_val < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) 		return ret_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) 	ip6_hdr = ipv6_hdr(skb); /* Reset as skb_cow() may have moved it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) 	if (len_delta) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) 		if (len_delta > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) 			skb_push(skb, len_delta);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) 			skb_pull(skb, -len_delta);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) 		memmove((char *)ip6_hdr - len_delta, ip6_hdr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) 			sizeof(*ip6_hdr) + start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) 		skb_reset_network_header(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) 		ip6_hdr = ipv6_hdr(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) 		payload = ntohs(ip6_hdr->payload_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) 		ip6_hdr->payload_len = htons(payload + len_delta);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) 	hop = (struct ipv6_opt_hdr *)(ip6_hdr + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) 	if (start == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) 		struct ipv6_opt_hdr *new_hop = (struct ipv6_opt_hdr *)buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) 		new_hop->nexthdr = ip6_hdr->nexthdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) 		new_hop->hdrlen = len_delta / 8 - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) 		ip6_hdr->nexthdr = NEXTHDR_HOP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) 		hop->hdrlen += len_delta / 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) 	memcpy((char *)hop + start, buf + (start & 3), new_end - start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) 	calipso_pad_write((unsigned char *)hop, new_end, pad);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361)  * calipso_skbuff_delattr - Delete any CALIPSO options from a packet
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362)  * @skb: the packet
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364)  * Description:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365)  * Removes any and all CALIPSO options from the given packet.  Returns zero on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366)  * success, negative values on failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) static int calipso_skbuff_delattr(struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) 	int ret_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) 	struct ipv6hdr *ip6_hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) 	struct ipv6_opt_hdr *old_hop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) 	u32 old_hop_len, start = 0, end = 0, delta, size, pad;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) 	if (!calipso_skbuff_optptr(skb))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) 	/* since we are changing the packet we should make a copy */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) 	ret_val = skb_cow(skb, skb_headroom(skb));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) 	if (ret_val < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) 		return ret_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) 	ip6_hdr = ipv6_hdr(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) 	old_hop = (struct ipv6_opt_hdr *)(ip6_hdr + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) 	old_hop_len = ipv6_optlen(old_hop);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) 	ret_val = calipso_opt_find(old_hop, &start, &end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) 	if (ret_val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) 		return ret_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) 	if (start == sizeof(*old_hop) && end == old_hop_len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) 		/* There's no other option in the header so we delete
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) 		 * the whole thing. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) 		delta = old_hop_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) 		size = sizeof(*ip6_hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) 		ip6_hdr->nexthdr = old_hop->nexthdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) 		delta = (end - start) & ~7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) 		if (delta)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) 			old_hop->hdrlen -= delta / 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) 		pad = (end - start) & 7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) 		size = sizeof(*ip6_hdr) + start + pad;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) 		calipso_pad_write((unsigned char *)old_hop, start, pad);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) 	if (delta) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) 		skb_pull(skb, delta);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) 		memmove((char *)ip6_hdr + delta, ip6_hdr, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) 		skb_reset_network_header(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416) static const struct netlbl_calipso_ops ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) 	.doi_add          = calipso_doi_add,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) 	.doi_free         = calipso_doi_free,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) 	.doi_remove       = calipso_doi_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420) 	.doi_getdef       = calipso_doi_getdef,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) 	.doi_putdef       = calipso_doi_putdef,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) 	.doi_walk         = calipso_doi_walk,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) 	.sock_getattr     = calipso_sock_getattr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) 	.sock_setattr     = calipso_sock_setattr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) 	.sock_delattr     = calipso_sock_delattr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426) 	.req_setattr      = calipso_req_setattr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) 	.req_delattr      = calipso_req_delattr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) 	.opt_getattr      = calipso_opt_getattr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) 	.skbuff_optptr    = calipso_skbuff_optptr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) 	.skbuff_setattr   = calipso_skbuff_setattr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) 	.skbuff_delattr   = calipso_skbuff_delattr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) 	.cache_invalidate = calipso_cache_invalidate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) 	.cache_add        = calipso_cache_add
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437)  * calipso_init - Initialize the CALIPSO module
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439)  * Description:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440)  * Initialize the CALIPSO module and prepare it for use.  Returns zero on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441)  * success and negative values on failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) int __init calipso_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446) 	int ret_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448) 	ret_val = calipso_cache_init();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) 	if (!ret_val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450) 		netlbl_calipso_ops_register(&ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451) 	return ret_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454) void calipso_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456) 	netlbl_calipso_ops_register(NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) 	calipso_cache_invalidate();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458) 	kfree(calipso_cache);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459) }