cipso_ipv4.c revision 714e85be3557222bc25f69c252326207c900a7db
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 49struct 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. */ 64static DEFINE_SPINLOCK(cipso_v4_doi_list_lock); 65static struct list_head cipso_v4_doi_list = LIST_HEAD_INIT(cipso_v4_doi_list); 66 67/* Label mapping cache */ 68int cipso_v4_cache_enabled = 1; 69int 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 73struct cipso_v4_map_cache_bkt { 74 spinlock_t lock; 75 u32 size; 76 struct list_head list; 77}; 78struct 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}; 88static struct cipso_v4_map_cache_bkt *cipso_v4_cache = NULL; 89 90/* Restricted bitmap (tag #1) flags */ 91int cipso_v4_rbm_optfmt = 0; 92int 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 */ 110static 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 */ 152static 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 */ 178static 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 */ 196static 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 */ 213static 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 */ 231static 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 */ 258void 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 */ 300static 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 if (prev_entry == NULL) { 323 spin_unlock_bh(&cipso_v4_cache[bkt].lock); 324 return 0; 325 } 326 327 if (prev_entry->activity > 0) 328 prev_entry->activity -= 1; 329 if (entry->activity > prev_entry->activity && 330 entry->activity - prev_entry->activity > 331 CIPSO_V4_CACHE_REORDERLIMIT) { 332 __list_del(entry->list.prev, entry->list.next); 333 __list_add(&entry->list, 334 prev_entry->list.prev, 335 &prev_entry->list); 336 } 337 338 spin_unlock_bh(&cipso_v4_cache[bkt].lock); 339 return 0; 340 } 341 prev_entry = entry; 342 } 343 spin_unlock_bh(&cipso_v4_cache[bkt].lock); 344 345 return -ENOENT; 346} 347 348/** 349 * cipso_v4_cache_add - Add an entry to the CIPSO cache 350 * @skb: the packet 351 * @secattr: the packet's security attributes 352 * 353 * Description: 354 * Add a new entry into the CIPSO label mapping cache. Add the new entry to 355 * head of the cache bucket's list, if the cache bucket is out of room remove 356 * the last entry in the list first. It is important to note that there is 357 * currently no checking for duplicate keys. Returns zero on success, 358 * negative values on failure. 359 * 360 */ 361int cipso_v4_cache_add(const struct sk_buff *skb, 362 const struct netlbl_lsm_secattr *secattr) 363{ 364 int ret_val = -EPERM; 365 u32 bkt; 366 struct cipso_v4_map_cache_entry *entry = NULL; 367 struct cipso_v4_map_cache_entry *old_entry = NULL; 368 unsigned char *cipso_ptr; 369 u32 cipso_ptr_len; 370 371 if (!cipso_v4_cache_enabled || cipso_v4_cache_bucketsize <= 0) 372 return 0; 373 374 cipso_ptr = CIPSO_V4_OPTPTR(skb); 375 cipso_ptr_len = cipso_ptr[1]; 376 377 entry = kzalloc(sizeof(*entry), GFP_ATOMIC); 378 if (entry == NULL) 379 return -ENOMEM; 380 entry->key = kmalloc(cipso_ptr_len, GFP_ATOMIC); 381 if (entry->key == NULL) { 382 ret_val = -ENOMEM; 383 goto cache_add_failure; 384 } 385 memcpy(entry->key, cipso_ptr, cipso_ptr_len); 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 407cache_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 */ 426static 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 */ 448int cipso_v4_doi_add(struct cipso_v4_doi *doi_def) 449{ 450 if (doi_def == NULL || doi_def->doi == CIPSO_V4_DOI_UNKNOWN) 451 return -EINVAL; 452 453 doi_def->valid = 1; 454 INIT_RCU_HEAD(&doi_def->rcu); 455 INIT_LIST_HEAD(&doi_def->dom_list); 456 457 rcu_read_lock(); 458 if (cipso_v4_doi_search(doi_def->doi) != NULL) 459 goto doi_add_failure_rlock; 460 spin_lock(&cipso_v4_doi_list_lock); 461 if (cipso_v4_doi_search(doi_def->doi) != NULL) 462 goto doi_add_failure_slock; 463 list_add_tail_rcu(&doi_def->list, &cipso_v4_doi_list); 464 spin_unlock(&cipso_v4_doi_list_lock); 465 rcu_read_unlock(); 466 467 return 0; 468 469doi_add_failure_slock: 470 spin_unlock(&cipso_v4_doi_list_lock); 471doi_add_failure_rlock: 472 rcu_read_unlock(); 473 return -EEXIST; 474} 475 476/** 477 * cipso_v4_doi_remove - Remove an existing DOI from the CIPSO protocol engine 478 * @doi: the DOI value 479 * @audit_secid: the LSM secid to use in the audit message 480 * @callback: the DOI cleanup/free callback 481 * 482 * Description: 483 * Removes a DOI definition from the CIPSO engine, @callback is called to 484 * free any memory. The NetLabel routines will be called to release their own 485 * LSM domain mappings as well as our own domain list. Returns zero on 486 * success and negative values on failure. 487 * 488 */ 489int cipso_v4_doi_remove(u32 doi, 490 struct netlbl_audit *audit_info, 491 void (*callback) (struct rcu_head * head)) 492{ 493 struct cipso_v4_doi *doi_def; 494 struct cipso_v4_domhsh_entry *dom_iter; 495 496 rcu_read_lock(); 497 if (cipso_v4_doi_search(doi) != NULL) { 498 spin_lock(&cipso_v4_doi_list_lock); 499 doi_def = cipso_v4_doi_search(doi); 500 if (doi_def == NULL) { 501 spin_unlock(&cipso_v4_doi_list_lock); 502 rcu_read_unlock(); 503 return -ENOENT; 504 } 505 doi_def->valid = 0; 506 list_del_rcu(&doi_def->list); 507 spin_unlock(&cipso_v4_doi_list_lock); 508 list_for_each_entry_rcu(dom_iter, &doi_def->dom_list, list) 509 if (dom_iter->valid) 510 netlbl_domhsh_remove(dom_iter->domain, 511 audit_info); 512 cipso_v4_cache_invalidate(); 513 rcu_read_unlock(); 514 515 call_rcu(&doi_def->rcu, callback); 516 return 0; 517 } 518 rcu_read_unlock(); 519 520 return -ENOENT; 521} 522 523/** 524 * cipso_v4_doi_getdef - Returns a pointer to a valid DOI definition 525 * @doi: the DOI value 526 * 527 * Description: 528 * Searches for a valid DOI definition and if one is found it is returned to 529 * the caller. Otherwise NULL is returned. The caller must ensure that 530 * rcu_read_lock() is held while accessing the returned definition. 531 * 532 */ 533struct cipso_v4_doi *cipso_v4_doi_getdef(u32 doi) 534{ 535 return cipso_v4_doi_search(doi); 536} 537 538/** 539 * cipso_v4_doi_walk - Iterate through the DOI definitions 540 * @skip_cnt: skip past this number of DOI definitions, updated 541 * @callback: callback for each DOI definition 542 * @cb_arg: argument for the callback function 543 * 544 * Description: 545 * Iterate over the DOI definition list, skipping the first @skip_cnt entries. 546 * For each entry call @callback, if @callback returns a negative value stop 547 * 'walking' through the list and return. Updates the value in @skip_cnt upon 548 * return. Returns zero on success, negative values on failure. 549 * 550 */ 551int cipso_v4_doi_walk(u32 *skip_cnt, 552 int (*callback) (struct cipso_v4_doi *doi_def, void *arg), 553 void *cb_arg) 554{ 555 int ret_val = -ENOENT; 556 u32 doi_cnt = 0; 557 struct cipso_v4_doi *iter_doi; 558 559 rcu_read_lock(); 560 list_for_each_entry_rcu(iter_doi, &cipso_v4_doi_list, list) 561 if (iter_doi->valid) { 562 if (doi_cnt++ < *skip_cnt) 563 continue; 564 ret_val = callback(iter_doi, cb_arg); 565 if (ret_val < 0) { 566 doi_cnt--; 567 goto doi_walk_return; 568 } 569 } 570 571doi_walk_return: 572 rcu_read_unlock(); 573 *skip_cnt = doi_cnt; 574 return ret_val; 575} 576 577/** 578 * cipso_v4_doi_domhsh_add - Adds a domain entry to a DOI definition 579 * @doi_def: the DOI definition 580 * @domain: the domain to add 581 * 582 * Description: 583 * Adds the @domain to the the DOI specified by @doi_def, this function 584 * should only be called by external functions (i.e. NetLabel). This function 585 * does allocate memory. Returns zero on success, negative values on failure. 586 * 587 */ 588int cipso_v4_doi_domhsh_add(struct cipso_v4_doi *doi_def, const char *domain) 589{ 590 struct cipso_v4_domhsh_entry *iter; 591 struct cipso_v4_domhsh_entry *new_dom; 592 593 new_dom = kzalloc(sizeof(*new_dom), GFP_KERNEL); 594 if (new_dom == NULL) 595 return -ENOMEM; 596 if (domain) { 597 new_dom->domain = kstrdup(domain, GFP_KERNEL); 598 if (new_dom->domain == NULL) { 599 kfree(new_dom); 600 return -ENOMEM; 601 } 602 } 603 new_dom->valid = 1; 604 INIT_RCU_HEAD(&new_dom->rcu); 605 606 rcu_read_lock(); 607 spin_lock(&cipso_v4_doi_list_lock); 608 list_for_each_entry_rcu(iter, &doi_def->dom_list, list) 609 if (iter->valid && 610 ((domain != NULL && iter->domain != NULL && 611 strcmp(iter->domain, domain) == 0) || 612 (domain == NULL && iter->domain == NULL))) { 613 spin_unlock(&cipso_v4_doi_list_lock); 614 rcu_read_unlock(); 615 kfree(new_dom->domain); 616 kfree(new_dom); 617 return -EEXIST; 618 } 619 list_add_tail_rcu(&new_dom->list, &doi_def->dom_list); 620 spin_unlock(&cipso_v4_doi_list_lock); 621 rcu_read_unlock(); 622 623 return 0; 624} 625 626/** 627 * cipso_v4_doi_domhsh_remove - Removes a domain entry from a DOI definition 628 * @doi_def: the DOI definition 629 * @domain: the domain to remove 630 * 631 * Description: 632 * Removes the @domain from the DOI specified by @doi_def, this function 633 * should only be called by external functions (i.e. NetLabel). Returns zero 634 * on success and negative values on error. 635 * 636 */ 637int cipso_v4_doi_domhsh_remove(struct cipso_v4_doi *doi_def, 638 const char *domain) 639{ 640 struct cipso_v4_domhsh_entry *iter; 641 642 rcu_read_lock(); 643 spin_lock(&cipso_v4_doi_list_lock); 644 list_for_each_entry_rcu(iter, &doi_def->dom_list, list) 645 if (iter->valid && 646 ((domain != NULL && iter->domain != NULL && 647 strcmp(iter->domain, domain) == 0) || 648 (domain == NULL && iter->domain == NULL))) { 649 iter->valid = 0; 650 list_del_rcu(&iter->list); 651 spin_unlock(&cipso_v4_doi_list_lock); 652 rcu_read_unlock(); 653 call_rcu(&iter->rcu, cipso_v4_doi_domhsh_free); 654 655 return 0; 656 } 657 spin_unlock(&cipso_v4_doi_list_lock); 658 rcu_read_unlock(); 659 660 return -ENOENT; 661} 662 663/* 664 * Label Mapping Functions 665 */ 666 667/** 668 * cipso_v4_map_lvl_valid - Checks to see if the given level is understood 669 * @doi_def: the DOI definition 670 * @level: the level to check 671 * 672 * Description: 673 * Checks the given level against the given DOI definition and returns a 674 * negative value if the level does not have a valid mapping and a zero value 675 * if the level is defined by the DOI. 676 * 677 */ 678static int cipso_v4_map_lvl_valid(const struct cipso_v4_doi *doi_def, u8 level) 679{ 680 switch (doi_def->type) { 681 case CIPSO_V4_MAP_PASS: 682 return 0; 683 case CIPSO_V4_MAP_STD: 684 if (doi_def->map.std->lvl.cipso[level] < CIPSO_V4_INV_LVL) 685 return 0; 686 break; 687 } 688 689 return -EFAULT; 690} 691 692/** 693 * cipso_v4_map_lvl_hton - Perform a level mapping from the host to the network 694 * @doi_def: the DOI definition 695 * @host_lvl: the host MLS level 696 * @net_lvl: the network/CIPSO MLS level 697 * 698 * Description: 699 * Perform a label mapping to translate a local MLS level to the correct 700 * CIPSO level using the given DOI definition. Returns zero on success, 701 * negative values otherwise. 702 * 703 */ 704static int cipso_v4_map_lvl_hton(const struct cipso_v4_doi *doi_def, 705 u32 host_lvl, 706 u32 *net_lvl) 707{ 708 switch (doi_def->type) { 709 case CIPSO_V4_MAP_PASS: 710 *net_lvl = host_lvl; 711 return 0; 712 case CIPSO_V4_MAP_STD: 713 if (host_lvl < doi_def->map.std->lvl.local_size) { 714 *net_lvl = doi_def->map.std->lvl.local[host_lvl]; 715 return 0; 716 } 717 break; 718 } 719 720 return -EINVAL; 721} 722 723/** 724 * cipso_v4_map_lvl_ntoh - Perform a level mapping from the network to the host 725 * @doi_def: the DOI definition 726 * @net_lvl: the network/CIPSO MLS level 727 * @host_lvl: the host MLS level 728 * 729 * Description: 730 * Perform a label mapping to translate a CIPSO level to the correct local MLS 731 * level using the given DOI definition. Returns zero on success, negative 732 * values otherwise. 733 * 734 */ 735static int cipso_v4_map_lvl_ntoh(const struct cipso_v4_doi *doi_def, 736 u32 net_lvl, 737 u32 *host_lvl) 738{ 739 struct cipso_v4_std_map_tbl *map_tbl; 740 741 switch (doi_def->type) { 742 case CIPSO_V4_MAP_PASS: 743 *host_lvl = net_lvl; 744 return 0; 745 case CIPSO_V4_MAP_STD: 746 map_tbl = doi_def->map.std; 747 if (net_lvl < map_tbl->lvl.cipso_size && 748 map_tbl->lvl.cipso[net_lvl] < CIPSO_V4_INV_LVL) { 749 *host_lvl = doi_def->map.std->lvl.cipso[net_lvl]; 750 return 0; 751 } 752 break; 753 } 754 755 return -EINVAL; 756} 757 758/** 759 * cipso_v4_map_cat_rbm_valid - Checks to see if the category bitmap is valid 760 * @doi_def: the DOI definition 761 * @bitmap: category bitmap 762 * @bitmap_len: bitmap length in bytes 763 * 764 * Description: 765 * Checks the given category bitmap against the given DOI definition and 766 * returns a negative value if any of the categories in the bitmap do not have 767 * a valid mapping and a zero value if all of the categories are valid. 768 * 769 */ 770static int cipso_v4_map_cat_rbm_valid(const struct cipso_v4_doi *doi_def, 771 const unsigned char *bitmap, 772 u32 bitmap_len) 773{ 774 int cat = -1; 775 u32 bitmap_len_bits = bitmap_len * 8; 776 u32 cipso_cat_size; 777 u32 *cipso_array; 778 779 switch (doi_def->type) { 780 case CIPSO_V4_MAP_PASS: 781 return 0; 782 case CIPSO_V4_MAP_STD: 783 cipso_cat_size = doi_def->map.std->cat.cipso_size; 784 cipso_array = doi_def->map.std->cat.cipso; 785 for (;;) { 786 cat = cipso_v4_bitmap_walk(bitmap, 787 bitmap_len_bits, 788 cat + 1, 789 1); 790 if (cat < 0) 791 break; 792 if (cat >= cipso_cat_size || 793 cipso_array[cat] >= CIPSO_V4_INV_CAT) 794 return -EFAULT; 795 } 796 797 if (cat == -1) 798 return 0; 799 break; 800 } 801 802 return -EFAULT; 803} 804 805/** 806 * cipso_v4_map_cat_rbm_hton - Perform a category mapping from host to network 807 * @doi_def: the DOI definition 808 * @host_cat: the category bitmap in host format 809 * @host_cat_len: the length of the host's category bitmap in bytes 810 * @net_cat: the zero'd out category bitmap in network/CIPSO format 811 * @net_cat_len: the length of the CIPSO bitmap in bytes 812 * 813 * Description: 814 * Perform a label mapping to translate a local MLS category bitmap to the 815 * correct CIPSO bitmap using the given DOI definition. Returns the minimum 816 * size in bytes of the network bitmap on success, negative values otherwise. 817 * 818 */ 819static int cipso_v4_map_cat_rbm_hton(const struct cipso_v4_doi *doi_def, 820 const unsigned char *host_cat, 821 u32 host_cat_len, 822 unsigned char *net_cat, 823 u32 net_cat_len) 824{ 825 int host_spot = -1; 826 u32 net_spot; 827 u32 net_spot_max = 0; 828 u32 host_clen_bits = host_cat_len * 8; 829 u32 net_clen_bits = net_cat_len * 8; 830 u32 host_cat_size; 831 u32 *host_cat_array; 832 833 switch (doi_def->type) { 834 case CIPSO_V4_MAP_PASS: 835 net_spot_max = host_cat_len; 836 while (net_spot_max > 0 && host_cat[net_spot_max - 1] == 0) 837 net_spot_max--; 838 if (net_spot_max > net_cat_len) 839 return -EINVAL; 840 memcpy(net_cat, host_cat, net_spot_max); 841 return net_spot_max; 842 case CIPSO_V4_MAP_STD: 843 host_cat_size = doi_def->map.std->cat.local_size; 844 host_cat_array = doi_def->map.std->cat.local; 845 for (;;) { 846 host_spot = cipso_v4_bitmap_walk(host_cat, 847 host_clen_bits, 848 host_spot + 1, 849 1); 850 if (host_spot < 0) 851 break; 852 if (host_spot >= host_cat_size) 853 return -EPERM; 854 855 net_spot = host_cat_array[host_spot]; 856 if (net_spot >= net_clen_bits) 857 return -ENOSPC; 858 cipso_v4_bitmap_setbit(net_cat, net_spot, 1); 859 860 if (net_spot > net_spot_max) 861 net_spot_max = net_spot; 862 } 863 864 if (host_spot == -2) 865 return -EFAULT; 866 867 if (++net_spot_max % 8) 868 return net_spot_max / 8 + 1; 869 return net_spot_max / 8; 870 } 871 872 return -EINVAL; 873} 874 875/** 876 * cipso_v4_map_cat_rbm_ntoh - Perform a category mapping from network to host 877 * @doi_def: the DOI definition 878 * @net_cat: the category bitmap in network/CIPSO format 879 * @net_cat_len: the length of the CIPSO bitmap in bytes 880 * @host_cat: the zero'd out category bitmap in host format 881 * @host_cat_len: the length of the host's category bitmap in bytes 882 * 883 * Description: 884 * Perform a label mapping to translate a CIPSO bitmap to the correct local 885 * MLS category bitmap using the given DOI definition. Returns the minimum 886 * size in bytes of the host bitmap on success, negative values otherwise. 887 * 888 */ 889static int cipso_v4_map_cat_rbm_ntoh(const struct cipso_v4_doi *doi_def, 890 const unsigned char *net_cat, 891 u32 net_cat_len, 892 unsigned char *host_cat, 893 u32 host_cat_len) 894{ 895 u32 host_spot; 896 u32 host_spot_max = 0; 897 int net_spot = -1; 898 u32 net_clen_bits = net_cat_len * 8; 899 u32 host_clen_bits = host_cat_len * 8; 900 u32 net_cat_size; 901 u32 *net_cat_array; 902 903 switch (doi_def->type) { 904 case CIPSO_V4_MAP_PASS: 905 if (net_cat_len > host_cat_len) 906 return -EINVAL; 907 memcpy(host_cat, net_cat, net_cat_len); 908 return net_cat_len; 909 case CIPSO_V4_MAP_STD: 910 net_cat_size = doi_def->map.std->cat.cipso_size; 911 net_cat_array = doi_def->map.std->cat.cipso; 912 for (;;) { 913 net_spot = cipso_v4_bitmap_walk(net_cat, 914 net_clen_bits, 915 net_spot + 1, 916 1); 917 if (net_spot < 0) 918 break; 919 if (net_spot >= net_cat_size || 920 net_cat_array[net_spot] >= CIPSO_V4_INV_CAT) 921 return -EPERM; 922 923 host_spot = net_cat_array[net_spot]; 924 if (host_spot >= host_clen_bits) 925 return -ENOSPC; 926 cipso_v4_bitmap_setbit(host_cat, host_spot, 1); 927 928 if (host_spot > host_spot_max) 929 host_spot_max = host_spot; 930 } 931 932 if (net_spot == -2) 933 return -EFAULT; 934 935 if (++host_spot_max % 8) 936 return host_spot_max / 8 + 1; 937 return host_spot_max / 8; 938 } 939 940 return -EINVAL; 941} 942 943/* 944 * Protocol Handling Functions 945 */ 946 947#define CIPSO_V4_HDR_LEN 6 948 949/** 950 * cipso_v4_gentag_hdr - Generate a CIPSO option header 951 * @doi_def: the DOI definition 952 * @len: the total tag length in bytes 953 * @buf: the CIPSO option buffer 954 * 955 * Description: 956 * Write a CIPSO header into the beginning of @buffer. Return zero on success, 957 * negative values on failure. 958 * 959 */ 960static int cipso_v4_gentag_hdr(const struct cipso_v4_doi *doi_def, 961 u32 len, 962 unsigned char *buf) 963{ 964 if (CIPSO_V4_HDR_LEN + len > 40) 965 return -ENOSPC; 966 967 buf[0] = IPOPT_CIPSO; 968 buf[1] = CIPSO_V4_HDR_LEN + len; 969 *(__be32 *)&buf[2] = htonl(doi_def->doi); 970 971 return 0; 972} 973 974#define CIPSO_V4_TAG1_CAT_LEN 30 975 976/** 977 * cipso_v4_gentag_rbm - Generate a CIPSO restricted bitmap tag (type #1) 978 * @doi_def: the DOI definition 979 * @secattr: the security attributes 980 * @buffer: the option buffer 981 * @buffer_len: length of buffer in bytes 982 * 983 * Description: 984 * Generate a CIPSO option using the restricted bitmap tag, tag type #1. The 985 * actual buffer length may be larger than the indicated size due to 986 * translation between host and network category bitmaps. Returns zero on 987 * success, negative values on failure. 988 * 989 */ 990static int cipso_v4_gentag_rbm(const struct cipso_v4_doi *doi_def, 991 const struct netlbl_lsm_secattr *secattr, 992 unsigned char **buffer, 993 u32 *buffer_len) 994{ 995 int ret_val = -EPERM; 996 unsigned char *buf = NULL; 997 u32 buf_len; 998 u32 level; 999 1000 if (secattr->mls_cat) { 1001 buf = kzalloc(CIPSO_V4_HDR_LEN + 4 + CIPSO_V4_TAG1_CAT_LEN, 1002 GFP_ATOMIC); 1003 if (buf == NULL) 1004 return -ENOMEM; 1005 1006 ret_val = cipso_v4_map_cat_rbm_hton(doi_def, 1007 secattr->mls_cat, 1008 secattr->mls_cat_len, 1009 &buf[CIPSO_V4_HDR_LEN + 4], 1010 CIPSO_V4_TAG1_CAT_LEN); 1011 if (ret_val < 0) 1012 goto gentag_failure; 1013 1014 /* This will send packets using the "optimized" format when 1015 * possibile as specified in section 3.4.2.6 of the 1016 * CIPSO draft. */ 1017 if (cipso_v4_rbm_optfmt && (ret_val > 0 && ret_val < 10)) 1018 ret_val = 10; 1019 1020 buf_len = 4 + ret_val; 1021 } else { 1022 buf = kzalloc(CIPSO_V4_HDR_LEN + 4, GFP_ATOMIC); 1023 if (buf == NULL) 1024 return -ENOMEM; 1025 buf_len = 4; 1026 } 1027 1028 ret_val = cipso_v4_map_lvl_hton(doi_def, secattr->mls_lvl, &level); 1029 if (ret_val != 0) 1030 goto gentag_failure; 1031 1032 ret_val = cipso_v4_gentag_hdr(doi_def, buf_len, buf); 1033 if (ret_val != 0) 1034 goto gentag_failure; 1035 1036 buf[CIPSO_V4_HDR_LEN] = 0x01; 1037 buf[CIPSO_V4_HDR_LEN + 1] = buf_len; 1038 buf[CIPSO_V4_HDR_LEN + 3] = level; 1039 1040 *buffer = buf; 1041 *buffer_len = CIPSO_V4_HDR_LEN + buf_len; 1042 1043 return 0; 1044 1045gentag_failure: 1046 kfree(buf); 1047 return ret_val; 1048} 1049 1050/** 1051 * cipso_v4_parsetag_rbm - Parse a CIPSO restricted bitmap tag 1052 * @doi_def: the DOI definition 1053 * @tag: the CIPSO tag 1054 * @secattr: the security attributes 1055 * 1056 * Description: 1057 * Parse a CIPSO restricted bitmap tag (tag type #1) and return the security 1058 * attributes in @secattr. Return zero on success, negatives values on 1059 * failure. 1060 * 1061 */ 1062static int cipso_v4_parsetag_rbm(const struct cipso_v4_doi *doi_def, 1063 const unsigned char *tag, 1064 struct netlbl_lsm_secattr *secattr) 1065{ 1066 int ret_val; 1067 u8 tag_len = tag[1]; 1068 u32 level; 1069 1070 ret_val = cipso_v4_map_lvl_ntoh(doi_def, tag[3], &level); 1071 if (ret_val != 0) 1072 return ret_val; 1073 secattr->mls_lvl = level; 1074 secattr->mls_lvl_vld = 1; 1075 1076 if (tag_len > 4) { 1077 switch (doi_def->type) { 1078 case CIPSO_V4_MAP_PASS: 1079 secattr->mls_cat_len = tag_len - 4; 1080 break; 1081 case CIPSO_V4_MAP_STD: 1082 secattr->mls_cat_len = 1083 doi_def->map.std->cat.local_size; 1084 break; 1085 } 1086 secattr->mls_cat = kzalloc(secattr->mls_cat_len, GFP_ATOMIC); 1087 if (secattr->mls_cat == NULL) 1088 return -ENOMEM; 1089 1090 ret_val = cipso_v4_map_cat_rbm_ntoh(doi_def, 1091 &tag[4], 1092 tag_len - 4, 1093 secattr->mls_cat, 1094 secattr->mls_cat_len); 1095 if (ret_val < 0) { 1096 kfree(secattr->mls_cat); 1097 return ret_val; 1098 } 1099 secattr->mls_cat_len = ret_val; 1100 } 1101 1102 return 0; 1103} 1104 1105/** 1106 * cipso_v4_validate - Validate a CIPSO option 1107 * @option: the start of the option, on error it is set to point to the error 1108 * 1109 * Description: 1110 * This routine is called to validate a CIPSO option, it checks all of the 1111 * fields to ensure that they are at least valid, see the draft snippet below 1112 * for details. If the option is valid then a zero value is returned and 1113 * the value of @option is unchanged. If the option is invalid then a 1114 * non-zero value is returned and @option is adjusted to point to the 1115 * offending portion of the option. From the IETF draft ... 1116 * 1117 * "If any field within the CIPSO options, such as the DOI identifier, is not 1118 * recognized the IP datagram is discarded and an ICMP 'parameter problem' 1119 * (type 12) is generated and returned. The ICMP code field is set to 'bad 1120 * parameter' (code 0) and the pointer is set to the start of the CIPSO field 1121 * that is unrecognized." 1122 * 1123 */ 1124int cipso_v4_validate(unsigned char **option) 1125{ 1126 unsigned char *opt = *option; 1127 unsigned char *tag; 1128 unsigned char opt_iter; 1129 unsigned char err_offset = 0; 1130 u8 opt_len; 1131 u8 tag_len; 1132 struct cipso_v4_doi *doi_def = NULL; 1133 u32 tag_iter; 1134 1135 /* caller already checks for length values that are too large */ 1136 opt_len = opt[1]; 1137 if (opt_len < 8) { 1138 err_offset = 1; 1139 goto validate_return; 1140 } 1141 1142 rcu_read_lock(); 1143 doi_def = cipso_v4_doi_getdef(ntohl(*((__be32 *)&opt[2]))); 1144 if (doi_def == NULL) { 1145 err_offset = 2; 1146 goto validate_return_locked; 1147 } 1148 1149 opt_iter = 6; 1150 tag = opt + opt_iter; 1151 while (opt_iter < opt_len) { 1152 for (tag_iter = 0; doi_def->tags[tag_iter] != tag[0];) 1153 if (doi_def->tags[tag_iter] == CIPSO_V4_TAG_INVALID || 1154 ++tag_iter == CIPSO_V4_TAG_MAXCNT) { 1155 err_offset = opt_iter; 1156 goto validate_return_locked; 1157 } 1158 1159 tag_len = tag[1]; 1160 if (tag_len > (opt_len - opt_iter)) { 1161 err_offset = opt_iter + 1; 1162 goto validate_return_locked; 1163 } 1164 1165 switch (tag[0]) { 1166 case CIPSO_V4_TAG_RBITMAP: 1167 if (tag_len < 4) { 1168 err_offset = opt_iter + 1; 1169 goto validate_return_locked; 1170 } 1171 1172 /* We are already going to do all the verification 1173 * necessary at the socket layer so from our point of 1174 * view it is safe to turn these checks off (and less 1175 * work), however, the CIPSO draft says we should do 1176 * all the CIPSO validations here but it doesn't 1177 * really specify _exactly_ what we need to validate 1178 * ... so, just make it a sysctl tunable. */ 1179 if (cipso_v4_rbm_strictvalid) { 1180 if (cipso_v4_map_lvl_valid(doi_def, 1181 tag[3]) < 0) { 1182 err_offset = opt_iter + 3; 1183 goto validate_return_locked; 1184 } 1185 if (tag_len > 4 && 1186 cipso_v4_map_cat_rbm_valid(doi_def, 1187 &tag[4], 1188 tag_len - 4) < 0) { 1189 err_offset = opt_iter + 4; 1190 goto validate_return_locked; 1191 } 1192 } 1193 break; 1194 default: 1195 err_offset = opt_iter; 1196 goto validate_return_locked; 1197 } 1198 1199 tag += tag_len; 1200 opt_iter += tag_len; 1201 } 1202 1203validate_return_locked: 1204 rcu_read_unlock(); 1205validate_return: 1206 *option = opt + err_offset; 1207 return err_offset; 1208} 1209 1210/** 1211 * cipso_v4_error - Send the correct reponse for a bad packet 1212 * @skb: the packet 1213 * @error: the error code 1214 * @gateway: CIPSO gateway flag 1215 * 1216 * Description: 1217 * Based on the error code given in @error, send an ICMP error message back to 1218 * the originating host. From the IETF draft ... 1219 * 1220 * "If the contents of the CIPSO [option] are valid but the security label is 1221 * outside of the configured host or port label range, the datagram is 1222 * discarded and an ICMP 'destination unreachable' (type 3) is generated and 1223 * returned. The code field of the ICMP is set to 'communication with 1224 * destination network administratively prohibited' (code 9) or to 1225 * 'communication with destination host administratively prohibited' 1226 * (code 10). The value of the code is dependent on whether the originator 1227 * of the ICMP message is acting as a CIPSO host or a CIPSO gateway. The 1228 * recipient of the ICMP message MUST be able to handle either value. The 1229 * same procedure is performed if a CIPSO [option] can not be added to an 1230 * IP packet because it is too large to fit in the IP options area." 1231 * 1232 * "If the error is triggered by receipt of an ICMP message, the message is 1233 * discarded and no response is permitted (consistent with general ICMP 1234 * processing rules)." 1235 * 1236 */ 1237void cipso_v4_error(struct sk_buff *skb, int error, u32 gateway) 1238{ 1239 if (skb->nh.iph->protocol == IPPROTO_ICMP || error != -EACCES) 1240 return; 1241 1242 if (gateway) 1243 icmp_send(skb, ICMP_DEST_UNREACH, ICMP_NET_ANO, 0); 1244 else 1245 icmp_send(skb, ICMP_DEST_UNREACH, ICMP_HOST_ANO, 0); 1246} 1247 1248/** 1249 * cipso_v4_socket_setattr - Add a CIPSO option to a socket 1250 * @sock: the socket 1251 * @doi_def: the CIPSO DOI to use 1252 * @secattr: the specific security attributes of the socket 1253 * 1254 * Description: 1255 * Set the CIPSO option on the given socket using the DOI definition and 1256 * security attributes passed to the function. This function requires 1257 * exclusive access to @sock->sk, which means it either needs to be in the 1258 * process of being created or locked via lock_sock(sock->sk). Returns zero on 1259 * success and negative values on failure. 1260 * 1261 */ 1262int cipso_v4_socket_setattr(const struct socket *sock, 1263 const struct cipso_v4_doi *doi_def, 1264 const struct netlbl_lsm_secattr *secattr) 1265{ 1266 int ret_val = -EPERM; 1267 u32 iter; 1268 unsigned char *buf = NULL; 1269 u32 buf_len = 0; 1270 u32 opt_len; 1271 struct ip_options *opt = NULL; 1272 struct sock *sk; 1273 struct inet_sock *sk_inet; 1274 struct inet_connection_sock *sk_conn; 1275 1276 /* In the case of sock_create_lite(), the sock->sk field is not 1277 * defined yet but it is not a problem as the only users of these 1278 * "lite" PF_INET sockets are functions which do an accept() call 1279 * afterwards so we will label the socket as part of the accept(). */ 1280 sk = sock->sk; 1281 if (sk == NULL) 1282 return 0; 1283 1284 /* XXX - This code assumes only one tag per CIPSO option which isn't 1285 * really a good assumption to make but since we only support the MAC 1286 * tags right now it is a safe assumption. */ 1287 iter = 0; 1288 do { 1289 switch (doi_def->tags[iter]) { 1290 case CIPSO_V4_TAG_RBITMAP: 1291 ret_val = cipso_v4_gentag_rbm(doi_def, 1292 secattr, 1293 &buf, 1294 &buf_len); 1295 break; 1296 default: 1297 ret_val = -EPERM; 1298 goto socket_setattr_failure; 1299 } 1300 1301 iter++; 1302 } while (ret_val != 0 && 1303 iter < CIPSO_V4_TAG_MAXCNT && 1304 doi_def->tags[iter] != CIPSO_V4_TAG_INVALID); 1305 if (ret_val != 0) 1306 goto socket_setattr_failure; 1307 1308 /* We can't use ip_options_get() directly because it makes a call to 1309 * ip_options_get_alloc() which allocates memory with GFP_KERNEL and 1310 * we won't always have CAP_NET_RAW even though we _always_ want to 1311 * set the IPOPT_CIPSO option. */ 1312 opt_len = (buf_len + 3) & ~3; 1313 opt = kzalloc(sizeof(*opt) + opt_len, GFP_ATOMIC); 1314 if (opt == NULL) { 1315 ret_val = -ENOMEM; 1316 goto socket_setattr_failure; 1317 } 1318 memcpy(opt->__data, buf, buf_len); 1319 opt->optlen = opt_len; 1320 opt->is_data = 1; 1321 opt->cipso = sizeof(struct iphdr); 1322 kfree(buf); 1323 buf = NULL; 1324 1325 sk_inet = inet_sk(sk); 1326 if (sk_inet->is_icsk) { 1327 sk_conn = inet_csk(sk); 1328 if (sk_inet->opt) 1329 sk_conn->icsk_ext_hdr_len -= sk_inet->opt->optlen; 1330 sk_conn->icsk_ext_hdr_len += opt->optlen; 1331 sk_conn->icsk_sync_mss(sk, sk_conn->icsk_pmtu_cookie); 1332 } 1333 opt = xchg(&sk_inet->opt, opt); 1334 kfree(opt); 1335 1336 return 0; 1337 1338socket_setattr_failure: 1339 kfree(buf); 1340 kfree(opt); 1341 return ret_val; 1342} 1343 1344/** 1345 * cipso_v4_sock_getattr - Get the security attributes from a sock 1346 * @sk: the sock 1347 * @secattr: the security attributes 1348 * 1349 * Description: 1350 * Query @sk to see if there is a CIPSO option attached to the sock and if 1351 * there is return the CIPSO security attributes in @secattr. This function 1352 * requires that @sk be locked, or privately held, but it does not do any 1353 * locking itself. Returns zero on success and negative values on failure. 1354 * 1355 */ 1356int cipso_v4_sock_getattr(struct sock *sk, struct netlbl_lsm_secattr *secattr) 1357{ 1358 int ret_val = -ENOMSG; 1359 struct inet_sock *sk_inet; 1360 unsigned char *cipso_ptr; 1361 u32 doi; 1362 struct cipso_v4_doi *doi_def; 1363 1364 sk_inet = inet_sk(sk); 1365 if (sk_inet->opt == NULL || sk_inet->opt->cipso == 0) 1366 return -ENOMSG; 1367 cipso_ptr = sk_inet->opt->__data + sk_inet->opt->cipso - 1368 sizeof(struct iphdr); 1369 ret_val = cipso_v4_cache_check(cipso_ptr, cipso_ptr[1], secattr); 1370 if (ret_val == 0) 1371 return ret_val; 1372 1373 doi = ntohl(*(__be32 *)&cipso_ptr[2]); 1374 rcu_read_lock(); 1375 doi_def = cipso_v4_doi_getdef(doi); 1376 if (doi_def == NULL) { 1377 rcu_read_unlock(); 1378 return -ENOMSG; 1379 } 1380 switch (cipso_ptr[6]) { 1381 case CIPSO_V4_TAG_RBITMAP: 1382 ret_val = cipso_v4_parsetag_rbm(doi_def, 1383 &cipso_ptr[6], 1384 secattr); 1385 break; 1386 } 1387 rcu_read_unlock(); 1388 1389 return ret_val; 1390} 1391 1392/** 1393 * cipso_v4_socket_getattr - Get the security attributes from a socket 1394 * @sock: the socket 1395 * @secattr: the security attributes 1396 * 1397 * Description: 1398 * Query @sock to see if there is a CIPSO option attached to the socket and if 1399 * there is return the CIPSO security attributes in @secattr. Returns zero on 1400 * success and negative values on failure. 1401 * 1402 */ 1403int cipso_v4_socket_getattr(const struct socket *sock, 1404 struct netlbl_lsm_secattr *secattr) 1405{ 1406 int ret_val; 1407 1408 lock_sock(sock->sk); 1409 ret_val = cipso_v4_sock_getattr(sock->sk, secattr); 1410 release_sock(sock->sk); 1411 1412 return ret_val; 1413} 1414 1415/** 1416 * cipso_v4_skbuff_getattr - Get the security attributes from the CIPSO option 1417 * @skb: the packet 1418 * @secattr: the security attributes 1419 * 1420 * Description: 1421 * Parse the given packet's CIPSO option and return the security attributes. 1422 * Returns zero on success and negative values on failure. 1423 * 1424 */ 1425int cipso_v4_skbuff_getattr(const struct sk_buff *skb, 1426 struct netlbl_lsm_secattr *secattr) 1427{ 1428 int ret_val = -ENOMSG; 1429 unsigned char *cipso_ptr; 1430 u32 doi; 1431 struct cipso_v4_doi *doi_def; 1432 1433 if (!CIPSO_V4_OPTEXIST(skb)) 1434 return -ENOMSG; 1435 cipso_ptr = CIPSO_V4_OPTPTR(skb); 1436 if (cipso_v4_cache_check(cipso_ptr, cipso_ptr[1], secattr) == 0) 1437 return 0; 1438 1439 doi = ntohl(*(__be32 *)&cipso_ptr[2]); 1440 rcu_read_lock(); 1441 doi_def = cipso_v4_doi_getdef(doi); 1442 if (doi_def == NULL) 1443 goto skbuff_getattr_return; 1444 switch (cipso_ptr[6]) { 1445 case CIPSO_V4_TAG_RBITMAP: 1446 ret_val = cipso_v4_parsetag_rbm(doi_def, 1447 &cipso_ptr[6], 1448 secattr); 1449 break; 1450 } 1451 1452skbuff_getattr_return: 1453 rcu_read_unlock(); 1454 return ret_val; 1455} 1456 1457/* 1458 * Setup Functions 1459 */ 1460 1461/** 1462 * cipso_v4_init - Initialize the CIPSO module 1463 * 1464 * Description: 1465 * Initialize the CIPSO module and prepare it for use. Returns zero on success 1466 * and negative values on failure. 1467 * 1468 */ 1469static int __init cipso_v4_init(void) 1470{ 1471 int ret_val; 1472 1473 ret_val = cipso_v4_cache_init(); 1474 if (ret_val != 0) 1475 panic("Failed to initialize the CIPSO/IPv4 cache (%d)\n", 1476 ret_val); 1477 1478 return 0; 1479} 1480 1481subsys_initcall(cipso_v4_init); 1482