Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ]
Version: [ 2.6.11.8 ] [ 2.6.25 ] [ 2.6.25.8 ] [ 2.6.31.13 ] Architecture: [ i386 ]

Diff markup

Differences between /linux/net/ipv4/cipso_ipv4.c (Version 2.6.25.8) and /linux/net/ipv4/cipso_ipv4.c (Version 2.6.25)


  1 /*                                                  1 /*
  2  * CIPSO - Commercial IP Security Option            2  * CIPSO - Commercial IP Security Option
  3  *                                                  3  *
  4  * This is an implementation of the CIPSO 2.2       4  * This is an implementation of the CIPSO 2.2 protocol as specified in
  5  * draft-ietf-cipso-ipsecurity-01.txt with add      5  * draft-ietf-cipso-ipsecurity-01.txt with additional tag types as found in
  6  * FIPS-188, copies of both documents can be f      6  * FIPS-188, copies of both documents can be found in the Documentation
  7  * directory.  While CIPSO never became a full      7  * directory.  While CIPSO never became a full IETF RFC standard many vendors
  8  * have chosen to adopt the protocol and over       8  * have chosen to adopt the protocol and over the years it has become a
  9  * de-facto standard for labeled networking.        9  * de-facto standard for labeled networking.
 10  *                                                 10  *
 11  * Author: Paul Moore <paul.moore@hp.com>          11  * Author: Paul Moore <paul.moore@hp.com>
 12  *                                                 12  *
 13  */                                                13  */
 14                                                    14 
 15 /*                                                 15 /*
 16  * (c) Copyright Hewlett-Packard Development C     16  * (c) Copyright Hewlett-Packard Development Company, L.P., 2006
 17  *                                                 17  *
 18  * This program is free software;  you can red     18  * This program is free software;  you can redistribute it and/or modify
 19  * it under the terms of the GNU General Publi     19  * it under the terms of the GNU General Public License as published by
 20  * the Free Software Foundation; either versio     20  * the Free Software Foundation; either version 2 of the License, or
 21  * (at your option) any later version.             21  * (at your option) any later version.
 22  *                                                 22  *
 23  * This program is distributed in the hope tha     23  * This program is distributed in the hope that it will be useful,
 24  * but WITHOUT ANY WARRANTY;  without even the     24  * but WITHOUT ANY WARRANTY;  without even the implied warranty of
 25  * MERCHANTABILITY or FITNESS FOR A PARTICULAR     25  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
 26  * the GNU General Public License for more det     26  * the GNU General Public License for more details.
 27  *                                                 27  *
 28  * You should have received a copy of the GNU      28  * You should have received a copy of the GNU General Public License
 29  * along with this program;  if not, write to      29  * along with this program;  if not, write to the Free Software
 30  * Foundation, Inc., 59 Temple Place, Suite 33     30  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 31  *                                                 31  *
 32  */                                                32  */
 33                                                    33 
 34 #include <linux/init.h>                            34 #include <linux/init.h>
 35 #include <linux/types.h>                           35 #include <linux/types.h>
 36 #include <linux/rcupdate.h>                        36 #include <linux/rcupdate.h>
 37 #include <linux/list.h>                            37 #include <linux/list.h>
 38 #include <linux/spinlock.h>                        38 #include <linux/spinlock.h>
 39 #include <linux/string.h>                          39 #include <linux/string.h>
 40 #include <linux/jhash.h>                           40 #include <linux/jhash.h>
 41 #include <net/ip.h>                                41 #include <net/ip.h>
 42 #include <net/icmp.h>                              42 #include <net/icmp.h>
 43 #include <net/tcp.h>                               43 #include <net/tcp.h>
 44 #include <net/netlabel.h>                          44 #include <net/netlabel.h>
 45 #include <net/cipso_ipv4.h>                        45 #include <net/cipso_ipv4.h>
 46 #include <asm/atomic.h>                            46 #include <asm/atomic.h>
 47 #include <asm/bug.h>                               47 #include <asm/bug.h>
 48 #include <asm/unaligned.h>                         48 #include <asm/unaligned.h>
 49                                                    49 
 50 struct cipso_v4_domhsh_entry {                     50 struct cipso_v4_domhsh_entry {
 51         char *domain;                              51         char *domain;
 52         u32 valid;                                 52         u32 valid;
 53         struct list_head list;                     53         struct list_head list;
 54         struct rcu_head rcu;                       54         struct rcu_head rcu;
 55 };                                                 55 };
 56                                                    56 
 57 /* List of available DOI definitions */            57 /* List of available DOI definitions */
 58 /* XXX - Updates should be minimal so having a     58 /* XXX - Updates should be minimal so having a single lock for the
 59  * cipso_v4_doi_list and the cipso_v4_doi_list     59  * cipso_v4_doi_list and the cipso_v4_doi_list->dom_list should be
 60  * okay. */                                        60  * okay. */
 61 /* XXX - This currently assumes a minimal numb     61 /* XXX - This currently assumes a minimal number of different DOIs in use,
 62  * if in practice there are a lot of different     62  * if in practice there are a lot of different DOIs this list should
 63  * probably be turned into a hash table or som     63  * probably be turned into a hash table or something similar so we
 64  * can do quick lookups. */                        64  * can do quick lookups. */
 65 static DEFINE_SPINLOCK(cipso_v4_doi_list_lock)     65 static DEFINE_SPINLOCK(cipso_v4_doi_list_lock);
 66 static LIST_HEAD(cipso_v4_doi_list);               66 static LIST_HEAD(cipso_v4_doi_list);
 67                                                    67 
 68 /* Label mapping cache */                          68 /* Label mapping cache */
 69 int cipso_v4_cache_enabled = 1;                    69 int cipso_v4_cache_enabled = 1;
 70 int cipso_v4_cache_bucketsize = 10;                70 int cipso_v4_cache_bucketsize = 10;
 71 #define CIPSO_V4_CACHE_BUCKETBITS     7            71 #define CIPSO_V4_CACHE_BUCKETBITS     7
 72 #define CIPSO_V4_CACHE_BUCKETS        (1 << CI     72 #define CIPSO_V4_CACHE_BUCKETS        (1 << CIPSO_V4_CACHE_BUCKETBITS)
 73 #define CIPSO_V4_CACHE_REORDERLIMIT   10           73 #define CIPSO_V4_CACHE_REORDERLIMIT   10
 74 struct cipso_v4_map_cache_bkt {                    74 struct cipso_v4_map_cache_bkt {
 75         spinlock_t lock;                           75         spinlock_t lock;
 76         u32 size;                                  76         u32 size;
 77         struct list_head list;                     77         struct list_head list;
 78 };                                                 78 };
 79 struct cipso_v4_map_cache_entry {                  79 struct cipso_v4_map_cache_entry {
 80         u32 hash;                                  80         u32 hash;
 81         unsigned char *key;                        81         unsigned char *key;
 82         size_t key_len;                            82         size_t key_len;
 83                                                    83 
 84         struct netlbl_lsm_cache *lsm_data;         84         struct netlbl_lsm_cache *lsm_data;
 85                                                    85 
 86         u32 activity;                              86         u32 activity;
 87         struct list_head list;                     87         struct list_head list;
 88 };                                                 88 };
 89 static struct cipso_v4_map_cache_bkt *cipso_v4     89 static struct cipso_v4_map_cache_bkt *cipso_v4_cache = NULL;
 90                                                    90 
 91 /* Restricted bitmap (tag #1) flags */             91 /* Restricted bitmap (tag #1) flags */
 92 int cipso_v4_rbm_optfmt = 0;                       92 int cipso_v4_rbm_optfmt = 0;
 93 int cipso_v4_rbm_strictvalid = 1;                  93 int cipso_v4_rbm_strictvalid = 1;
 94                                                    94 
 95 /*                                                 95 /*
 96  * Protocol Constants                              96  * Protocol Constants
 97  */                                                97  */
 98                                                    98 
 99 /* Maximum size of the CIPSO IP option, derive     99 /* Maximum size of the CIPSO IP option, derived from the fact that the maximum
100  * IPv4 header size is 60 bytes and the base I    100  * IPv4 header size is 60 bytes and the base IPv4 header is 20 bytes long. */
101 #define CIPSO_V4_OPT_LEN_MAX          40          101 #define CIPSO_V4_OPT_LEN_MAX          40
102                                                   102 
103 /* Length of the base CIPSO option, this inclu    103 /* Length of the base CIPSO option, this includes the option type (1 byte), the
104  * option length (1 byte), and the DOI (4 byte    104  * option length (1 byte), and the DOI (4 bytes). */
105 #define CIPSO_V4_HDR_LEN              6           105 #define CIPSO_V4_HDR_LEN              6
106                                                   106 
107 /* Base length of the restrictive category bit    107 /* Base length of the restrictive category bitmap tag (tag #1). */
108 #define CIPSO_V4_TAG_RBM_BLEN         4           108 #define CIPSO_V4_TAG_RBM_BLEN         4
109                                                   109 
110 /* Base length of the enumerated category tag     110 /* Base length of the enumerated category tag (tag #2). */
111 #define CIPSO_V4_TAG_ENUM_BLEN        4           111 #define CIPSO_V4_TAG_ENUM_BLEN        4
112                                                   112 
113 /* Base length of the ranged categories bitmap    113 /* Base length of the ranged categories bitmap tag (tag #5). */
114 #define CIPSO_V4_TAG_RNG_BLEN         4           114 #define CIPSO_V4_TAG_RNG_BLEN         4
115 /* The maximum number of category ranges permi    115 /* The maximum number of category ranges permitted in the ranged category tag
116  * (tag #5).  You may note that the IETF draft    116  * (tag #5).  You may note that the IETF draft states that the maximum number
117  * of category ranges is 7, but if the low end    117  * of category ranges is 7, but if the low end of the last category range is
118  * zero then it is possibile to fit 8 category    118  * zero then it is possibile to fit 8 category ranges because the zero should
119  * be omitted. */                                 119  * be omitted. */
120 #define CIPSO_V4_TAG_RNG_CAT_MAX      8           120 #define CIPSO_V4_TAG_RNG_CAT_MAX      8
121                                                   121 
122 /*                                                122 /*
123  * Helper Functions                               123  * Helper Functions
124  */                                               124  */
125                                                   125 
126 /**                                               126 /**
127  * cipso_v4_bitmap_walk - Walk a bitmap lookin    127  * cipso_v4_bitmap_walk - Walk a bitmap looking for a bit
128  * @bitmap: the bitmap                            128  * @bitmap: the bitmap
129  * @bitmap_len: length in bits                    129  * @bitmap_len: length in bits
130  * @offset: starting offset                       130  * @offset: starting offset
131  * @state: if non-zero, look for a set (1) bit    131  * @state: if non-zero, look for a set (1) bit else look for a cleared (0) bit
132  *                                                132  *
133  * Description:                                   133  * Description:
134  * Starting at @offset, walk the bitmap from l    134  * Starting at @offset, walk the bitmap from left to right until either the
135  * desired bit is found or we reach the end.      135  * desired bit is found or we reach the end.  Return the bit offset, -1 if
136  * not found, or -2 if error.                     136  * not found, or -2 if error.
137  */                                               137  */
138 static int cipso_v4_bitmap_walk(const unsigned    138 static int cipso_v4_bitmap_walk(const unsigned char *bitmap,
139                                 u32 bitmap_len    139                                 u32 bitmap_len,
140                                 u32 offset,       140                                 u32 offset,
141                                 u8 state)         141                                 u8 state)
142 {                                                 142 {
143         u32 bit_spot;                             143         u32 bit_spot;
144         u32 byte_offset;                          144         u32 byte_offset;
145         unsigned char bitmask;                    145         unsigned char bitmask;
146         unsigned char byte;                       146         unsigned char byte;
147                                                   147 
148         /* gcc always rounds to zero when doin    148         /* gcc always rounds to zero when doing integer division */
149         byte_offset = offset / 8;                 149         byte_offset = offset / 8;
150         byte = bitmap[byte_offset];               150         byte = bitmap[byte_offset];
151         bit_spot = offset;                        151         bit_spot = offset;
152         bitmask = 0x80 >> (offset % 8);           152         bitmask = 0x80 >> (offset % 8);
153                                                   153 
154         while (bit_spot < bitmap_len) {           154         while (bit_spot < bitmap_len) {
155                 if ((state && (byte & bitmask)    155                 if ((state && (byte & bitmask) == bitmask) ||
156                     (state == 0 && (byte & bit    156                     (state == 0 && (byte & bitmask) == 0))
157                         return bit_spot;          157                         return bit_spot;
158                                                   158 
159                 bit_spot++;                       159                 bit_spot++;
160                 bitmask >>= 1;                    160                 bitmask >>= 1;
161                 if (bitmask == 0) {               161                 if (bitmask == 0) {
162                         byte = bitmap[++byte_o    162                         byte = bitmap[++byte_offset];
163                         bitmask = 0x80;           163                         bitmask = 0x80;
164                 }                                 164                 }
165         }                                         165         }
166                                                   166 
167         return -1;                                167         return -1;
168 }                                                 168 }
169                                                   169 
170 /**                                               170 /**
171  * cipso_v4_bitmap_setbit - Sets a single bit     171  * cipso_v4_bitmap_setbit - Sets a single bit in a bitmap
172  * @bitmap: the bitmap                            172  * @bitmap: the bitmap
173  * @bit: the bit                                  173  * @bit: the bit
174  * @state: if non-zero, set the bit (1) else c    174  * @state: if non-zero, set the bit (1) else clear the bit (0)
175  *                                                175  *
176  * Description:                                   176  * Description:
177  * Set a single bit in the bitmask.  Returns z    177  * Set a single bit in the bitmask.  Returns zero on success, negative values
178  * on error.                                      178  * on error.
179  */                                               179  */
180 static void cipso_v4_bitmap_setbit(unsigned ch    180 static void cipso_v4_bitmap_setbit(unsigned char *bitmap,
181                                    u32 bit,       181                                    u32 bit,
182                                    u8 state)      182                                    u8 state)
183 {                                                 183 {
184         u32 byte_spot;                            184         u32 byte_spot;
185         u8 bitmask;                               185         u8 bitmask;
186                                                   186 
187         /* gcc always rounds to zero when doin    187         /* gcc always rounds to zero when doing integer division */
188         byte_spot = bit / 8;                      188         byte_spot = bit / 8;
189         bitmask = 0x80 >> (bit % 8);              189         bitmask = 0x80 >> (bit % 8);
190         if (state)                                190         if (state)
191                 bitmap[byte_spot] |= bitmask;     191                 bitmap[byte_spot] |= bitmask;
192         else                                      192         else
193                 bitmap[byte_spot] &= ~bitmask;    193                 bitmap[byte_spot] &= ~bitmask;
194 }                                                 194 }
195                                                   195 
196 /**                                               196 /**
197  * cipso_v4_doi_domhsh_free - Frees a domain l    197  * cipso_v4_doi_domhsh_free - Frees a domain list entry
198  * @entry: the entry's RCU field                  198  * @entry: the entry's RCU field
199  *                                                199  *
200  * Description:                                   200  * Description:
201  * This function is designed to be used as a c    201  * This function is designed to be used as a callback to the call_rcu()
202  * function so that the memory allocated to a     202  * function so that the memory allocated to a domain list entry can be released
203  * safely.                                        203  * safely.
204  *                                                204  *
205  */                                               205  */
206 static void cipso_v4_doi_domhsh_free(struct rc    206 static void cipso_v4_doi_domhsh_free(struct rcu_head *entry)
207 {                                                 207 {
208         struct cipso_v4_domhsh_entry *ptr;        208         struct cipso_v4_domhsh_entry *ptr;
209                                                   209 
210         ptr = container_of(entry, struct cipso    210         ptr = container_of(entry, struct cipso_v4_domhsh_entry, rcu);
211         kfree(ptr->domain);                       211         kfree(ptr->domain);
212         kfree(ptr);                               212         kfree(ptr);
213 }                                                 213 }
214                                                   214 
215 /**                                               215 /**
216  * cipso_v4_cache_entry_free - Frees a cache e    216  * cipso_v4_cache_entry_free - Frees a cache entry
217  * @entry: the entry to free                      217  * @entry: the entry to free
218  *                                                218  *
219  * Description:                                   219  * Description:
220  * This function frees the memory associated w    220  * This function frees the memory associated with a cache entry including the
221  * LSM cache data if there are no longer any u    221  * LSM cache data if there are no longer any users, i.e. reference count == 0.
222  *                                                222  *
223  */                                               223  */
224 static void cipso_v4_cache_entry_free(struct c    224 static void cipso_v4_cache_entry_free(struct cipso_v4_map_cache_entry *entry)
225 {                                                 225 {
226         if (entry->lsm_data)                      226         if (entry->lsm_data)
227                 netlbl_secattr_cache_free(entr    227                 netlbl_secattr_cache_free(entry->lsm_data);
228         kfree(entry->key);                        228         kfree(entry->key);
229         kfree(entry);                             229         kfree(entry);
230 }                                                 230 }
231                                                   231 
232 /**                                               232 /**
233  * cipso_v4_map_cache_hash - Hashing function     233  * cipso_v4_map_cache_hash - Hashing function for the CIPSO cache
234  * @key: the hash key                             234  * @key: the hash key
235  * @key_len: the length of the key in bytes       235  * @key_len: the length of the key in bytes
236  *                                                236  *
237  * Description:                                   237  * Description:
238  * The CIPSO tag hashing function.  Returns a     238  * The CIPSO tag hashing function.  Returns a 32-bit hash value.
239  *                                                239  *
240  */                                               240  */
241 static u32 cipso_v4_map_cache_hash(const unsig    241 static u32 cipso_v4_map_cache_hash(const unsigned char *key, u32 key_len)
242 {                                                 242 {
243         return jhash(key, key_len, 0);            243         return jhash(key, key_len, 0);
244 }                                                 244 }
245                                                   245 
246 /*                                                246 /*
247  * Label Mapping Cache Functions                  247  * Label Mapping Cache Functions
248  */                                               248  */
249                                                   249 
250 /**                                               250 /**
251  * cipso_v4_cache_init - Initialize the CIPSO     251  * cipso_v4_cache_init - Initialize the CIPSO cache
252  *                                                252  *
253  * Description:                                   253  * Description:
254  * Initializes the CIPSO label mapping cache,     254  * Initializes the CIPSO label mapping cache, this function should be called
255  * before any of the other functions defined i    255  * before any of the other functions defined in this file.  Returns zero on
256  * success, negative values on error.             256  * success, negative values on error.
257  *                                                257  *
258  */                                               258  */
259 static int cipso_v4_cache_init(void)              259 static int cipso_v4_cache_init(void)
260 {                                                 260 {
261         u32 iter;                                 261         u32 iter;
262                                                   262 
263         cipso_v4_cache = kcalloc(CIPSO_V4_CACH    263         cipso_v4_cache = kcalloc(CIPSO_V4_CACHE_BUCKETS,
264                                  sizeof(struct    264                                  sizeof(struct cipso_v4_map_cache_bkt),
265                                  GFP_KERNEL);     265                                  GFP_KERNEL);
266         if (cipso_v4_cache == NULL)               266         if (cipso_v4_cache == NULL)
267                 return -ENOMEM;                   267                 return -ENOMEM;
268                                                   268 
269         for (iter = 0; iter < CIPSO_V4_CACHE_B    269         for (iter = 0; iter < CIPSO_V4_CACHE_BUCKETS; iter++) {
270                 spin_lock_init(&cipso_v4_cache    270                 spin_lock_init(&cipso_v4_cache[iter].lock);
271                 cipso_v4_cache[iter].size = 0;    271                 cipso_v4_cache[iter].size = 0;
272                 INIT_LIST_HEAD(&cipso_v4_cache    272                 INIT_LIST_HEAD(&cipso_v4_cache[iter].list);
273         }                                         273         }
274                                                   274 
275         return 0;                                 275         return 0;
276 }                                                 276 }
277                                                   277 
278 /**                                               278 /**
279  * cipso_v4_cache_invalidate - Invalidates the    279  * cipso_v4_cache_invalidate - Invalidates the current CIPSO cache
280  *                                                280  *
281  * Description:                                   281  * Description:
282  * Invalidates and frees any entries in the CI    282  * Invalidates and frees any entries in the CIPSO cache.  Returns zero on
283  * success and negative values on failure.        283  * success and negative values on failure.
284  *                                                284  *
285  */                                               285  */
286 void cipso_v4_cache_invalidate(void)              286 void cipso_v4_cache_invalidate(void)
287 {                                                 287 {
288         struct cipso_v4_map_cache_entry *entry    288         struct cipso_v4_map_cache_entry *entry, *tmp_entry;
289         u32 iter;                                 289         u32 iter;
290                                                   290 
291         for (iter = 0; iter < CIPSO_V4_CACHE_B    291         for (iter = 0; iter < CIPSO_V4_CACHE_BUCKETS; iter++) {
292                 spin_lock_bh(&cipso_v4_cache[i    292                 spin_lock_bh(&cipso_v4_cache[iter].lock);
293                 list_for_each_entry_safe(entry    293                 list_for_each_entry_safe(entry,
294                                          tmp_e    294                                          tmp_entry,
295                                          &cips    295                                          &cipso_v4_cache[iter].list, list) {
296                         list_del(&entry->list)    296                         list_del(&entry->list);
297                         cipso_v4_cache_entry_f    297                         cipso_v4_cache_entry_free(entry);
298                 }                                 298                 }
299                 cipso_v4_cache[iter].size = 0;    299                 cipso_v4_cache[iter].size = 0;
300                 spin_unlock_bh(&cipso_v4_cache    300                 spin_unlock_bh(&cipso_v4_cache[iter].lock);
301         }                                         301         }
302                                                   302 
303         return;                                   303         return;
304 }                                                 304 }
305                                                   305 
306 /**                                               306 /**
307  * cipso_v4_cache_check - Check the CIPSO cach    307  * cipso_v4_cache_check - Check the CIPSO cache for a label mapping
308  * @key: the buffer to check                      308  * @key: the buffer to check
309  * @key_len: buffer length in bytes               309  * @key_len: buffer length in bytes
310  * @secattr: the security attribute struct to     310  * @secattr: the security attribute struct to use
311  *                                                311  *
312  * Description:                                   312  * Description:
313  * This function checks the cache to see if a     313  * This function checks the cache to see if a label mapping already exists for
314  * the given key.  If there is a match then th    314  * the given key.  If there is a match then the cache is adjusted and the
315  * @secattr struct is populated with the corre    315  * @secattr struct is populated with the correct LSM security attributes.  The
316  * cache is adjusted in the following manner i    316  * cache is adjusted in the following manner if the entry is not already the
317  * first in the cache bucket:                     317  * first in the cache bucket:
318  *                                                318  *
319  *  1. The cache entry's activity counter is i    319  *  1. The cache entry's activity counter is incremented
320  *  2. The previous (higher ranking) entry's a    320  *  2. The previous (higher ranking) entry's activity counter is decremented
321  *  3. If the difference between the two activ    321  *  3. If the difference between the two activity counters is geater than
322  *     CIPSO_V4_CACHE_REORDERLIMIT the two ent    322  *     CIPSO_V4_CACHE_REORDERLIMIT the two entries are swapped
323  *                                                323  *
324  * Returns zero on success, -ENOENT for a cach    324  * Returns zero on success, -ENOENT for a cache miss, and other negative values
325  * on error.                                      325  * on error.
326  *                                                326  *
327  */                                               327  */
328 static int cipso_v4_cache_check(const unsigned    328 static int cipso_v4_cache_check(const unsigned char *key,
329                                 u32 key_len,      329                                 u32 key_len,
330                                 struct netlbl_    330                                 struct netlbl_lsm_secattr *secattr)
331 {                                                 331 {
332         u32 bkt;                                  332         u32 bkt;
333         struct cipso_v4_map_cache_entry *entry    333         struct cipso_v4_map_cache_entry *entry;
334         struct cipso_v4_map_cache_entry *prev_    334         struct cipso_v4_map_cache_entry *prev_entry = NULL;
335         u32 hash;                                 335         u32 hash;
336                                                   336 
337         if (!cipso_v4_cache_enabled)              337         if (!cipso_v4_cache_enabled)
338                 return -ENOENT;                   338                 return -ENOENT;
339                                                   339 
340         hash = cipso_v4_map_cache_hash(key, ke    340         hash = cipso_v4_map_cache_hash(key, key_len);
341         bkt = hash & (CIPSO_V4_CACHE_BUCKETBIT    341         bkt = hash & (CIPSO_V4_CACHE_BUCKETBITS - 1);
342         spin_lock_bh(&cipso_v4_cache[bkt].lock    342         spin_lock_bh(&cipso_v4_cache[bkt].lock);
343         list_for_each_entry(entry, &cipso_v4_c    343         list_for_each_entry(entry, &cipso_v4_cache[bkt].list, list) {
344                 if (entry->hash == hash &&        344                 if (entry->hash == hash &&
345                     entry->key_len == key_len     345                     entry->key_len == key_len &&
346                     memcmp(entry->key, key, ke    346                     memcmp(entry->key, key, key_len) == 0) {
347                         entry->activity += 1;     347                         entry->activity += 1;
348                         atomic_inc(&entry->lsm    348                         atomic_inc(&entry->lsm_data->refcount);
349                         secattr->cache = entry    349                         secattr->cache = entry->lsm_data;
350                         secattr->flags |= NETL    350                         secattr->flags |= NETLBL_SECATTR_CACHE;
351                         secattr->type = NETLBL    351                         secattr->type = NETLBL_NLTYPE_CIPSOV4;
352                         if (prev_entry == NULL    352                         if (prev_entry == NULL) {
353                                 spin_unlock_bh    353                                 spin_unlock_bh(&cipso_v4_cache[bkt].lock);
354                                 return 0;         354                                 return 0;
355                         }                         355                         }
356                                                   356 
357                         if (prev_entry->activi    357                         if (prev_entry->activity > 0)
358                                 prev_entry->ac    358                                 prev_entry->activity -= 1;
359                         if (entry->activity >     359                         if (entry->activity > prev_entry->activity &&
360                             entry->activity -     360                             entry->activity - prev_entry->activity >
361                             CIPSO_V4_CACHE_REO    361                             CIPSO_V4_CACHE_REORDERLIMIT) {
362                                 __list_del(ent    362                                 __list_del(entry->list.prev, entry->list.next);
363                                 __list_add(&en    363                                 __list_add(&entry->list,
364                                            pre    364                                            prev_entry->list.prev,
365                                            &pr    365                                            &prev_entry->list);
366                         }                         366                         }
367                                                   367 
368                         spin_unlock_bh(&cipso_    368                         spin_unlock_bh(&cipso_v4_cache[bkt].lock);
369                         return 0;                 369                         return 0;
370                 }                                 370                 }
371                 prev_entry = entry;               371                 prev_entry = entry;
372         }                                         372         }
373         spin_unlock_bh(&cipso_v4_cache[bkt].lo    373         spin_unlock_bh(&cipso_v4_cache[bkt].lock);
374                                                   374 
375         return -ENOENT;                           375         return -ENOENT;
376 }                                                 376 }
377                                                   377 
378 /**                                               378 /**
379  * cipso_v4_cache_add - Add an entry to the CI    379  * cipso_v4_cache_add - Add an entry to the CIPSO cache
380  * @skb: the packet                               380  * @skb: the packet
381  * @secattr: the packet's security attributes     381  * @secattr: the packet's security attributes
382  *                                                382  *
383  * Description:                                   383  * Description:
384  * Add a new entry into the CIPSO label mappin    384  * Add a new entry into the CIPSO label mapping cache.  Add the new entry to
385  * head of the cache bucket's list, if the cac    385  * head of the cache bucket's list, if the cache bucket is out of room remove
386  * the last entry in the list first.  It is im    386  * the last entry in the list first.  It is important to note that there is
387  * currently no checking for duplicate keys.      387  * currently no checking for duplicate keys.  Returns zero on success,
388  * negative values on failure.                    388  * negative values on failure.
389  *                                                389  *
390  */                                               390  */
391 int cipso_v4_cache_add(const struct sk_buff *s    391 int cipso_v4_cache_add(const struct sk_buff *skb,
392                        const struct netlbl_lsm    392                        const struct netlbl_lsm_secattr *secattr)
393 {                                                 393 {
394         int ret_val = -EPERM;                     394         int ret_val = -EPERM;
395         u32 bkt;                                  395         u32 bkt;
396         struct cipso_v4_map_cache_entry *entry    396         struct cipso_v4_map_cache_entry *entry = NULL;
397         struct cipso_v4_map_cache_entry *old_e    397         struct cipso_v4_map_cache_entry *old_entry = NULL;
398         unsigned char *cipso_ptr;                 398         unsigned char *cipso_ptr;
399         u32 cipso_ptr_len;                        399         u32 cipso_ptr_len;
400                                                   400 
401         if (!cipso_v4_cache_enabled || cipso_v    401         if (!cipso_v4_cache_enabled || cipso_v4_cache_bucketsize <= 0)
402                 return 0;                         402                 return 0;
403                                                   403 
404         cipso_ptr = CIPSO_V4_OPTPTR(skb);         404         cipso_ptr = CIPSO_V4_OPTPTR(skb);
405         cipso_ptr_len = cipso_ptr[1];             405         cipso_ptr_len = cipso_ptr[1];
406                                                   406 
407         entry = kzalloc(sizeof(*entry), GFP_AT    407         entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
408         if (entry == NULL)                        408         if (entry == NULL)
409                 return -ENOMEM;                   409                 return -ENOMEM;
410         entry->key = kmemdup(cipso_ptr, cipso_    410         entry->key = kmemdup(cipso_ptr, cipso_ptr_len, GFP_ATOMIC);
411         if (entry->key == NULL) {                 411         if (entry->key == NULL) {
412                 ret_val = -ENOMEM;                412                 ret_val = -ENOMEM;
413                 goto cache_add_failure;           413                 goto cache_add_failure;
414         }                                         414         }
415         entry->key_len = cipso_ptr_len;           415         entry->key_len = cipso_ptr_len;
416         entry->hash = cipso_v4_map_cache_hash(    416         entry->hash = cipso_v4_map_cache_hash(cipso_ptr, cipso_ptr_len);
417         atomic_inc(&secattr->cache->refcount);    417         atomic_inc(&secattr->cache->refcount);
418         entry->lsm_data = secattr->cache;         418         entry->lsm_data = secattr->cache;
419                                                   419 
420         bkt = entry->hash & (CIPSO_V4_CACHE_BU    420         bkt = entry->hash & (CIPSO_V4_CACHE_BUCKETBITS - 1);
421         spin_lock_bh(&cipso_v4_cache[bkt].lock    421         spin_lock_bh(&cipso_v4_cache[bkt].lock);
422         if (cipso_v4_cache[bkt].size < cipso_v    422         if (cipso_v4_cache[bkt].size < cipso_v4_cache_bucketsize) {
423                 list_add(&entry->list, &cipso_    423                 list_add(&entry->list, &cipso_v4_cache[bkt].list);
424                 cipso_v4_cache[bkt].size += 1;    424                 cipso_v4_cache[bkt].size += 1;
425         } else {                                  425         } else {
426                 old_entry = list_entry(cipso_v    426                 old_entry = list_entry(cipso_v4_cache[bkt].list.prev,
427                                        struct     427                                        struct cipso_v4_map_cache_entry, list);
428                 list_del(&old_entry->list);       428                 list_del(&old_entry->list);
429                 list_add(&entry->list, &cipso_    429                 list_add(&entry->list, &cipso_v4_cache[bkt].list);
430                 cipso_v4_cache_entry_free(old_    430                 cipso_v4_cache_entry_free(old_entry);
431         }                                         431         }
432         spin_unlock_bh(&cipso_v4_cache[bkt].lo    432         spin_unlock_bh(&cipso_v4_cache[bkt].lock);
433                                                   433 
434         return 0;                                 434         return 0;
435                                                   435 
436 cache_add_failure:                                436 cache_add_failure:
437         if (entry)                                437         if (entry)
438                 cipso_v4_cache_entry_free(entr    438                 cipso_v4_cache_entry_free(entry);
439         return ret_val;                           439         return ret_val;
440 }                                                 440 }
441                                                   441 
442 /*                                                442 /*
443  * DOI List Functions                             443  * DOI List Functions
444  */                                               444  */
445                                                   445 
446 /**                                               446 /**
447  * cipso_v4_doi_search - Searches for a DOI de    447  * cipso_v4_doi_search - Searches for a DOI definition
448  * @doi: the DOI to search for                    448  * @doi: the DOI to search for
449  *                                                449  *
450  * Description:                                   450  * Description:
451  * Search the DOI definition list for a DOI de    451  * Search the DOI definition list for a DOI definition with a DOI value that
452  * matches @doi.  The caller is responsibile f    452  * matches @doi.  The caller is responsibile for calling rcu_read_[un]lock().
453  * Returns a pointer to the DOI definition on     453  * Returns a pointer to the DOI definition on success and NULL on failure.
454  */                                               454  */
455 static struct cipso_v4_doi *cipso_v4_doi_searc    455 static struct cipso_v4_doi *cipso_v4_doi_search(u32 doi)
456 {                                                 456 {
457         struct cipso_v4_doi *iter;                457         struct cipso_v4_doi *iter;
458                                                   458 
459         list_for_each_entry_rcu(iter, &cipso_v    459         list_for_each_entry_rcu(iter, &cipso_v4_doi_list, list)
460                 if (iter->doi == doi && iter->    460                 if (iter->doi == doi && iter->valid)
461                         return iter;              461                         return iter;
462         return NULL;                              462         return NULL;
463 }                                                 463 }
464                                                   464 
465 /**                                               465 /**
466  * cipso_v4_doi_add - Add a new DOI to the CIP    466  * cipso_v4_doi_add - Add a new DOI to the CIPSO protocol engine
467  * @doi_def: the DOI structure                    467  * @doi_def: the DOI structure
468  *                                                468  *
469  * Description:                                   469  * Description:
470  * The caller defines a new DOI for use by the    470  * The caller defines a new DOI for use by the CIPSO engine and calls this
471  * function to add it to the list of acceptabl    471  * function to add it to the list of acceptable domains.  The caller must
472  * ensure that the mapping table specified in     472  * ensure that the mapping table specified in @doi_def->map meets all of the
473  * requirements of the mapping type (see cipso    473  * requirements of the mapping type (see cipso_ipv4.h for details).  Returns
474  * zero on success and non-zero on failure.       474  * zero on success and non-zero on failure.
475  *                                                475  *
476  */                                               476  */
477 int cipso_v4_doi_add(struct cipso_v4_doi *doi_    477 int cipso_v4_doi_add(struct cipso_v4_doi *doi_def)
478 {                                                 478 {
479         u32 iter;                                 479         u32 iter;
480                                                   480 
481         if (doi_def == NULL || doi_def->doi ==    481         if (doi_def == NULL || doi_def->doi == CIPSO_V4_DOI_UNKNOWN)
482                 return -EINVAL;                   482                 return -EINVAL;
483         for (iter = 0; iter < CIPSO_V4_TAG_MAX    483         for (iter = 0; iter < CIPSO_V4_TAG_MAXCNT; iter++) {
484                 switch (doi_def->tags[iter]) {    484                 switch (doi_def->tags[iter]) {
485                 case CIPSO_V4_TAG_RBITMAP:        485                 case CIPSO_V4_TAG_RBITMAP:
486                         break;                    486                         break;
487                 case CIPSO_V4_TAG_RANGE:          487                 case CIPSO_V4_TAG_RANGE:
488                         if (doi_def->type != C    488                         if (doi_def->type != CIPSO_V4_MAP_PASS)
489                                 return -EINVAL    489                                 return -EINVAL;
490                         break;                    490                         break;
491                 case CIPSO_V4_TAG_INVALID:        491                 case CIPSO_V4_TAG_INVALID:
492                         if (iter == 0)            492                         if (iter == 0)
493                                 return -EINVAL    493                                 return -EINVAL;
494                         break;                    494                         break;
495                 case CIPSO_V4_TAG_ENUM:           495                 case CIPSO_V4_TAG_ENUM:
496                         if (doi_def->type != C    496                         if (doi_def->type != CIPSO_V4_MAP_PASS)
497                                 return -EINVAL    497                                 return -EINVAL;
498                         break;                    498                         break;
499                 default:                          499                 default:
500                         return -EINVAL;           500                         return -EINVAL;
501                 }                                 501                 }
502         }                                         502         }
503                                                   503 
504         doi_def->valid = 1;                       504         doi_def->valid = 1;
505         INIT_RCU_HEAD(&doi_def->rcu);             505         INIT_RCU_HEAD(&doi_def->rcu);
506         INIT_LIST_HEAD(&doi_def->dom_list);       506         INIT_LIST_HEAD(&doi_def->dom_list);
507                                                   507 
508         spin_lock(&cipso_v4_doi_list_lock);       508         spin_lock(&cipso_v4_doi_list_lock);
509         if (cipso_v4_doi_search(doi_def->doi)     509         if (cipso_v4_doi_search(doi_def->doi) != NULL)
510                 goto doi_add_failure;             510                 goto doi_add_failure;
511         list_add_tail_rcu(&doi_def->list, &cip    511         list_add_tail_rcu(&doi_def->list, &cipso_v4_doi_list);
512         spin_unlock(&cipso_v4_doi_list_lock);     512         spin_unlock(&cipso_v4_doi_list_lock);
513                                                   513 
514         return 0;                                 514         return 0;
515                                                   515 
516 doi_add_failure:                                  516 doi_add_failure:
517         spin_unlock(&cipso_v4_doi_list_lock);     517         spin_unlock(&cipso_v4_doi_list_lock);
518         return -EEXIST;                           518         return -EEXIST;
519 }                                                 519 }
520                                                   520 
521 /**                                               521 /**
522  * cipso_v4_doi_remove - Remove an existing DO    522  * cipso_v4_doi_remove - Remove an existing DOI from the CIPSO protocol engine
523  * @doi: the DOI value                            523  * @doi: the DOI value
524  * @audit_secid: the LSM secid to use in the a    524  * @audit_secid: the LSM secid to use in the audit message
525  * @callback: the DOI cleanup/free callback       525  * @callback: the DOI cleanup/free callback
526  *                                                526  *
527  * Description:                                   527  * Description:
528  * Removes a DOI definition from the CIPSO eng    528  * Removes a DOI definition from the CIPSO engine, @callback is called to
529  * free any memory.  The NetLabel routines wil    529  * free any memory.  The NetLabel routines will be called to release their own
530  * LSM domain mappings as well as our own doma    530  * LSM domain mappings as well as our own domain list.  Returns zero on
531  * success and negative values on failure.        531  * success and negative values on failure.
532  *                                                532  *
533  */                                               533  */
534 int cipso_v4_doi_remove(u32 doi,                  534 int cipso_v4_doi_remove(u32 doi,
535                         struct netlbl_audit *a    535                         struct netlbl_audit *audit_info,
536                         void (*callback) (stru    536                         void (*callback) (struct rcu_head * head))
537 {                                                 537 {
538         struct cipso_v4_doi *doi_def;             538         struct cipso_v4_doi *doi_def;
539         struct cipso_v4_domhsh_entry *dom_iter    539         struct cipso_v4_domhsh_entry *dom_iter;
540                                                   540 
541         spin_lock(&cipso_v4_doi_list_lock);       541         spin_lock(&cipso_v4_doi_list_lock);
542         doi_def = cipso_v4_doi_search(doi);       542         doi_def = cipso_v4_doi_search(doi);
543         if (doi_def != NULL) {                    543         if (doi_def != NULL) {
544                 doi_def->valid = 0;               544                 doi_def->valid = 0;
545                 list_del_rcu(&doi_def->list);     545                 list_del_rcu(&doi_def->list);
546                 spin_unlock(&cipso_v4_doi_list    546                 spin_unlock(&cipso_v4_doi_list_lock);
547                 rcu_read_lock();                  547                 rcu_read_lock();
548                 list_for_each_entry_rcu(dom_it    548                 list_for_each_entry_rcu(dom_iter, &doi_def->dom_list, list)
549                         if (dom_iter->valid)      549                         if (dom_iter->valid)
550                                 netlbl_cfg_map    550                                 netlbl_cfg_map_del(dom_iter->domain,
551                                                   551                                                    audit_info);
552                 rcu_read_unlock();                552                 rcu_read_unlock();
553                 cipso_v4_cache_invalidate();      553                 cipso_v4_cache_invalidate();
554                 call_rcu(&doi_def->rcu, callba    554                 call_rcu(&doi_def->rcu, callback);
555                 return 0;                         555                 return 0;
556         }                                         556         }
557         spin_unlock(&cipso_v4_doi_list_lock);     557         spin_unlock(&cipso_v4_doi_list_lock);
558                                                   558 
559         return -ENOENT;                           559         return -ENOENT;
560 }                                                 560 }
561                                                   561 
562 /**                                               562 /**
563  * cipso_v4_doi_getdef - Returns a pointer to     563  * cipso_v4_doi_getdef - Returns a pointer to a valid DOI definition
564  * @doi: the DOI value                            564  * @doi: the DOI value
565  *                                                565  *
566  * Description:                                   566  * Description:
567  * Searches for a valid DOI definition and if     567  * Searches for a valid DOI definition and if one is found it is returned to
568  * the caller.  Otherwise NULL is returned.  T    568  * the caller.  Otherwise NULL is returned.  The caller must ensure that
569  * rcu_read_lock() is held while accessing the    569  * rcu_read_lock() is held while accessing the returned definition.
570  *                                                570  *
571  */                                               571  */
572 struct cipso_v4_doi *cipso_v4_doi_getdef(u32 d    572 struct cipso_v4_doi *cipso_v4_doi_getdef(u32 doi)
573 {                                                 573 {
574         return cipso_v4_doi_search(doi);          574         return cipso_v4_doi_search(doi);
575 }                                                 575 }
576                                                   576 
577 /**                                               577 /**
578  * cipso_v4_doi_walk - Iterate through the DOI    578  * cipso_v4_doi_walk - Iterate through the DOI definitions
579  * @skip_cnt: skip past this number of DOI def    579  * @skip_cnt: skip past this number of DOI definitions, updated
580  * @callback: callback for each DOI definition    580  * @callback: callback for each DOI definition
581  * @cb_arg: argument for the callback function    581  * @cb_arg: argument for the callback function
582  *                                                582  *
583  * Description:                                   583  * Description:
584  * Iterate over the DOI definition list, skipp    584  * Iterate over the DOI definition list, skipping the first @skip_cnt entries.
585  * For each entry call @callback, if @callback    585  * For each entry call @callback, if @callback returns a negative value stop
586  * 'walking' through the list and return.  Upd    586  * 'walking' through the list and return.  Updates the value in @skip_cnt upon
587  * return.  Returns zero on success, negative     587  * return.  Returns zero on success, negative values on failure.
588  *                                                588  *
589  */                                               589  */
590 int cipso_v4_doi_walk(u32 *skip_cnt,              590 int cipso_v4_doi_walk(u32 *skip_cnt,
591                      int (*callback) (struct c    591                      int (*callback) (struct cipso_v4_doi *doi_def, void *arg),
592                      void *cb_arg)                592                      void *cb_arg)
593 {                                                 593 {
594         int ret_val = -ENOENT;                    594         int ret_val = -ENOENT;
595         u32 doi_cnt = 0;                          595         u32 doi_cnt = 0;
596         struct cipso_v4_doi *iter_doi;            596         struct cipso_v4_doi *iter_doi;
597                                                   597 
598         rcu_read_lock();                          598         rcu_read_lock();
599         list_for_each_entry_rcu(iter_doi, &cip    599         list_for_each_entry_rcu(iter_doi, &cipso_v4_doi_list, list)
600                 if (iter_doi->valid) {            600                 if (iter_doi->valid) {
601                         if (doi_cnt++ < *skip_    601                         if (doi_cnt++ < *skip_cnt)
602                                 continue;         602                                 continue;
603                         ret_val = callback(ite    603                         ret_val = callback(iter_doi, cb_arg);
604                         if (ret_val < 0) {        604                         if (ret_val < 0) {
605                                 doi_cnt--;        605                                 doi_cnt--;
606                                 goto doi_walk_    606                                 goto doi_walk_return;
607                         }                         607                         }
608                 }                                 608                 }
609                                                   609 
610 doi_walk_return:                                  610 doi_walk_return:
611         rcu_read_unlock();                        611         rcu_read_unlock();
612         *skip_cnt = doi_cnt;                      612         *skip_cnt = doi_cnt;
613         return ret_val;                           613         return ret_val;
614 }                                                 614 }
615                                                   615 
616 /**                                               616 /**
617  * cipso_v4_doi_domhsh_add - Adds a domain ent    617  * cipso_v4_doi_domhsh_add - Adds a domain entry to a DOI definition
618  * @doi_def: the DOI definition                   618  * @doi_def: the DOI definition
619  * @domain: the domain to add                     619  * @domain: the domain to add
620  *                                                620  *
621  * Description:                                   621  * Description:
622  * Adds the @domain to the DOI specified by @d    622  * Adds the @domain to the DOI specified by @doi_def, this function
623  * should only be called by external functions    623  * should only be called by external functions (i.e. NetLabel).  This function
624  * does allocate memory.  Returns zero on succ    624  * does allocate memory.  Returns zero on success, negative values on failure.
625  *                                                625  *
626  */                                               626  */
627 int cipso_v4_doi_domhsh_add(struct cipso_v4_do    627 int cipso_v4_doi_domhsh_add(struct cipso_v4_doi *doi_def, const char *domain)
628 {                                                 628 {
629         struct cipso_v4_domhsh_entry *iter;       629         struct cipso_v4_domhsh_entry *iter;
630         struct cipso_v4_domhsh_entry *new_dom;    630         struct cipso_v4_domhsh_entry *new_dom;
631                                                   631 
632         new_dom = kzalloc(sizeof(*new_dom), GF    632         new_dom = kzalloc(sizeof(*new_dom), GFP_KERNEL);
633         if (new_dom == NULL)                      633         if (new_dom == NULL)
634                 return -ENOMEM;                   634                 return -ENOMEM;
635         if (domain) {                             635         if (domain) {
636                 new_dom->domain = kstrdup(doma    636                 new_dom->domain = kstrdup(domain, GFP_KERNEL);
637                 if (new_dom->domain == NULL) {    637                 if (new_dom->domain == NULL) {
638                         kfree(new_dom);           638                         kfree(new_dom);
639                         return -ENOMEM;           639                         return -ENOMEM;
640                 }                                 640                 }
641         }                                         641         }
642         new_dom->valid = 1;                       642         new_dom->valid = 1;
643         INIT_RCU_HEAD(&new_dom->rcu);             643         INIT_RCU_HEAD(&new_dom->rcu);
644                                                   644 
645         spin_lock(&cipso_v4_doi_list_lock);       645         spin_lock(&cipso_v4_doi_list_lock);
646         list_for_each_entry(iter, &doi_def->do    646         list_for_each_entry(iter, &doi_def->dom_list, list)
647                 if (iter->valid &&                647                 if (iter->valid &&
648                     ((domain != NULL && iter->    648                     ((domain != NULL && iter->domain != NULL &&
649                       strcmp(iter->domain, dom    649                       strcmp(iter->domain, domain) == 0) ||
650                      (domain == NULL && iter->    650                      (domain == NULL && iter->domain == NULL))) {
651                         spin_unlock(&cipso_v4_    651                         spin_unlock(&cipso_v4_doi_list_lock);
652                         kfree(new_dom->domain)    652                         kfree(new_dom->domain);
653                         kfree(new_dom);           653                         kfree(new_dom);
654                         return -EEXIST;           654                         return -EEXIST;
655                 }                                 655                 }
656         list_add_tail_rcu(&new_dom->list, &doi    656         list_add_tail_rcu(&new_dom->list, &doi_def->dom_list);
657         spin_unlock(&cipso_v4_doi_list_lock);     657         spin_unlock(&cipso_v4_doi_list_lock);
658                                                   658 
659         return 0;                                 659         return 0;
660 }                                                 660 }
661                                                   661 
662 /**                                               662 /**
663  * cipso_v4_doi_domhsh_remove - Removes a doma    663  * cipso_v4_doi_domhsh_remove - Removes a domain entry from a DOI definition
664  * @doi_def: the DOI definition                   664  * @doi_def: the DOI definition
665  * @domain: the domain to remove                  665  * @domain: the domain to remove
666  *                                                666  *
667  * Description:                                   667  * Description:
668  * Removes the @domain from the DOI specified     668  * Removes the @domain from the DOI specified by @doi_def, this function
669  * should only be called by external functions    669  * should only be called by external functions (i.e. NetLabel).   Returns zero
670  * on success and negative values on error.       670  * on success and negative values on error.
671  *                                                671  *
672  */                                               672  */
673 int cipso_v4_doi_domhsh_remove(struct cipso_v4    673 int cipso_v4_doi_domhsh_remove(struct cipso_v4_doi *doi_def,
674                                const char *dom    674                                const char *domain)
675 {                                                 675 {
676         struct cipso_v4_domhsh_entry *iter;       676         struct cipso_v4_domhsh_entry *iter;
677                                                   677 
678         spin_lock(&cipso_v4_doi_list_lock);       678         spin_lock(&cipso_v4_doi_list_lock);
679         list_for_each_entry(iter, &doi_def->do    679         list_for_each_entry(iter, &doi_def->dom_list, list)
680                 if (iter->valid &&                680                 if (iter->valid &&
681                     ((domain != NULL && iter->    681                     ((domain != NULL && iter->domain != NULL &&
682                       strcmp(iter->domain, dom    682                       strcmp(iter->domain, domain) == 0) ||
683                      (domain == NULL && iter->    683                      (domain == NULL && iter->domain == NULL))) {
684                         iter->valid = 0;          684                         iter->valid = 0;
685                         list_del_rcu(&iter->li    685                         list_del_rcu(&iter->list);
686                         spin_unlock(&cipso_v4_    686                         spin_unlock(&cipso_v4_doi_list_lock);
687                         call_rcu(&iter->rcu, c    687                         call_rcu(&iter->rcu, cipso_v4_doi_domhsh_free);
688                         return 0;                 688                         return 0;
689                 }                                 689                 }
690         spin_unlock(&cipso_v4_doi_list_lock);     690         spin_unlock(&cipso_v4_doi_list_lock);
691                                                   691 
692         return -ENOENT;                           692         return -ENOENT;
693 }                                                 693 }
694                                                   694 
695 /*                                                695 /*
696  * Label Mapping Functions                        696  * Label Mapping Functions
697  */                                               697  */
698                                                   698 
699 /**                                               699 /**
700  * cipso_v4_map_lvl_valid - Checks to see if t    700  * cipso_v4_map_lvl_valid - Checks to see if the given level is understood
701  * @doi_def: the DOI definition                   701  * @doi_def: the DOI definition
702  * @level: the level to check                     702  * @level: the level to check
703  *                                                703  *
704  * Description:                                   704  * Description:
705  * Checks the given level against the given DO    705  * Checks the given level against the given DOI definition and returns a
706  * negative value if the level does not have a    706  * negative value if the level does not have a valid mapping and a zero value
707  * if the level is defined by the DOI.            707  * if the level is defined by the DOI.
708  *                                                708  *
709  */                                               709  */
710 static int cipso_v4_map_lvl_valid(const struct    710 static int cipso_v4_map_lvl_valid(const struct cipso_v4_doi *doi_def, u8 level)
711 {                                                 711 {
712         switch (doi_def->type) {                  712         switch (doi_def->type) {
713         case CIPSO_V4_MAP_PASS:                   713         case CIPSO_V4_MAP_PASS:
714                 return 0;                         714                 return 0;
715         case CIPSO_V4_MAP_STD:                    715         case CIPSO_V4_MAP_STD:
716                 if (doi_def->map.std->lvl.cips    716                 if (doi_def->map.std->lvl.cipso[level] < CIPSO_V4_INV_LVL)
717                         return 0;                 717                         return 0;
718                 break;                            718                 break;
719         }                                         719         }
720                                                   720 
721         return -EFAULT;                           721         return -EFAULT;
722 }                                                 722 }
723                                                   723 
724 /**                                               724 /**
725  * cipso_v4_map_lvl_hton - Perform a level map    725  * cipso_v4_map_lvl_hton - Perform a level mapping from the host to the network
726  * @doi_def: the DOI definition                   726  * @doi_def: the DOI definition
727  * @host_lvl: the host MLS level                  727  * @host_lvl: the host MLS level
728  * @net_lvl: the network/CIPSO MLS level          728  * @net_lvl: the network/CIPSO MLS level
729  *                                                729  *
730  * Description:                                   730  * Description:
731  * Perform a label mapping to translate a loca    731  * Perform a label mapping to translate a local MLS level to the correct
732  * CIPSO level using the given DOI definition.    732  * CIPSO level using the given DOI definition.  Returns zero on success,
733  * negative values otherwise.                     733  * negative values otherwise.
734  *                                                734  *
735  */                                               735  */
736 static int cipso_v4_map_lvl_hton(const struct     736 static int cipso_v4_map_lvl_hton(const struct cipso_v4_doi *doi_def,
737                                  u32 host_lvl,    737                                  u32 host_lvl,
738                                  u32 *net_lvl)    738                                  u32 *net_lvl)
739 {                                                 739 {
740         switch (doi_def->type) {                  740         switch (doi_def->type) {
741         case CIPSO_V4_MAP_PASS:                   741         case CIPSO_V4_MAP_PASS:
742                 *net_lvl = host_lvl;              742                 *net_lvl = host_lvl;
743                 return 0;                         743                 return 0;
744         case CIPSO_V4_MAP_STD:                    744         case CIPSO_V4_MAP_STD:
745                 if (host_lvl < doi_def->map.st    745                 if (host_lvl < doi_def->map.std->lvl.local_size &&
746                     doi_def->map.std->lvl.loca    746                     doi_def->map.std->lvl.local[host_lvl] < CIPSO_V4_INV_LVL) {
747                         *net_lvl = doi_def->ma    747                         *net_lvl = doi_def->map.std->lvl.local[host_lvl];
748                         return 0;                 748                         return 0;
749                 }                                 749                 }
750                 return -EPERM;                    750                 return -EPERM;
751         }                                         751         }
752                                                   752 
753         return -EINVAL;                           753         return -EINVAL;
754 }                                                 754 }
755                                                   755 
756 /**                                               756 /**
757  * cipso_v4_map_lvl_ntoh - Perform a level map    757  * cipso_v4_map_lvl_ntoh - Perform a level mapping from the network to the host
758  * @doi_def: the DOI definition                   758  * @doi_def: the DOI definition
759  * @net_lvl: the network/CIPSO MLS level          759  * @net_lvl: the network/CIPSO MLS level
760  * @host_lvl: the host MLS level                  760  * @host_lvl: the host MLS level
761  *                                                761  *
762  * Description:                                   762  * Description:
763  * Perform a label mapping to translate a CIPS    763  * Perform a label mapping to translate a CIPSO level to the correct local MLS
764  * level using the given DOI definition.  Retu    764  * level using the given DOI definition.  Returns zero on success, negative
765  * values otherwise.                              765  * values otherwise.
766  *                                                766  *
767  */                                               767  */
768 static int cipso_v4_map_lvl_ntoh(const struct     768 static int cipso_v4_map_lvl_ntoh(const struct cipso_v4_doi *doi_def,
769                                  u32 net_lvl,     769                                  u32 net_lvl,
770                                  u32 *host_lvl    770                                  u32 *host_lvl)
771 {                                                 771 {
772         struct cipso_v4_std_map_tbl *map_tbl;     772         struct cipso_v4_std_map_tbl *map_tbl;
773                                                   773 
774         switch (doi_def->type) {                  774         switch (doi_def->type) {
775         case CIPSO_V4_MAP_PASS:                   775         case CIPSO_V4_MAP_PASS:
776                 *host_lvl = net_lvl;              776                 *host_lvl = net_lvl;
777                 return 0;                         777                 return 0;
778         case CIPSO_V4_MAP_STD:                    778         case CIPSO_V4_MAP_STD:
779                 map_tbl = doi_def->map.std;       779                 map_tbl = doi_def->map.std;
780                 if (net_lvl < map_tbl->lvl.cip    780                 if (net_lvl < map_tbl->lvl.cipso_size &&
781                     map_tbl->lvl.cipso[net_lvl    781                     map_tbl->lvl.cipso[net_lvl] < CIPSO_V4_INV_LVL) {
782                         *host_lvl = doi_def->m    782                         *host_lvl = doi_def->map.std->lvl.cipso[net_lvl];
783                         return 0;                 783                         return 0;
784                 }                                 784                 }
785                 return -EPERM;                    785                 return -EPERM;
786         }                                         786         }
787                                                   787 
788         return -EINVAL;                           788         return -EINVAL;
789 }                                                 789 }
790                                                   790 
791 /**                                               791 /**
792  * cipso_v4_map_cat_rbm_valid - Checks to see     792  * cipso_v4_map_cat_rbm_valid - Checks to see if the category bitmap is valid
793  * @doi_def: the DOI definition                   793  * @doi_def: the DOI definition
794  * @bitmap: category bitmap                       794  * @bitmap: category bitmap
795  * @bitmap_len: bitmap length in bytes            795  * @bitmap_len: bitmap length in bytes
796  *                                                796  *
797  * Description:                                   797  * Description:
798  * Checks the given category bitmap against th    798  * Checks the given category bitmap against the given DOI definition and
799  * returns a negative value if any of the cate    799  * returns a negative value if any of the categories in the bitmap do not have
800  * a valid mapping and a zero value if all of     800  * a valid mapping and a zero value if all of the categories are valid.
801  *                                                801  *
802  */                                               802  */
803 static int cipso_v4_map_cat_rbm_valid(const st    803 static int cipso_v4_map_cat_rbm_valid(const struct cipso_v4_doi *doi_def,
804                                       const un    804                                       const unsigned char *bitmap,
805                                       u32 bitm    805                                       u32 bitmap_len)
806 {                                                 806 {
807         int cat = -1;                             807         int cat = -1;
808         u32 bitmap_len_bits = bitmap_len * 8;     808         u32 bitmap_len_bits = bitmap_len * 8;
809         u32 cipso_cat_size;                       809         u32 cipso_cat_size;
810         u32 *cipso_array;                         810         u32 *cipso_array;
811                                                   811 
812         switch (doi_def->type) {                  812         switch (doi_def->type) {
813         case CIPSO_V4_MAP_PASS:                   813         case CIPSO_V4_MAP_PASS:
814                 return 0;                         814                 return 0;
815         case CIPSO_V4_MAP_STD:                    815         case CIPSO_V4_MAP_STD:
816                 cipso_cat_size = doi_def->map.    816                 cipso_cat_size = doi_def->map.std->cat.cipso_size;
817                 cipso_array = doi_def->map.std    817                 cipso_array = doi_def->map.std->cat.cipso;
818                 for (;;) {                        818                 for (;;) {
819                         cat = cipso_v4_bitmap_    819                         cat = cipso_v4_bitmap_walk(bitmap,
820                                                   820                                                    bitmap_len_bits,
821                                                   821                                                    cat + 1,
822                                                   822                                                    1);
823                         if (cat < 0)              823                         if (cat < 0)
824                                 break;            824                                 break;
825                         if (cat >= cipso_cat_s    825                         if (cat >= cipso_cat_size ||
826                             cipso_array[cat] >    826                             cipso_array[cat] >= CIPSO_V4_INV_CAT)
827                                 return -EFAULT    827                                 return -EFAULT;
828                 }                                 828                 }
829                                                   829 
830                 if (cat == -1)                    830                 if (cat == -1)
831                         return 0;                 831                         return 0;
832                 break;                            832                 break;
833         }                                         833         }
834                                                   834 
835         return -EFAULT;                           835         return -EFAULT;
836 }                                                 836 }
837                                                   837 
838 /**                                               838 /**
839  * cipso_v4_map_cat_rbm_hton - Perform a categ    839  * cipso_v4_map_cat_rbm_hton - Perform a category mapping from host to network
840  * @doi_def: the DOI definition                   840  * @doi_def: the DOI definition
841  * @secattr: the security attributes              841  * @secattr: the security attributes
842  * @net_cat: the zero'd out category bitmap in    842  * @net_cat: the zero'd out category bitmap in network/CIPSO format
843  * @net_cat_len: the length of the CIPSO bitma    843  * @net_cat_len: the length of the CIPSO bitmap in bytes
844  *                                                844  *
845  * Description:                                   845  * Description:
846  * Perform a label mapping to translate a loca    846  * Perform a label mapping to translate a local MLS category bitmap to the
847  * correct CIPSO bitmap using the given DOI de    847  * correct CIPSO bitmap using the given DOI definition.  Returns the minimum
848  * size in bytes of the network bitmap on succ    848  * size in bytes of the network bitmap on success, negative values otherwise.
849  *                                                849  *
850  */                                               850  */
851 static int cipso_v4_map_cat_rbm_hton(const str    851 static int cipso_v4_map_cat_rbm_hton(const struct cipso_v4_doi *doi_def,
852                                      const str    852                                      const struct netlbl_lsm_secattr *secattr,
853                                      unsigned     853                                      unsigned char *net_cat,
854                                      u32 net_c    854                                      u32 net_cat_len)
855 {                                                 855 {
856         int host_spot = -1;                       856         int host_spot = -1;
857         u32 net_spot = CIPSO_V4_INV_CAT;          857         u32 net_spot = CIPSO_V4_INV_CAT;
858         u32 net_spot_max = 0;                     858         u32 net_spot_max = 0;
859         u32 net_clen_bits = net_cat_len * 8;      859         u32 net_clen_bits = net_cat_len * 8;
860         u32 host_cat_size = 0;                    860         u32 host_cat_size = 0;
861         u32 *host_cat_array = NULL;               861         u32 *host_cat_array = NULL;
862                                                   862 
863         if (doi_def->type == CIPSO_V4_MAP_STD)    863         if (doi_def->type == CIPSO_V4_MAP_STD) {
864                 host_cat_size = doi_def->map.s    864                 host_cat_size = doi_def->map.std->cat.local_size;
865                 host_cat_array = doi_def->map.    865                 host_cat_array = doi_def->map.std->cat.local;
866         }                                         866         }
867                                                   867 
868         for (;;) {                                868         for (;;) {
869                 host_spot = netlbl_secattr_cat    869                 host_spot = netlbl_secattr_catmap_walk(secattr->attr.mls.cat,
870                                                   870                                                        host_spot + 1);
871                 if (host_spot < 0)                871                 if (host_spot < 0)
872                         break;                    872                         break;
873                                                   873 
874                 switch (doi_def->type) {          874                 switch (doi_def->type) {
875                 case CIPSO_V4_MAP_PASS:           875                 case CIPSO_V4_MAP_PASS:
876                         net_spot = host_spot;     876                         net_spot = host_spot;
877                         break;                    877                         break;
878                 case CIPSO_V4_MAP_STD:            878                 case CIPSO_V4_MAP_STD:
879                         if (host_spot >= host_    879                         if (host_spot >= host_cat_size)
880                                 return -EPERM;    880                                 return -EPERM;
881                         net_spot = host_cat_ar    881                         net_spot = host_cat_array[host_spot];
882                         if (net_spot >= CIPSO_    882                         if (net_spot >= CIPSO_V4_INV_CAT)
883                                 return -EPERM;    883                                 return -EPERM;
884                         break;                    884                         break;
885                 }                                 885                 }
886                 if (net_spot >= net_clen_bits)    886                 if (net_spot >= net_clen_bits)
887                         return -ENOSPC;           887                         return -ENOSPC;
888                 cipso_v4_bitmap_setbit(net_cat    888                 cipso_v4_bitmap_setbit(net_cat, net_spot, 1);
889                                                   889 
890                 if (net_spot > net_spot_max)      890                 if (net_spot > net_spot_max)
891                         net_spot_max = net_spo    891                         net_spot_max = net_spot;
892         }                                         892         }
893                                                   893 
894         if (++net_spot_max % 8)                   894         if (++net_spot_max % 8)
895                 return net_spot_max / 8 + 1;      895                 return net_spot_max / 8 + 1;
896         return net_spot_max / 8;                  896         return net_spot_max / 8;
897 }                                                 897 }
898                                                   898 
899 /**                                               899 /**
900  * cipso_v4_map_cat_rbm_ntoh - Perform a categ    900  * cipso_v4_map_cat_rbm_ntoh - Perform a category mapping from network to host
901  * @doi_def: the DOI definition                   901  * @doi_def: the DOI definition
902  * @net_cat: the category bitmap in network/CI    902  * @net_cat: the category bitmap in network/CIPSO format
903  * @net_cat_len: the length of the CIPSO bitma    903  * @net_cat_len: the length of the CIPSO bitmap in bytes
904  * @secattr: the security attributes              904  * @secattr: the security attributes
905  *                                                905  *
906  * Description:                                   906  * Description:
907  * Perform a label mapping to translate a CIPS    907  * Perform a label mapping to translate a CIPSO bitmap to the correct local
908  * MLS category bitmap using the given DOI def    908  * MLS category bitmap using the given DOI definition.  Returns zero on
909  * success, negative values on failure.           909  * success, negative values on failure.
910  *                                                910  *
911  */                                               911  */
912 static int cipso_v4_map_cat_rbm_ntoh(const str    912 static int cipso_v4_map_cat_rbm_ntoh(const struct cipso_v4_doi *doi_def,
913                                      const uns    913                                      const unsigned char *net_cat,
914                                      u32 net_c    914                                      u32 net_cat_len,
915                                      struct ne    915                                      struct netlbl_lsm_secattr *secattr)
916 {                                                 916 {
917         int ret_val;                              917         int ret_val;
918         int net_spot = -1;                        918         int net_spot = -1;
919         u32 host_spot = CIPSO_V4_INV_CAT;         919         u32 host_spot = CIPSO_V4_INV_CAT;
920         u32 net_clen_bits = net_cat_len * 8;      920         u32 net_clen_bits = net_cat_len * 8;
921         u32 net_cat_size = 0;                     921         u32 net_cat_size = 0;
922         u32 *net_cat_array = NULL;                922         u32 *net_cat_array = NULL;
923                                                   923 
924         if (doi_def->type == CIPSO_V4_MAP_STD)    924         if (doi_def->type == CIPSO_V4_MAP_STD) {
925                 net_cat_size = doi_def->map.st    925                 net_cat_size = doi_def->map.std->cat.cipso_size;
926                 net_cat_array = doi_def->map.s    926                 net_cat_array = doi_def->map.std->cat.cipso;
927         }                                         927         }
928                                                   928 
929         for (;;) {                                929         for (;;) {
930                 net_spot = cipso_v4_bitmap_wal    930                 net_spot = cipso_v4_bitmap_walk(net_cat,
931                                                   931                                                 net_clen_bits,
932                                                   932                                                 net_spot + 1,
933                                                   933                                                 1);
934                 if (net_spot < 0) {               934                 if (net_spot < 0) {
935                         if (net_spot == -2)       935                         if (net_spot == -2)
936                                 return -EFAULT    936                                 return -EFAULT;
937                         return 0;                 937                         return 0;
938                 }                                 938                 }
939                                                   939 
940                 switch (doi_def->type) {          940                 switch (doi_def->type) {
941                 case CIPSO_V4_MAP_PASS:           941                 case CIPSO_V4_MAP_PASS:
942                         host_spot = net_spot;     942                         host_spot = net_spot;
943                         break;                    943                         break;
944                 case CIPSO_V4_MAP_STD:            944                 case CIPSO_V4_MAP_STD:
945                         if (net_spot >= net_ca    945                         if (net_spot >= net_cat_size)
946                                 return -EPERM;    946                                 return -EPERM;
947                         host_spot = net_cat_ar    947                         host_spot = net_cat_array[net_spot];
948                         if (host_spot >= CIPSO    948                         if (host_spot >= CIPSO_V4_INV_CAT)
949                                 return -EPERM;    949                                 return -EPERM;
950                         break;                    950                         break;
951                 }                                 951                 }
952                 ret_val = netlbl_secattr_catma    952                 ret_val = netlbl_secattr_catmap_setbit(secattr->attr.mls.cat,
953                                                   953                                                        host_spot,
954                                                   954                                                        GFP_ATOMIC);
955                 if (ret_val != 0)                 955                 if (ret_val != 0)
956                         return ret_val;           956                         return ret_val;
957         }                                         957         }
958                                                   958 
959         return -EINVAL;                           959         return -EINVAL;
960 }                                                 960 }
961                                                   961 
962 /**                                               962 /**
963  * cipso_v4_map_cat_enum_valid - Checks to see    963  * cipso_v4_map_cat_enum_valid - Checks to see if the categories are valid
964  * @doi_def: the DOI definition                   964  * @doi_def: the DOI definition
965  * @enumcat: category list                        965  * @enumcat: category list
966  * @enumcat_len: length of the category list i    966  * @enumcat_len: length of the category list in bytes
967  *                                                967  *
968  * Description:                                   968  * Description:
969  * Checks the given categories against the giv    969  * Checks the given categories against the given DOI definition and returns a
970  * negative value if any of the categories do     970  * negative value if any of the categories do not have a valid mapping and a
971  * zero value if all of the categories are val    971  * zero value if all of the categories are valid.
972  *                                                972  *
973  */                                               973  */
974 static int cipso_v4_map_cat_enum_valid(const s    974 static int cipso_v4_map_cat_enum_valid(const struct cipso_v4_doi *doi_def,
975                                        const u    975                                        const unsigned char *enumcat,
976                                        u32 enu    976                                        u32 enumcat_len)
977 {                                                 977 {
978         u16 cat;                                  978         u16 cat;
979         int cat_prev = -1;                        979         int cat_prev = -1;
980         u32 iter;                                 980         u32 iter;
981                                                   981 
982         if (doi_def->type != CIPSO_V4_MAP_PASS    982         if (doi_def->type != CIPSO_V4_MAP_PASS || enumcat_len & 0x01)
983                 return -EFAULT;                   983                 return -EFAULT;
984                                                   984 
985         for (iter = 0; iter < enumcat_len; ite    985         for (iter = 0; iter < enumcat_len; iter += 2) {
986                 cat = ntohs(get_unaligned((__b    986                 cat = ntohs(get_unaligned((__be16 *)&enumcat[iter]));
987                 if (cat <= cat_prev)              987                 if (cat <= cat_prev)
988                         return -EFAULT;           988                         return -EFAULT;
989                 cat_prev = cat;                   989                 cat_prev = cat;
990         }                                         990         }
991                                                   991 
992         return 0;                                 992         return 0;
993 }                                                 993 }
994                                                   994 
995 /**                                               995 /**
996  * cipso_v4_map_cat_enum_hton - Perform a cate    996  * cipso_v4_map_cat_enum_hton - Perform a category mapping from host to network
997  * @doi_def: the DOI definition                   997  * @doi_def: the DOI definition
998  * @secattr: the security attributes              998  * @secattr: the security attributes
999  * @net_cat: the zero'd out category list in n    999  * @net_cat: the zero'd out category list in network/CIPSO format
1000  * @net_cat_len: the length of the CIPSO cate    1000  * @net_cat_len: the length of the CIPSO category list in bytes
1001  *                                               1001  *
1002  * Description:                                  1002  * Description:
1003  * Perform a label mapping to translate a loc    1003  * Perform a label mapping to translate a local MLS category bitmap to the
1004  * correct CIPSO category list using the give    1004  * correct CIPSO category list using the given DOI definition.   Returns the
1005  * size in bytes of the network category bitm    1005  * size in bytes of the network category bitmap on success, negative values
1006  * otherwise.                                    1006  * otherwise.
1007  *                                               1007  *
1008  */                                              1008  */
1009 static int cipso_v4_map_cat_enum_hton(const s    1009 static int cipso_v4_map_cat_enum_hton(const struct cipso_v4_doi *doi_def,
1010                                       const s    1010                                       const struct netlbl_lsm_secattr *secattr,
1011                                       unsigne    1011                                       unsigned char *net_cat,
1012                                       u32 net    1012                                       u32 net_cat_len)
1013 {                                                1013 {
1014         int cat = -1;                            1014         int cat = -1;
1015         u32 cat_iter = 0;                        1015         u32 cat_iter = 0;
1016                                                  1016 
1017         for (;;) {                               1017         for (;;) {
1018                 cat = netlbl_secattr_catmap_w    1018                 cat = netlbl_secattr_catmap_walk(secattr->attr.mls.cat,
1019                                                  1019                                                  cat + 1);
1020                 if (cat < 0)                     1020                 if (cat < 0)
1021                         break;                   1021                         break;
1022                 if ((cat_iter + 2) > net_cat_    1022                 if ((cat_iter + 2) > net_cat_len)
1023                         return -ENOSPC;          1023                         return -ENOSPC;
1024                                                  1024 
1025                 *((__be16 *)&net_cat[cat_iter    1025                 *((__be16 *)&net_cat[cat_iter]) = htons(cat);
1026                 cat_iter += 2;                   1026                 cat_iter += 2;
1027         }                                        1027         }
1028                                                  1028 
1029         return cat_iter;                         1029         return cat_iter;
1030 }                                                1030 }
1031                                                  1031 
1032 /**                                              1032 /**
1033  * cipso_v4_map_cat_enum_ntoh - Perform a cat    1033  * cipso_v4_map_cat_enum_ntoh - Perform a category mapping from network to host
1034  * @doi_def: the DOI definition                  1034  * @doi_def: the DOI definition
1035  * @net_cat: the category list in network/CIP    1035  * @net_cat: the category list in network/CIPSO format
1036  * @net_cat_len: the length of the CIPSO bitm    1036  * @net_cat_len: the length of the CIPSO bitmap in bytes
1037  * @secattr: the security attributes             1037  * @secattr: the security attributes
1038  *                                               1038  *
1039  * Description:                                  1039  * Description:
1040  * Perform a label mapping to translate a CIP    1040  * Perform a label mapping to translate a CIPSO category list to the correct
1041  * local MLS category bitmap using the given     1041  * local MLS category bitmap using the given DOI definition.  Returns zero on
1042  * success, negative values on failure.          1042  * success, negative values on failure.
1043  *                                               1043  *
1044  */                                              1044  */
1045 static int cipso_v4_map_cat_enum_ntoh(const s    1045 static int cipso_v4_map_cat_enum_ntoh(const struct cipso_v4_doi *doi_def,
1046                                       const u    1046                                       const unsigned char *net_cat,
1047                                       u32 net    1047                                       u32 net_cat_len,
1048                                       struct     1048                                       struct netlbl_lsm_secattr *secattr)
1049 {                                                1049 {
1050         int ret_val;                             1050         int ret_val;
1051         u32 iter;                                1051         u32 iter;
1052                                                  1052 
1053         for (iter = 0; iter < net_cat_len; it    1053         for (iter = 0; iter < net_cat_len; iter += 2) {
1054                 ret_val = netlbl_secattr_catm    1054                 ret_val = netlbl_secattr_catmap_setbit(secattr->attr.mls.cat,
1055                                 ntohs(get_una    1055                                 ntohs(get_unaligned((__be16 *)&net_cat[iter])),
1056                                 GFP_ATOMIC);     1056                                 GFP_ATOMIC);
1057                 if (ret_val != 0)                1057                 if (ret_val != 0)
1058                         return ret_val;          1058                         return ret_val;
1059         }                                        1059         }
1060                                                  1060 
1061         return 0;                                1061         return 0;
1062 }                                                1062 }
1063                                                  1063 
1064 /**                                              1064 /**
1065  * cipso_v4_map_cat_rng_valid - Checks to see    1065  * cipso_v4_map_cat_rng_valid - Checks to see if the categories are valid
1066  * @doi_def: the DOI definition                  1066  * @doi_def: the DOI definition
1067  * @rngcat: category list                        1067  * @rngcat: category list
1068  * @rngcat_len: length of the category list i    1068  * @rngcat_len: length of the category list in bytes
1069  *                                               1069  *
1070  * Description:                                  1070  * Description:
1071  * Checks the given categories against the gi    1071  * Checks the given categories against the given DOI definition and returns a
1072  * negative value if any of the categories do    1072  * negative value if any of the categories do not have a valid mapping and a
1073  * zero value if all of the categories are va    1073  * zero value if all of the categories are valid.
1074  *                                               1074  *
1075  */                                              1075  */
1076 static int cipso_v4_map_cat_rng_valid(const s    1076 static int cipso_v4_map_cat_rng_valid(const struct cipso_v4_doi *doi_def,
1077                                       const u    1077                                       const unsigned char *rngcat,
1078                                       u32 rng    1078                                       u32 rngcat_len)
1079 {                                                1079 {
1080         u16 cat_high;                            1080         u16 cat_high;
1081         u16 cat_low;                             1081         u16 cat_low;
1082         u32 cat_prev = CIPSO_V4_MAX_REM_CATS     1082         u32 cat_prev = CIPSO_V4_MAX_REM_CATS + 1;
1083         u32 iter;                                1083         u32 iter;
1084                                                  1084 
1085         if (doi_def->type != CIPSO_V4_MAP_PAS    1085         if (doi_def->type != CIPSO_V4_MAP_PASS || rngcat_len & 0x01)
1086                 return -EFAULT;                  1086                 return -EFAULT;
1087                                                  1087 
1088         for (iter = 0; iter < rngcat_len; ite    1088         for (iter = 0; iter < rngcat_len; iter += 4) {
1089                 cat_high = ntohs(get_unaligne    1089                 cat_high = ntohs(get_unaligned((__be16 *)&rngcat[iter]));
1090                 if ((iter + 4) <= rngcat_len)    1090                 if ((iter + 4) <= rngcat_len)
1091                         cat_low = ntohs(         1091                         cat_low = ntohs(
1092                                 get_unaligned    1092                                 get_unaligned((__be16 *)&rngcat[iter + 2]));
1093                 else                             1093                 else
1094                         cat_low = 0;             1094                         cat_low = 0;
1095                                                  1095 
1096                 if (cat_high > cat_prev)         1096                 if (cat_high > cat_prev)
1097                         return -EFAULT;          1097                         return -EFAULT;
1098                                                  1098 
1099                 cat_prev = cat_low;              1099                 cat_prev = cat_low;
1100         }                                        1100         }
1101                                                  1101 
1102         return 0;                                1102         return 0;
1103 }                                                1103 }
1104                                                  1104 
1105 /**                                              1105 /**
1106  * cipso_v4_map_cat_rng_hton - Perform a cate    1106  * cipso_v4_map_cat_rng_hton - Perform a category mapping from host to network
1107  * @doi_def: the DOI definition                  1107  * @doi_def: the DOI definition
1108  * @secattr: the security attributes             1108  * @secattr: the security attributes
1109  * @net_cat: the zero'd out category list in     1109  * @net_cat: the zero'd out category list in network/CIPSO format
1110  * @net_cat_len: the length of the CIPSO cate    1110  * @net_cat_len: the length of the CIPSO category list in bytes
1111  *                                               1111  *
1112  * Description:                                  1112  * Description:
1113  * Perform a label mapping to translate a loc    1113  * Perform a label mapping to translate a local MLS category bitmap to the
1114  * correct CIPSO category list using the give    1114  * correct CIPSO category list using the given DOI definition.   Returns the
1115  * size in bytes of the network category bitm    1115  * size in bytes of the network category bitmap on success, negative values
1116  * otherwise.                                    1116  * otherwise.
1117  *                                               1117  *
1118  */                                              1118  */
1119 static int cipso_v4_map_cat_rng_hton(const st    1119 static int cipso_v4_map_cat_rng_hton(const struct cipso_v4_doi *doi_def,
1120                                      const st    1120                                      const struct netlbl_lsm_secattr *secattr,
1121                                      unsigned    1121                                      unsigned char *net_cat,
1122                                      u32 net_    1122                                      u32 net_cat_len)
1123 {                                                1123 {
1124         int iter = -1;                           1124         int iter = -1;
1125         u16 array[CIPSO_V4_TAG_RNG_CAT_MAX *     1125         u16 array[CIPSO_V4_TAG_RNG_CAT_MAX * 2];
1126         u32 array_cnt = 0;                       1126         u32 array_cnt = 0;
1127         u32 cat_size = 0;                        1127         u32 cat_size = 0;
1128                                                  1128 
1129         /* make sure we don't overflow the 'a    1129         /* make sure we don't overflow the 'array[]' variable */
1130         if (net_cat_len >                        1130         if (net_cat_len >
1131             (CIPSO_V4_OPT_LEN_MAX - CIPSO_V4_    1131             (CIPSO_V4_OPT_LEN_MAX - CIPSO_V4_HDR_LEN - CIPSO_V4_TAG_RNG_BLEN))
1132                 return -ENOSPC;                  1132                 return -ENOSPC;
1133                                                  1133 
1134         for (;;) {                               1134         for (;;) {
1135                 iter = netlbl_secattr_catmap_    1135                 iter = netlbl_secattr_catmap_walk(secattr->attr.mls.cat,
1136                                                  1136                                                   iter + 1);
1137                 if (iter < 0)                    1137                 if (iter < 0)
1138                         break;                   1138                         break;
1139                 cat_size += (iter == 0 ? 0 :     1139                 cat_size += (iter == 0 ? 0 : sizeof(u16));
1140                 if (cat_size > net_cat_len)      1140                 if (cat_size > net_cat_len)
1141                         return -ENOSPC;          1141                         return -ENOSPC;
1142                 array[array_cnt++] = iter;       1142                 array[array_cnt++] = iter;
1143                                                  1143 
1144                 iter = netlbl_secattr_catmap_    1144                 iter = netlbl_secattr_catmap_walk_rng(secattr->attr.mls.cat,
1145                                                  1145                                                       iter);
1146                 if (iter < 0)                    1146                 if (iter < 0)
1147                         return -EFAULT;          1147                         return -EFAULT;
1148                 cat_size += sizeof(u16);         1148                 cat_size += sizeof(u16);
1149                 if (cat_size > net_cat_len)      1149                 if (cat_size > net_cat_len)
1150                         return -ENOSPC;          1150                         return -ENOSPC;
1151                 array[array_cnt++] = iter;       1151                 array[array_cnt++] = iter;
1152         }                                        1152         }
1153                                                  1153 
1154         for (iter = 0; array_cnt > 0;) {         1154         for (iter = 0; array_cnt > 0;) {
1155                 *((__be16 *)&net_cat[iter]) =    1155                 *((__be16 *)&net_cat[iter]) = htons(array[--array_cnt]);
1156                 iter += 2;                       1156                 iter += 2;
1157                 array_cnt--;                     1157                 array_cnt--;
1158                 if (array[array_cnt] != 0) {     1158                 if (array[array_cnt] != 0) {
1159                         *((__be16 *)&net_cat[    1159                         *((__be16 *)&net_cat[iter]) = htons(array[array_cnt]);
1160                         iter += 2;               1160                         iter += 2;
1161                 }                                1161                 }
1162         }                                        1162         }
1163                                                  1163 
1164         return cat_size;                         1164         return cat_size;
1165 }                                                1165 }
1166                                                  1166 
1167 /**                                              1167 /**
1168  * cipso_v4_map_cat_rng_ntoh - Perform a cate    1168  * cipso_v4_map_cat_rng_ntoh - Perform a category mapping from network to host
1169  * @doi_def: the DOI definition                  1169  * @doi_def: the DOI definition
1170  * @net_cat: the category list in network/CIP    1170  * @net_cat: the category list in network/CIPSO format
1171  * @net_cat_len: the length of the CIPSO bitm    1171  * @net_cat_len: the length of the CIPSO bitmap in bytes
1172  * @secattr: the security attributes             1172  * @secattr: the security attributes
1173  *                                               1173  *
1174  * Description:                                  1174  * Description:
1175  * Perform a label mapping to translate a CIP    1175  * Perform a label mapping to translate a CIPSO category list to the correct
1176  * local MLS category bitmap using the given     1176  * local MLS category bitmap using the given DOI definition.  Returns zero on
1177  * success, negative values on failure.          1177  * success, negative values on failure.
1178  *                                               1178  *
1179  */                                              1179  */
1180 static int cipso_v4_map_cat_rng_ntoh(const st    1180 static int cipso_v4_map_cat_rng_ntoh(const struct cipso_v4_doi *doi_def,
1181                                      const un    1181                                      const unsigned char *net_cat,
1182                                      u32 net_    1182                                      u32 net_cat_len,
1183                                      struct n    1183                                      struct netlbl_lsm_secattr *secattr)
1184 {                                                1184 {
1185         int ret_val;                             1185         int ret_val;
1186         u32 net_iter;                            1186         u32 net_iter;
1187         u16 cat_low;                             1187         u16 cat_low;
1188         u16 cat_high;                            1188         u16 cat_high;
1189                                                  1189 
1190         for (net_iter = 0; net_iter < net_cat    1190         for (net_iter = 0; net_iter < net_cat_len; net_iter += 4) {
1191                 cat_high = ntohs(get_unaligne    1191                 cat_high = ntohs(get_unaligned((__be16 *)&net_cat[net_iter]));
1192                 if ((net_iter + 4) <= net_cat    1192                 if ((net_iter + 4) <= net_cat_len)
1193                         cat_low = ntohs(         1193                         cat_low = ntohs(
1194                               get_unaligned((    1194                               get_unaligned((__be16 *)&net_cat[net_iter + 2]));
1195                 else                             1195                 else
1196                         cat_low = 0;             1196                         cat_low = 0;
1197                                                  1197 
1198                 ret_val = netlbl_secattr_catm    1198                 ret_val = netlbl_secattr_catmap_setrng(secattr->attr.mls.cat,
1199                                                  1199                                                        cat_low,
1200                                                  1200                                                        cat_high,
1201                                                  1201                                                        GFP_ATOMIC);
1202                 if (ret_val != 0)                1202                 if (ret_val != 0)
1203                         return ret_val;          1203                         return ret_val;
1204         }                                        1204         }
1205                                                  1205 
1206         return 0;                                1206         return 0;
1207 }                                                1207 }
1208                                                  1208 
1209 /*                                               1209 /*
1210  * Protocol Handling Functions                   1210  * Protocol Handling Functions
1211  */                                              1211  */
1212                                                  1212 
1213 /**                                              1213 /**
1214  * cipso_v4_gentag_hdr - Generate a CIPSO opt    1214  * cipso_v4_gentag_hdr - Generate a CIPSO option header
1215  * @doi_def: the DOI definition                  1215  * @doi_def: the DOI definition
1216  * @len: the total tag length in bytes, not i    1216  * @len: the total tag length in bytes, not including this header
1217  * @buf: the CIPSO option buffer                 1217  * @buf: the CIPSO option buffer
1218  *                                               1218  *
1219  * Description:                                  1219  * Description:
1220  * Write a CIPSO header into the beginning of    1220  * Write a CIPSO header into the beginning of @buffer.
1221  *                                               1221  *
1222  */                                              1222  */
1223 static void cipso_v4_gentag_hdr(const struct     1223 static void cipso_v4_gentag_hdr(const struct cipso_v4_doi *doi_def,
1224                                 unsigned char    1224                                 unsigned char *buf,
1225                                 u32 len)         1225                                 u32 len)
1226 {                                                1226 {
1227         buf[0] = IPOPT_CIPSO;                    1227         buf[0] = IPOPT_CIPSO;
1228         buf[1] = CIPSO_V4_HDR_LEN + len;         1228         buf[1] = CIPSO_V4_HDR_LEN + len;
1229         *(__be32 *)&buf[2] = htonl(doi_def->d    1229         *(__be32 *)&buf[2] = htonl(doi_def->doi);
1230 }                                                1230 }
1231                                                  1231 
1232 /**                                              1232 /**
1233  * cipso_v4_gentag_rbm - Generate a CIPSO res    1233  * cipso_v4_gentag_rbm - Generate a CIPSO restricted bitmap tag (type #1)
1234  * @doi_def: the DOI definition                  1234  * @doi_def: the DOI definition
1235  * @secattr: the security attributes             1235  * @secattr: the security attributes
1236  * @buffer: the option buffer                    1236  * @buffer: the option buffer
1237  * @buffer_len: length of buffer in bytes        1237  * @buffer_len: length of buffer in bytes
1238  *                                               1238  *
1239  * Description:                                  1239  * Description:
1240  * Generate a CIPSO option using the restrict    1240  * Generate a CIPSO option using the restricted bitmap tag, tag type #1.  The
1241  * actual buffer length may be larger than th    1241  * actual buffer length may be larger than the indicated size due to
1242  * translation between host and network categ    1242  * translation between host and network category bitmaps.  Returns the size of
1243  * the tag on success, negative values on fai    1243  * the tag on success, negative values on failure.
1244  *                                               1244  *
1245  */                                              1245  */
1246 static int cipso_v4_gentag_rbm(const struct c    1246 static int cipso_v4_gentag_rbm(const struct cipso_v4_doi *doi_def,
1247                                const struct n    1247                                const struct netlbl_lsm_secattr *secattr,
1248                                unsigned char     1248                                unsigned char *buffer,
1249                                u32 buffer_len    1249                                u32 buffer_len)
1250 {                                                1250 {
1251         int ret_val;                             1251         int ret_val;
1252         u32 tag_len;                             1252         u32 tag_len;
1253         u32 level;                               1253         u32 level;
1254                                                  1254 
1255         if ((secattr->flags & NETLBL_SECATTR_    1255         if ((secattr->flags & NETLBL_SECATTR_MLS_LVL) == 0)
1256                 return -EPERM;                   1256                 return -EPERM;
1257                                                  1257 
1258         ret_val = cipso_v4_map_lvl_hton(doi_d    1258         ret_val = cipso_v4_map_lvl_hton(doi_def,
1259                                         secat    1259                                         secattr->attr.mls.lvl,
1260                                         &leve    1260                                         &level);
1261         if (ret_val != 0)                        1261         if (ret_val != 0)
1262                 return ret_val;                  1262                 return ret_val;
1263                                                  1263 
1264         if (secattr->flags & NETLBL_SECATTR_M    1264         if (secattr->flags & NETLBL_SECATTR_MLS_CAT) {
1265                 ret_val = cipso_v4_map_cat_rb    1265                 ret_val = cipso_v4_map_cat_rbm_hton(doi_def,
1266                                                  1266                                                     secattr,
1267                                                  1267                                                     &buffer[4],
1268                                                  1268                                                     buffer_len - 4);
1269                 if (ret_val < 0)                 1269                 if (ret_val < 0)
1270                         return ret_val;          1270                         return ret_val;
1271                                                  1271 
1272                 /* This will send packets usi    1272                 /* This will send packets using the "optimized" format when
1273                  * possibile as specified in     1273                  * possibile as specified in  section 3.4.2.6 of the
1274                  * CIPSO draft. */               1274                  * CIPSO draft. */
1275                 if (cipso_v4_rbm_optfmt && re    1275                 if (cipso_v4_rbm_optfmt && ret_val > 0 && ret_val <= 10)
1276                         tag_len = 14;            1276                         tag_len = 14;
1277                 else                             1277                 else
1278                         tag_len = 4 + ret_val    1278                         tag_len = 4 + ret_val;
1279         } else                                   1279         } else
1280                 tag_len = 4;                     1280                 tag_len = 4;
1281                                                  1281 
1282         buffer[0] = 0x01;                        1282         buffer[0] = 0x01;
1283         buffer[1] = tag_len;                     1283         buffer[1] = tag_len;
1284         buffer[3] = level;                       1284         buffer[3] = level;
1285                                                  1285 
1286         return tag_len;                          1286         return tag_len;
1287 }                                                1287 }
1288                                                  1288 
1289 /**                                              1289 /**
1290  * cipso_v4_parsetag_rbm - Parse a CIPSO rest    1290  * cipso_v4_parsetag_rbm - Parse a CIPSO restricted bitmap tag
1291  * @doi_def: the DOI definition                  1291  * @doi_def: the DOI definition
1292  * @tag: the CIPSO tag                           1292  * @tag: the CIPSO tag
1293  * @secattr: the security attributes             1293  * @secattr: the security attributes
1294  *                                               1294  *
1295  * Description:                                  1295  * Description:
1296  * Parse a CIPSO restricted bitmap tag (tag t    1296  * Parse a CIPSO restricted bitmap tag (tag type #1) and return the security
1297  * attributes in @secattr.  Return zero on su    1297  * attributes in @secattr.  Return zero on success, negatives values on
1298  * failure.                                      1298  * failure.
1299  *                                               1299  *
1300  */                                              1300  */
1301 static int cipso_v4_parsetag_rbm(const struct    1301 static int cipso_v4_parsetag_rbm(const struct cipso_v4_doi *doi_def,
1302                                  const unsign    1302                                  const unsigned char *tag,
1303                                  struct netlb    1303                                  struct netlbl_lsm_secattr *secattr)
1304 {                                                1304 {
1305         int ret_val;                             1305         int ret_val;
1306         u8 tag_len = tag[1];                     1306         u8 tag_len = tag[1];
1307         u32 level;                               1307         u32 level;
1308                                                  1308 
1309         ret_val = cipso_v4_map_lvl_ntoh(doi_d    1309         ret_val = cipso_v4_map_lvl_ntoh(doi_def, tag[3], &level);
1310         if (ret_val != 0)                        1310         if (ret_val != 0)
1311                 return ret_val;                  1311                 return ret_val;
1312         secattr->attr.mls.lvl = level;           1312         secattr->attr.mls.lvl = level;
1313         secattr->flags |= NETLBL_SECATTR_MLS_    1313         secattr->flags |= NETLBL_SECATTR_MLS_LVL;
1314                                                  1314 
1315         if (tag_len > 4) {                       1315         if (tag_len > 4) {
1316                 secattr->attr.mls.cat =          1316                 secattr->attr.mls.cat =
1317                                        netlbl    1317                                        netlbl_secattr_catmap_alloc(GFP_ATOMIC);
1318                 if (secattr->attr.mls.cat ==     1318                 if (secattr->attr.mls.cat == NULL)
1319                         return -ENOMEM;          1319                         return -ENOMEM;
1320                                                  1320 
1321                 ret_val = cipso_v4_map_cat_rb    1321                 ret_val = cipso_v4_map_cat_rbm_ntoh(doi_def,
1322                                                  1322                                                     &tag[4],
1323                                                  1323                                                     tag_len - 4,
1324                                                  1324                                                     secattr);
1325                 if (ret_val != 0) {              1325                 if (ret_val != 0) {
1326                         netlbl_secattr_catmap    1326                         netlbl_secattr_catmap_free(secattr->attr.mls.cat);
1327                         return ret_val;          1327                         return ret_val;
1328                 }                                1328                 }
1329                                                  1329 
1330                 secattr->flags |= NETLBL_SECA    1330                 secattr->flags |= NETLBL_SECATTR_MLS_CAT;
1331         }                                        1331         }
1332                                                  1332 
1333         return 0;                                1333         return 0;
1334 }                                                1334 }
1335                                                  1335 
1336 /**                                              1336 /**
1337  * cipso_v4_gentag_enum - Generate a CIPSO en    1337  * cipso_v4_gentag_enum - Generate a CIPSO enumerated tag (type #2)
1338  * @doi_def: the DOI definition                  1338  * @doi_def: the DOI definition
1339  * @secattr: the security attributes             1339  * @secattr: the security attributes
1340  * @buffer: the option buffer                    1340  * @buffer: the option buffer
1341  * @buffer_len: length of buffer in bytes        1341  * @buffer_len: length of buffer in bytes
1342  *                                               1342  *
1343  * Description:                                  1343  * Description:
1344  * Generate a CIPSO option using the enumerat    1344  * Generate a CIPSO option using the enumerated tag, tag type #2.  Returns the
1345  * size of the tag on success, negative value    1345  * size of the tag on success, negative values on failure.
1346  *                                               1346  *
1347  */                                              1347  */
1348 static int cipso_v4_gentag_enum(const struct     1348 static int cipso_v4_gentag_enum(const struct cipso_v4_doi *doi_def,
1349                                 const struct     1349                                 const struct netlbl_lsm_secattr *secattr,
1350                                 unsigned char    1350                                 unsigned char *buffer,
1351                                 u32 buffer_le    1351                                 u32 buffer_len)
1352 {                                                1352 {
1353         int ret_val;                             1353         int ret_val;
1354         u32 tag_len;                             1354         u32 tag_len;
1355         u32 level;                               1355         u32 level;
1356                                                  1356 
1357         if (!(secattr->flags & NETLBL_SECATTR    1357         if (!(secattr->flags & NETLBL_SECATTR_MLS_LVL))
1358                 return -EPERM;                   1358                 return -EPERM;
1359                                                  1359 
1360         ret_val = cipso_v4_map_lvl_hton(doi_d    1360         ret_val = cipso_v4_map_lvl_hton(doi_def,
1361                                         secat    1361                                         secattr->attr.mls.lvl,
1362                                         &leve    1362                                         &level);
1363         if (ret_val != 0)                        1363         if (ret_val != 0)
1364                 return ret_val;                  1364                 return ret_val;
1365                                                  1365 
1366         if (secattr->flags & NETLBL_SECATTR_M    1366         if (secattr->flags & NETLBL_SECATTR_MLS_CAT) {
1367                 ret_val = cipso_v4_map_cat_en    1367                 ret_val = cipso_v4_map_cat_enum_hton(doi_def,
1368                                                  1368                                                      secattr,
1369                                                  1369                                                      &buffer[4],
1370                                                  1370                                                      buffer_len - 4);
1371                 if (ret_val < 0)                 1371                 if (ret_val < 0)
1372                         return ret_val;          1372                         return ret_val;
1373                                                  1373 
1374                 tag_len = 4 + ret_val;           1374                 tag_len = 4 + ret_val;
1375         } else                                   1375         } else
1376                 tag_len = 4;                     1376                 tag_len = 4;
1377                                                  1377 
1378         buffer[0] = 0x02;                        1378         buffer[0] = 0x02;
1379         buffer[1] = tag_len;                     1379         buffer[1] = tag_len;
1380         buffer[3] = level;                       1380         buffer[3] = level;
1381                                                  1381 
1382         return tag_len;                          1382         return tag_len;
1383 }                                                1383 }
1384                                                  1384 
1385 /**                                              1385 /**
1386  * cipso_v4_parsetag_enum - Parse a CIPSO enu    1386  * cipso_v4_parsetag_enum - Parse a CIPSO enumerated tag
1387  * @doi_def: the DOI definition                  1387  * @doi_def: the DOI definition
1388  * @tag: the CIPSO tag                           1388  * @tag: the CIPSO tag
1389  * @secattr: the security attributes             1389  * @secattr: the security attributes
1390  *                                               1390  *
1391  * Description:                                  1391  * Description:
1392  * Parse a CIPSO enumerated tag (tag type #2)    1392  * Parse a CIPSO enumerated tag (tag type #2) and return the security
1393  * attributes in @secattr.  Return zero on su    1393  * attributes in @secattr.  Return zero on success, negatives values on
1394  * failure.                                      1394  * failure.
1395  *                                               1395  *
1396  */                                              1396  */
1397 static int cipso_v4_parsetag_enum(const struc    1397 static int cipso_v4_parsetag_enum(const struct cipso_v4_doi *doi_def,
1398                                   const unsig    1398                                   const unsigned char *tag,
1399                                   struct netl    1399                                   struct netlbl_lsm_secattr *secattr)
1400 {                                                1400 {
1401         int ret_val;                             1401         int ret_val;
1402         u8 tag_len = tag[1];                     1402         u8 tag_len = tag[1];
1403         u32 level;                               1403         u32 level;
1404                                                  1404 
1405         ret_val = cipso_v4_map_lvl_ntoh(doi_d    1405         ret_val = cipso_v4_map_lvl_ntoh(doi_def, tag[3], &level);
1406         if (ret_val != 0)                        1406         if (ret_val != 0)
1407                 return ret_val;                  1407                 return ret_val;
1408         secattr->attr.mls.lvl = level;           1408         secattr->attr.mls.lvl = level;
1409         secattr->flags |= NETLBL_SECATTR_MLS_    1409         secattr->flags |= NETLBL_SECATTR_MLS_LVL;
1410                                                  1410 
1411         if (tag_len > 4) {                       1411         if (tag_len > 4) {
1412                 secattr->attr.mls.cat =          1412                 secattr->attr.mls.cat =
1413                                        netlbl    1413                                        netlbl_secattr_catmap_alloc(GFP_ATOMIC);
1414                 if (secattr->attr.mls.cat ==     1414                 if (secattr->attr.mls.cat == NULL)
1415                         return -ENOMEM;          1415                         return -ENOMEM;
1416                                                  1416 
1417                 ret_val = cipso_v4_map_cat_en    1417                 ret_val = cipso_v4_map_cat_enum_ntoh(doi_def,
1418                                                  1418                                                      &tag[4],
1419                                                  1419                                                      tag_len - 4,
1420                                                  1420                                                      secattr);
1421                 if (ret_val != 0) {              1421                 if (ret_val != 0) {
1422                         netlbl_secattr_catmap    1422                         netlbl_secattr_catmap_free(secattr->attr.mls.cat);
1423                         return ret_val;          1423                         return ret_val;
1424                 }                                1424                 }
1425                                                  1425 
1426                 secattr->flags |= NETLBL_SECA    1426                 secattr->flags |= NETLBL_SECATTR_MLS_CAT;
1427         }                                        1427         }
1428                                                  1428 
1429         return 0;                                1429         return 0;
1430 }                                                1430 }
1431                                                  1431 
1432 /**                                              1432 /**
1433  * cipso_v4_gentag_rng - Generate a CIPSO ran    1433  * cipso_v4_gentag_rng - Generate a CIPSO ranged tag (type #5)
1434  * @doi_def: the DOI definition                  1434  * @doi_def: the DOI definition
1435  * @secattr: the security attributes             1435  * @secattr: the security attributes
1436  * @buffer: the option buffer                    1436  * @buffer: the option buffer
1437  * @buffer_len: length of buffer in bytes        1437  * @buffer_len: length of buffer in bytes
1438  *                                               1438  *
1439  * Description:                                  1439  * Description:
1440  * Generate a CIPSO option using the ranged t    1440  * Generate a CIPSO option using the ranged tag, tag type #5.  Returns the
1441  * size of the tag on success, negative value    1441  * size of the tag on success, negative values on failure.
1442  *                                               1442  *
1443  */                                              1443  */
1444 static int cipso_v4_gentag_rng(const struct c    1444 static int cipso_v4_gentag_rng(const struct cipso_v4_doi *doi_def,
1445                                const struct n    1445                                const struct netlbl_lsm_secattr *secattr,
1446                                unsigned char     1446                                unsigned char *buffer,
1447                                u32 buffer_len    1447                                u32 buffer_len)
1448 {                                                1448 {
1449         int ret_val;                             1449         int ret_val;
1450         u32 tag_len;                             1450         u32 tag_len;
1451         u32 level;                               1451         u32 level;
1452                                                  1452 
1453         if (!(secattr->flags & NETLBL_SECATTR    1453         if (!(secattr->flags & NETLBL_SECATTR_MLS_LVL))
1454                 return -EPERM;                   1454                 return -EPERM;
1455                                                  1455 
1456         ret_val = cipso_v4_map_lvl_hton(doi_d    1456         ret_val = cipso_v4_map_lvl_hton(doi_def,
1457                                         secat    1457                                         secattr->attr.mls.lvl,
1458                                         &leve    1458                                         &level);
1459         if (ret_val != 0)                        1459         if (ret_val != 0)
1460                 return ret_val;                  1460                 return ret_val;
1461                                                  1461 
1462         if (secattr->flags & NETLBL_SECATTR_M    1462         if (secattr->flags & NETLBL_SECATTR_MLS_CAT) {
1463                 ret_val = cipso_v4_map_cat_rn    1463                 ret_val = cipso_v4_map_cat_rng_hton(doi_def,
1464                                                  1464                                                     secattr,
1465                                                  1465                                                     &buffer[4],
1466                                                  1466                                                     buffer_len - 4);
1467                 if (ret_val < 0)                 1467                 if (ret_val < 0)
1468                         return ret_val;          1468                         return ret_val;
1469                                                  1469 
1470                 tag_len = 4 + ret_val;           1470                 tag_len = 4 + ret_val;
1471         } else                                   1471         } else
1472                 tag_len = 4;                     1472                 tag_len = 4;
1473                                                  1473 
1474         buffer[0] = 0x05;                        1474         buffer[0] = 0x05;
1475         buffer[1] = tag_len;                     1475         buffer[1] = tag_len;
1476         buffer[3] = level;                       1476         buffer[3] = level;
1477                                                  1477 
1478         return tag_len;                          1478         return tag_len;
1479 }                                                1479 }
1480                                                  1480 
1481 /**                                              1481 /**
1482  * cipso_v4_parsetag_rng - Parse a CIPSO rang    1482  * cipso_v4_parsetag_rng - Parse a CIPSO ranged tag
1483  * @doi_def: the DOI definition                  1483  * @doi_def: the DOI definition
1484  * @tag: the CIPSO tag                           1484  * @tag: the CIPSO tag
1485  * @secattr: the security attributes             1485  * @secattr: the security attributes
1486  *                                               1486  *
1487  * Description:                                  1487  * Description:
1488  * Parse a CIPSO ranged tag (tag type #5) and    1488  * Parse a CIPSO ranged tag (tag type #5) and return the security attributes
1489  * in @secattr.  Return zero on success, nega    1489  * in @secattr.  Return zero on success, negatives values on failure.
1490  *                                               1490  *
1491  */                                              1491  */
1492 static int cipso_v4_parsetag_rng(const struct    1492 static int cipso_v4_parsetag_rng(const struct cipso_v4_doi *doi_def,
1493                                  const unsign    1493                                  const unsigned char *tag,
1494                                  struct netlb    1494                                  struct netlbl_lsm_secattr *secattr)
1495 {                                                1495 {
1496         int ret_val;                             1496         int ret_val;
1497         u8 tag_len = tag[1];                     1497         u8 tag_len = tag[1];
1498         u32 level;                               1498         u32 level;
1499                                                  1499 
1500         ret_val = cipso_v4_map_lvl_ntoh(doi_d    1500         ret_val = cipso_v4_map_lvl_ntoh(doi_def, tag[3], &level);
1501         if (ret_val != 0)                        1501         if (ret_val != 0)
1502                 return ret_val;                  1502                 return ret_val;
1503         secattr->attr.mls.lvl = level;           1503         secattr->attr.mls.lvl = level;
1504         secattr->flags |= NETLBL_SECATTR_MLS_    1504         secattr->flags |= NETLBL_SECATTR_MLS_LVL;
1505                                                  1505 
1506         if (tag_len > 4) {                       1506         if (tag_len > 4) {
1507                 secattr->attr.mls.cat =          1507                 secattr->attr.mls.cat =
1508                                        netlbl    1508                                        netlbl_secattr_catmap_alloc(GFP_ATOMIC);
1509                 if (secattr->attr.mls.cat ==     1509                 if (secattr->attr.mls.cat == NULL)
1510                         return -ENOMEM;          1510                         return -ENOMEM;
1511                                                  1511 
1512                 ret_val = cipso_v4_map_cat_rn    1512                 ret_val = cipso_v4_map_cat_rng_ntoh(doi_def,
1513                                                  1513                                                     &tag[4],
1514                                                  1514                                                     tag_len - 4,
1515                                                  1515                                                     secattr);
1516                 if (ret_val != 0) {              1516                 if (ret_val != 0) {
1517                         netlbl_secattr_catmap    1517                         netlbl_secattr_catmap_free(secattr->attr.mls.cat);
1518                         return ret_val;          1518                         return ret_val;
1519                 }                                1519                 }
1520                                                  1520 
1521                 secattr->flags |= NETLBL_SECA    1521                 secattr->flags |= NETLBL_SECATTR_MLS_CAT;
1522         }                                        1522         }
1523                                                  1523 
1524         return 0;                                1524         return 0;
1525 }                                                1525 }
1526                                                  1526 
1527 /**                                              1527 /**
1528  * cipso_v4_validate - Validate a CIPSO optio    1528  * cipso_v4_validate - Validate a CIPSO option
1529  * @option: the start of the option, on error    1529  * @option: the start of the option, on error it is set to point to the error
1530  *                                               1530  *
1531  * Description:                                  1531  * Description:
1532  * This routine is called to validate a CIPSO    1532  * This routine is called to validate a CIPSO option, it checks all of the
1533  * fields to ensure that they are at least va    1533  * fields to ensure that they are at least valid, see the draft snippet below
1534  * for details.  If the option is valid then     1534  * for details.  If the option is valid then a zero value is returned and
1535  * the value of @option is unchanged.  If the    1535  * the value of @option is unchanged.  If the option is invalid then a
1536  * non-zero value is returned and @option is     1536  * non-zero value is returned and @option is adjusted to point to the
1537  * offending portion of the option.  From the    1537  * offending portion of the option.  From the IETF draft ...
1538  *                                               1538  *
1539  *  "If any field within the CIPSO options, s    1539  *  "If any field within the CIPSO options, such as the DOI identifier, is not
1540  *   recognized the IP datagram is discarded     1540  *   recognized the IP datagram is discarded and an ICMP 'parameter problem'
1541  *   (type 12) is generated and returned.  Th    1541  *   (type 12) is generated and returned.  The ICMP code field is set to 'bad
1542  *   parameter' (code 0) and the pointer is s    1542  *   parameter' (code 0) and the pointer is set to the start of the CIPSO field
1543  *   that is unrecognized."                      1543  *   that is unrecognized."
1544  *                                               1544  *
1545  */                                              1545  */
1546 int cipso_v4_validate(unsigned char **option)    1546 int cipso_v4_validate(unsigned char **option)
1547 {                                                1547 {
1548         unsigned char *opt = *option;            1548         unsigned char *opt = *option;
1549         unsigned char *tag;                      1549         unsigned char *tag;
1550         unsigned char opt_iter;                  1550         unsigned char opt_iter;
1551         unsigned char err_offset = 0;            1551         unsigned char err_offset = 0;
1552         u8 opt_len;                              1552         u8 opt_len;
1553         u8 tag_len;                              1553         u8 tag_len;
1554         struct cipso_v4_doi *doi_def = NULL;     1554         struct cipso_v4_doi *doi_def = NULL;
1555         u32 tag_iter;                            1555         u32 tag_iter;
1556                                                  1556 
1557         /* caller already checks for length v    1557         /* caller already checks for length values that are too large */
1558         opt_len = opt[1];                        1558         opt_len = opt[1];
1559         if (opt_len < 8) {                       1559         if (opt_len < 8) {
1560                 err_offset = 1;                  1560                 err_offset = 1;
1561                 goto validate_return;            1561                 goto validate_return;
1562         }                                        1562         }
1563                                                  1563 
1564         rcu_read_lock();                         1564         rcu_read_lock();
1565         doi_def = cipso_v4_doi_search(ntohl(g    1565         doi_def = cipso_v4_doi_search(ntohl(get_unaligned((__be32 *)&opt[2])));
1566         if (doi_def == NULL) {                   1566         if (doi_def == NULL) {
1567                 err_offset = 2;                  1567                 err_offset = 2;
1568                 goto validate_return_locked;     1568                 goto validate_return_locked;
1569         }                                        1569         }
1570                                                  1570 
1571         opt_iter = 6;                            1571         opt_iter = 6;
1572         tag = opt + opt_iter;                    1572         tag = opt + opt_iter;
1573         while (opt_iter < opt_len) {             1573         while (opt_iter < opt_len) {
1574                 for (tag_iter = 0; doi_def->t    1574                 for (tag_iter = 0; doi_def->tags[tag_iter] != tag[0];)
1575                         if (doi_def->tags[tag    1575                         if (doi_def->tags[tag_iter] == CIPSO_V4_TAG_INVALID ||
1576                             ++tag_iter == CIP    1576                             ++tag_iter == CIPSO_V4_TAG_MAXCNT) {
1577                                 err_offset =     1577                                 err_offset = opt_iter;
1578                                 goto validate    1578                                 goto validate_return_locked;
1579                         }                        1579                         }
1580                                                  1580 
1581                 tag_len = tag[1];                1581                 tag_len = tag[1];
1582                 if (tag_len > (opt_len - opt_    1582                 if (tag_len > (opt_len - opt_iter)) {
1583                         err_offset = opt_iter    1583                         err_offset = opt_iter + 1;
1584                         goto validate_return_    1584                         goto validate_return_locked;
1585                 }                                1585                 }
1586                                                  1586 
1587                 switch (tag[0]) {                1587                 switch (tag[0]) {
1588                 case CIPSO_V4_TAG_RBITMAP:       1588                 case CIPSO_V4_TAG_RBITMAP:
1589                         if (tag_len < 4) {       1589                         if (tag_len < 4) {
1590                                 err_offset =     1590                                 err_offset = opt_iter + 1;
1591                                 goto validate    1591                                 goto validate_return_locked;
1592                         }                        1592                         }
1593                                                  1593 
1594                         /* We are already goi    1594                         /* We are already going to do all the verification
1595                          * necessary at the s    1595                          * necessary at the socket layer so from our point of
1596                          * view it is safe to    1596                          * view it is safe to turn these checks off (and less
1597                          * work), however, th    1597                          * work), however, the CIPSO draft says we should do
1598                          * all the CIPSO vali    1598                          * all the CIPSO validations here but it doesn't
1599                          * really specify _ex    1599                          * really specify _exactly_ what we need to validate
1600                          * ... so, just make     1600                          * ... so, just make it a sysctl tunable. */
1601                         if (cipso_v4_rbm_stri    1601                         if (cipso_v4_rbm_strictvalid) {
1602                                 if (cipso_v4_    1602                                 if (cipso_v4_map_lvl_valid(doi_def,
1603                                                  1603                                                            tag[3]) < 0) {
1604                                         err_o    1604                                         err_offset = opt_iter + 3;
1605                                         goto     1605                                         goto validate_return_locked;
1606                                 }                1606                                 }
1607                                 if (tag_len >    1607                                 if (tag_len > 4 &&
1608                                     cipso_v4_    1608                                     cipso_v4_map_cat_rbm_valid(doi_def,
1609                                                  1609                                                             &tag[4],
1610                                                  1610                                                             tag_len - 4) < 0) {
1611                                         err_o    1611                                         err_offset = opt_iter + 4;
1612                                         goto     1612                                         goto validate_return_locked;
1613                                 }                1613                                 }
1614                         }                        1614                         }
1615                         break;                   1615                         break;
1616                 case CIPSO_V4_TAG_ENUM:          1616                 case CIPSO_V4_TAG_ENUM:
1617                         if (tag_len < 4) {       1617                         if (tag_len < 4) {
1618                                 err_offset =     1618                                 err_offset = opt_iter + 1;
1619                                 goto validate    1619                                 goto validate_return_locked;
1620                         }                        1620                         }
1621                                                  1621 
1622                         if (cipso_v4_map_lvl_    1622                         if (cipso_v4_map_lvl_valid(doi_def,
1623                                                  1623                                                    tag[3]) < 0) {
1624                                 err_offset =     1624                                 err_offset = opt_iter + 3;
1625                                 goto validate    1625                                 goto validate_return_locked;
1626                         }                        1626                         }
1627                         if (tag_len > 4 &&       1627                         if (tag_len > 4 &&
1628                             cipso_v4_map_cat_    1628                             cipso_v4_map_cat_enum_valid(doi_def,
1629                                                  1629                                                         &tag[4],
1630                                                  1630                                                         tag_len - 4) < 0) {
1631                                 err_offset =     1631                                 err_offset = opt_iter + 4;
1632                                 goto validate    1632                                 goto validate_return_locked;
1633                         }                        1633                         }
1634                         break;                   1634                         break;
1635                 case CIPSO_V4_TAG_RANGE:         1635                 case CIPSO_V4_TAG_RANGE:
1636                         if (tag_len < 4) {       1636                         if (tag_len < 4) {
1637                                 err_offset =     1637                                 err_offset = opt_iter + 1;
1638                                 goto validate    1638                                 goto validate_return_locked;
1639                         }                        1639                         }
1640                                                  1640 
1641                         if (cipso_v4_map_lvl_    1641                         if (cipso_v4_map_lvl_valid(doi_def,
1642                                                  1642                                                    tag[3]) < 0) {
1643                                 err_offset =     1643                                 err_offset = opt_iter + 3;
1644                                 goto validate    1644                                 goto validate_return_locked;
1645                         }                        1645                         }
1646                         if (tag_len > 4 &&       1646                         if (tag_len > 4 &&
1647                             cipso_v4_map_cat_    1647                             cipso_v4_map_cat_rng_valid(doi_def,
1648                                                  1648                                                        &tag[4],
1649                                                  1649                                                        tag_len - 4) < 0) {
1650                                 err_offset =     1650                                 err_offset = opt_iter + 4;
1651                                 goto validate    1651                                 goto validate_return_locked;
1652                         }                        1652                         }
1653                         break;                   1653                         break;
1654                 default:                         1654                 default:
1655                         err_offset = opt_iter    1655                         err_offset = opt_iter;
1656                         goto validate_return_    1656                         goto validate_return_locked;
1657                 }                                1657                 }
1658                                                  1658 
1659                 tag += tag_len;                  1659                 tag += tag_len;
1660                 opt_iter += tag_len;             1660                 opt_iter += tag_len;
1661         }                                        1661         }
1662                                                  1662 
1663 validate_return_locked:                          1663 validate_return_locked:
1664         rcu_read_unlock();                       1664         rcu_read_unlock();
1665 validate_return:                                 1665 validate_return:
1666         *option = opt + err_offset;              1666         *option = opt + err_offset;
1667         return err_offset;                       1667         return err_offset;
1668 }                                                1668 }
1669                                                  1669 
1670 /**                                              1670 /**
1671  * cipso_v4_error - Send the correct reponse     1671  * cipso_v4_error - Send the correct reponse for a bad packet
1672  * @skb: the packet                              1672  * @skb: the packet
1673  * @error: the error code                        1673  * @error: the error code
1674  * @gateway: CIPSO gateway flag                  1674  * @gateway: CIPSO gateway flag
1675  *                                               1675  *
1676  * Description:                                  1676  * Description:
1677  * Based on the error code given in @error, s    1677  * Based on the error code given in @error, send an ICMP error message back to
1678  * the originating host.  From the IETF draft    1678  * the originating host.  From the IETF draft ...
1679  *                                               1679  *
1680  *  "If the contents of the CIPSO [option] ar    1680  *  "If the contents of the CIPSO [option] are valid but the security label is
1681  *   outside of the configured host or port l    1681  *   outside of the configured host or port label range, the datagram is
1682  *   discarded and an ICMP 'destination unrea    1682  *   discarded and an ICMP 'destination unreachable' (type 3) is generated and
1683  *   returned.  The code field of the ICMP is    1683  *   returned.  The code field of the ICMP is set to 'communication with
1684  *   destination network administratively pro    1684  *   destination network administratively prohibited' (code 9) or to
1685  *   'communication with destination host adm    1685  *   'communication with destination host administratively prohibited'
1686  *   (code 10).  The value of the code is dep    1686  *   (code 10).  The value of the code is dependent on whether the originator
1687  *   of the ICMP message is acting as a CIPSO    1687  *   of the ICMP message is acting as a CIPSO host or a CIPSO gateway.  The
1688  *   recipient of the ICMP message MUST be ab    1688  *   recipient of the ICMP message MUST be able to handle either value.  The
1689  *   same procedure is performed if a CIPSO [    1689  *   same procedure is performed if a CIPSO [option] can not be added to an
1690  *   IP packet because it is too large to fit    1690  *   IP packet because it is too large to fit in the IP options area."
1691  *                                               1691  *
1692  *  "If the error is triggered by receipt of     1692  *  "If the error is triggered by receipt of an ICMP message, the message is
1693  *   discarded and no response is permitted (    1693  *   discarded and no response is permitted (consistent with general ICMP
1694  *   processing rules)."                         1694  *   processing rules)."
1695  *                                               1695  *
1696  */                                              1696  */
1697 void cipso_v4_error(struct sk_buff *skb, int     1697 void cipso_v4_error(struct sk_buff *skb, int error, u32 gateway)
1698 {                                                1698 {
1699         if (ip_hdr(skb)->protocol == IPPROTO_    1699         if (ip_hdr(skb)->protocol == IPPROTO_ICMP || error != -EACCES)
1700                 return;                          1700                 return;
1701                                                  1701 
1702         if (gateway)                             1702         if (gateway)
1703                 icmp_send(skb, ICMP_DEST_UNRE    1703                 icmp_send(skb, ICMP_DEST_UNREACH, ICMP_NET_ANO, 0);
1704         else                                     1704         else
1705                 icmp_send(skb, ICMP_DEST_UNRE    1705                 icmp_send(skb, ICMP_DEST_UNREACH, ICMP_HOST_ANO, 0);
1706 }                                                1706 }
1707                                                  1707 
1708 /**                                              1708 /**
1709  * cipso_v4_sock_setattr - Add a CIPSO option    1709  * cipso_v4_sock_setattr - Add a CIPSO option to a socket
1710  * @sk: the socket                               1710  * @sk: the socket
1711  * @doi_def: the CIPSO DOI to use                1711  * @doi_def: the CIPSO DOI to use
1712  * @secattr: the specific security attributes    1712  * @secattr: the specific security attributes of the socket
1713  *                                               1713  *
1714  * Description:                                  1714  * Description:
1715  * Set the CIPSO option on the given socket u    1715  * Set the CIPSO option on the given socket using the DOI definition and
1716  * security attributes passed to the function    1716  * security attributes passed to the function.  This function requires
1717  * exclusive access to @sk, which means it ei    1717  * exclusive access to @sk, which means it either needs to be in the
1718  * process of being created or locked.  Retur    1718  * process of being created or locked.  Returns zero on success and negative
1719  * values on failure.                            1719  * values on failure.
1720  *                                               1720  *
1721  */                                              1721  */
1722 int cipso_v4_sock_setattr(struct sock *sk,       1722 int cipso_v4_sock_setattr(struct sock *sk,
1723                           const struct cipso_    1723                           const struct cipso_v4_doi *doi_def,
1724                           const struct netlbl    1724                           const struct netlbl_lsm_secattr *secattr)
1725 {                                                1725 {
1726         int ret_val = -EPERM;                    1726         int ret_val = -EPERM;
1727         u32 iter;                                1727         u32 iter;
1728         unsigned char *buf;                      1728         unsigned char *buf;
1729         u32 buf_len = 0;                         1729         u32 buf_len = 0;
1730         u32 opt_len;                             1730         u32 opt_len;
1731         struct ip_options *opt = NULL;           1731         struct ip_options *opt = NULL;
1732         struct inet_sock *sk_inet;               1732         struct inet_sock *sk_inet;
1733         struct inet_connection_sock *sk_conn;    1733         struct inet_connection_sock *sk_conn;
1734                                                  1734 
1735         /* In the case of sock_create_lite(),    1735         /* In the case of sock_create_lite(), the sock->sk field is not
1736          * defined yet but it is not a proble    1736          * defined yet but it is not a problem as the only users of these
1737          * "lite" PF_INET sockets are functio    1737          * "lite" PF_INET sockets are functions which do an accept() call
1738          * afterwards so we will label the so    1738          * afterwards so we will label the socket as part of the accept(). */
1739         if (sk == NULL)                          1739         if (sk == NULL)
1740                 return 0;                        1740                 return 0;
1741                                                  1741 
1742         /* We allocate the maximum CIPSO opti    1742         /* We allocate the maximum CIPSO option size here so we are probably
1743          * being a little wasteful, but it ma    1743          * being a little wasteful, but it makes our life _much_ easier later
1744          * on and after all we are only talki    1744          * on and after all we are only talking about 40 bytes. */
1745         buf_len = CIPSO_V4_OPT_LEN_MAX;          1745         buf_len = CIPSO_V4_OPT_LEN_MAX;
1746         buf = kmalloc(buf_len, GFP_ATOMIC);      1746         buf = kmalloc(buf_len, GFP_ATOMIC);
1747         if (buf == NULL) {                       1747         if (buf == NULL) {
1748                 ret_val = -ENOMEM;               1748                 ret_val = -ENOMEM;
1749                 goto socket_setattr_failure;     1749                 goto socket_setattr_failure;
1750         }                                        1750         }
1751                                                  1751 
1752         /* XXX - This code assumes only one t    1752         /* XXX - This code assumes only one tag per CIPSO option which isn't
1753          * really a good assumption to make b    1753          * really a good assumption to make but since we only support the MAC
1754          * tags right now it is a safe assump    1754          * tags right now it is a safe assumption. */
1755         iter = 0;                                1755         iter = 0;
1756         do {                                     1756         do {
1757                 memset(buf, 0, buf_len);         1757                 memset(buf, 0, buf_len);
1758                 switch (doi_def->tags[iter])     1758                 switch (doi_def->tags[iter]) {
1759                 case CIPSO_V4_TAG_RBITMAP:       1759                 case CIPSO_V4_TAG_RBITMAP:
1760                         ret_val = cipso_v4_ge    1760                         ret_val = cipso_v4_gentag_rbm(doi_def,
1761                                                  1761                                                    secattr,
1762                                                  1762                                                    &buf[CIPSO_V4_HDR_LEN],
1763                                                  1763                                                    buf_len - CIPSO_V4_HDR_LEN);
1764                         break;                   1764                         break;
1765                 case CIPSO_V4_TAG_ENUM:          1765                 case CIPSO_V4_TAG_ENUM:
1766                         ret_val = cipso_v4_ge    1766                         ret_val = cipso_v4_gentag_enum(doi_def,
1767                                                  1767                                                    secattr,
1768                                                  1768                                                    &buf[CIPSO_V4_HDR_LEN],
1769                                                  1769                                                    buf_len - CIPSO_V4_HDR_LEN);
1770                         break;                   1770                         break;
1771                 case CIPSO_V4_TAG_RANGE:         1771                 case CIPSO_V4_TAG_RANGE:
1772                         ret_val = cipso_v4_ge    1772                         ret_val = cipso_v4_gentag_rng(doi_def,
1773                                                  1773                                                    secattr,
1774                                                  1774                                                    &buf[CIPSO_V4_HDR_LEN],
1775                                                  1775                                                    buf_len - CIPSO_V4_HDR_LEN);
1776                         break;                   1776                         break;
1777                 default:                         1777                 default:
1778                         ret_val = -EPERM;        1778                         ret_val = -EPERM;
1779                         goto socket_setattr_f    1779                         goto socket_setattr_failure;
1780                 }                                1780                 }
1781                                                  1781 
1782                 iter++;                          1782                 iter++;
1783         } while (ret_val < 0 &&                  1783         } while (ret_val < 0 &&
1784                  iter < CIPSO_V4_TAG_MAXCNT &    1784                  iter < CIPSO_V4_TAG_MAXCNT &&
1785                  doi_def->tags[iter] != CIPSO    1785                  doi_def->tags[iter] != CIPSO_V4_TAG_INVALID);
1786         if (ret_val < 0)                         1786         if (ret_val < 0)
1787                 goto socket_setattr_failure;     1787                 goto socket_setattr_failure;
1788         cipso_v4_gentag_hdr(doi_def, buf, ret    1788         cipso_v4_gentag_hdr(doi_def, buf, ret_val);
1789         buf_len = CIPSO_V4_HDR_LEN + ret_val;    1789         buf_len = CIPSO_V4_HDR_LEN + ret_val;
1790                                                  1790 
1791         /* We can't use ip_options_get() dire    1791         /* We can't use ip_options_get() directly because it makes a call to
1792          * ip_options_get_alloc() which alloc    1792          * ip_options_get_alloc() which allocates memory with GFP_KERNEL and
1793          * we won't always have CAP_NET_RAW e    1793          * we won't always have CAP_NET_RAW even though we _always_ want to
1794          * set the IPOPT_CIPSO option. */        1794          * set the IPOPT_CIPSO option. */
1795         opt_len = (buf_len + 3) & ~3;            1795         opt_len = (buf_len + 3) & ~3;
1796         opt = kzalloc(sizeof(*opt) + opt_len,    1796         opt = kzalloc(sizeof(*opt) + opt_len, GFP_ATOMIC);
1797         if (opt == NULL) {                       1797         if (opt == NULL) {
1798                 ret_val = -ENOMEM;               1798                 ret_val = -ENOMEM;
1799                 goto socket_setattr_failure;     1799                 goto socket_setattr_failure;
1800         }                                        1800         }
1801         memcpy(opt->__data, buf, buf_len);       1801         memcpy(opt->__data, buf, buf_len);
1802         opt->optlen = opt_len;                   1802         opt->optlen = opt_len;
1803         opt->is_data = 1;                        1803         opt->is_data = 1;
1804         opt->cipso = sizeof(struct iphdr);       1804         opt->cipso = sizeof(struct iphdr);
1805         kfree(buf);                              1805         kfree(buf);
1806         buf = NULL;                              1806         buf = NULL;
1807                                                  1807 
1808         sk_inet = inet_sk(sk);                   1808         sk_inet = inet_sk(sk);
1809         if (sk_inet->is_icsk) {                  1809         if (sk_inet->is_icsk) {
1810                 sk_conn = inet_csk(sk);          1810                 sk_conn = inet_csk(sk);
1811                 if (sk_inet->opt)                1811                 if (sk_inet->opt)
1812                         sk_conn->icsk_ext_hdr    1812                         sk_conn->icsk_ext_hdr_len -= sk_inet->opt->optlen;
1813                 sk_conn->icsk_ext_hdr_len +=     1813                 sk_conn->icsk_ext_hdr_len += opt->optlen;
1814                 sk_conn->icsk_sync_mss(sk, sk    1814                 sk_conn->icsk_sync_mss(sk, sk_conn->icsk_pmtu_cookie);
1815         }                                        1815         }
1816         opt = xchg(&sk_inet->opt, opt);          1816         opt = xchg(&sk_inet->opt, opt);
1817         kfree(opt);                              1817         kfree(opt);
1818                                                  1818 
1819         return 0;                                1819         return 0;
1820                                                  1820 
1821 socket_setattr_failure:                          1821 socket_setattr_failure:
1822         kfree(buf);                              1822         kfree(buf);
1823         kfree(opt);                              1823         kfree(opt);
1824         return ret_val;                          1824         return ret_val;
1825 }                                                1825 }
1826                                                  1826 
1827 /**                                              1827 /**
1828  * cipso_v4_getattr - Helper function for the    1828  * cipso_v4_getattr - Helper function for the cipso_v4_*_getattr functions
1829  * @cipso: the CIPSO v4 option                   1829  * @cipso: the CIPSO v4 option
1830  * @secattr: the security attributes             1830  * @secattr: the security attributes
1831  *                                               1831  *
1832  * Description:                                  1832  * Description:
1833  * Inspect @cipso and return the security att    1833  * Inspect @cipso and return the security attributes in @secattr.  Returns zero
1834  * on success and negative values on failure.    1834  * on success and negative values on failure.
1835  *                                               1835  *
1836  */                                              1836  */
1837 static int cipso_v4_getattr(const unsigned ch    1837 static int cipso_v4_getattr(const unsigned char *cipso,
1838                             struct netlbl_lsm    1838                             struct netlbl_lsm_secattr *secattr)
1839 {                                                1839 {
1840         int ret_val = -ENOMSG;                   1840         int ret_val = -ENOMSG;
1841         u32 doi;                                 1841         u32 doi;
1842         struct cipso_v4_doi *doi_def;            1842         struct cipso_v4_doi *doi_def;
1843                                                  1843 
1844         if (cipso_v4_cache_check(cipso, cipso    1844         if (cipso_v4_cache_check(cipso, cipso[1], secattr) == 0)
1845                 return 0;                        1845                 return 0;
1846                                                  1846 
1847         doi = ntohl(get_unaligned((__be32 *)&    1847         doi = ntohl(get_unaligned((__be32 *)&cipso[2]));
1848         rcu_read_lock();                         1848         rcu_read_lock();
1849         doi_def = cipso_v4_doi_search(doi);      1849         doi_def = cipso_v4_doi_search(doi);
1850         if (doi_def == NULL)                     1850         if (doi_def == NULL)
1851                 goto getattr_return;             1851                 goto getattr_return;
1852         /* XXX - This code assumes only one t    1852         /* XXX - This code assumes only one tag per CIPSO option which isn't
1853          * really a good assumption to make b    1853          * really a good assumption to make but since we only support the MAC
1854          * tags right now it is a safe assump    1854          * tags right now it is a safe assumption. */
1855         switch (cipso[6]) {                      1855         switch (cipso[6]) {
1856         case CIPSO_V4_TAG_RBITMAP:               1856         case CIPSO_V4_TAG_RBITMAP:
1857                 ret_val = cipso_v4_parsetag_r    1857                 ret_val = cipso_v4_parsetag_rbm(doi_def, &cipso[6], secattr);
1858                 break;                           1858                 break;
1859         case CIPSO_V4_TAG_ENUM:                  1859         case CIPSO_V4_TAG_ENUM:
1860                 ret_val = cipso_v4_parsetag_e    1860                 ret_val = cipso_v4_parsetag_enum(doi_def, &cipso[6], secattr);
1861                 break;                           1861                 break;
1862         case CIPSO_V4_TAG_RANGE:                 1862         case CIPSO_V4_TAG_RANGE:
1863                 ret_val = cipso_v4_parsetag_r    1863                 ret_val = cipso_v4_parsetag_rng(doi_def, &cipso[6], secattr);
1864                 break;                           1864                 break;
1865         }                                        1865         }
1866         if (ret_val == 0)                        1866         if (ret_val == 0)
1867                 secattr->type = NETLBL_NLTYPE    1867                 secattr->type = NETLBL_NLTYPE_CIPSOV4;
1868                                                  1868 
1869 getattr_return:                                  1869 getattr_return:
1870         rcu_read_unlock();                       1870         rcu_read_unlock();
1871         return ret_val;                          1871         return ret_val;
1872 }                                                1872 }
1873                                                  1873 
1874 /**                                              1874 /**
1875  * cipso_v4_sock_getattr - Get the security a    1875  * cipso_v4_sock_getattr - Get the security attributes from a sock
1876  * @sk: the sock                                 1876  * @sk: the sock
1877  * @secattr: the security attributes             1877  * @secattr: the security attributes
1878  *                                               1878  *
1879  * Description:                                  1879  * Description:
1880  * Query @sk to see if there is a CIPSO optio    1880  * Query @sk to see if there is a CIPSO option attached to the sock and if
1881  * there is return the CIPSO security attribu    1881  * there is return the CIPSO security attributes in @secattr.  This function
1882  * requires that @sk be locked, or privately     1882  * requires that @sk be locked, or privately held, but it does not do any
1883  * locking itself.  Returns zero on success a    1883  * locking itself.  Returns zero on success and negative values on failure.
1884  *                                               1884  *
1885  */                                              1885  */
1886 int cipso_v4_sock_getattr(struct sock *sk, st    1886 int cipso_v4_sock_getattr(struct sock *sk, struct netlbl_lsm_secattr *secattr)
1887 {                                                1887 {
1888         struct ip_options *opt;                  1888         struct ip_options *opt;
1889                                                  1889 
1890         opt = inet_sk(sk)->opt;                  1890         opt = inet_sk(sk)->opt;
1891         if (opt == NULL || opt->cipso == 0)      1891         if (opt == NULL || opt->cipso == 0)
1892                 return -ENOMSG;                  1892                 return -ENOMSG;
1893                                                  1893 
1894         return cipso_v4_getattr(opt->__data +    1894         return cipso_v4_getattr(opt->__data + opt->cipso - sizeof(struct iphdr),
1895                                 secattr);        1895                                 secattr);
1896 }                                                1896 }
1897                                                  1897 
1898 /**                                              1898 /**
1899  * cipso_v4_skbuff_getattr - Get the security    1899  * cipso_v4_skbuff_getattr - Get the security attributes from the CIPSO option
1900  * @skb: the packet                              1900  * @skb: the packet
1901  * @secattr: the security attributes             1901  * @secattr: the security attributes
1902  *                                               1902  *
1903  * Description:                                  1903  * Description:
1904  * Parse the given packet's CIPSO option and     1904  * Parse the given packet's CIPSO option and return the security attributes.
1905  * Returns zero on success and negative value    1905  * Returns zero on success and negative values on failure.
1906  *                                               1906  *
1907  */                                              1907  */
1908 int cipso_v4_skbuff_getattr(const struct sk_b    1908 int cipso_v4_skbuff_getattr(const struct sk_buff *skb,
1909                             struct netlbl_lsm    1909                             struct netlbl_lsm_secattr *secattr)
1910 {                                                1910 {
1911         return cipso_v4_getattr(CIPSO_V4_OPTP    1911         return cipso_v4_getattr(CIPSO_V4_OPTPTR(skb), secattr);
1912 }                                                1912 }
1913                                                  1913 
1914 /*                                               1914 /*
1915  * Setup Functions                               1915  * Setup Functions
1916  */                                              1916  */
1917                                                  1917 
1918 /**                                              1918 /**
1919  * cipso_v4_init - Initialize the CIPSO modul    1919  * cipso_v4_init - Initialize the CIPSO module
1920  *                                               1920  *
1921  * Description:                                  1921  * Description:
1922  * Initialize the CIPSO module and prepare it    1922  * Initialize the CIPSO module and prepare it for use.  Returns zero on success
1923  * and negative values on failure.               1923  * and negative values on failure.
1924  *                                               1924  *
1925  */                                              1925  */
1926 static int __init cipso_v4_init(void)            1926 static int __init cipso_v4_init(void)
1927 {                                                1927 {
1928         int ret_val;                             1928         int ret_val;
1929                                                  1929 
1930         ret_val = cipso_v4_cache_init();         1930         ret_val = cipso_v4_cache_init();
1931         if (ret_val != 0)                        1931         if (ret_val != 0)
1932                 panic("Failed to initialize t    1932                 panic("Failed to initialize the CIPSO/IPv4 cache (%d)\n",
1933                       ret_val);                  1933                       ret_val);
1934                                                  1934 
1935         return 0;                                1935         return 0;
1936 }                                                1936 }
1937                                                  1937 
1938 subsys_initcall(cipso_v4_init);                  1938 subsys_initcall(cipso_v4_init);
1939                                                  1939 
  This page was automatically generated by the LXR engine.