[NetLabel]: add audit support for configuration changes
[linux-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, copies of both documents can be found in the Documentation
7  * directory.  While CIPSO never became a full IETF RFC standard many vendors
8  * have chosen to adopt the protocol and over the years it has become a
9  * de-facto standard for labeled networking.
10  *
11  * Author: Paul Moore <paul.moore@hp.com>
12  *
13  */
14
15 /*
16  * (c) Copyright Hewlett-Packard Development Company, L.P., 2006
17  *
18  * This program is free software;  you can redistribute it and/or modify
19  * it under the terms of the GNU General Public License as published by
20  * the Free Software Foundation; either version 2 of the License, or
21  * (at your option) any later version.
22  *
23  * This program is distributed in the hope that it will be useful,
24  * but WITHOUT ANY WARRANTY;  without even the implied warranty of
25  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
26  * the GNU General Public License for more details.
27  *
28  * You should have received a copy of the GNU General Public License
29  * along with this program;  if not, write to the Free Software
30  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
31  *
32  */
33
34 #include <linux/init.h>
35 #include <linux/types.h>
36 #include <linux/rcupdate.h>
37 #include <linux/list.h>
38 #include <linux/spinlock.h>
39 #include <linux/string.h>
40 #include <linux/jhash.h>
41 #include <net/ip.h>
42 #include <net/icmp.h>
43 #include <net/tcp.h>
44 #include <net/netlabel.h>
45 #include <net/cipso_ipv4.h>
46 #include <asm/bug.h>
47
48 struct cipso_v4_domhsh_entry {
49         char *domain;
50         u32 valid;
51         struct list_head list;
52         struct rcu_head rcu;
53 };
54
55 /* List of available DOI definitions */
56 /* XXX - Updates should be minimal so having a single lock for the
57  * cipso_v4_doi_list and the cipso_v4_doi_list->dom_list should be
58  * okay. */
59 /* XXX - This currently assumes a minimal number of different DOIs in use,
60  * if in practice there are a lot of different DOIs this list should
61  * probably be turned into a hash table or something similar so we
62  * can do quick lookups. */
63 static DEFINE_SPINLOCK(cipso_v4_doi_list_lock);
64 static struct list_head cipso_v4_doi_list = LIST_HEAD_INIT(cipso_v4_doi_list);
65
66 /* Label mapping cache */
67 int cipso_v4_cache_enabled = 1;
68 int cipso_v4_cache_bucketsize = 10;
69 #define CIPSO_V4_CACHE_BUCKETBITS     7
70 #define CIPSO_V4_CACHE_BUCKETS        (1 << CIPSO_V4_CACHE_BUCKETBITS)
71 #define CIPSO_V4_CACHE_REORDERLIMIT   10
72 struct cipso_v4_map_cache_bkt {
73         spinlock_t lock;
74         u32 size;
75         struct list_head list;
76 };
77 struct cipso_v4_map_cache_entry {
78         u32 hash;
79         unsigned char *key;
80         size_t key_len;
81
82         struct netlbl_lsm_cache lsm_data;
83
84         u32 activity;
85         struct list_head list;
86 };
87 static struct cipso_v4_map_cache_bkt *cipso_v4_cache = NULL;
88
89 /* Restricted bitmap (tag #1) flags */
90 int cipso_v4_rbm_optfmt = 0;
91 int cipso_v4_rbm_strictvalid = 1;
92
93 /*
94  * Helper Functions
95  */
96
97 /**
98  * cipso_v4_bitmap_walk - Walk a bitmap looking for a bit
99  * @bitmap: the bitmap
100  * @bitmap_len: length in bits
101  * @offset: starting offset
102  * @state: if non-zero, look for a set (1) bit else look for a cleared (0) bit
103  *
104  * Description:
105  * Starting at @offset, walk the bitmap from left to right until either the
106  * desired bit is found or we reach the end.  Return the bit offset, -1 if
107  * not found, or -2 if error.
108  */
109 static int cipso_v4_bitmap_walk(const unsigned char *bitmap,
110                                 u32 bitmap_len,
111                                 u32 offset,
112                                 u8 state)
113 {
114         u32 bit_spot;
115         u32 byte_offset;
116         unsigned char bitmask;
117         unsigned char byte;
118
119         /* gcc always rounds to zero when doing integer division */
120         byte_offset = offset / 8;
121         byte = bitmap[byte_offset];
122         bit_spot = offset;
123         bitmask = 0x80 >> (offset % 8);
124
125         while (bit_spot < bitmap_len) {
126                 if ((state && (byte & bitmask) == bitmask) ||
127                     (state == 0 && (byte & bitmask) == 0))
128                         return bit_spot;
129
130                 bit_spot++;
131                 bitmask >>= 1;
132                 if (bitmask == 0) {
133                         byte = bitmap[++byte_offset];
134                         bitmask = 0x80;
135                 }
136         }
137
138         return -1;
139 }
140
141 /**
142  * cipso_v4_bitmap_setbit - Sets a single bit in a bitmap
143  * @bitmap: the bitmap
144  * @bit: the bit
145  * @state: if non-zero, set the bit (1) else clear the bit (0)
146  *
147  * Description:
148  * Set a single bit in the bitmask.  Returns zero on success, negative values
149  * on error.
150  */
151 static void cipso_v4_bitmap_setbit(unsigned char *bitmap,
152                                    u32 bit,
153                                    u8 state)
154 {
155         u32 byte_spot;
156         u8 bitmask;
157
158         /* gcc always rounds to zero when doing integer division */
159         byte_spot = bit / 8;
160         bitmask = 0x80 >> (bit % 8);
161         if (state)
162                 bitmap[byte_spot] |= bitmask;
163         else
164                 bitmap[byte_spot] &= ~bitmask;
165 }
166
167 /**
168  * cipso_v4_doi_domhsh_free - Frees a domain list entry
169  * @entry: the entry's RCU field
170  *
171  * Description:
172  * This function is designed to be used as a callback to the call_rcu()
173  * function so that the memory allocated to a domain list entry can be released
174  * safely.
175  *
176  */
177 static void cipso_v4_doi_domhsh_free(struct rcu_head *entry)
178 {
179         struct cipso_v4_domhsh_entry *ptr;
180
181         ptr = container_of(entry, struct cipso_v4_domhsh_entry, rcu);
182         kfree(ptr->domain);
183         kfree(ptr);
184 }
185
186 /**
187  * cipso_v4_cache_entry_free - Frees a cache entry
188  * @entry: the entry to free
189  *
190  * Description:
191  * This function frees the memory associated with a cache entry.
192  *
193  */
194 static void cipso_v4_cache_entry_free(struct cipso_v4_map_cache_entry *entry)
195 {
196         if (entry->lsm_data.free)
197                 entry->lsm_data.free(entry->lsm_data.data);
198         kfree(entry->key);
199         kfree(entry);
200 }
201
202 /**
203  * cipso_v4_map_cache_hash - Hashing function for the CIPSO cache
204  * @key: the hash key
205  * @key_len: the length of the key in bytes
206  *
207  * Description:
208  * The CIPSO tag hashing function.  Returns a 32-bit hash value.
209  *
210  */
211 static u32 cipso_v4_map_cache_hash(const unsigned char *key, u32 key_len)
212 {
213         return jhash(key, key_len, 0);
214 }
215
216 /*
217  * Label Mapping Cache Functions
218  */
219
220 /**
221  * cipso_v4_cache_init - Initialize the CIPSO cache
222  *
223  * Description:
224  * Initializes the CIPSO label mapping cache, this function should be called
225  * before any of the other functions defined in this file.  Returns zero on
226  * success, negative values on error.
227  *
228  */
229 static int cipso_v4_cache_init(void)
230 {
231         u32 iter;
232
233         cipso_v4_cache = kcalloc(CIPSO_V4_CACHE_BUCKETS,
234                                  sizeof(struct cipso_v4_map_cache_bkt),
235                                  GFP_KERNEL);
236         if (cipso_v4_cache == NULL)
237                 return -ENOMEM;
238
239         for (iter = 0; iter < CIPSO_V4_CACHE_BUCKETS; iter++) {
240                 spin_lock_init(&cipso_v4_cache[iter].lock);
241                 cipso_v4_cache[iter].size = 0;
242                 INIT_LIST_HEAD(&cipso_v4_cache[iter].list);
243         }
244
245         return 0;
246 }
247
248 /**
249  * cipso_v4_cache_invalidate - Invalidates the current CIPSO cache
250  *
251  * Description:
252  * Invalidates and frees any entries in the CIPSO cache.  Returns zero on
253  * success and negative values on failure.
254  *
255  */
256 void cipso_v4_cache_invalidate(void)
257 {
258         struct cipso_v4_map_cache_entry *entry, *tmp_entry;
259         u32 iter;
260
261         for (iter = 0; iter < CIPSO_V4_CACHE_BUCKETS; iter++) {
262                 spin_lock_bh(&cipso_v4_cache[iter].lock);
263                 list_for_each_entry_safe(entry,
264                                          tmp_entry,
265                                          &cipso_v4_cache[iter].list, list) {
266                         list_del(&entry->list);
267                         cipso_v4_cache_entry_free(entry);
268                 }
269                 cipso_v4_cache[iter].size = 0;
270                 spin_unlock_bh(&cipso_v4_cache[iter].lock);
271         }
272
273         return;
274 }
275
276 /**
277  * cipso_v4_cache_check - Check the CIPSO cache for a label mapping
278  * @key: the buffer to check
279  * @key_len: buffer length in bytes
280  * @secattr: the security attribute struct to use
281  *
282  * Description:
283  * This function checks the cache to see if a label mapping already exists for
284  * the given key.  If there is a match then the cache is adjusted and the
285  * @secattr struct is populated with the correct LSM security attributes.  The
286  * cache is adjusted in the following manner if the entry is not already the
287  * first in the cache bucket:
288  *
289  *  1. The cache entry's activity counter is incremented
290  *  2. The previous (higher ranking) entry's activity counter is decremented
291  *  3. If the difference between the two activity counters is geater than
292  *     CIPSO_V4_CACHE_REORDERLIMIT the two entries are swapped
293  *
294  * Returns zero on success, -ENOENT for a cache miss, and other negative values
295  * on error.
296  *
297  */
298 static int cipso_v4_cache_check(const unsigned char *key,
299                                 u32 key_len,
300                                 struct netlbl_lsm_secattr *secattr)
301 {
302         u32 bkt;
303         struct cipso_v4_map_cache_entry *entry;
304         struct cipso_v4_map_cache_entry *prev_entry = NULL;
305         u32 hash;
306
307         if (!cipso_v4_cache_enabled)
308                 return -ENOENT;
309
310         hash = cipso_v4_map_cache_hash(key, key_len);
311         bkt = hash & (CIPSO_V4_CACHE_BUCKETBITS - 1);
312         spin_lock_bh(&cipso_v4_cache[bkt].lock);
313         list_for_each_entry(entry, &cipso_v4_cache[bkt].list, list) {
314                 if (entry->hash == hash &&
315                     entry->key_len == key_len &&
316                     memcmp(entry->key, key, key_len) == 0) {
317                         entry->activity += 1;
318                         secattr->cache.free = entry->lsm_data.free;
319                         secattr->cache.data = entry->lsm_data.data;
320                         if (prev_entry == NULL) {
321                                 spin_unlock_bh(&cipso_v4_cache[bkt].lock);
322                                 return 0;
323                         }
324
325                         if (prev_entry->activity > 0)
326                                 prev_entry->activity -= 1;
327                         if (entry->activity > prev_entry->activity &&
328                             entry->activity - prev_entry->activity >
329                             CIPSO_V4_CACHE_REORDERLIMIT) {
330                                 __list_del(entry->list.prev, entry->list.next);
331                                 __list_add(&entry->list,
332                                            prev_entry->list.prev,
333                                            &prev_entry->list);
334                         }
335
336                         spin_unlock_bh(&cipso_v4_cache[bkt].lock);
337                         return 0;
338                 }
339                 prev_entry = entry;
340         }
341         spin_unlock_bh(&cipso_v4_cache[bkt].lock);
342
343         return -ENOENT;
344 }
345
346 /**
347  * cipso_v4_cache_add - Add an entry to the CIPSO cache
348  * @skb: the packet
349  * @secattr: the packet's security attributes
350  *
351  * Description:
352  * Add a new entry into the CIPSO label mapping cache.  Add the new entry to
353  * head of the cache bucket's list, if the cache bucket is out of room remove
354  * the last entry in the list first.  It is important to note that there is
355  * currently no checking for duplicate keys.  Returns zero on success,
356  * negative values on failure.
357  *
358  */
359 int cipso_v4_cache_add(const struct sk_buff *skb,
360                        const struct netlbl_lsm_secattr *secattr)
361 {
362         int ret_val = -EPERM;
363         u32 bkt;
364         struct cipso_v4_map_cache_entry *entry = NULL;
365         struct cipso_v4_map_cache_entry *old_entry = NULL;
366         unsigned char *cipso_ptr;
367         u32 cipso_ptr_len;
368
369         if (!cipso_v4_cache_enabled || cipso_v4_cache_bucketsize <= 0)
370                 return 0;
371
372         cipso_ptr = CIPSO_V4_OPTPTR(skb);
373         cipso_ptr_len = cipso_ptr[1];
374
375         entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
376         if (entry == NULL)
377                 return -ENOMEM;
378         entry->key = kmalloc(cipso_ptr_len, GFP_ATOMIC);
379         if (entry->key == NULL) {
380                 ret_val = -ENOMEM;
381                 goto cache_add_failure;
382         }
383         memcpy(entry->key, cipso_ptr, cipso_ptr_len);
384         entry->key_len = cipso_ptr_len;
385         entry->hash = cipso_v4_map_cache_hash(cipso_ptr, cipso_ptr_len);
386         entry->lsm_data.free = secattr->cache.free;
387         entry->lsm_data.data = secattr->cache.data;
388
389         bkt = entry->hash & (CIPSO_V4_CACHE_BUCKETBITS - 1);
390         spin_lock_bh(&cipso_v4_cache[bkt].lock);
391         if (cipso_v4_cache[bkt].size < cipso_v4_cache_bucketsize) {
392                 list_add(&entry->list, &cipso_v4_cache[bkt].list);
393                 cipso_v4_cache[bkt].size += 1;
394         } else {
395                 old_entry = list_entry(cipso_v4_cache[bkt].list.prev,
396                                        struct cipso_v4_map_cache_entry, list);
397                 list_del(&old_entry->list);
398                 list_add(&entry->list, &cipso_v4_cache[bkt].list);
399                 cipso_v4_cache_entry_free(old_entry);
400         }
401         spin_unlock_bh(&cipso_v4_cache[bkt].lock);
402
403         return 0;
404
405 cache_add_failure:
406         if (entry)
407                 cipso_v4_cache_entry_free(entry);
408         return ret_val;
409 }
410
411 /*
412  * DOI List Functions
413  */
414
415 /**
416  * cipso_v4_doi_search - Searches for a DOI definition
417  * @doi: the DOI to search for
418  *
419  * Description:
420  * Search the DOI definition list for a DOI definition with a DOI value that
421  * matches @doi.  The caller is responsibile for calling rcu_read_[un]lock().
422  * Returns a pointer to the DOI definition on success and NULL on failure.
423  */
424 static struct cipso_v4_doi *cipso_v4_doi_search(u32 doi)
425 {
426         struct cipso_v4_doi *iter;
427
428         list_for_each_entry_rcu(iter, &cipso_v4_doi_list, list)
429                 if (iter->doi == doi && iter->valid)
430                         return iter;
431         return NULL;
432 }
433
434 /**
435  * cipso_v4_doi_add - Add a new DOI to the CIPSO protocol engine
436  * @doi_def: the DOI structure
437  *
438  * Description:
439  * The caller defines a new DOI for use by the CIPSO engine and calls this
440  * function to add it to the list of acceptable domains.  The caller must
441  * ensure that the mapping table specified in @doi_def->map meets all of the
442  * requirements of the mapping type (see cipso_ipv4.h for details).  Returns
443  * zero on success and non-zero on failure.
444  *
445  */
446 int cipso_v4_doi_add(struct cipso_v4_doi *doi_def)
447 {
448         if (doi_def == NULL || doi_def->doi == CIPSO_V4_DOI_UNKNOWN)
449                 return -EINVAL;
450
451         doi_def->valid = 1;
452         INIT_RCU_HEAD(&doi_def->rcu);
453         INIT_LIST_HEAD(&doi_def->dom_list);
454
455         rcu_read_lock();
456         if (cipso_v4_doi_search(doi_def->doi) != NULL)
457                 goto doi_add_failure_rlock;
458         spin_lock(&cipso_v4_doi_list_lock);
459         if (cipso_v4_doi_search(doi_def->doi) != NULL)
460                 goto doi_add_failure_slock;
461         list_add_tail_rcu(&doi_def->list, &cipso_v4_doi_list);
462         spin_unlock(&cipso_v4_doi_list_lock);
463         rcu_read_unlock();
464
465         return 0;
466
467 doi_add_failure_slock:
468         spin_unlock(&cipso_v4_doi_list_lock);
469 doi_add_failure_rlock:
470         rcu_read_unlock();
471         return -EEXIST;
472 }
473
474 /**
475  * cipso_v4_doi_remove - Remove an existing DOI from the CIPSO protocol engine
476  * @doi: the DOI value
477  * @audit_secid: the LSM secid to use in the audit message
478  * @callback: the DOI cleanup/free callback
479  *
480  * Description:
481  * Removes a DOI definition from the CIPSO engine, @callback is called to
482  * free any memory.  The NetLabel routines will be called to release their own
483  * LSM domain mappings as well as our own domain list.  Returns zero on
484  * success and negative values on failure.
485  *
486  */
487 int cipso_v4_doi_remove(u32 doi,
488                         u32 audit_secid,
489                         void (*callback) (struct rcu_head * head))
490 {
491         struct cipso_v4_doi *doi_def;
492         struct cipso_v4_domhsh_entry *dom_iter;
493
494         rcu_read_lock();
495         if (cipso_v4_doi_search(doi) != NULL) {
496                 spin_lock(&cipso_v4_doi_list_lock);
497                 doi_def = cipso_v4_doi_search(doi);
498                 if (doi_def == NULL) {
499                         spin_unlock(&cipso_v4_doi_list_lock);
500                         rcu_read_unlock();
501                         return -ENOENT;
502                 }
503                 doi_def->valid = 0;
504                 list_del_rcu(&doi_def->list);
505                 spin_unlock(&cipso_v4_doi_list_lock);
506                 list_for_each_entry_rcu(dom_iter, &doi_def->dom_list, list)
507                         if (dom_iter->valid)
508                                 netlbl_domhsh_remove(dom_iter->domain,
509                                                      audit_secid);
510                 cipso_v4_cache_invalidate();
511                 rcu_read_unlock();
512
513                 call_rcu(&doi_def->rcu, callback);
514                 return 0;
515         }
516         rcu_read_unlock();
517
518         return -ENOENT;
519 }
520
521 /**
522  * cipso_v4_doi_getdef - Returns a pointer to a valid DOI definition
523  * @doi: the DOI value
524  *
525  * Description:
526  * Searches for a valid DOI definition and if one is found it is returned to
527  * the caller.  Otherwise NULL is returned.  The caller must ensure that
528  * rcu_read_lock() is held while accessing the returned definition.
529  *
530  */
531 struct cipso_v4_doi *cipso_v4_doi_getdef(u32 doi)
532 {
533         return cipso_v4_doi_search(doi);
534 }
535
536 /**
537  * cipso_v4_doi_walk - Iterate through the DOI definitions
538  * @skip_cnt: skip past this number of DOI definitions, updated
539  * @callback: callback for each DOI definition
540  * @cb_arg: argument for the callback function
541  *
542  * Description:
543  * Iterate over the DOI definition list, skipping the first @skip_cnt entries.
544  * For each entry call @callback, if @callback returns a negative value stop
545  * 'walking' through the list and return.  Updates the value in @skip_cnt upon
546  * return.  Returns zero on success, negative values on failure.
547  *
548  */
549 int cipso_v4_doi_walk(u32 *skip_cnt,
550                      int (*callback) (struct cipso_v4_doi *doi_def, void *arg),
551                      void *cb_arg)
552 {
553         int ret_val = -ENOENT;
554         u32 doi_cnt = 0;
555         struct cipso_v4_doi *iter_doi;
556
557         rcu_read_lock();
558         list_for_each_entry_rcu(iter_doi, &cipso_v4_doi_list, list)
559                 if (iter_doi->valid) {
560                         if (doi_cnt++ < *skip_cnt)
561                                 continue;
562                         ret_val = callback(iter_doi, cb_arg);
563                         if (ret_val < 0) {
564                                 doi_cnt--;
565                                 goto doi_walk_return;
566                         }
567                 }
568
569 doi_walk_return:
570         rcu_read_unlock();
571         *skip_cnt = doi_cnt;
572         return ret_val;
573 }
574
575 /**
576  * cipso_v4_doi_domhsh_add - Adds a domain entry to a DOI definition
577  * @doi_def: the DOI definition
578  * @domain: the domain to add
579  *
580  * Description:
581  * Adds the @domain to the the DOI specified by @doi_def, this function
582  * should only be called by external functions (i.e. NetLabel).  This function
583  * does allocate memory.  Returns zero on success, negative values on failure.
584  *
585  */
586 int cipso_v4_doi_domhsh_add(struct cipso_v4_doi *doi_def, const char *domain)
587 {
588         struct cipso_v4_domhsh_entry *iter;
589         struct cipso_v4_domhsh_entry *new_dom;
590
591         new_dom = kzalloc(sizeof(*new_dom), GFP_KERNEL);
592         if (new_dom == NULL)
593                 return -ENOMEM;
594         if (domain) {
595                 new_dom->domain = kstrdup(domain, GFP_KERNEL);
596                 if (new_dom->domain == NULL) {
597                         kfree(new_dom);
598                         return -ENOMEM;
599                 }
600         }
601         new_dom->valid = 1;
602         INIT_RCU_HEAD(&new_dom->rcu);
603
604         rcu_read_lock();
605         spin_lock(&cipso_v4_doi_list_lock);
606         list_for_each_entry_rcu(iter, &doi_def->dom_list, list)
607                 if (iter->valid &&
608                     ((domain != NULL && iter->domain != NULL &&
609                       strcmp(iter->domain, domain) == 0) ||
610                      (domain == NULL && iter->domain == NULL))) {
611                         spin_unlock(&cipso_v4_doi_list_lock);
612                         rcu_read_unlock();
613                         kfree(new_dom->domain);
614                         kfree(new_dom);
615                         return -EEXIST;
616                 }
617         list_add_tail_rcu(&new_dom->list, &doi_def->dom_list);
618         spin_unlock(&cipso_v4_doi_list_lock);
619         rcu_read_unlock();
620
621         return 0;
622 }
623
624 /**
625  * cipso_v4_doi_domhsh_remove - Removes a domain entry from a DOI definition
626  * @doi_def: the DOI definition
627  * @domain: the domain to remove
628  *
629  * Description:
630  * Removes the @domain from the DOI specified by @doi_def, this function
631  * should only be called by external functions (i.e. NetLabel).   Returns zero
632  * on success and negative values on error.
633  *
634  */
635 int cipso_v4_doi_domhsh_remove(struct cipso_v4_doi *doi_def,
636                                const char *domain)
637 {
638         struct cipso_v4_domhsh_entry *iter;
639
640         rcu_read_lock();
641         spin_lock(&cipso_v4_doi_list_lock);
642         list_for_each_entry_rcu(iter, &doi_def->dom_list, list)
643                 if (iter->valid &&
644                     ((domain != NULL && iter->domain != NULL &&
645                       strcmp(iter->domain, domain) == 0) ||
646                      (domain == NULL && iter->domain == NULL))) {
647                         iter->valid = 0;
648                         list_del_rcu(&iter->list);
649                         spin_unlock(&cipso_v4_doi_list_lock);
650                         rcu_read_unlock();
651                         call_rcu(&iter->rcu, cipso_v4_doi_domhsh_free);
652
653                         return 0;
654                 }
655         spin_unlock(&cipso_v4_doi_list_lock);
656         rcu_read_unlock();
657
658         return -ENOENT;
659 }
660
661 /*
662  * Label Mapping Functions
663  */
664
665 /**
666  * cipso_v4_map_lvl_valid - Checks to see if the given level is understood
667  * @doi_def: the DOI definition
668  * @level: the level to check
669  *
670  * Description:
671  * Checks the given level against the given DOI definition and returns a
672  * negative value if the level does not have a valid mapping and a zero value
673  * if the level is defined by the DOI.
674  *
675  */
676 static int cipso_v4_map_lvl_valid(const struct cipso_v4_doi *doi_def, u8 level)
677 {
678         switch (doi_def->type) {
679         case CIPSO_V4_MAP_PASS:
680                 return 0;
681         case CIPSO_V4_MAP_STD:
682                 if (doi_def->map.std->lvl.cipso[level] < CIPSO_V4_INV_LVL)
683                         return 0;
684                 break;
685         }
686
687         return -EFAULT;
688 }
689
690 /**
691  * cipso_v4_map_lvl_hton - Perform a level mapping from the host to the network
692  * @doi_def: the DOI definition
693  * @host_lvl: the host MLS level
694  * @net_lvl: the network/CIPSO MLS level
695  *
696  * Description:
697  * Perform a label mapping to translate a local MLS level to the correct
698  * CIPSO level using the given DOI definition.  Returns zero on success,
699  * negative values otherwise.
700  *
701  */
702 static int cipso_v4_map_lvl_hton(const struct cipso_v4_doi *doi_def,
703                                  u32 host_lvl,
704                                  u32 *net_lvl)
705 {
706         switch (doi_def->type) {
707         case CIPSO_V4_MAP_PASS:
708                 *net_lvl = host_lvl;
709                 return 0;
710         case CIPSO_V4_MAP_STD:
711                 if (host_lvl < doi_def->map.std->lvl.local_size) {
712                         *net_lvl = doi_def->map.std->lvl.local[host_lvl];
713                         return 0;
714                 }
715                 break;
716         }
717
718         return -EINVAL;
719 }
720
721 /**
722  * cipso_v4_map_lvl_ntoh - Perform a level mapping from the network to the host
723  * @doi_def: the DOI definition
724  * @net_lvl: the network/CIPSO MLS level
725  * @host_lvl: the host MLS level
726  *
727  * Description:
728  * Perform a label mapping to translate a CIPSO level to the correct local MLS
729  * level using the given DOI definition.  Returns zero on success, negative
730  * values otherwise.
731  *
732  */
733 static int cipso_v4_map_lvl_ntoh(const struct cipso_v4_doi *doi_def,
734                                  u32 net_lvl,
735                                  u32 *host_lvl)
736 {
737         struct cipso_v4_std_map_tbl *map_tbl;
738
739         switch (doi_def->type) {
740         case CIPSO_V4_MAP_PASS:
741                 *host_lvl = net_lvl;
742                 return 0;
743         case CIPSO_V4_MAP_STD:
744                 map_tbl = doi_def->map.std;
745                 if (net_lvl < map_tbl->lvl.cipso_size &&
746                     map_tbl->lvl.cipso[net_lvl] < CIPSO_V4_INV_LVL) {
747                         *host_lvl = doi_def->map.std->lvl.cipso[net_lvl];
748                         return 0;
749                 }
750                 break;
751         }
752
753         return -EINVAL;
754 }
755
756 /**
757  * cipso_v4_map_cat_rbm_valid - Checks to see if the category bitmap is valid
758  * @doi_def: the DOI definition
759  * @bitmap: category bitmap
760  * @bitmap_len: bitmap length in bytes
761  *
762  * Description:
763  * Checks the given category bitmap against the given DOI definition and
764  * returns a negative value if any of the categories in the bitmap do not have
765  * a valid mapping and a zero value if all of the categories are valid.
766  *
767  */
768 static int cipso_v4_map_cat_rbm_valid(const struct cipso_v4_doi *doi_def,
769                                       const unsigned char *bitmap,
770                                       u32 bitmap_len)
771 {
772         int cat = -1;
773         u32 bitmap_len_bits = bitmap_len * 8;
774         u32 cipso_cat_size = doi_def->map.std->cat.cipso_size;
775         u32 *cipso_array = doi_def->map.std->cat.cipso;
776
777         switch (doi_def->type) {
778         case CIPSO_V4_MAP_PASS:
779                 return 0;
780         case CIPSO_V4_MAP_STD:
781                 for (;;) {
782                         cat = cipso_v4_bitmap_walk(bitmap,
783                                                    bitmap_len_bits,
784                                                    cat + 1,
785                                                    1);
786                         if (cat < 0)
787                                 break;
788                         if (cat >= cipso_cat_size ||
789                             cipso_array[cat] >= CIPSO_V4_INV_CAT)
790                                 return -EFAULT;
791                 }
792
793                 if (cat == -1)
794                         return 0;
795                 break;
796         }
797
798         return -EFAULT;
799 }
800
801 /**
802  * cipso_v4_map_cat_rbm_hton - Perform a category mapping from host to network
803  * @doi_def: the DOI definition
804  * @host_cat: the category bitmap in host format
805  * @host_cat_len: the length of the host's category bitmap in bytes
806  * @net_cat: the zero'd out category bitmap in network/CIPSO format
807  * @net_cat_len: the length of the CIPSO bitmap in bytes
808  *
809  * Description:
810  * Perform a label mapping to translate a local MLS category bitmap to the
811  * correct CIPSO bitmap using the given DOI definition.  Returns the minimum
812  * size in bytes of the network bitmap on success, negative values otherwise.
813  *
814  */
815 static int cipso_v4_map_cat_rbm_hton(const struct cipso_v4_doi *doi_def,
816                                      const unsigned char *host_cat,
817                                      u32 host_cat_len,
818                                      unsigned char *net_cat,
819                                      u32 net_cat_len)
820 {
821         int host_spot = -1;
822         u32 net_spot;
823         u32 net_spot_max = 0;
824         u32 host_clen_bits = host_cat_len * 8;
825         u32 net_clen_bits = net_cat_len * 8;
826         u32 host_cat_size = doi_def->map.std->cat.local_size;
827         u32 *host_cat_array = doi_def->map.std->cat.local;
828
829         switch (doi_def->type) {
830         case CIPSO_V4_MAP_PASS:
831                 net_spot_max = host_cat_len - 1;
832                 while (net_spot_max > 0 && host_cat[net_spot_max] == 0)
833                         net_spot_max--;
834                 if (net_spot_max > net_cat_len)
835                         return -EINVAL;
836                 memcpy(net_cat, host_cat, net_spot_max);
837                 return net_spot_max;
838         case CIPSO_V4_MAP_STD:
839                 for (;;) {
840                         host_spot = cipso_v4_bitmap_walk(host_cat,
841                                                          host_clen_bits,
842                                                          host_spot + 1,
843                                                          1);
844                         if (host_spot < 0)
845                                 break;
846                         if (host_spot >= host_cat_size)
847                                 return -EPERM;
848
849                         net_spot = host_cat_array[host_spot];
850                         if (net_spot >= net_clen_bits)
851                                 return -ENOSPC;
852                         cipso_v4_bitmap_setbit(net_cat, net_spot, 1);
853
854                         if (net_spot > net_spot_max)
855                                 net_spot_max = net_spot;
856                 }
857
858                 if (host_spot == -2)
859                         return -EFAULT;
860
861                 if (++net_spot_max % 8)
862                         return net_spot_max / 8 + 1;
863                 return net_spot_max / 8;
864         }
865
866         return -EINVAL;
867 }
868
869 /**
870  * cipso_v4_map_cat_rbm_ntoh - Perform a category mapping from network to host
871  * @doi_def: the DOI definition
872  * @net_cat: the category bitmap in network/CIPSO format
873  * @net_cat_len: the length of the CIPSO bitmap in bytes
874  * @host_cat: the zero'd out category bitmap in host format
875  * @host_cat_len: the length of the host's category bitmap in bytes
876  *
877  * Description:
878  * Perform a label mapping to translate a CIPSO bitmap to the correct local
879  * MLS category bitmap using the given DOI definition.  Returns the minimum
880  * size in bytes of the host bitmap on success, negative values otherwise.
881  *
882  */
883 static int cipso_v4_map_cat_rbm_ntoh(const struct cipso_v4_doi *doi_def,
884                                      const unsigned char *net_cat,
885                                      u32 net_cat_len,
886                                      unsigned char *host_cat,
887                                      u32 host_cat_len)
888 {
889         u32 host_spot;
890         u32 host_spot_max = 0;
891         int net_spot = -1;
892         u32 net_clen_bits = net_cat_len * 8;
893         u32 host_clen_bits = host_cat_len * 8;
894         u32 net_cat_size = doi_def->map.std->cat.cipso_size;
895         u32 *net_cat_array = doi_def->map.std->cat.cipso;
896
897         switch (doi_def->type) {
898         case CIPSO_V4_MAP_PASS:
899                 if (net_cat_len > host_cat_len)
900                         return -EINVAL;
901                 memcpy(host_cat, net_cat, net_cat_len);
902                 return net_cat_len;
903         case CIPSO_V4_MAP_STD:
904                 for (;;) {
905                         net_spot = cipso_v4_bitmap_walk(net_cat,
906                                                         net_clen_bits,
907                                                         net_spot + 1,
908                                                         1);
909                         if (net_spot < 0)
910                                 break;
911                         if (net_spot >= net_cat_size ||
912                             net_cat_array[net_spot] >= CIPSO_V4_INV_CAT)
913                                 return -EPERM;
914
915                         host_spot = net_cat_array[net_spot];
916                         if (host_spot >= host_clen_bits)
917                                 return -ENOSPC;
918                         cipso_v4_bitmap_setbit(host_cat, host_spot, 1);
919
920                         if (host_spot > host_spot_max)
921                                 host_spot_max = host_spot;
922                 }
923
924                 if (net_spot == -2)
925                         return -EFAULT;
926
927                 if (++host_spot_max % 8)
928                         return host_spot_max / 8 + 1;
929                 return host_spot_max / 8;
930         }
931
932         return -EINVAL;
933 }
934
935 /*
936  * Protocol Handling Functions
937  */
938
939 #define CIPSO_V4_HDR_LEN              6
940
941 /**
942  * cipso_v4_gentag_hdr - Generate a CIPSO option header
943  * @doi_def: the DOI definition
944  * @len: the total tag length in bytes
945  * @buf: the CIPSO option buffer
946  *
947  * Description:
948  * Write a CIPSO header into the beginning of @buffer.  Return zero on success,
949  * negative values on failure.
950  *
951  */
952 static int cipso_v4_gentag_hdr(const struct cipso_v4_doi *doi_def,
953                                u32 len,
954                                unsigned char *buf)
955 {
956         if (CIPSO_V4_HDR_LEN + len > 40)
957                 return -ENOSPC;
958
959         buf[0] = IPOPT_CIPSO;
960         buf[1] = CIPSO_V4_HDR_LEN + len;
961         *(u32 *)&buf[2] = htonl(doi_def->doi);
962
963         return 0;
964 }
965
966 #define CIPSO_V4_TAG1_CAT_LEN         30
967
968 /**
969  * cipso_v4_gentag_rbm - Generate a CIPSO restricted bitmap tag (type #1)
970  * @doi_def: the DOI definition
971  * @secattr: the security attributes
972  * @buffer: the option buffer
973  * @buffer_len: length of buffer in bytes
974  *
975  * Description:
976  * Generate a CIPSO option using the restricted bitmap tag, tag type #1.  The
977  * actual buffer length may be larger than the indicated size due to
978  * translation between host and network category bitmaps.  Returns zero on
979  * success, negative values on failure.
980  *
981  */
982 static int cipso_v4_gentag_rbm(const struct cipso_v4_doi *doi_def,
983                                const struct netlbl_lsm_secattr *secattr,
984                                unsigned char **buffer,
985                                u32 *buffer_len)
986 {
987         int ret_val = -EPERM;
988         unsigned char *buf = NULL;
989         u32 buf_len;
990         u32 level;
991
992         if (secattr->mls_cat) {
993                 buf = kzalloc(CIPSO_V4_HDR_LEN + 4 + CIPSO_V4_TAG1_CAT_LEN,
994                               GFP_ATOMIC);
995                 if (buf == NULL)
996                         return -ENOMEM;
997
998                 ret_val = cipso_v4_map_cat_rbm_hton(doi_def,
999                                                     secattr->mls_cat,
1000                                                     secattr->mls_cat_len,
1001                                                     &buf[CIPSO_V4_HDR_LEN + 4],
1002                                                     CIPSO_V4_TAG1_CAT_LEN);
1003                 if (ret_val < 0)
1004                         goto gentag_failure;
1005
1006                 /* This will send packets using the "optimized" format when
1007                  * possibile as specified in  section 3.4.2.6 of the
1008                  * CIPSO draft. */
1009                 if (cipso_v4_rbm_optfmt && (ret_val > 0 && ret_val < 10))
1010                         ret_val = 10;
1011
1012                 buf_len = 4 + ret_val;
1013         } else {
1014                 buf = kzalloc(CIPSO_V4_HDR_LEN + 4, GFP_ATOMIC);
1015                 if (buf == NULL)
1016                         return -ENOMEM;
1017                 buf_len = 4;
1018         }
1019
1020         ret_val = cipso_v4_map_lvl_hton(doi_def, secattr->mls_lvl, &level);
1021         if (ret_val != 0)
1022                 goto gentag_failure;
1023
1024         ret_val = cipso_v4_gentag_hdr(doi_def, buf_len, buf);
1025         if (ret_val != 0)
1026                 goto gentag_failure;
1027
1028         buf[CIPSO_V4_HDR_LEN] = 0x01;
1029         buf[CIPSO_V4_HDR_LEN + 1] = buf_len;
1030         buf[CIPSO_V4_HDR_LEN + 3] = level;
1031
1032         *buffer = buf;
1033         *buffer_len = CIPSO_V4_HDR_LEN + buf_len;
1034
1035         return 0;
1036
1037 gentag_failure:
1038         kfree(buf);
1039         return ret_val;
1040 }
1041
1042 /**
1043  * cipso_v4_parsetag_rbm - Parse a CIPSO restricted bitmap tag
1044  * @doi_def: the DOI definition
1045  * @tag: the CIPSO tag
1046  * @secattr: the security attributes
1047  *
1048  * Description:
1049  * Parse a CIPSO restricted bitmap tag (tag type #1) and return the security
1050  * attributes in @secattr.  Return zero on success, negatives values on
1051  * failure.
1052  *
1053  */
1054 static int cipso_v4_parsetag_rbm(const struct cipso_v4_doi *doi_def,
1055                                  const unsigned char *tag,
1056                                  struct netlbl_lsm_secattr *secattr)
1057 {
1058         int ret_val;
1059         u8 tag_len = tag[1];
1060         u32 level;
1061
1062         ret_val = cipso_v4_map_lvl_ntoh(doi_def, tag[3], &level);
1063         if (ret_val != 0)
1064                 return ret_val;
1065         secattr->mls_lvl = level;
1066         secattr->mls_lvl_vld = 1;
1067
1068         if (tag_len > 4) {
1069                 switch (doi_def->type) {
1070                 case CIPSO_V4_MAP_PASS:
1071                         secattr->mls_cat_len = tag_len - 4;
1072                         break;
1073                 case CIPSO_V4_MAP_STD:
1074                         secattr->mls_cat_len =
1075                                 doi_def->map.std->cat.local_size;
1076                         break;
1077                 }
1078                 secattr->mls_cat = kzalloc(secattr->mls_cat_len, GFP_ATOMIC);
1079                 if (secattr->mls_cat == NULL)
1080                         return -ENOMEM;
1081
1082                 ret_val = cipso_v4_map_cat_rbm_ntoh(doi_def,
1083                                                     &tag[4],
1084                                                     tag_len - 4,
1085                                                     secattr->mls_cat,
1086                                                     secattr->mls_cat_len);
1087                 if (ret_val < 0) {
1088                         kfree(secattr->mls_cat);
1089                         return ret_val;
1090                 }
1091                 secattr->mls_cat_len = ret_val;
1092         }
1093
1094         return 0;
1095 }
1096
1097 /**
1098  * cipso_v4_validate - Validate a CIPSO option
1099  * @option: the start of the option, on error it is set to point to the error
1100  *
1101  * Description:
1102  * This routine is called to validate a CIPSO option, it checks all of the
1103  * fields to ensure that they are at least valid, see the draft snippet below
1104  * for details.  If the option is valid then a zero value is returned and
1105  * the value of @option is unchanged.  If the option is invalid then a
1106  * non-zero value is returned and @option is adjusted to point to the
1107  * offending portion of the option.  From the IETF draft ...
1108  *
1109  *  "If any field within the CIPSO options, such as the DOI identifier, is not
1110  *   recognized the IP datagram is discarded and an ICMP 'parameter problem'
1111  *   (type 12) is generated and returned.  The ICMP code field is set to 'bad
1112  *   parameter' (code 0) and the pointer is set to the start of the CIPSO field
1113  *   that is unrecognized."
1114  *
1115  */
1116 int cipso_v4_validate(unsigned char **option)
1117 {
1118         unsigned char *opt = *option;
1119         unsigned char *tag;
1120         unsigned char opt_iter;
1121         unsigned char err_offset = 0;
1122         u8 opt_len;
1123         u8 tag_len;
1124         struct cipso_v4_doi *doi_def = NULL;
1125         u32 tag_iter;
1126
1127         /* caller already checks for length values that are too large */
1128         opt_len = opt[1];
1129         if (opt_len < 8) {
1130                 err_offset = 1;
1131                 goto validate_return;
1132         }
1133
1134         rcu_read_lock();
1135         doi_def = cipso_v4_doi_getdef(ntohl(*((u32 *)&opt[2])));
1136         if (doi_def == NULL) {
1137                 err_offset = 2;
1138                 goto validate_return_locked;
1139         }
1140
1141         opt_iter = 6;
1142         tag = opt + opt_iter;
1143         while (opt_iter < opt_len) {
1144                 for (tag_iter = 0; doi_def->tags[tag_iter] != tag[0];)
1145                         if (doi_def->tags[tag_iter] == CIPSO_V4_TAG_INVALID ||
1146                             ++tag_iter == CIPSO_V4_TAG_MAXCNT) {
1147                                 err_offset = opt_iter;
1148                                 goto validate_return_locked;
1149                         }
1150
1151                 tag_len = tag[1];
1152                 if (tag_len > (opt_len - opt_iter)) {
1153                         err_offset = opt_iter + 1;
1154                         goto validate_return_locked;
1155                 }
1156
1157                 switch (tag[0]) {
1158                 case CIPSO_V4_TAG_RBITMAP:
1159                         if (tag_len < 4) {
1160                                 err_offset = opt_iter + 1;
1161                                 goto validate_return_locked;
1162                         }
1163
1164                         /* We are already going to do all the verification
1165                          * necessary at the socket layer so from our point of
1166                          * view it is safe to turn these checks off (and less
1167                          * work), however, the CIPSO draft says we should do
1168                          * all the CIPSO validations here but it doesn't
1169                          * really specify _exactly_ what we need to validate
1170                          * ... so, just make it a sysctl tunable. */
1171                         if (cipso_v4_rbm_strictvalid) {
1172                                 if (cipso_v4_map_lvl_valid(doi_def,
1173                                                            tag[3]) < 0) {
1174                                         err_offset = opt_iter + 3;
1175                                         goto validate_return_locked;
1176                                 }
1177                                 if (tag_len > 4 &&
1178                                     cipso_v4_map_cat_rbm_valid(doi_def,
1179                                                             &tag[4],
1180                                                             tag_len - 4) < 0) {
1181                                         err_offset = opt_iter + 4;
1182                                         goto validate_return_locked;
1183                                 }
1184                         }
1185                         break;
1186                 default:
1187                         err_offset = opt_iter;
1188                         goto validate_return_locked;
1189                 }
1190
1191                 tag += tag_len;
1192                 opt_iter += tag_len;
1193         }
1194
1195 validate_return_locked:
1196         rcu_read_unlock();
1197 validate_return:
1198         *option = opt + err_offset;
1199         return err_offset;
1200 }
1201
1202 /**
1203  * cipso_v4_error - Send the correct reponse for a bad packet
1204  * @skb: the packet
1205  * @error: the error code
1206  * @gateway: CIPSO gateway flag
1207  *
1208  * Description:
1209  * Based on the error code given in @error, send an ICMP error message back to
1210  * the originating host.  From the IETF draft ...
1211  *
1212  *  "If the contents of the CIPSO [option] are valid but the security label is
1213  *   outside of the configured host or port label range, the datagram is
1214  *   discarded and an ICMP 'destination unreachable' (type 3) is generated and
1215  *   returned.  The code field of the ICMP is set to 'communication with
1216  *   destination network administratively prohibited' (code 9) or to
1217  *   'communication with destination host administratively prohibited'
1218  *   (code 10).  The value of the code is dependent on whether the originator
1219  *   of the ICMP message is acting as a CIPSO host or a CIPSO gateway.  The
1220  *   recipient of the ICMP message MUST be able to handle either value.  The
1221  *   same procedure is performed if a CIPSO [option] can not be added to an
1222  *   IP packet because it is too large to fit in the IP options area."
1223  *
1224  *  "If the error is triggered by receipt of an ICMP message, the message is
1225  *   discarded and no response is permitted (consistent with general ICMP
1226  *   processing rules)."
1227  *
1228  */
1229 void cipso_v4_error(struct sk_buff *skb, int error, u32 gateway)
1230 {
1231         if (skb->nh.iph->protocol == IPPROTO_ICMP || error != -EACCES)
1232                 return;
1233
1234         if (gateway)
1235                 icmp_send(skb, ICMP_DEST_UNREACH, ICMP_NET_ANO, 0);
1236         else
1237                 icmp_send(skb, ICMP_DEST_UNREACH, ICMP_HOST_ANO, 0);
1238 }
1239
1240 /**
1241  * cipso_v4_socket_setattr - Add a CIPSO option to a socket
1242  * @sock: the socket
1243  * @doi_def: the CIPSO DOI to use
1244  * @secattr: the specific security attributes of the socket
1245  *
1246  * Description:
1247  * Set the CIPSO option on the given socket using the DOI definition and
1248  * security attributes passed to the function.  This function requires
1249  * exclusive access to @sock->sk, which means it either needs to be in the
1250  * process of being created or locked via lock_sock(sock->sk).  Returns zero on
1251  * success and negative values on failure.
1252  *
1253  */
1254 int cipso_v4_socket_setattr(const struct socket *sock,
1255                             const struct cipso_v4_doi *doi_def,
1256                             const struct netlbl_lsm_secattr *secattr)
1257 {
1258         int ret_val = -EPERM;
1259         u32 iter;
1260         unsigned char *buf = NULL;
1261         u32 buf_len = 0;
1262         u32 opt_len;
1263         struct ip_options *opt = NULL;
1264         struct sock *sk;
1265         struct inet_sock *sk_inet;
1266         struct inet_connection_sock *sk_conn;
1267
1268         /* In the case of sock_create_lite(), the sock->sk field is not
1269          * defined yet but it is not a problem as the only users of these
1270          * "lite" PF_INET sockets are functions which do an accept() call
1271          * afterwards so we will label the socket as part of the accept(). */
1272         sk = sock->sk;
1273         if (sk == NULL)
1274                 return 0;
1275
1276         /* XXX - This code assumes only one tag per CIPSO option which isn't
1277          * really a good assumption to make but since we only support the MAC
1278          * tags right now it is a safe assumption. */
1279         iter = 0;
1280         do {
1281                 switch (doi_def->tags[iter]) {
1282                 case CIPSO_V4_TAG_RBITMAP:
1283                         ret_val = cipso_v4_gentag_rbm(doi_def,
1284                                                       secattr,
1285                                                       &buf,
1286                                                       &buf_len);
1287                         break;
1288                 default:
1289                         ret_val = -EPERM;
1290                         goto socket_setattr_failure;
1291                 }
1292
1293                 iter++;
1294         } while (ret_val != 0 &&
1295                  iter < CIPSO_V4_TAG_MAXCNT &&
1296                  doi_def->tags[iter] != CIPSO_V4_TAG_INVALID);
1297         if (ret_val != 0)
1298                 goto socket_setattr_failure;
1299
1300         /* We can't use ip_options_get() directly because it makes a call to
1301          * ip_options_get_alloc() which allocates memory with GFP_KERNEL and
1302          * we can't block here. */
1303         opt_len = (buf_len + 3) & ~3;
1304         opt = kzalloc(sizeof(*opt) + opt_len, GFP_ATOMIC);
1305         if (opt == NULL) {
1306                 ret_val = -ENOMEM;
1307                 goto socket_setattr_failure;
1308         }
1309         memcpy(opt->__data, buf, buf_len);
1310         opt->optlen = opt_len;
1311         opt->is_data = 1;
1312         kfree(buf);
1313         buf = NULL;
1314         ret_val = ip_options_compile(opt, NULL);
1315         if (ret_val != 0)
1316                 goto socket_setattr_failure;
1317
1318         sk_inet = inet_sk(sk);
1319         if (sk_inet->is_icsk) {
1320                 sk_conn = inet_csk(sk);
1321                 if (sk_inet->opt)
1322                         sk_conn->icsk_ext_hdr_len -= sk_inet->opt->optlen;
1323                 sk_conn->icsk_ext_hdr_len += opt->optlen;
1324                 sk_conn->icsk_sync_mss(sk, sk_conn->icsk_pmtu_cookie);
1325         }
1326         opt = xchg(&sk_inet->opt, opt);
1327         kfree(opt);
1328
1329         return 0;
1330
1331 socket_setattr_failure:
1332         kfree(buf);
1333         kfree(opt);
1334         return ret_val;
1335 }
1336
1337 /**
1338  * cipso_v4_sock_getattr - Get the security attributes from a sock
1339  * @sk: the sock
1340  * @secattr: the security attributes
1341  *
1342  * Description:
1343  * Query @sk to see if there is a CIPSO option attached to the sock and if
1344  * there is return the CIPSO security attributes in @secattr.  This function
1345  * requires that @sk be locked, or privately held, but it does not do any
1346  * locking itself.  Returns zero on success and negative values on failure.
1347  *
1348  */
1349 int cipso_v4_sock_getattr(struct sock *sk, struct netlbl_lsm_secattr *secattr)
1350 {
1351         int ret_val = -ENOMSG;
1352         struct inet_sock *sk_inet;
1353         unsigned char *cipso_ptr;
1354         u32 doi;
1355         struct cipso_v4_doi *doi_def;
1356
1357         sk_inet = inet_sk(sk);
1358         if (sk_inet->opt == NULL || sk_inet->opt->cipso == 0)
1359                 return -ENOMSG;
1360         cipso_ptr = sk_inet->opt->__data + sk_inet->opt->cipso -
1361                 sizeof(struct iphdr);
1362         ret_val = cipso_v4_cache_check(cipso_ptr, cipso_ptr[1], secattr);
1363         if (ret_val == 0)
1364                 return ret_val;
1365
1366         doi = ntohl(*(u32 *)&cipso_ptr[2]);
1367         rcu_read_lock();
1368         doi_def = cipso_v4_doi_getdef(doi);
1369         if (doi_def == NULL) {
1370                 rcu_read_unlock();
1371                 return -ENOMSG;
1372         }
1373         switch (cipso_ptr[6]) {
1374         case CIPSO_V4_TAG_RBITMAP:
1375                 ret_val = cipso_v4_parsetag_rbm(doi_def,
1376                                                 &cipso_ptr[6],
1377                                                 secattr);
1378                 break;
1379         }
1380         rcu_read_unlock();
1381
1382         return ret_val;
1383 }
1384
1385 /**
1386  * cipso_v4_socket_getattr - Get the security attributes from a socket
1387  * @sock: the socket
1388  * @secattr: the security attributes
1389  *
1390  * Description:
1391  * Query @sock to see if there is a CIPSO option attached to the socket and if
1392  * there is return the CIPSO security attributes in @secattr.  Returns zero on
1393  * success and negative values on failure.
1394  *
1395  */
1396 int cipso_v4_socket_getattr(const struct socket *sock,
1397                             struct netlbl_lsm_secattr *secattr)
1398 {
1399         int ret_val;
1400
1401         lock_sock(sock->sk);
1402         ret_val = cipso_v4_sock_getattr(sock->sk, secattr);
1403         release_sock(sock->sk);
1404
1405         return ret_val;
1406 }
1407
1408 /**
1409  * cipso_v4_skbuff_getattr - Get the security attributes from the CIPSO option
1410  * @skb: the packet
1411  * @secattr: the security attributes
1412  *
1413  * Description:
1414  * Parse the given packet's CIPSO option and return the security attributes.
1415  * Returns zero on success and negative values on failure.
1416  *
1417  */
1418 int cipso_v4_skbuff_getattr(const struct sk_buff *skb,
1419                             struct netlbl_lsm_secattr *secattr)
1420 {
1421         int ret_val = -ENOMSG;
1422         unsigned char *cipso_ptr;
1423         u32 doi;
1424         struct cipso_v4_doi *doi_def;
1425
1426         if (!CIPSO_V4_OPTEXIST(skb))
1427                 return -ENOMSG;
1428         cipso_ptr = CIPSO_V4_OPTPTR(skb);
1429         if (cipso_v4_cache_check(cipso_ptr, cipso_ptr[1], secattr) == 0)
1430                 return 0;
1431
1432         doi = ntohl(*(u32 *)&cipso_ptr[2]);
1433         rcu_read_lock();
1434         doi_def = cipso_v4_doi_getdef(doi);
1435         if (doi_def == NULL)
1436                 goto skbuff_getattr_return;
1437         switch (cipso_ptr[6]) {
1438         case CIPSO_V4_TAG_RBITMAP:
1439                 ret_val = cipso_v4_parsetag_rbm(doi_def,
1440                                                 &cipso_ptr[6],
1441                                                 secattr);
1442                 break;
1443         }
1444
1445 skbuff_getattr_return:
1446         rcu_read_unlock();
1447         return ret_val;
1448 }
1449
1450 /*
1451  * Setup Functions
1452  */
1453
1454 /**
1455  * cipso_v4_init - Initialize the CIPSO module
1456  *
1457  * Description:
1458  * Initialize the CIPSO module and prepare it for use.  Returns zero on success
1459  * and negative values on failure.
1460  *
1461  */
1462 static int __init cipso_v4_init(void)
1463 {
1464         int ret_val;
1465
1466         ret_val = cipso_v4_cache_init();
1467         if (ret_val != 0)
1468                 panic("Failed to initialize the CIPSO/IPv4 cache (%d)\n",
1469                       ret_val);
1470
1471         return 0;
1472 }
1473
1474 subsys_initcall(cipso_v4_init);