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