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