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