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