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