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