cipso_ipv4.c revision 14a72f53fb1bb5d5c2bdd8cf172219519664729a
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_sock_getattr - Get the security attributes from a sock 1490 * @sk: the sock 1491 * @secattr: the security attributes 1492 * 1493 * Description: 1494 * Query @sk to see if there is a CIPSO option attached to the sock and if 1495 * there is return the CIPSO security attributes in @secattr. This function 1496 * requires that @sk be locked, or privately held, but it does not do any 1497 * locking itself. Returns zero on success and negative values on failure. 1498 * 1499 */ 1500int cipso_v4_sock_getattr(struct sock *sk, struct netlbl_lsm_secattr *secattr) 1501{ 1502 int ret_val = -ENOMSG; 1503 struct inet_sock *sk_inet; 1504 unsigned char *cipso_ptr; 1505 u32 doi; 1506 struct cipso_v4_doi *doi_def; 1507 1508 sk_inet = inet_sk(sk); 1509 if (sk_inet->opt == NULL || sk_inet->opt->cipso == 0) 1510 return -ENOMSG; 1511 cipso_ptr = sk_inet->opt->__data + sk_inet->opt->cipso - 1512 sizeof(struct iphdr); 1513 ret_val = cipso_v4_cache_check(cipso_ptr, cipso_ptr[1], secattr); 1514 if (ret_val == 0) 1515 return ret_val; 1516 1517 doi = ntohl(*(u32 *)&cipso_ptr[2]); 1518 rcu_read_lock(); 1519 doi_def = cipso_v4_doi_getdef(doi); 1520 if (doi_def == NULL) { 1521 rcu_read_unlock(); 1522 return -ENOMSG; 1523 } 1524 switch (cipso_ptr[6]) { 1525 case CIPSO_V4_TAG_RBITMAP: 1526 ret_val = cipso_v4_parsetag_rbm(doi_def, 1527 &cipso_ptr[6], 1528 secattr); 1529 break; 1530 } 1531 rcu_read_unlock(); 1532 1533 return ret_val; 1534} 1535 1536/** 1537 * cipso_v4_socket_getattr - Get the security attributes from a socket 1538 * @sock: the socket 1539 * @secattr: the security attributes 1540 * 1541 * Description: 1542 * Query @sock to see if there is a CIPSO option attached to the socket and if 1543 * there is return the CIPSO security attributes in @secattr. Returns zero on 1544 * success and negative values on failure. 1545 * 1546 */ 1547int cipso_v4_socket_getattr(const struct socket *sock, 1548 struct netlbl_lsm_secattr *secattr) 1549{ 1550 int ret_val; 1551 1552 lock_sock(sock->sk); 1553 ret_val = cipso_v4_sock_getattr(sock->sk, secattr); 1554 release_sock(sock->sk); 1555 1556 return ret_val; 1557} 1558 1559/** 1560 * cipso_v4_skbuff_getattr - Get the security attributes from the CIPSO option 1561 * @skb: the packet 1562 * @secattr: the security attributes 1563 * 1564 * Description: 1565 * Parse the given packet's CIPSO option and return the security attributes. 1566 * Returns zero on success and negative values on failure. 1567 * 1568 */ 1569int cipso_v4_skbuff_getattr(const struct sk_buff *skb, 1570 struct netlbl_lsm_secattr *secattr) 1571{ 1572 int ret_val = -ENOMSG; 1573 unsigned char *cipso_ptr; 1574 u32 doi; 1575 struct cipso_v4_doi *doi_def; 1576 1577 if (!CIPSO_V4_OPTEXIST(skb)) 1578 return -ENOMSG; 1579 cipso_ptr = CIPSO_V4_OPTPTR(skb); 1580 if (cipso_v4_cache_check(cipso_ptr, cipso_ptr[1], secattr) == 0) 1581 return 0; 1582 1583 doi = ntohl(*(u32 *)&cipso_ptr[2]); 1584 rcu_read_lock(); 1585 doi_def = cipso_v4_doi_getdef(doi); 1586 if (doi_def == NULL) 1587 goto skbuff_getattr_return; 1588 switch (cipso_ptr[6]) { 1589 case CIPSO_V4_TAG_RBITMAP: 1590 ret_val = cipso_v4_parsetag_rbm(doi_def, 1591 &cipso_ptr[6], 1592 secattr); 1593 break; 1594 } 1595 1596skbuff_getattr_return: 1597 rcu_read_unlock(); 1598 return ret_val; 1599} 1600 1601/* 1602 * Setup Functions 1603 */ 1604 1605/** 1606 * cipso_v4_init - Initialize the CIPSO module 1607 * 1608 * Description: 1609 * Initialize the CIPSO module and prepare it for use. Returns zero on success 1610 * and negative values on failure. 1611 * 1612 */ 1613static int __init cipso_v4_init(void) 1614{ 1615 int ret_val; 1616 1617 ret_val = cipso_v4_cache_init(); 1618 if (ret_val != 0) 1619 panic("Failed to initialize the CIPSO/IPv4 cache (%d)\n", 1620 ret_val); 1621 1622 return 0; 1623} 1624 1625subsys_initcall(cipso_v4_init); 1626