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