Merge branch 'upstream-linus' of master.kernel.org:/pub/scm/linux/kernel/git/jgarzik...
[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  * @callback: the DOI cleanup/free callback
478  *
479  * Description:
480  * Removes a DOI definition from the CIPSO engine, @callback is called to
481  * free any memory.  The NetLabel routines will be called to release their own
482  * LSM domain mappings as well as our own domain list.  Returns zero on
483  * success and negative values on failure.
484  *
485  */
486 int cipso_v4_doi_remove(u32 doi, void (*callback) (struct rcu_head * head))
487 {
488         struct cipso_v4_doi *doi_def;
489         struct cipso_v4_domhsh_entry *dom_iter;
490
491         rcu_read_lock();
492         if (cipso_v4_doi_search(doi) != NULL) {
493                 spin_lock(&cipso_v4_doi_list_lock);
494                 doi_def = cipso_v4_doi_search(doi);
495                 if (doi_def == NULL) {
496                         spin_unlock(&cipso_v4_doi_list_lock);
497                         rcu_read_unlock();
498                         return -ENOENT;
499                 }
500                 doi_def->valid = 0;
501                 list_del_rcu(&doi_def->list);
502                 spin_unlock(&cipso_v4_doi_list_lock);
503                 list_for_each_entry_rcu(dom_iter, &doi_def->dom_list, list)
504                         if (dom_iter->valid)
505                                 netlbl_domhsh_remove(dom_iter->domain);
506                 cipso_v4_cache_invalidate();
507                 rcu_read_unlock();
508
509                 call_rcu(&doi_def->rcu, callback);
510                 return 0;
511         }
512         rcu_read_unlock();
513
514         return -ENOENT;
515 }
516
517 /**
518  * cipso_v4_doi_getdef - Returns a pointer to a valid DOI definition
519  * @doi: the DOI value
520  *
521  * Description:
522  * Searches for a valid DOI definition and if one is found it is returned to
523  * the caller.  Otherwise NULL is returned.  The caller must ensure that
524  * rcu_read_lock() is held while accessing the returned definition.
525  *
526  */
527 struct cipso_v4_doi *cipso_v4_doi_getdef(u32 doi)
528 {
529         return cipso_v4_doi_search(doi);
530 }
531
532 /**
533  * cipso_v4_doi_walk - Iterate through the DOI definitions
534  * @skip_cnt: skip past this number of DOI definitions, updated
535  * @callback: callback for each DOI definition
536  * @cb_arg: argument for the callback function
537  *
538  * Description:
539  * Iterate over the DOI definition list, skipping the first @skip_cnt entries.
540  * For each entry call @callback, if @callback returns a negative value stop
541  * 'walking' through the list and return.  Updates the value in @skip_cnt upon
542  * return.  Returns zero on success, negative values on failure.
543  *
544  */
545 int cipso_v4_doi_walk(u32 *skip_cnt,
546                      int (*callback) (struct cipso_v4_doi *doi_def, void *arg),
547                      void *cb_arg)
548 {
549         int ret_val = -ENOENT;
550         u32 doi_cnt = 0;
551         struct cipso_v4_doi *iter_doi;
552
553         rcu_read_lock();
554         list_for_each_entry_rcu(iter_doi, &cipso_v4_doi_list, list)
555                 if (iter_doi->valid) {
556                         if (doi_cnt++ < *skip_cnt)
557                                 continue;
558                         ret_val = callback(iter_doi, cb_arg);
559                         if (ret_val < 0) {
560                                 doi_cnt--;
561                                 goto doi_walk_return;
562                         }
563                 }
564
565 doi_walk_return:
566         rcu_read_unlock();
567         *skip_cnt = doi_cnt;
568         return ret_val;
569 }
570
571 /**
572  * cipso_v4_doi_domhsh_add - Adds a domain entry to a DOI definition
573  * @doi_def: the DOI definition
574  * @domain: the domain to add
575  *
576  * Description:
577  * Adds the @domain to the the DOI specified by @doi_def, this function
578  * should only be called by external functions (i.e. NetLabel).  This function
579  * does allocate memory.  Returns zero on success, negative values on failure.
580  *
581  */
582 int cipso_v4_doi_domhsh_add(struct cipso_v4_doi *doi_def, const char *domain)
583 {
584         struct cipso_v4_domhsh_entry *iter;
585         struct cipso_v4_domhsh_entry *new_dom;
586
587         new_dom = kzalloc(sizeof(*new_dom), GFP_KERNEL);
588         if (new_dom == NULL)
589                 return -ENOMEM;
590         if (domain) {
591                 new_dom->domain = kstrdup(domain, GFP_KERNEL);
592                 if (new_dom->domain == NULL) {
593                         kfree(new_dom);
594                         return -ENOMEM;
595                 }
596         }
597         new_dom->valid = 1;
598         INIT_RCU_HEAD(&new_dom->rcu);
599
600         rcu_read_lock();
601         spin_lock(&cipso_v4_doi_list_lock);
602         list_for_each_entry_rcu(iter, &doi_def->dom_list, list)
603                 if (iter->valid &&
604                     ((domain != NULL && iter->domain != NULL &&
605                       strcmp(iter->domain, domain) == 0) ||
606                      (domain == NULL && iter->domain == NULL))) {
607                         spin_unlock(&cipso_v4_doi_list_lock);
608                         rcu_read_unlock();
609                         kfree(new_dom->domain);
610                         kfree(new_dom);
611                         return -EEXIST;
612                 }
613         list_add_tail_rcu(&new_dom->list, &doi_def->dom_list);
614         spin_unlock(&cipso_v4_doi_list_lock);
615         rcu_read_unlock();
616
617         return 0;
618 }
619
620 /**
621  * cipso_v4_doi_domhsh_remove - Removes a domain entry from a DOI definition
622  * @doi_def: the DOI definition
623  * @domain: the domain to remove
624  *
625  * Description:
626  * Removes the @domain from the DOI specified by @doi_def, this function
627  * should only be called by external functions (i.e. NetLabel).   Returns zero
628  * on success and negative values on error.
629  *
630  */
631 int cipso_v4_doi_domhsh_remove(struct cipso_v4_doi *doi_def,
632                                const char *domain)
633 {
634         struct cipso_v4_domhsh_entry *iter;
635
636         rcu_read_lock();
637         spin_lock(&cipso_v4_doi_list_lock);
638         list_for_each_entry_rcu(iter, &doi_def->dom_list, list)
639                 if (iter->valid &&
640                     ((domain != NULL && iter->domain != NULL &&
641                       strcmp(iter->domain, domain) == 0) ||
642                      (domain == NULL && iter->domain == NULL))) {
643                         iter->valid = 0;
644                         list_del_rcu(&iter->list);
645                         spin_unlock(&cipso_v4_doi_list_lock);
646                         rcu_read_unlock();
647                         call_rcu(&iter->rcu, cipso_v4_doi_domhsh_free);
648
649                         return 0;
650                 }
651         spin_unlock(&cipso_v4_doi_list_lock);
652         rcu_read_unlock();
653
654         return -ENOENT;
655 }
656
657 /*
658  * Label Mapping Functions
659  */
660
661 /**
662  * cipso_v4_map_lvl_valid - Checks to see if the given level is understood
663  * @doi_def: the DOI definition
664  * @level: the level to check
665  *
666  * Description:
667  * Checks the given level against the given DOI definition and returns a
668  * negative value if the level does not have a valid mapping and a zero value
669  * if the level is defined by the DOI.
670  *
671  */
672 static int cipso_v4_map_lvl_valid(const struct cipso_v4_doi *doi_def, u8 level)
673 {
674         switch (doi_def->type) {
675         case CIPSO_V4_MAP_PASS:
676                 return 0;
677         case CIPSO_V4_MAP_STD:
678                 if (doi_def->map.std->lvl.cipso[level] < CIPSO_V4_INV_LVL)
679                         return 0;
680                 break;
681         }
682
683         return -EFAULT;
684 }
685
686 /**
687  * cipso_v4_map_lvl_hton - Perform a level mapping from the host to the network
688  * @doi_def: the DOI definition
689  * @host_lvl: the host MLS level
690  * @net_lvl: the network/CIPSO MLS level
691  *
692  * Description:
693  * Perform a label mapping to translate a local MLS level to the correct
694  * CIPSO level using the given DOI definition.  Returns zero on success,
695  * negative values otherwise.
696  *
697  */
698 static int cipso_v4_map_lvl_hton(const struct cipso_v4_doi *doi_def,
699                                  u32 host_lvl,
700                                  u32 *net_lvl)
701 {
702         switch (doi_def->type) {
703         case CIPSO_V4_MAP_PASS:
704                 *net_lvl = host_lvl;
705                 return 0;
706         case CIPSO_V4_MAP_STD:
707                 if (host_lvl < doi_def->map.std->lvl.local_size) {
708                         *net_lvl = doi_def->map.std->lvl.local[host_lvl];
709                         return 0;
710                 }
711                 break;
712         }
713
714         return -EINVAL;
715 }
716
717 /**
718  * cipso_v4_map_lvl_ntoh - Perform a level mapping from the network to the host
719  * @doi_def: the DOI definition
720  * @net_lvl: the network/CIPSO MLS level
721  * @host_lvl: the host MLS level
722  *
723  * Description:
724  * Perform a label mapping to translate a CIPSO level to the correct local MLS
725  * level using the given DOI definition.  Returns zero on success, negative
726  * values otherwise.
727  *
728  */
729 static int cipso_v4_map_lvl_ntoh(const struct cipso_v4_doi *doi_def,
730                                  u32 net_lvl,
731                                  u32 *host_lvl)
732 {
733         struct cipso_v4_std_map_tbl *map_tbl;
734
735         switch (doi_def->type) {
736         case CIPSO_V4_MAP_PASS:
737                 *host_lvl = net_lvl;
738                 return 0;
739         case CIPSO_V4_MAP_STD:
740                 map_tbl = doi_def->map.std;
741                 if (net_lvl < map_tbl->lvl.cipso_size &&
742                     map_tbl->lvl.cipso[net_lvl] < CIPSO_V4_INV_LVL) {
743                         *host_lvl = doi_def->map.std->lvl.cipso[net_lvl];
744                         return 0;
745                 }
746                 break;
747         }
748
749         return -EINVAL;
750 }
751
752 /**
753  * cipso_v4_map_cat_rbm_valid - Checks to see if the category bitmap is valid
754  * @doi_def: the DOI definition
755  * @bitmap: category bitmap
756  * @bitmap_len: bitmap length in bytes
757  *
758  * Description:
759  * Checks the given category bitmap against the given DOI definition and
760  * returns a negative value if any of the categories in the bitmap do not have
761  * a valid mapping and a zero value if all of the categories are valid.
762  *
763  */
764 static int cipso_v4_map_cat_rbm_valid(const struct cipso_v4_doi *doi_def,
765                                       const unsigned char *bitmap,
766                                       u32 bitmap_len)
767 {
768         int cat = -1;
769         u32 bitmap_len_bits = bitmap_len * 8;
770         u32 cipso_cat_size = doi_def->map.std->cat.cipso_size;
771         u32 *cipso_array = doi_def->map.std->cat.cipso;
772
773         switch (doi_def->type) {
774         case CIPSO_V4_MAP_PASS:
775                 return 0;
776         case CIPSO_V4_MAP_STD:
777                 for (;;) {
778                         cat = cipso_v4_bitmap_walk(bitmap,
779                                                    bitmap_len_bits,
780                                                    cat + 1,
781                                                    1);
782                         if (cat < 0)
783                                 break;
784                         if (cat >= cipso_cat_size ||
785                             cipso_array[cat] >= CIPSO_V4_INV_CAT)
786                                 return -EFAULT;
787                 }
788
789                 if (cat == -1)
790                         return 0;
791                 break;
792         }
793
794         return -EFAULT;
795 }
796
797 /**
798  * cipso_v4_map_cat_rbm_hton - Perform a category mapping from host to network
799  * @doi_def: the DOI definition
800  * @host_cat: the category bitmap in host format
801  * @host_cat_len: the length of the host's category bitmap in bytes
802  * @net_cat: the zero'd out category bitmap in network/CIPSO format
803  * @net_cat_len: the length of the CIPSO bitmap in bytes
804  *
805  * Description:
806  * Perform a label mapping to translate a local MLS category bitmap to the
807  * correct CIPSO bitmap using the given DOI definition.  Returns the minimum
808  * size in bytes of the network bitmap on success, negative values otherwise.
809  *
810  */
811 static int cipso_v4_map_cat_rbm_hton(const struct cipso_v4_doi *doi_def,
812                                      const unsigned char *host_cat,
813                                      u32 host_cat_len,
814                                      unsigned char *net_cat,
815                                      u32 net_cat_len)
816 {
817         int host_spot = -1;
818         u32 net_spot;
819         u32 net_spot_max = 0;
820         u32 host_clen_bits = host_cat_len * 8;
821         u32 net_clen_bits = net_cat_len * 8;
822         u32 host_cat_size = doi_def->map.std->cat.local_size;
823         u32 *host_cat_array = doi_def->map.std->cat.local;
824
825         switch (doi_def->type) {
826         case CIPSO_V4_MAP_PASS:
827                 net_spot_max = host_cat_len - 1;
828                 while (net_spot_max > 0 && host_cat[net_spot_max] == 0)
829                         net_spot_max--;
830                 if (net_spot_max > net_cat_len)
831                         return -EINVAL;
832                 memcpy(net_cat, host_cat, net_spot_max);
833                 return net_spot_max;
834         case CIPSO_V4_MAP_STD:
835                 for (;;) {
836                         host_spot = cipso_v4_bitmap_walk(host_cat,
837                                                          host_clen_bits,
838                                                          host_spot + 1,
839                                                          1);
840                         if (host_spot < 0)
841                                 break;
842                         if (host_spot >= host_cat_size)
843                                 return -EPERM;
844
845                         net_spot = host_cat_array[host_spot];
846                         if (net_spot >= net_clen_bits)
847                                 return -ENOSPC;
848                         cipso_v4_bitmap_setbit(net_cat, net_spot, 1);
849
850                         if (net_spot > net_spot_max)
851                                 net_spot_max = net_spot;
852                 }
853
854                 if (host_spot == -2)
855                         return -EFAULT;
856
857                 if (++net_spot_max % 8)
858                         return net_spot_max / 8 + 1;
859                 return net_spot_max / 8;
860         }
861
862         return -EINVAL;
863 }
864
865 /**
866  * cipso_v4_map_cat_rbm_ntoh - Perform a category mapping from network to host
867  * @doi_def: the DOI definition
868  * @net_cat: the category bitmap in network/CIPSO format
869  * @net_cat_len: the length of the CIPSO bitmap in bytes
870  * @host_cat: the zero'd out category bitmap in host format
871  * @host_cat_len: the length of the host's category bitmap in bytes
872  *
873  * Description:
874  * Perform a label mapping to translate a CIPSO bitmap to the correct local
875  * MLS category bitmap using the given DOI definition.  Returns the minimum
876  * size in bytes of the host bitmap on success, negative values otherwise.
877  *
878  */
879 static int cipso_v4_map_cat_rbm_ntoh(const struct cipso_v4_doi *doi_def,
880                                      const unsigned char *net_cat,
881                                      u32 net_cat_len,
882                                      unsigned char *host_cat,
883                                      u32 host_cat_len)
884 {
885         u32 host_spot;
886         u32 host_spot_max = 0;
887         int net_spot = -1;
888         u32 net_clen_bits = net_cat_len * 8;
889         u32 host_clen_bits = host_cat_len * 8;
890         u32 net_cat_size = doi_def->map.std->cat.cipso_size;
891         u32 *net_cat_array = doi_def->map.std->cat.cipso;
892
893         switch (doi_def->type) {
894         case CIPSO_V4_MAP_PASS:
895                 if (net_cat_len > host_cat_len)
896                         return -EINVAL;
897                 memcpy(host_cat, net_cat, net_cat_len);
898                 return net_cat_len;
899         case CIPSO_V4_MAP_STD:
900                 for (;;) {
901                         net_spot = cipso_v4_bitmap_walk(net_cat,
902                                                         net_clen_bits,
903                                                         net_spot + 1,
904                                                         1);
905                         if (net_spot < 0)
906                                 break;
907                         if (net_spot >= net_cat_size ||
908                             net_cat_array[net_spot] >= CIPSO_V4_INV_CAT)
909                                 return -EPERM;
910
911                         host_spot = net_cat_array[net_spot];
912                         if (host_spot >= host_clen_bits)
913                                 return -ENOSPC;
914                         cipso_v4_bitmap_setbit(host_cat, host_spot, 1);
915
916                         if (host_spot > host_spot_max)
917                                 host_spot_max = host_spot;
918                 }
919
920                 if (net_spot == -2)
921                         return -EFAULT;
922
923                 if (++host_spot_max % 8)
924                         return host_spot_max / 8 + 1;
925                 return host_spot_max / 8;
926         }
927
928         return -EINVAL;
929 }
930
931 /*
932  * Protocol Handling Functions
933  */
934
935 #define CIPSO_V4_HDR_LEN              6
936
937 /**
938  * cipso_v4_gentag_hdr - Generate a CIPSO option header
939  * @doi_def: the DOI definition
940  * @len: the total tag length in bytes
941  * @buf: the CIPSO option buffer
942  *
943  * Description:
944  * Write a CIPSO header into the beginning of @buffer.  Return zero on success,
945  * negative values on failure.
946  *
947  */
948 static int cipso_v4_gentag_hdr(const struct cipso_v4_doi *doi_def,
949                                u32 len,
950                                unsigned char *buf)
951 {
952         if (CIPSO_V4_HDR_LEN + len > 40)
953                 return -ENOSPC;
954
955         buf[0] = IPOPT_CIPSO;
956         buf[1] = CIPSO_V4_HDR_LEN + len;
957         *(u32 *)&buf[2] = htonl(doi_def->doi);
958
959         return 0;
960 }
961
962 #define CIPSO_V4_TAG1_CAT_LEN         30
963
964 /**
965  * cipso_v4_gentag_rbm - Generate a CIPSO restricted bitmap tag (type #1)
966  * @doi_def: the DOI definition
967  * @secattr: the security attributes
968  * @buffer: the option buffer
969  * @buffer_len: length of buffer in bytes
970  *
971  * Description:
972  * Generate a CIPSO option using the restricted bitmap tag, tag type #1.  The
973  * actual buffer length may be larger than the indicated size due to
974  * translation between host and network category bitmaps.  Returns zero on
975  * success, negative values on failure.
976  *
977  */
978 static int cipso_v4_gentag_rbm(const struct cipso_v4_doi *doi_def,
979                                const struct netlbl_lsm_secattr *secattr,
980                                unsigned char **buffer,
981                                u32 *buffer_len)
982 {
983         int ret_val = -EPERM;
984         unsigned char *buf = NULL;
985         u32 buf_len;
986         u32 level;
987
988         if (secattr->mls_cat) {
989                 buf = kzalloc(CIPSO_V4_HDR_LEN + 4 + CIPSO_V4_TAG1_CAT_LEN,
990                               GFP_ATOMIC);
991                 if (buf == NULL)
992                         return -ENOMEM;
993
994                 ret_val = cipso_v4_map_cat_rbm_hton(doi_def,
995                                                     secattr->mls_cat,
996                                                     secattr->mls_cat_len,
997                                                     &buf[CIPSO_V4_HDR_LEN + 4],
998                                                     CIPSO_V4_TAG1_CAT_LEN);
999                 if (ret_val < 0)
1000                         goto gentag_failure;
1001
1002                 /* This will send packets using the "optimized" format when
1003                  * possibile as specified in  section 3.4.2.6 of the
1004                  * CIPSO draft. */
1005                 if (cipso_v4_rbm_optfmt && (ret_val > 0 && ret_val < 10))
1006                         ret_val = 10;
1007
1008                 buf_len = 4 + ret_val;
1009         } else {
1010                 buf = kzalloc(CIPSO_V4_HDR_LEN + 4, GFP_ATOMIC);
1011                 if (buf == NULL)
1012                         return -ENOMEM;
1013                 buf_len = 4;
1014         }
1015
1016         ret_val = cipso_v4_map_lvl_hton(doi_def, secattr->mls_lvl, &level);
1017         if (ret_val != 0)
1018                 goto gentag_failure;
1019
1020         ret_val = cipso_v4_gentag_hdr(doi_def, buf_len, buf);
1021         if (ret_val != 0)
1022                 goto gentag_failure;
1023
1024         buf[CIPSO_V4_HDR_LEN] = 0x01;
1025         buf[CIPSO_V4_HDR_LEN + 1] = buf_len;
1026         buf[CIPSO_V4_HDR_LEN + 3] = level;
1027
1028         *buffer = buf;
1029         *buffer_len = CIPSO_V4_HDR_LEN + buf_len;
1030
1031         return 0;
1032
1033 gentag_failure:
1034         kfree(buf);
1035         return ret_val;
1036 }
1037
1038 /**
1039  * cipso_v4_parsetag_rbm - Parse a CIPSO restricted bitmap tag
1040  * @doi_def: the DOI definition
1041  * @tag: the CIPSO tag
1042  * @secattr: the security attributes
1043  *
1044  * Description:
1045  * Parse a CIPSO restricted bitmap tag (tag type #1) and return the security
1046  * attributes in @secattr.  Return zero on success, negatives values on
1047  * failure.
1048  *
1049  */
1050 static int cipso_v4_parsetag_rbm(const struct cipso_v4_doi *doi_def,
1051                                  const unsigned char *tag,
1052                                  struct netlbl_lsm_secattr *secattr)
1053 {
1054         int ret_val;
1055         u8 tag_len = tag[1];
1056         u32 level;
1057
1058         ret_val = cipso_v4_map_lvl_ntoh(doi_def, tag[3], &level);
1059         if (ret_val != 0)
1060                 return ret_val;
1061         secattr->mls_lvl = level;
1062         secattr->mls_lvl_vld = 1;
1063
1064         if (tag_len > 4) {
1065                 switch (doi_def->type) {
1066                 case CIPSO_V4_MAP_PASS:
1067                         secattr->mls_cat_len = tag_len - 4;
1068                         break;
1069                 case CIPSO_V4_MAP_STD:
1070                         secattr->mls_cat_len =
1071                                 doi_def->map.std->cat.local_size;
1072                         break;
1073                 }
1074                 secattr->mls_cat = kzalloc(secattr->mls_cat_len, GFP_ATOMIC);
1075                 if (secattr->mls_cat == NULL)
1076                         return -ENOMEM;
1077
1078                 ret_val = cipso_v4_map_cat_rbm_ntoh(doi_def,
1079                                                     &tag[4],
1080                                                     tag_len - 4,
1081                                                     secattr->mls_cat,
1082                                                     secattr->mls_cat_len);
1083                 if (ret_val < 0) {
1084                         kfree(secattr->mls_cat);
1085                         return ret_val;
1086                 }
1087                 secattr->mls_cat_len = ret_val;
1088         }
1089
1090         return 0;
1091 }
1092
1093 /**
1094  * cipso_v4_validate - Validate a CIPSO option
1095  * @option: the start of the option, on error it is set to point to the error
1096  *
1097  * Description:
1098  * This routine is called to validate a CIPSO option, it checks all of the
1099  * fields to ensure that they are at least valid, see the draft snippet below
1100  * for details.  If the option is valid then a zero value is returned and
1101  * the value of @option is unchanged.  If the option is invalid then a
1102  * non-zero value is returned and @option is adjusted to point to the
1103  * offending portion of the option.  From the IETF draft ...
1104  *
1105  *  "If any field within the CIPSO options, such as the DOI identifier, is not
1106  *   recognized the IP datagram is discarded and an ICMP 'parameter problem'
1107  *   (type 12) is generated and returned.  The ICMP code field is set to 'bad
1108  *   parameter' (code 0) and the pointer is set to the start of the CIPSO field
1109  *   that is unrecognized."
1110  *
1111  */
1112 int cipso_v4_validate(unsigned char **option)
1113 {
1114         unsigned char *opt = *option;
1115         unsigned char *tag;
1116         unsigned char opt_iter;
1117         unsigned char err_offset = 0;
1118         u8 opt_len;
1119         u8 tag_len;
1120         struct cipso_v4_doi *doi_def = NULL;
1121         u32 tag_iter;
1122
1123         /* caller already checks for length values that are too large */
1124         opt_len = opt[1];
1125         if (opt_len < 8) {
1126                 err_offset = 1;
1127                 goto validate_return;
1128         }
1129
1130         rcu_read_lock();
1131         doi_def = cipso_v4_doi_getdef(ntohl(*((u32 *)&opt[2])));
1132         if (doi_def == NULL) {
1133                 err_offset = 2;
1134                 goto validate_return_locked;
1135         }
1136
1137         opt_iter = 6;
1138         tag = opt + opt_iter;
1139         while (opt_iter < opt_len) {
1140                 for (tag_iter = 0; doi_def->tags[tag_iter] != tag[0];)
1141                         if (doi_def->tags[tag_iter] == CIPSO_V4_TAG_INVALID ||
1142                             ++tag_iter == CIPSO_V4_TAG_MAXCNT) {
1143                                 err_offset = opt_iter;
1144                                 goto validate_return_locked;
1145                         }
1146
1147                 tag_len = tag[1];
1148                 if (tag_len > (opt_len - opt_iter)) {
1149                         err_offset = opt_iter + 1;
1150                         goto validate_return_locked;
1151                 }
1152
1153                 switch (tag[0]) {
1154                 case CIPSO_V4_TAG_RBITMAP:
1155                         if (tag_len < 4) {
1156                                 err_offset = opt_iter + 1;
1157                                 goto validate_return_locked;
1158                         }
1159
1160                         /* We are already going to do all the verification
1161                          * necessary at the socket layer so from our point of
1162                          * view it is safe to turn these checks off (and less
1163                          * work), however, the CIPSO draft says we should do
1164                          * all the CIPSO validations here but it doesn't
1165                          * really specify _exactly_ what we need to validate
1166                          * ... so, just make it a sysctl tunable. */
1167                         if (cipso_v4_rbm_strictvalid) {
1168                                 if (cipso_v4_map_lvl_valid(doi_def,
1169                                                            tag[3]) < 0) {
1170                                         err_offset = opt_iter + 3;
1171                                         goto validate_return_locked;
1172                                 }
1173                                 if (tag_len > 4 &&
1174                                     cipso_v4_map_cat_rbm_valid(doi_def,
1175                                                             &tag[4],
1176                                                             tag_len - 4) < 0) {
1177                                         err_offset = opt_iter + 4;
1178                                         goto validate_return_locked;
1179                                 }
1180                         }
1181                         break;
1182                 default:
1183                         err_offset = opt_iter;
1184                         goto validate_return_locked;
1185                 }
1186
1187                 tag += tag_len;
1188                 opt_iter += tag_len;
1189         }
1190
1191 validate_return_locked:
1192         rcu_read_unlock();
1193 validate_return:
1194         *option = opt + err_offset;
1195         return err_offset;
1196 }
1197
1198 /**
1199  * cipso_v4_error - Send the correct reponse for a bad packet
1200  * @skb: the packet
1201  * @error: the error code
1202  * @gateway: CIPSO gateway flag
1203  *
1204  * Description:
1205  * Based on the error code given in @error, send an ICMP error message back to
1206  * the originating host.  From the IETF draft ...
1207  *
1208  *  "If the contents of the CIPSO [option] are valid but the security label is
1209  *   outside of the configured host or port label range, the datagram is
1210  *   discarded and an ICMP 'destination unreachable' (type 3) is generated and
1211  *   returned.  The code field of the ICMP is set to 'communication with
1212  *   destination network administratively prohibited' (code 9) or to
1213  *   'communication with destination host administratively prohibited'
1214  *   (code 10).  The value of the code is dependent on whether the originator
1215  *   of the ICMP message is acting as a CIPSO host or a CIPSO gateway.  The
1216  *   recipient of the ICMP message MUST be able to handle either value.  The
1217  *   same procedure is performed if a CIPSO [option] can not be added to an
1218  *   IP packet because it is too large to fit in the IP options area."
1219  *
1220  *  "If the error is triggered by receipt of an ICMP message, the message is
1221  *   discarded and no response is permitted (consistent with general ICMP
1222  *   processing rules)."
1223  *
1224  */
1225 void cipso_v4_error(struct sk_buff *skb, int error, u32 gateway)
1226 {
1227         if (skb->nh.iph->protocol == IPPROTO_ICMP || error != -EACCES)
1228                 return;
1229
1230         if (gateway)
1231                 icmp_send(skb, ICMP_DEST_UNREACH, ICMP_NET_ANO, 0);
1232         else
1233                 icmp_send(skb, ICMP_DEST_UNREACH, ICMP_HOST_ANO, 0);
1234 }
1235
1236 /**
1237  * cipso_v4_socket_setattr - Add a CIPSO option to a socket
1238  * @sock: the socket
1239  * @doi_def: the CIPSO DOI to use
1240  * @secattr: the specific security attributes of the socket
1241  *
1242  * Description:
1243  * Set the CIPSO option on the given socket using the DOI definition and
1244  * security attributes passed to the function.  This function requires
1245  * exclusive access to @sock->sk, which means it either needs to be in the
1246  * process of being created or locked via lock_sock(sock->sk).  Returns zero on
1247  * success and negative values on failure.
1248  *
1249  */
1250 int cipso_v4_socket_setattr(const struct socket *sock,
1251                             const struct cipso_v4_doi *doi_def,
1252                             const struct netlbl_lsm_secattr *secattr)
1253 {
1254         int ret_val = -EPERM;
1255         u32 iter;
1256         unsigned char *buf = NULL;
1257         u32 buf_len = 0;
1258         u32 opt_len;
1259         struct ip_options *opt = NULL;
1260         struct sock *sk;
1261         struct inet_sock *sk_inet;
1262         struct inet_connection_sock *sk_conn;
1263
1264         /* In the case of sock_create_lite(), the sock->sk field is not
1265          * defined yet but it is not a problem as the only users of these
1266          * "lite" PF_INET sockets are functions which do an accept() call
1267          * afterwards so we will label the socket as part of the accept(). */
1268         sk = sock->sk;
1269         if (sk == NULL)
1270                 return 0;
1271
1272         /* XXX - This code assumes only one tag per CIPSO option which isn't
1273          * really a good assumption to make but since we only support the MAC
1274          * tags right now it is a safe assumption. */
1275         iter = 0;
1276         do {
1277                 switch (doi_def->tags[iter]) {
1278                 case CIPSO_V4_TAG_RBITMAP:
1279                         ret_val = cipso_v4_gentag_rbm(doi_def,
1280                                                       secattr,
1281                                                       &buf,
1282                                                       &buf_len);
1283                         break;
1284                 default:
1285                         ret_val = -EPERM;
1286                         goto socket_setattr_failure;
1287                 }
1288
1289                 iter++;
1290         } while (ret_val != 0 &&
1291                  iter < CIPSO_V4_TAG_MAXCNT &&
1292                  doi_def->tags[iter] != CIPSO_V4_TAG_INVALID);
1293         if (ret_val != 0)
1294                 goto socket_setattr_failure;
1295
1296         /* We can't use ip_options_get() directly because it makes a call to
1297          * ip_options_get_alloc() which allocates memory with GFP_KERNEL and
1298          * we can't block here. */
1299         opt_len = (buf_len + 3) & ~3;
1300         opt = kzalloc(sizeof(*opt) + opt_len, GFP_ATOMIC);
1301         if (opt == NULL) {
1302                 ret_val = -ENOMEM;
1303                 goto socket_setattr_failure;
1304         }
1305         memcpy(opt->__data, buf, buf_len);
1306         opt->optlen = opt_len;
1307         opt->is_data = 1;
1308         kfree(buf);
1309         buf = NULL;
1310         ret_val = ip_options_compile(opt, NULL);
1311         if (ret_val != 0)
1312                 goto socket_setattr_failure;
1313
1314         sk_inet = inet_sk(sk);
1315         if (sk_inet->is_icsk) {
1316                 sk_conn = inet_csk(sk);
1317                 if (sk_inet->opt)
1318                         sk_conn->icsk_ext_hdr_len -= sk_inet->opt->optlen;
1319                 sk_conn->icsk_ext_hdr_len += opt->optlen;
1320                 sk_conn->icsk_sync_mss(sk, sk_conn->icsk_pmtu_cookie);
1321         }
1322         opt = xchg(&sk_inet->opt, opt);
1323         kfree(opt);
1324
1325         return 0;
1326
1327 socket_setattr_failure:
1328         kfree(buf);
1329         kfree(opt);
1330         return ret_val;
1331 }
1332
1333 /**
1334  * cipso_v4_sock_getattr - Get the security attributes from a sock
1335  * @sk: the sock
1336  * @secattr: the security attributes
1337  *
1338  * Description:
1339  * Query @sk to see if there is a CIPSO option attached to the sock and if
1340  * there is return the CIPSO security attributes in @secattr.  This function
1341  * requires that @sk be locked, or privately held, but it does not do any
1342  * locking itself.  Returns zero on success and negative values on failure.
1343  *
1344  */
1345 int cipso_v4_sock_getattr(struct sock *sk, struct netlbl_lsm_secattr *secattr)
1346 {
1347         int ret_val = -ENOMSG;
1348         struct inet_sock *sk_inet;
1349         unsigned char *cipso_ptr;
1350         u32 doi;
1351         struct cipso_v4_doi *doi_def;
1352
1353         sk_inet = inet_sk(sk);
1354         if (sk_inet->opt == NULL || sk_inet->opt->cipso == 0)
1355                 return -ENOMSG;
1356         cipso_ptr = sk_inet->opt->__data + sk_inet->opt->cipso -
1357                 sizeof(struct iphdr);
1358         ret_val = cipso_v4_cache_check(cipso_ptr, cipso_ptr[1], secattr);
1359         if (ret_val == 0)
1360                 return ret_val;
1361
1362         doi = ntohl(*(u32 *)&cipso_ptr[2]);
1363         rcu_read_lock();
1364         doi_def = cipso_v4_doi_getdef(doi);
1365         if (doi_def == NULL) {
1366                 rcu_read_unlock();
1367                 return -ENOMSG;
1368         }
1369         switch (cipso_ptr[6]) {
1370         case CIPSO_V4_TAG_RBITMAP:
1371                 ret_val = cipso_v4_parsetag_rbm(doi_def,
1372                                                 &cipso_ptr[6],
1373                                                 secattr);
1374                 break;
1375         }
1376         rcu_read_unlock();
1377
1378         return ret_val;
1379 }
1380
1381 /**
1382  * cipso_v4_socket_getattr - Get the security attributes from a socket
1383  * @sock: the socket
1384  * @secattr: the security attributes
1385  *
1386  * Description:
1387  * Query @sock to see if there is a CIPSO option attached to the socket and if
1388  * there is return the CIPSO security attributes in @secattr.  Returns zero on
1389  * success and negative values on failure.
1390  *
1391  */
1392 int cipso_v4_socket_getattr(const struct socket *sock,
1393                             struct netlbl_lsm_secattr *secattr)
1394 {
1395         int ret_val;
1396
1397         lock_sock(sock->sk);
1398         ret_val = cipso_v4_sock_getattr(sock->sk, secattr);
1399         release_sock(sock->sk);
1400
1401         return ret_val;
1402 }
1403
1404 /**
1405  * cipso_v4_skbuff_getattr - Get the security attributes from the CIPSO option
1406  * @skb: the packet
1407  * @secattr: the security attributes
1408  *
1409  * Description:
1410  * Parse the given packet's CIPSO option and return the security attributes.
1411  * Returns zero on success and negative values on failure.
1412  *
1413  */
1414 int cipso_v4_skbuff_getattr(const struct sk_buff *skb,
1415                             struct netlbl_lsm_secattr *secattr)
1416 {
1417         int ret_val = -ENOMSG;
1418         unsigned char *cipso_ptr;
1419         u32 doi;
1420         struct cipso_v4_doi *doi_def;
1421
1422         if (!CIPSO_V4_OPTEXIST(skb))
1423                 return -ENOMSG;
1424         cipso_ptr = CIPSO_V4_OPTPTR(skb);
1425         if (cipso_v4_cache_check(cipso_ptr, cipso_ptr[1], secattr) == 0)
1426                 return 0;
1427
1428         doi = ntohl(*(u32 *)&cipso_ptr[2]);
1429         rcu_read_lock();
1430         doi_def = cipso_v4_doi_getdef(doi);
1431         if (doi_def == NULL)
1432                 goto skbuff_getattr_return;
1433         switch (cipso_ptr[6]) {
1434         case CIPSO_V4_TAG_RBITMAP:
1435                 ret_val = cipso_v4_parsetag_rbm(doi_def,
1436                                                 &cipso_ptr[6],
1437                                                 secattr);
1438                 break;
1439         }
1440
1441 skbuff_getattr_return:
1442         rcu_read_unlock();
1443         return ret_val;
1444 }
1445
1446 /*
1447  * Setup Functions
1448  */
1449
1450 /**
1451  * cipso_v4_init - Initialize the CIPSO module
1452  *
1453  * Description:
1454  * Initialize the CIPSO module and prepare it for use.  Returns zero on success
1455  * and negative values on failure.
1456  *
1457  */
1458 static int __init cipso_v4_init(void)
1459 {
1460         int ret_val;
1461
1462         ret_val = cipso_v4_cache_init();
1463         if (ret_val != 0)
1464                 panic("Failed to initialize the CIPSO/IPv4 cache (%d)\n",
1465                       ret_val);
1466
1467         return 0;
1468 }
1469
1470 subsys_initcall(cipso_v4_init);