Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.22-rc3 1995 lines 54 kB view raw
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 * Protocol Constants 96 */ 97 98/* Maximum size of the CIPSO IP option, derived from the fact that the maximum 99 * IPv4 header size is 60 bytes and the base IPv4 header is 20 bytes long. */ 100#define CIPSO_V4_OPT_LEN_MAX 40 101 102/* Length of the base CIPSO option, this includes the option type (1 byte), the 103 * option length (1 byte), and the DOI (4 bytes). */ 104#define CIPSO_V4_HDR_LEN 6 105 106/* Base length of the restrictive category bitmap tag (tag #1). */ 107#define CIPSO_V4_TAG_RBM_BLEN 4 108 109/* Base length of the enumerated category tag (tag #2). */ 110#define CIPSO_V4_TAG_ENUM_BLEN 4 111 112/* Base length of the ranged categories bitmap tag (tag #5). */ 113#define CIPSO_V4_TAG_RNG_BLEN 4 114/* The maximum number of category ranges permitted in the ranged category tag 115 * (tag #5). You may note that the IETF draft states that the maximum number 116 * of category ranges is 7, but if the low end of the last category range is 117 * zero then it is possibile to fit 8 category ranges because the zero should 118 * be omitted. */ 119#define CIPSO_V4_TAG_RNG_CAT_MAX 8 120 121/* 122 * Helper Functions 123 */ 124 125/** 126 * cipso_v4_bitmap_walk - Walk a bitmap looking for a bit 127 * @bitmap: the bitmap 128 * @bitmap_len: length in bits 129 * @offset: starting offset 130 * @state: if non-zero, look for a set (1) bit else look for a cleared (0) bit 131 * 132 * Description: 133 * Starting at @offset, walk the bitmap from left to right until either the 134 * desired bit is found or we reach the end. Return the bit offset, -1 if 135 * not found, or -2 if error. 136 */ 137static int cipso_v4_bitmap_walk(const unsigned char *bitmap, 138 u32 bitmap_len, 139 u32 offset, 140 u8 state) 141{ 142 u32 bit_spot; 143 u32 byte_offset; 144 unsigned char bitmask; 145 unsigned char byte; 146 147 /* gcc always rounds to zero when doing integer division */ 148 byte_offset = offset / 8; 149 byte = bitmap[byte_offset]; 150 bit_spot = offset; 151 bitmask = 0x80 >> (offset % 8); 152 153 while (bit_spot < bitmap_len) { 154 if ((state && (byte & bitmask) == bitmask) || 155 (state == 0 && (byte & bitmask) == 0)) 156 return bit_spot; 157 158 bit_spot++; 159 bitmask >>= 1; 160 if (bitmask == 0) { 161 byte = bitmap[++byte_offset]; 162 bitmask = 0x80; 163 } 164 } 165 166 return -1; 167} 168 169/** 170 * cipso_v4_bitmap_setbit - Sets a single bit in a bitmap 171 * @bitmap: the bitmap 172 * @bit: the bit 173 * @state: if non-zero, set the bit (1) else clear the bit (0) 174 * 175 * Description: 176 * Set a single bit in the bitmask. Returns zero on success, negative values 177 * on error. 178 */ 179static void cipso_v4_bitmap_setbit(unsigned char *bitmap, 180 u32 bit, 181 u8 state) 182{ 183 u32 byte_spot; 184 u8 bitmask; 185 186 /* gcc always rounds to zero when doing integer division */ 187 byte_spot = bit / 8; 188 bitmask = 0x80 >> (bit % 8); 189 if (state) 190 bitmap[byte_spot] |= bitmask; 191 else 192 bitmap[byte_spot] &= ~bitmask; 193} 194 195/** 196 * cipso_v4_doi_domhsh_free - Frees a domain list entry 197 * @entry: the entry's RCU field 198 * 199 * Description: 200 * This function is designed to be used as a callback to the call_rcu() 201 * function so that the memory allocated to a domain list entry can be released 202 * safely. 203 * 204 */ 205static void cipso_v4_doi_domhsh_free(struct rcu_head *entry) 206{ 207 struct cipso_v4_domhsh_entry *ptr; 208 209 ptr = container_of(entry, struct cipso_v4_domhsh_entry, rcu); 210 kfree(ptr->domain); 211 kfree(ptr); 212} 213 214/** 215 * cipso_v4_cache_entry_free - Frees a cache entry 216 * @entry: the entry to free 217 * 218 * Description: 219 * This function frees the memory associated with a cache entry including the 220 * LSM cache data if there are no longer any users, i.e. reference count == 0. 221 * 222 */ 223static void cipso_v4_cache_entry_free(struct cipso_v4_map_cache_entry *entry) 224{ 225 if (entry->lsm_data) 226 netlbl_secattr_cache_free(entry->lsm_data); 227 kfree(entry->key); 228 kfree(entry); 229} 230 231/** 232 * cipso_v4_map_cache_hash - Hashing function for the CIPSO cache 233 * @key: the hash key 234 * @key_len: the length of the key in bytes 235 * 236 * Description: 237 * The CIPSO tag hashing function. Returns a 32-bit hash value. 238 * 239 */ 240static u32 cipso_v4_map_cache_hash(const unsigned char *key, u32 key_len) 241{ 242 return jhash(key, key_len, 0); 243} 244 245/* 246 * Label Mapping Cache Functions 247 */ 248 249/** 250 * cipso_v4_cache_init - Initialize the CIPSO cache 251 * 252 * Description: 253 * Initializes the CIPSO label mapping cache, this function should be called 254 * before any of the other functions defined in this file. Returns zero on 255 * success, negative values on error. 256 * 257 */ 258static int cipso_v4_cache_init(void) 259{ 260 u32 iter; 261 262 cipso_v4_cache = kcalloc(CIPSO_V4_CACHE_BUCKETS, 263 sizeof(struct cipso_v4_map_cache_bkt), 264 GFP_KERNEL); 265 if (cipso_v4_cache == NULL) 266 return -ENOMEM; 267 268 for (iter = 0; iter < CIPSO_V4_CACHE_BUCKETS; iter++) { 269 spin_lock_init(&cipso_v4_cache[iter].lock); 270 cipso_v4_cache[iter].size = 0; 271 INIT_LIST_HEAD(&cipso_v4_cache[iter].list); 272 } 273 274 return 0; 275} 276 277/** 278 * cipso_v4_cache_invalidate - Invalidates the current CIPSO cache 279 * 280 * Description: 281 * Invalidates and frees any entries in the CIPSO cache. Returns zero on 282 * success and negative values on failure. 283 * 284 */ 285void cipso_v4_cache_invalidate(void) 286{ 287 struct cipso_v4_map_cache_entry *entry, *tmp_entry; 288 u32 iter; 289 290 for (iter = 0; iter < CIPSO_V4_CACHE_BUCKETS; iter++) { 291 spin_lock_bh(&cipso_v4_cache[iter].lock); 292 list_for_each_entry_safe(entry, 293 tmp_entry, 294 &cipso_v4_cache[iter].list, list) { 295 list_del(&entry->list); 296 cipso_v4_cache_entry_free(entry); 297 } 298 cipso_v4_cache[iter].size = 0; 299 spin_unlock_bh(&cipso_v4_cache[iter].lock); 300 } 301 302 return; 303} 304 305/** 306 * cipso_v4_cache_check - Check the CIPSO cache for a label mapping 307 * @key: the buffer to check 308 * @key_len: buffer length in bytes 309 * @secattr: the security attribute struct to use 310 * 311 * Description: 312 * This function checks the cache to see if a label mapping already exists for 313 * the given key. If there is a match then the cache is adjusted and the 314 * @secattr struct is populated with the correct LSM security attributes. The 315 * cache is adjusted in the following manner if the entry is not already the 316 * first in the cache bucket: 317 * 318 * 1. The cache entry's activity counter is incremented 319 * 2. The previous (higher ranking) entry's activity counter is decremented 320 * 3. If the difference between the two activity counters is geater than 321 * CIPSO_V4_CACHE_REORDERLIMIT the two entries are swapped 322 * 323 * Returns zero on success, -ENOENT for a cache miss, and other negative values 324 * on error. 325 * 326 */ 327static int cipso_v4_cache_check(const unsigned char *key, 328 u32 key_len, 329 struct netlbl_lsm_secattr *secattr) 330{ 331 u32 bkt; 332 struct cipso_v4_map_cache_entry *entry; 333 struct cipso_v4_map_cache_entry *prev_entry = NULL; 334 u32 hash; 335 336 if (!cipso_v4_cache_enabled) 337 return -ENOENT; 338 339 hash = cipso_v4_map_cache_hash(key, key_len); 340 bkt = hash & (CIPSO_V4_CACHE_BUCKETBITS - 1); 341 spin_lock_bh(&cipso_v4_cache[bkt].lock); 342 list_for_each_entry(entry, &cipso_v4_cache[bkt].list, list) { 343 if (entry->hash == hash && 344 entry->key_len == key_len && 345 memcmp(entry->key, key, key_len) == 0) { 346 entry->activity += 1; 347 atomic_inc(&entry->lsm_data->refcount); 348 secattr->cache = entry->lsm_data; 349 secattr->flags |= NETLBL_SECATTR_CACHE; 350 if (prev_entry == NULL) { 351 spin_unlock_bh(&cipso_v4_cache[bkt].lock); 352 return 0; 353 } 354 355 if (prev_entry->activity > 0) 356 prev_entry->activity -= 1; 357 if (entry->activity > prev_entry->activity && 358 entry->activity - prev_entry->activity > 359 CIPSO_V4_CACHE_REORDERLIMIT) { 360 __list_del(entry->list.prev, entry->list.next); 361 __list_add(&entry->list, 362 prev_entry->list.prev, 363 &prev_entry->list); 364 } 365 366 spin_unlock_bh(&cipso_v4_cache[bkt].lock); 367 return 0; 368 } 369 prev_entry = entry; 370 } 371 spin_unlock_bh(&cipso_v4_cache[bkt].lock); 372 373 return -ENOENT; 374} 375 376/** 377 * cipso_v4_cache_add - Add an entry to the CIPSO cache 378 * @skb: the packet 379 * @secattr: the packet's security attributes 380 * 381 * Description: 382 * Add a new entry into the CIPSO label mapping cache. Add the new entry to 383 * head of the cache bucket's list, if the cache bucket is out of room remove 384 * the last entry in the list first. It is important to note that there is 385 * currently no checking for duplicate keys. Returns zero on success, 386 * negative values on failure. 387 * 388 */ 389int cipso_v4_cache_add(const struct sk_buff *skb, 390 const struct netlbl_lsm_secattr *secattr) 391{ 392 int ret_val = -EPERM; 393 u32 bkt; 394 struct cipso_v4_map_cache_entry *entry = NULL; 395 struct cipso_v4_map_cache_entry *old_entry = NULL; 396 unsigned char *cipso_ptr; 397 u32 cipso_ptr_len; 398 399 if (!cipso_v4_cache_enabled || cipso_v4_cache_bucketsize <= 0) 400 return 0; 401 402 cipso_ptr = CIPSO_V4_OPTPTR(skb); 403 cipso_ptr_len = cipso_ptr[1]; 404 405 entry = kzalloc(sizeof(*entry), GFP_ATOMIC); 406 if (entry == NULL) 407 return -ENOMEM; 408 entry->key = kmemdup(cipso_ptr, cipso_ptr_len, GFP_ATOMIC); 409 if (entry->key == NULL) { 410 ret_val = -ENOMEM; 411 goto cache_add_failure; 412 } 413 entry->key_len = cipso_ptr_len; 414 entry->hash = cipso_v4_map_cache_hash(cipso_ptr, cipso_ptr_len); 415 atomic_inc(&secattr->cache->refcount); 416 entry->lsm_data = secattr->cache; 417 418 bkt = entry->hash & (CIPSO_V4_CACHE_BUCKETBITS - 1); 419 spin_lock_bh(&cipso_v4_cache[bkt].lock); 420 if (cipso_v4_cache[bkt].size < cipso_v4_cache_bucketsize) { 421 list_add(&entry->list, &cipso_v4_cache[bkt].list); 422 cipso_v4_cache[bkt].size += 1; 423 } else { 424 old_entry = list_entry(cipso_v4_cache[bkt].list.prev, 425 struct cipso_v4_map_cache_entry, list); 426 list_del(&old_entry->list); 427 list_add(&entry->list, &cipso_v4_cache[bkt].list); 428 cipso_v4_cache_entry_free(old_entry); 429 } 430 spin_unlock_bh(&cipso_v4_cache[bkt].lock); 431 432 return 0; 433 434cache_add_failure: 435 if (entry) 436 cipso_v4_cache_entry_free(entry); 437 return ret_val; 438} 439 440/* 441 * DOI List Functions 442 */ 443 444/** 445 * cipso_v4_doi_search - Searches for a DOI definition 446 * @doi: the DOI to search for 447 * 448 * Description: 449 * Search the DOI definition list for a DOI definition with a DOI value that 450 * matches @doi. The caller is responsibile for calling rcu_read_[un]lock(). 451 * Returns a pointer to the DOI definition on success and NULL on failure. 452 */ 453static struct cipso_v4_doi *cipso_v4_doi_search(u32 doi) 454{ 455 struct cipso_v4_doi *iter; 456 457 list_for_each_entry_rcu(iter, &cipso_v4_doi_list, list) 458 if (iter->doi == doi && iter->valid) 459 return iter; 460 return NULL; 461} 462 463/** 464 * cipso_v4_doi_add - Add a new DOI to the CIPSO protocol engine 465 * @doi_def: the DOI structure 466 * 467 * Description: 468 * The caller defines a new DOI for use by the CIPSO engine and calls this 469 * function to add it to the list of acceptable domains. The caller must 470 * ensure that the mapping table specified in @doi_def->map meets all of the 471 * requirements of the mapping type (see cipso_ipv4.h for details). Returns 472 * zero on success and non-zero on failure. 473 * 474 */ 475int cipso_v4_doi_add(struct cipso_v4_doi *doi_def) 476{ 477 u32 iter; 478 479 if (doi_def == NULL || doi_def->doi == CIPSO_V4_DOI_UNKNOWN) 480 return -EINVAL; 481 for (iter = 0; iter < CIPSO_V4_TAG_MAXCNT; iter++) { 482 switch (doi_def->tags[iter]) { 483 case CIPSO_V4_TAG_RBITMAP: 484 break; 485 case CIPSO_V4_TAG_RANGE: 486 if (doi_def->type != CIPSO_V4_MAP_PASS) 487 return -EINVAL; 488 break; 489 case CIPSO_V4_TAG_INVALID: 490 if (iter == 0) 491 return -EINVAL; 492 break; 493 case CIPSO_V4_TAG_ENUM: 494 if (doi_def->type != CIPSO_V4_MAP_PASS) 495 return -EINVAL; 496 break; 497 default: 498 return -EINVAL; 499 } 500 } 501 502 doi_def->valid = 1; 503 INIT_RCU_HEAD(&doi_def->rcu); 504 INIT_LIST_HEAD(&doi_def->dom_list); 505 506 rcu_read_lock(); 507 if (cipso_v4_doi_search(doi_def->doi) != NULL) 508 goto doi_add_failure_rlock; 509 spin_lock(&cipso_v4_doi_list_lock); 510 if (cipso_v4_doi_search(doi_def->doi) != NULL) 511 goto doi_add_failure_slock; 512 list_add_tail_rcu(&doi_def->list, &cipso_v4_doi_list); 513 spin_unlock(&cipso_v4_doi_list_lock); 514 rcu_read_unlock(); 515 516 return 0; 517 518doi_add_failure_slock: 519 spin_unlock(&cipso_v4_doi_list_lock); 520doi_add_failure_rlock: 521 rcu_read_unlock(); 522 return -EEXIST; 523} 524 525/** 526 * cipso_v4_doi_remove - Remove an existing DOI from the CIPSO protocol engine 527 * @doi: the DOI value 528 * @audit_secid: the LSM secid to use in the audit message 529 * @callback: the DOI cleanup/free callback 530 * 531 * Description: 532 * Removes a DOI definition from the CIPSO engine, @callback is called to 533 * free any memory. The NetLabel routines will be called to release their own 534 * LSM domain mappings as well as our own domain list. Returns zero on 535 * success and negative values on failure. 536 * 537 */ 538int cipso_v4_doi_remove(u32 doi, 539 struct netlbl_audit *audit_info, 540 void (*callback) (struct rcu_head * head)) 541{ 542 struct cipso_v4_doi *doi_def; 543 struct cipso_v4_domhsh_entry *dom_iter; 544 545 rcu_read_lock(); 546 if (cipso_v4_doi_search(doi) != NULL) { 547 spin_lock(&cipso_v4_doi_list_lock); 548 doi_def = cipso_v4_doi_search(doi); 549 if (doi_def == NULL) { 550 spin_unlock(&cipso_v4_doi_list_lock); 551 rcu_read_unlock(); 552 return -ENOENT; 553 } 554 doi_def->valid = 0; 555 list_del_rcu(&doi_def->list); 556 spin_unlock(&cipso_v4_doi_list_lock); 557 list_for_each_entry_rcu(dom_iter, &doi_def->dom_list, list) 558 if (dom_iter->valid) 559 netlbl_domhsh_remove(dom_iter->domain, 560 audit_info); 561 cipso_v4_cache_invalidate(); 562 rcu_read_unlock(); 563 564 call_rcu(&doi_def->rcu, callback); 565 return 0; 566 } 567 rcu_read_unlock(); 568 569 return -ENOENT; 570} 571 572/** 573 * cipso_v4_doi_getdef - Returns a pointer to a valid DOI definition 574 * @doi: the DOI value 575 * 576 * Description: 577 * Searches for a valid DOI definition and if one is found it is returned to 578 * the caller. Otherwise NULL is returned. The caller must ensure that 579 * rcu_read_lock() is held while accessing the returned definition. 580 * 581 */ 582struct cipso_v4_doi *cipso_v4_doi_getdef(u32 doi) 583{ 584 return cipso_v4_doi_search(doi); 585} 586 587/** 588 * cipso_v4_doi_walk - Iterate through the DOI definitions 589 * @skip_cnt: skip past this number of DOI definitions, updated 590 * @callback: callback for each DOI definition 591 * @cb_arg: argument for the callback function 592 * 593 * Description: 594 * Iterate over the DOI definition list, skipping the first @skip_cnt entries. 595 * For each entry call @callback, if @callback returns a negative value stop 596 * 'walking' through the list and return. Updates the value in @skip_cnt upon 597 * return. Returns zero on success, negative values on failure. 598 * 599 */ 600int cipso_v4_doi_walk(u32 *skip_cnt, 601 int (*callback) (struct cipso_v4_doi *doi_def, void *arg), 602 void *cb_arg) 603{ 604 int ret_val = -ENOENT; 605 u32 doi_cnt = 0; 606 struct cipso_v4_doi *iter_doi; 607 608 rcu_read_lock(); 609 list_for_each_entry_rcu(iter_doi, &cipso_v4_doi_list, list) 610 if (iter_doi->valid) { 611 if (doi_cnt++ < *skip_cnt) 612 continue; 613 ret_val = callback(iter_doi, cb_arg); 614 if (ret_val < 0) { 615 doi_cnt--; 616 goto doi_walk_return; 617 } 618 } 619 620doi_walk_return: 621 rcu_read_unlock(); 622 *skip_cnt = doi_cnt; 623 return ret_val; 624} 625 626/** 627 * cipso_v4_doi_domhsh_add - Adds a domain entry to a DOI definition 628 * @doi_def: the DOI definition 629 * @domain: the domain to add 630 * 631 * Description: 632 * Adds the @domain to the DOI specified by @doi_def, this function 633 * should only be called by external functions (i.e. NetLabel). This function 634 * does allocate memory. Returns zero on success, negative values on failure. 635 * 636 */ 637int cipso_v4_doi_domhsh_add(struct cipso_v4_doi *doi_def, const char *domain) 638{ 639 struct cipso_v4_domhsh_entry *iter; 640 struct cipso_v4_domhsh_entry *new_dom; 641 642 new_dom = kzalloc(sizeof(*new_dom), GFP_KERNEL); 643 if (new_dom == NULL) 644 return -ENOMEM; 645 if (domain) { 646 new_dom->domain = kstrdup(domain, GFP_KERNEL); 647 if (new_dom->domain == NULL) { 648 kfree(new_dom); 649 return -ENOMEM; 650 } 651 } 652 new_dom->valid = 1; 653 INIT_RCU_HEAD(&new_dom->rcu); 654 655 rcu_read_lock(); 656 spin_lock(&cipso_v4_doi_list_lock); 657 list_for_each_entry_rcu(iter, &doi_def->dom_list, list) 658 if (iter->valid && 659 ((domain != NULL && iter->domain != NULL && 660 strcmp(iter->domain, domain) == 0) || 661 (domain == NULL && iter->domain == NULL))) { 662 spin_unlock(&cipso_v4_doi_list_lock); 663 rcu_read_unlock(); 664 kfree(new_dom->domain); 665 kfree(new_dom); 666 return -EEXIST; 667 } 668 list_add_tail_rcu(&new_dom->list, &doi_def->dom_list); 669 spin_unlock(&cipso_v4_doi_list_lock); 670 rcu_read_unlock(); 671 672 return 0; 673} 674 675/** 676 * cipso_v4_doi_domhsh_remove - Removes a domain entry from a DOI definition 677 * @doi_def: the DOI definition 678 * @domain: the domain to remove 679 * 680 * Description: 681 * Removes the @domain from the DOI specified by @doi_def, this function 682 * should only be called by external functions (i.e. NetLabel). Returns zero 683 * on success and negative values on error. 684 * 685 */ 686int cipso_v4_doi_domhsh_remove(struct cipso_v4_doi *doi_def, 687 const char *domain) 688{ 689 struct cipso_v4_domhsh_entry *iter; 690 691 rcu_read_lock(); 692 spin_lock(&cipso_v4_doi_list_lock); 693 list_for_each_entry_rcu(iter, &doi_def->dom_list, list) 694 if (iter->valid && 695 ((domain != NULL && iter->domain != NULL && 696 strcmp(iter->domain, domain) == 0) || 697 (domain == NULL && iter->domain == NULL))) { 698 iter->valid = 0; 699 list_del_rcu(&iter->list); 700 spin_unlock(&cipso_v4_doi_list_lock); 701 rcu_read_unlock(); 702 call_rcu(&iter->rcu, cipso_v4_doi_domhsh_free); 703 704 return 0; 705 } 706 spin_unlock(&cipso_v4_doi_list_lock); 707 rcu_read_unlock(); 708 709 return -ENOENT; 710} 711 712/* 713 * Label Mapping Functions 714 */ 715 716/** 717 * cipso_v4_map_lvl_valid - Checks to see if the given level is understood 718 * @doi_def: the DOI definition 719 * @level: the level to check 720 * 721 * Description: 722 * Checks the given level against the given DOI definition and returns a 723 * negative value if the level does not have a valid mapping and a zero value 724 * if the level is defined by the DOI. 725 * 726 */ 727static int cipso_v4_map_lvl_valid(const struct cipso_v4_doi *doi_def, u8 level) 728{ 729 switch (doi_def->type) { 730 case CIPSO_V4_MAP_PASS: 731 return 0; 732 case CIPSO_V4_MAP_STD: 733 if (doi_def->map.std->lvl.cipso[level] < CIPSO_V4_INV_LVL) 734 return 0; 735 break; 736 } 737 738 return -EFAULT; 739} 740 741/** 742 * cipso_v4_map_lvl_hton - Perform a level mapping from the host to the network 743 * @doi_def: the DOI definition 744 * @host_lvl: the host MLS level 745 * @net_lvl: the network/CIPSO MLS level 746 * 747 * Description: 748 * Perform a label mapping to translate a local MLS level to the correct 749 * CIPSO level using the given DOI definition. Returns zero on success, 750 * negative values otherwise. 751 * 752 */ 753static int cipso_v4_map_lvl_hton(const struct cipso_v4_doi *doi_def, 754 u32 host_lvl, 755 u32 *net_lvl) 756{ 757 switch (doi_def->type) { 758 case CIPSO_V4_MAP_PASS: 759 *net_lvl = host_lvl; 760 return 0; 761 case CIPSO_V4_MAP_STD: 762 if (host_lvl < doi_def->map.std->lvl.local_size && 763 doi_def->map.std->lvl.local[host_lvl] < CIPSO_V4_INV_LVL) { 764 *net_lvl = doi_def->map.std->lvl.local[host_lvl]; 765 return 0; 766 } 767 return -EPERM; 768 } 769 770 return -EINVAL; 771} 772 773/** 774 * cipso_v4_map_lvl_ntoh - Perform a level mapping from the network to the host 775 * @doi_def: the DOI definition 776 * @net_lvl: the network/CIPSO MLS level 777 * @host_lvl: the host MLS level 778 * 779 * Description: 780 * Perform a label mapping to translate a CIPSO level to the correct local MLS 781 * level using the given DOI definition. Returns zero on success, negative 782 * values otherwise. 783 * 784 */ 785static int cipso_v4_map_lvl_ntoh(const struct cipso_v4_doi *doi_def, 786 u32 net_lvl, 787 u32 *host_lvl) 788{ 789 struct cipso_v4_std_map_tbl *map_tbl; 790 791 switch (doi_def->type) { 792 case CIPSO_V4_MAP_PASS: 793 *host_lvl = net_lvl; 794 return 0; 795 case CIPSO_V4_MAP_STD: 796 map_tbl = doi_def->map.std; 797 if (net_lvl < map_tbl->lvl.cipso_size && 798 map_tbl->lvl.cipso[net_lvl] < CIPSO_V4_INV_LVL) { 799 *host_lvl = doi_def->map.std->lvl.cipso[net_lvl]; 800 return 0; 801 } 802 return -EPERM; 803 } 804 805 return -EINVAL; 806} 807 808/** 809 * cipso_v4_map_cat_rbm_valid - Checks to see if the category bitmap is valid 810 * @doi_def: the DOI definition 811 * @bitmap: category bitmap 812 * @bitmap_len: bitmap length in bytes 813 * 814 * Description: 815 * Checks the given category bitmap against the given DOI definition and 816 * returns a negative value if any of the categories in the bitmap do not have 817 * a valid mapping and a zero value if all of the categories are valid. 818 * 819 */ 820static int cipso_v4_map_cat_rbm_valid(const struct cipso_v4_doi *doi_def, 821 const unsigned char *bitmap, 822 u32 bitmap_len) 823{ 824 int cat = -1; 825 u32 bitmap_len_bits = bitmap_len * 8; 826 u32 cipso_cat_size; 827 u32 *cipso_array; 828 829 switch (doi_def->type) { 830 case CIPSO_V4_MAP_PASS: 831 return 0; 832 case CIPSO_V4_MAP_STD: 833 cipso_cat_size = doi_def->map.std->cat.cipso_size; 834 cipso_array = doi_def->map.std->cat.cipso; 835 for (;;) { 836 cat = cipso_v4_bitmap_walk(bitmap, 837 bitmap_len_bits, 838 cat + 1, 839 1); 840 if (cat < 0) 841 break; 842 if (cat >= cipso_cat_size || 843 cipso_array[cat] >= CIPSO_V4_INV_CAT) 844 return -EFAULT; 845 } 846 847 if (cat == -1) 848 return 0; 849 break; 850 } 851 852 return -EFAULT; 853} 854 855/** 856 * cipso_v4_map_cat_rbm_hton - Perform a category mapping from host to network 857 * @doi_def: the DOI definition 858 * @secattr: the security attributes 859 * @net_cat: the zero'd out category bitmap in network/CIPSO format 860 * @net_cat_len: the length of the CIPSO bitmap in bytes 861 * 862 * Description: 863 * Perform a label mapping to translate a local MLS category bitmap to the 864 * correct CIPSO bitmap using the given DOI definition. Returns the minimum 865 * size in bytes of the network bitmap on success, negative values otherwise. 866 * 867 */ 868static int cipso_v4_map_cat_rbm_hton(const struct cipso_v4_doi *doi_def, 869 const struct netlbl_lsm_secattr *secattr, 870 unsigned char *net_cat, 871 u32 net_cat_len) 872{ 873 int host_spot = -1; 874 u32 net_spot = CIPSO_V4_INV_CAT; 875 u32 net_spot_max = 0; 876 u32 net_clen_bits = net_cat_len * 8; 877 u32 host_cat_size = 0; 878 u32 *host_cat_array = NULL; 879 880 if (doi_def->type == CIPSO_V4_MAP_STD) { 881 host_cat_size = doi_def->map.std->cat.local_size; 882 host_cat_array = doi_def->map.std->cat.local; 883 } 884 885 for (;;) { 886 host_spot = netlbl_secattr_catmap_walk(secattr->mls_cat, 887 host_spot + 1); 888 if (host_spot < 0) 889 break; 890 891 switch (doi_def->type) { 892 case CIPSO_V4_MAP_PASS: 893 net_spot = host_spot; 894 break; 895 case CIPSO_V4_MAP_STD: 896 if (host_spot >= host_cat_size) 897 return -EPERM; 898 net_spot = host_cat_array[host_spot]; 899 if (net_spot >= CIPSO_V4_INV_CAT) 900 return -EPERM; 901 break; 902 } 903 if (net_spot >= net_clen_bits) 904 return -ENOSPC; 905 cipso_v4_bitmap_setbit(net_cat, net_spot, 1); 906 907 if (net_spot > net_spot_max) 908 net_spot_max = net_spot; 909 } 910 911 if (++net_spot_max % 8) 912 return net_spot_max / 8 + 1; 913 return net_spot_max / 8; 914} 915 916/** 917 * cipso_v4_map_cat_rbm_ntoh - Perform a category mapping from network to host 918 * @doi_def: the DOI definition 919 * @net_cat: the category bitmap in network/CIPSO format 920 * @net_cat_len: the length of the CIPSO bitmap in bytes 921 * @secattr: the security attributes 922 * 923 * Description: 924 * Perform a label mapping to translate a CIPSO bitmap to the correct local 925 * MLS category bitmap using the given DOI definition. Returns zero on 926 * success, negative values on failure. 927 * 928 */ 929static int cipso_v4_map_cat_rbm_ntoh(const struct cipso_v4_doi *doi_def, 930 const unsigned char *net_cat, 931 u32 net_cat_len, 932 struct netlbl_lsm_secattr *secattr) 933{ 934 int ret_val; 935 int net_spot = -1; 936 u32 host_spot = CIPSO_V4_INV_CAT; 937 u32 net_clen_bits = net_cat_len * 8; 938 u32 net_cat_size = 0; 939 u32 *net_cat_array = NULL; 940 941 if (doi_def->type == CIPSO_V4_MAP_STD) { 942 net_cat_size = doi_def->map.std->cat.cipso_size; 943 net_cat_array = doi_def->map.std->cat.cipso; 944 } 945 946 for (;;) { 947 net_spot = cipso_v4_bitmap_walk(net_cat, 948 net_clen_bits, 949 net_spot + 1, 950 1); 951 if (net_spot < 0) { 952 if (net_spot == -2) 953 return -EFAULT; 954 return 0; 955 } 956 957 switch (doi_def->type) { 958 case CIPSO_V4_MAP_PASS: 959 host_spot = net_spot; 960 break; 961 case CIPSO_V4_MAP_STD: 962 if (net_spot >= net_cat_size) 963 return -EPERM; 964 host_spot = net_cat_array[net_spot]; 965 if (host_spot >= CIPSO_V4_INV_CAT) 966 return -EPERM; 967 break; 968 } 969 ret_val = netlbl_secattr_catmap_setbit(secattr->mls_cat, 970 host_spot, 971 GFP_ATOMIC); 972 if (ret_val != 0) 973 return ret_val; 974 } 975 976 return -EINVAL; 977} 978 979/** 980 * cipso_v4_map_cat_enum_valid - Checks to see if the categories are valid 981 * @doi_def: the DOI definition 982 * @enumcat: category list 983 * @enumcat_len: length of the category list in bytes 984 * 985 * Description: 986 * Checks the given categories against the given DOI definition and returns a 987 * negative value if any of the categories do not have a valid mapping and a 988 * zero value if all of the categories are valid. 989 * 990 */ 991static int cipso_v4_map_cat_enum_valid(const struct cipso_v4_doi *doi_def, 992 const unsigned char *enumcat, 993 u32 enumcat_len) 994{ 995 u16 cat; 996 int cat_prev = -1; 997 u32 iter; 998 999 if (doi_def->type != CIPSO_V4_MAP_PASS || enumcat_len & 0x01) 1000 return -EFAULT; 1001 1002 for (iter = 0; iter < enumcat_len; iter += 2) { 1003 cat = ntohs(*((__be16 *)&enumcat[iter])); 1004 if (cat <= cat_prev) 1005 return -EFAULT; 1006 cat_prev = cat; 1007 } 1008 1009 return 0; 1010} 1011 1012/** 1013 * cipso_v4_map_cat_enum_hton - Perform a category mapping from host to network 1014 * @doi_def: the DOI definition 1015 * @secattr: the security attributes 1016 * @net_cat: the zero'd out category list in network/CIPSO format 1017 * @net_cat_len: the length of the CIPSO category list in bytes 1018 * 1019 * Description: 1020 * Perform a label mapping to translate a local MLS category bitmap to the 1021 * correct CIPSO category list using the given DOI definition. Returns the 1022 * size in bytes of the network category bitmap on success, negative values 1023 * otherwise. 1024 * 1025 */ 1026static int cipso_v4_map_cat_enum_hton(const struct cipso_v4_doi *doi_def, 1027 const struct netlbl_lsm_secattr *secattr, 1028 unsigned char *net_cat, 1029 u32 net_cat_len) 1030{ 1031 int cat = -1; 1032 u32 cat_iter = 0; 1033 1034 for (;;) { 1035 cat = netlbl_secattr_catmap_walk(secattr->mls_cat, cat + 1); 1036 if (cat < 0) 1037 break; 1038 if ((cat_iter + 2) > net_cat_len) 1039 return -ENOSPC; 1040 1041 *((__be16 *)&net_cat[cat_iter]) = htons(cat); 1042 cat_iter += 2; 1043 } 1044 1045 return cat_iter; 1046} 1047 1048/** 1049 * cipso_v4_map_cat_enum_ntoh - Perform a category mapping from network to host 1050 * @doi_def: the DOI definition 1051 * @net_cat: the category list in network/CIPSO format 1052 * @net_cat_len: the length of the CIPSO bitmap in bytes 1053 * @secattr: the security attributes 1054 * 1055 * Description: 1056 * Perform a label mapping to translate a CIPSO category list to the correct 1057 * local MLS category bitmap using the given DOI definition. Returns zero on 1058 * success, negative values on failure. 1059 * 1060 */ 1061static int cipso_v4_map_cat_enum_ntoh(const struct cipso_v4_doi *doi_def, 1062 const unsigned char *net_cat, 1063 u32 net_cat_len, 1064 struct netlbl_lsm_secattr *secattr) 1065{ 1066 int ret_val; 1067 u32 iter; 1068 1069 for (iter = 0; iter < net_cat_len; iter += 2) { 1070 ret_val = netlbl_secattr_catmap_setbit(secattr->mls_cat, 1071 ntohs(*((__be16 *)&net_cat[iter])), 1072 GFP_ATOMIC); 1073 if (ret_val != 0) 1074 return ret_val; 1075 } 1076 1077 return 0; 1078} 1079 1080/** 1081 * cipso_v4_map_cat_rng_valid - Checks to see if the categories are valid 1082 * @doi_def: the DOI definition 1083 * @rngcat: category list 1084 * @rngcat_len: length of the category list in bytes 1085 * 1086 * Description: 1087 * Checks the given categories against the given DOI definition and returns a 1088 * negative value if any of the categories do not have a valid mapping and a 1089 * zero value if all of the categories are valid. 1090 * 1091 */ 1092static int cipso_v4_map_cat_rng_valid(const struct cipso_v4_doi *doi_def, 1093 const unsigned char *rngcat, 1094 u32 rngcat_len) 1095{ 1096 u16 cat_high; 1097 u16 cat_low; 1098 u32 cat_prev = CIPSO_V4_MAX_REM_CATS + 1; 1099 u32 iter; 1100 1101 if (doi_def->type != CIPSO_V4_MAP_PASS || rngcat_len & 0x01) 1102 return -EFAULT; 1103 1104 for (iter = 0; iter < rngcat_len; iter += 4) { 1105 cat_high = ntohs(*((__be16 *)&rngcat[iter])); 1106 if ((iter + 4) <= rngcat_len) 1107 cat_low = ntohs(*((__be16 *)&rngcat[iter + 2])); 1108 else 1109 cat_low = 0; 1110 1111 if (cat_high > cat_prev) 1112 return -EFAULT; 1113 1114 cat_prev = cat_low; 1115 } 1116 1117 return 0; 1118} 1119 1120/** 1121 * cipso_v4_map_cat_rng_hton - Perform a category mapping from host to network 1122 * @doi_def: the DOI definition 1123 * @secattr: the security attributes 1124 * @net_cat: the zero'd out category list in network/CIPSO format 1125 * @net_cat_len: the length of the CIPSO category list in bytes 1126 * 1127 * Description: 1128 * Perform a label mapping to translate a local MLS category bitmap to the 1129 * correct CIPSO category list using the given DOI definition. Returns the 1130 * size in bytes of the network category bitmap on success, negative values 1131 * otherwise. 1132 * 1133 */ 1134static int cipso_v4_map_cat_rng_hton(const struct cipso_v4_doi *doi_def, 1135 const struct netlbl_lsm_secattr *secattr, 1136 unsigned char *net_cat, 1137 u32 net_cat_len) 1138{ 1139 int iter = -1; 1140 u16 array[CIPSO_V4_TAG_RNG_CAT_MAX * 2]; 1141 u32 array_cnt = 0; 1142 u32 cat_size = 0; 1143 1144 /* make sure we don't overflow the 'array[]' variable */ 1145 if (net_cat_len > 1146 (CIPSO_V4_OPT_LEN_MAX - CIPSO_V4_HDR_LEN - CIPSO_V4_TAG_RNG_BLEN)) 1147 return -ENOSPC; 1148 1149 for (;;) { 1150 iter = netlbl_secattr_catmap_walk(secattr->mls_cat, iter + 1); 1151 if (iter < 0) 1152 break; 1153 cat_size += (iter == 0 ? 0 : sizeof(u16)); 1154 if (cat_size > net_cat_len) 1155 return -ENOSPC; 1156 array[array_cnt++] = iter; 1157 1158 iter = netlbl_secattr_catmap_walk_rng(secattr->mls_cat, iter); 1159 if (iter < 0) 1160 return -EFAULT; 1161 cat_size += sizeof(u16); 1162 if (cat_size > net_cat_len) 1163 return -ENOSPC; 1164 array[array_cnt++] = iter; 1165 } 1166 1167 for (iter = 0; array_cnt > 0;) { 1168 *((__be16 *)&net_cat[iter]) = htons(array[--array_cnt]); 1169 iter += 2; 1170 array_cnt--; 1171 if (array[array_cnt] != 0) { 1172 *((__be16 *)&net_cat[iter]) = htons(array[array_cnt]); 1173 iter += 2; 1174 } 1175 } 1176 1177 return cat_size; 1178} 1179 1180/** 1181 * cipso_v4_map_cat_rng_ntoh - Perform a category mapping from network to host 1182 * @doi_def: the DOI definition 1183 * @net_cat: the category list in network/CIPSO format 1184 * @net_cat_len: the length of the CIPSO bitmap in bytes 1185 * @secattr: the security attributes 1186 * 1187 * Description: 1188 * Perform a label mapping to translate a CIPSO category list to the correct 1189 * local MLS category bitmap using the given DOI definition. Returns zero on 1190 * success, negative values on failure. 1191 * 1192 */ 1193static int cipso_v4_map_cat_rng_ntoh(const struct cipso_v4_doi *doi_def, 1194 const unsigned char *net_cat, 1195 u32 net_cat_len, 1196 struct netlbl_lsm_secattr *secattr) 1197{ 1198 int ret_val; 1199 u32 net_iter; 1200 u16 cat_low; 1201 u16 cat_high; 1202 1203 for (net_iter = 0; net_iter < net_cat_len; net_iter += 4) { 1204 cat_high = ntohs(*((__be16 *)&net_cat[net_iter])); 1205 if ((net_iter + 4) <= net_cat_len) 1206 cat_low = ntohs(*((__be16 *)&net_cat[net_iter + 2])); 1207 else 1208 cat_low = 0; 1209 1210 ret_val = netlbl_secattr_catmap_setrng(secattr->mls_cat, 1211 cat_low, 1212 cat_high, 1213 GFP_ATOMIC); 1214 if (ret_val != 0) 1215 return ret_val; 1216 } 1217 1218 return 0; 1219} 1220 1221/* 1222 * Protocol Handling Functions 1223 */ 1224 1225/** 1226 * cipso_v4_gentag_hdr - Generate a CIPSO option header 1227 * @doi_def: the DOI definition 1228 * @len: the total tag length in bytes, not including this header 1229 * @buf: the CIPSO option buffer 1230 * 1231 * Description: 1232 * Write a CIPSO header into the beginning of @buffer. 1233 * 1234 */ 1235static void cipso_v4_gentag_hdr(const struct cipso_v4_doi *doi_def, 1236 unsigned char *buf, 1237 u32 len) 1238{ 1239 buf[0] = IPOPT_CIPSO; 1240 buf[1] = CIPSO_V4_HDR_LEN + len; 1241 *(__be32 *)&buf[2] = htonl(doi_def->doi); 1242} 1243 1244/** 1245 * cipso_v4_gentag_rbm - Generate a CIPSO restricted bitmap tag (type #1) 1246 * @doi_def: the DOI definition 1247 * @secattr: the security attributes 1248 * @buffer: the option buffer 1249 * @buffer_len: length of buffer in bytes 1250 * 1251 * Description: 1252 * Generate a CIPSO option using the restricted bitmap tag, tag type #1. The 1253 * actual buffer length may be larger than the indicated size due to 1254 * translation between host and network category bitmaps. Returns the size of 1255 * the tag on success, negative values on failure. 1256 * 1257 */ 1258static int cipso_v4_gentag_rbm(const struct cipso_v4_doi *doi_def, 1259 const struct netlbl_lsm_secattr *secattr, 1260 unsigned char *buffer, 1261 u32 buffer_len) 1262{ 1263 int ret_val; 1264 u32 tag_len; 1265 u32 level; 1266 1267 if ((secattr->flags & NETLBL_SECATTR_MLS_LVL) == 0) 1268 return -EPERM; 1269 1270 ret_val = cipso_v4_map_lvl_hton(doi_def, secattr->mls_lvl, &level); 1271 if (ret_val != 0) 1272 return ret_val; 1273 1274 if (secattr->flags & NETLBL_SECATTR_MLS_CAT) { 1275 ret_val = cipso_v4_map_cat_rbm_hton(doi_def, 1276 secattr, 1277 &buffer[4], 1278 buffer_len - 4); 1279 if (ret_val < 0) 1280 return ret_val; 1281 1282 /* This will send packets using the "optimized" format when 1283 * possibile as specified in section 3.4.2.6 of the 1284 * CIPSO draft. */ 1285 if (cipso_v4_rbm_optfmt && ret_val > 0 && ret_val <= 10) 1286 tag_len = 14; 1287 else 1288 tag_len = 4 + ret_val; 1289 } else 1290 tag_len = 4; 1291 1292 buffer[0] = 0x01; 1293 buffer[1] = tag_len; 1294 buffer[3] = level; 1295 1296 return tag_len; 1297} 1298 1299/** 1300 * cipso_v4_parsetag_rbm - Parse a CIPSO restricted bitmap tag 1301 * @doi_def: the DOI definition 1302 * @tag: the CIPSO tag 1303 * @secattr: the security attributes 1304 * 1305 * Description: 1306 * Parse a CIPSO restricted bitmap tag (tag type #1) and return the security 1307 * attributes in @secattr. Return zero on success, negatives values on 1308 * failure. 1309 * 1310 */ 1311static int cipso_v4_parsetag_rbm(const struct cipso_v4_doi *doi_def, 1312 const unsigned char *tag, 1313 struct netlbl_lsm_secattr *secattr) 1314{ 1315 int ret_val; 1316 u8 tag_len = tag[1]; 1317 u32 level; 1318 1319 ret_val = cipso_v4_map_lvl_ntoh(doi_def, tag[3], &level); 1320 if (ret_val != 0) 1321 return ret_val; 1322 secattr->mls_lvl = level; 1323 secattr->flags |= NETLBL_SECATTR_MLS_LVL; 1324 1325 if (tag_len > 4) { 1326 secattr->mls_cat = netlbl_secattr_catmap_alloc(GFP_ATOMIC); 1327 if (secattr->mls_cat == NULL) 1328 return -ENOMEM; 1329 1330 ret_val = cipso_v4_map_cat_rbm_ntoh(doi_def, 1331 &tag[4], 1332 tag_len - 4, 1333 secattr); 1334 if (ret_val != 0) { 1335 netlbl_secattr_catmap_free(secattr->mls_cat); 1336 return ret_val; 1337 } 1338 1339 secattr->flags |= NETLBL_SECATTR_MLS_CAT; 1340 } 1341 1342 return 0; 1343} 1344 1345/** 1346 * cipso_v4_gentag_enum - Generate a CIPSO enumerated tag (type #2) 1347 * @doi_def: the DOI definition 1348 * @secattr: the security attributes 1349 * @buffer: the option buffer 1350 * @buffer_len: length of buffer in bytes 1351 * 1352 * Description: 1353 * Generate a CIPSO option using the enumerated tag, tag type #2. Returns the 1354 * size of the tag on success, negative values on failure. 1355 * 1356 */ 1357static int cipso_v4_gentag_enum(const struct cipso_v4_doi *doi_def, 1358 const struct netlbl_lsm_secattr *secattr, 1359 unsigned char *buffer, 1360 u32 buffer_len) 1361{ 1362 int ret_val; 1363 u32 tag_len; 1364 u32 level; 1365 1366 if (!(secattr->flags & NETLBL_SECATTR_MLS_LVL)) 1367 return -EPERM; 1368 1369 ret_val = cipso_v4_map_lvl_hton(doi_def, secattr->mls_lvl, &level); 1370 if (ret_val != 0) 1371 return ret_val; 1372 1373 if (secattr->flags & NETLBL_SECATTR_MLS_CAT) { 1374 ret_val = cipso_v4_map_cat_enum_hton(doi_def, 1375 secattr, 1376 &buffer[4], 1377 buffer_len - 4); 1378 if (ret_val < 0) 1379 return ret_val; 1380 1381 tag_len = 4 + ret_val; 1382 } else 1383 tag_len = 4; 1384 1385 buffer[0] = 0x02; 1386 buffer[1] = tag_len; 1387 buffer[3] = level; 1388 1389 return tag_len; 1390} 1391 1392/** 1393 * cipso_v4_parsetag_enum - Parse a CIPSO enumerated tag 1394 * @doi_def: the DOI definition 1395 * @tag: the CIPSO tag 1396 * @secattr: the security attributes 1397 * 1398 * Description: 1399 * Parse a CIPSO enumerated tag (tag type #2) and return the security 1400 * attributes in @secattr. Return zero on success, negatives values on 1401 * failure. 1402 * 1403 */ 1404static int cipso_v4_parsetag_enum(const struct cipso_v4_doi *doi_def, 1405 const unsigned char *tag, 1406 struct netlbl_lsm_secattr *secattr) 1407{ 1408 int ret_val; 1409 u8 tag_len = tag[1]; 1410 u32 level; 1411 1412 ret_val = cipso_v4_map_lvl_ntoh(doi_def, tag[3], &level); 1413 if (ret_val != 0) 1414 return ret_val; 1415 secattr->mls_lvl = level; 1416 secattr->flags |= NETLBL_SECATTR_MLS_LVL; 1417 1418 if (tag_len > 4) { 1419 secattr->mls_cat = netlbl_secattr_catmap_alloc(GFP_ATOMIC); 1420 if (secattr->mls_cat == NULL) 1421 return -ENOMEM; 1422 1423 ret_val = cipso_v4_map_cat_enum_ntoh(doi_def, 1424 &tag[4], 1425 tag_len - 4, 1426 secattr); 1427 if (ret_val != 0) { 1428 netlbl_secattr_catmap_free(secattr->mls_cat); 1429 return ret_val; 1430 } 1431 1432 secattr->flags |= NETLBL_SECATTR_MLS_CAT; 1433 } 1434 1435 return 0; 1436} 1437 1438/** 1439 * cipso_v4_gentag_rng - Generate a CIPSO ranged tag (type #5) 1440 * @doi_def: the DOI definition 1441 * @secattr: the security attributes 1442 * @buffer: the option buffer 1443 * @buffer_len: length of buffer in bytes 1444 * 1445 * Description: 1446 * Generate a CIPSO option using the ranged tag, tag type #5. Returns the 1447 * size of the tag on success, negative values on failure. 1448 * 1449 */ 1450static int cipso_v4_gentag_rng(const struct cipso_v4_doi *doi_def, 1451 const struct netlbl_lsm_secattr *secattr, 1452 unsigned char *buffer, 1453 u32 buffer_len) 1454{ 1455 int ret_val; 1456 u32 tag_len; 1457 u32 level; 1458 1459 if (!(secattr->flags & NETLBL_SECATTR_MLS_LVL)) 1460 return -EPERM; 1461 1462 ret_val = cipso_v4_map_lvl_hton(doi_def, secattr->mls_lvl, &level); 1463 if (ret_val != 0) 1464 return ret_val; 1465 1466 if (secattr->flags & NETLBL_SECATTR_MLS_CAT) { 1467 ret_val = cipso_v4_map_cat_rng_hton(doi_def, 1468 secattr, 1469 &buffer[4], 1470 buffer_len - 4); 1471 if (ret_val < 0) 1472 return ret_val; 1473 1474 tag_len = 4 + ret_val; 1475 } else 1476 tag_len = 4; 1477 1478 buffer[0] = 0x05; 1479 buffer[1] = tag_len; 1480 buffer[3] = level; 1481 1482 return tag_len; 1483} 1484 1485/** 1486 * cipso_v4_parsetag_rng - Parse a CIPSO ranged tag 1487 * @doi_def: the DOI definition 1488 * @tag: the CIPSO tag 1489 * @secattr: the security attributes 1490 * 1491 * Description: 1492 * Parse a CIPSO ranged tag (tag type #5) and return the security attributes 1493 * in @secattr. Return zero on success, negatives values on failure. 1494 * 1495 */ 1496static int cipso_v4_parsetag_rng(const struct cipso_v4_doi *doi_def, 1497 const unsigned char *tag, 1498 struct netlbl_lsm_secattr *secattr) 1499{ 1500 int ret_val; 1501 u8 tag_len = tag[1]; 1502 u32 level; 1503 1504 ret_val = cipso_v4_map_lvl_ntoh(doi_def, tag[3], &level); 1505 if (ret_val != 0) 1506 return ret_val; 1507 secattr->mls_lvl = level; 1508 secattr->flags |= NETLBL_SECATTR_MLS_LVL; 1509 1510 if (tag_len > 4) { 1511 secattr->mls_cat = netlbl_secattr_catmap_alloc(GFP_ATOMIC); 1512 if (secattr->mls_cat == NULL) 1513 return -ENOMEM; 1514 1515 ret_val = cipso_v4_map_cat_rng_ntoh(doi_def, 1516 &tag[4], 1517 tag_len - 4, 1518 secattr); 1519 if (ret_val != 0) { 1520 netlbl_secattr_catmap_free(secattr->mls_cat); 1521 return ret_val; 1522 } 1523 1524 secattr->flags |= NETLBL_SECATTR_MLS_CAT; 1525 } 1526 1527 return 0; 1528} 1529 1530/** 1531 * cipso_v4_validate - Validate a CIPSO option 1532 * @option: the start of the option, on error it is set to point to the error 1533 * 1534 * Description: 1535 * This routine is called to validate a CIPSO option, it checks all of the 1536 * fields to ensure that they are at least valid, see the draft snippet below 1537 * for details. If the option is valid then a zero value is returned and 1538 * the value of @option is unchanged. If the option is invalid then a 1539 * non-zero value is returned and @option is adjusted to point to the 1540 * offending portion of the option. From the IETF draft ... 1541 * 1542 * "If any field within the CIPSO options, such as the DOI identifier, is not 1543 * recognized the IP datagram is discarded and an ICMP 'parameter problem' 1544 * (type 12) is generated and returned. The ICMP code field is set to 'bad 1545 * parameter' (code 0) and the pointer is set to the start of the CIPSO field 1546 * that is unrecognized." 1547 * 1548 */ 1549int cipso_v4_validate(unsigned char **option) 1550{ 1551 unsigned char *opt = *option; 1552 unsigned char *tag; 1553 unsigned char opt_iter; 1554 unsigned char err_offset = 0; 1555 u8 opt_len; 1556 u8 tag_len; 1557 struct cipso_v4_doi *doi_def = NULL; 1558 u32 tag_iter; 1559 1560 /* caller already checks for length values that are too large */ 1561 opt_len = opt[1]; 1562 if (opt_len < 8) { 1563 err_offset = 1; 1564 goto validate_return; 1565 } 1566 1567 rcu_read_lock(); 1568 doi_def = cipso_v4_doi_search(ntohl(*((__be32 *)&opt[2]))); 1569 if (doi_def == NULL) { 1570 err_offset = 2; 1571 goto validate_return_locked; 1572 } 1573 1574 opt_iter = 6; 1575 tag = opt + opt_iter; 1576 while (opt_iter < opt_len) { 1577 for (tag_iter = 0; doi_def->tags[tag_iter] != tag[0];) 1578 if (doi_def->tags[tag_iter] == CIPSO_V4_TAG_INVALID || 1579 ++tag_iter == CIPSO_V4_TAG_MAXCNT) { 1580 err_offset = opt_iter; 1581 goto validate_return_locked; 1582 } 1583 1584 tag_len = tag[1]; 1585 if (tag_len > (opt_len - opt_iter)) { 1586 err_offset = opt_iter + 1; 1587 goto validate_return_locked; 1588 } 1589 1590 switch (tag[0]) { 1591 case CIPSO_V4_TAG_RBITMAP: 1592 if (tag_len < 4) { 1593 err_offset = opt_iter + 1; 1594 goto validate_return_locked; 1595 } 1596 1597 /* We are already going to do all the verification 1598 * necessary at the socket layer so from our point of 1599 * view it is safe to turn these checks off (and less 1600 * work), however, the CIPSO draft says we should do 1601 * all the CIPSO validations here but it doesn't 1602 * really specify _exactly_ what we need to validate 1603 * ... so, just make it a sysctl tunable. */ 1604 if (cipso_v4_rbm_strictvalid) { 1605 if (cipso_v4_map_lvl_valid(doi_def, 1606 tag[3]) < 0) { 1607 err_offset = opt_iter + 3; 1608 goto validate_return_locked; 1609 } 1610 if (tag_len > 4 && 1611 cipso_v4_map_cat_rbm_valid(doi_def, 1612 &tag[4], 1613 tag_len - 4) < 0) { 1614 err_offset = opt_iter + 4; 1615 goto validate_return_locked; 1616 } 1617 } 1618 break; 1619 case CIPSO_V4_TAG_ENUM: 1620 if (tag_len < 4) { 1621 err_offset = opt_iter + 1; 1622 goto validate_return_locked; 1623 } 1624 1625 if (cipso_v4_map_lvl_valid(doi_def, 1626 tag[3]) < 0) { 1627 err_offset = opt_iter + 3; 1628 goto validate_return_locked; 1629 } 1630 if (tag_len > 4 && 1631 cipso_v4_map_cat_enum_valid(doi_def, 1632 &tag[4], 1633 tag_len - 4) < 0) { 1634 err_offset = opt_iter + 4; 1635 goto validate_return_locked; 1636 } 1637 break; 1638 case CIPSO_V4_TAG_RANGE: 1639 if (tag_len < 4) { 1640 err_offset = opt_iter + 1; 1641 goto validate_return_locked; 1642 } 1643 1644 if (cipso_v4_map_lvl_valid(doi_def, 1645 tag[3]) < 0) { 1646 err_offset = opt_iter + 3; 1647 goto validate_return_locked; 1648 } 1649 if (tag_len > 4 && 1650 cipso_v4_map_cat_rng_valid(doi_def, 1651 &tag[4], 1652 tag_len - 4) < 0) { 1653 err_offset = opt_iter + 4; 1654 goto validate_return_locked; 1655 } 1656 break; 1657 default: 1658 err_offset = opt_iter; 1659 goto validate_return_locked; 1660 } 1661 1662 tag += tag_len; 1663 opt_iter += tag_len; 1664 } 1665 1666validate_return_locked: 1667 rcu_read_unlock(); 1668validate_return: 1669 *option = opt + err_offset; 1670 return err_offset; 1671} 1672 1673/** 1674 * cipso_v4_error - Send the correct reponse for a bad packet 1675 * @skb: the packet 1676 * @error: the error code 1677 * @gateway: CIPSO gateway flag 1678 * 1679 * Description: 1680 * Based on the error code given in @error, send an ICMP error message back to 1681 * the originating host. From the IETF draft ... 1682 * 1683 * "If the contents of the CIPSO [option] are valid but the security label is 1684 * outside of the configured host or port label range, the datagram is 1685 * discarded and an ICMP 'destination unreachable' (type 3) is generated and 1686 * returned. The code field of the ICMP is set to 'communication with 1687 * destination network administratively prohibited' (code 9) or to 1688 * 'communication with destination host administratively prohibited' 1689 * (code 10). The value of the code is dependent on whether the originator 1690 * of the ICMP message is acting as a CIPSO host or a CIPSO gateway. The 1691 * recipient of the ICMP message MUST be able to handle either value. The 1692 * same procedure is performed if a CIPSO [option] can not be added to an 1693 * IP packet because it is too large to fit in the IP options area." 1694 * 1695 * "If the error is triggered by receipt of an ICMP message, the message is 1696 * discarded and no response is permitted (consistent with general ICMP 1697 * processing rules)." 1698 * 1699 */ 1700void cipso_v4_error(struct sk_buff *skb, int error, u32 gateway) 1701{ 1702 if (ip_hdr(skb)->protocol == IPPROTO_ICMP || error != -EACCES) 1703 return; 1704 1705 if (gateway) 1706 icmp_send(skb, ICMP_DEST_UNREACH, ICMP_NET_ANO, 0); 1707 else 1708 icmp_send(skb, ICMP_DEST_UNREACH, ICMP_HOST_ANO, 0); 1709} 1710 1711/** 1712 * cipso_v4_socket_setattr - Add a CIPSO option to a socket 1713 * @sock: the socket 1714 * @doi_def: the CIPSO DOI to use 1715 * @secattr: the specific security attributes of the socket 1716 * 1717 * Description: 1718 * Set the CIPSO option on the given socket using the DOI definition and 1719 * security attributes passed to the function. This function requires 1720 * exclusive access to @sock->sk, which means it either needs to be in the 1721 * process of being created or locked via lock_sock(sock->sk). Returns zero on 1722 * success and negative values on failure. 1723 * 1724 */ 1725int cipso_v4_socket_setattr(const struct socket *sock, 1726 const struct cipso_v4_doi *doi_def, 1727 const struct netlbl_lsm_secattr *secattr) 1728{ 1729 int ret_val = -EPERM; 1730 u32 iter; 1731 unsigned char *buf; 1732 u32 buf_len = 0; 1733 u32 opt_len; 1734 struct ip_options *opt = NULL; 1735 struct sock *sk; 1736 struct inet_sock *sk_inet; 1737 struct inet_connection_sock *sk_conn; 1738 1739 /* In the case of sock_create_lite(), the sock->sk field is not 1740 * defined yet but it is not a problem as the only users of these 1741 * "lite" PF_INET sockets are functions which do an accept() call 1742 * afterwards so we will label the socket as part of the accept(). */ 1743 sk = sock->sk; 1744 if (sk == NULL) 1745 return 0; 1746 1747 /* We allocate the maximum CIPSO option size here so we are probably 1748 * being a little wasteful, but it makes our life _much_ easier later 1749 * on and after all we are only talking about 40 bytes. */ 1750 buf_len = CIPSO_V4_OPT_LEN_MAX; 1751 buf = kmalloc(buf_len, GFP_ATOMIC); 1752 if (buf == NULL) { 1753 ret_val = -ENOMEM; 1754 goto socket_setattr_failure; 1755 } 1756 1757 /* XXX - This code assumes only one tag per CIPSO option which isn't 1758 * really a good assumption to make but since we only support the MAC 1759 * tags right now it is a safe assumption. */ 1760 iter = 0; 1761 do { 1762 memset(buf, 0, buf_len); 1763 switch (doi_def->tags[iter]) { 1764 case CIPSO_V4_TAG_RBITMAP: 1765 ret_val = cipso_v4_gentag_rbm(doi_def, 1766 secattr, 1767 &buf[CIPSO_V4_HDR_LEN], 1768 buf_len - CIPSO_V4_HDR_LEN); 1769 break; 1770 case CIPSO_V4_TAG_ENUM: 1771 ret_val = cipso_v4_gentag_enum(doi_def, 1772 secattr, 1773 &buf[CIPSO_V4_HDR_LEN], 1774 buf_len - CIPSO_V4_HDR_LEN); 1775 break; 1776 case CIPSO_V4_TAG_RANGE: 1777 ret_val = cipso_v4_gentag_rng(doi_def, 1778 secattr, 1779 &buf[CIPSO_V4_HDR_LEN], 1780 buf_len - CIPSO_V4_HDR_LEN); 1781 break; 1782 default: 1783 ret_val = -EPERM; 1784 goto socket_setattr_failure; 1785 } 1786 1787 iter++; 1788 } while (ret_val < 0 && 1789 iter < CIPSO_V4_TAG_MAXCNT && 1790 doi_def->tags[iter] != CIPSO_V4_TAG_INVALID); 1791 if (ret_val < 0) 1792 goto socket_setattr_failure; 1793 cipso_v4_gentag_hdr(doi_def, buf, ret_val); 1794 buf_len = CIPSO_V4_HDR_LEN + ret_val; 1795 1796 /* We can't use ip_options_get() directly because it makes a call to 1797 * ip_options_get_alloc() which allocates memory with GFP_KERNEL and 1798 * we won't always have CAP_NET_RAW even though we _always_ want to 1799 * set the IPOPT_CIPSO option. */ 1800 opt_len = (buf_len + 3) & ~3; 1801 opt = kzalloc(sizeof(*opt) + opt_len, GFP_ATOMIC); 1802 if (opt == NULL) { 1803 ret_val = -ENOMEM; 1804 goto socket_setattr_failure; 1805 } 1806 memcpy(opt->__data, buf, buf_len); 1807 opt->optlen = opt_len; 1808 opt->is_data = 1; 1809 opt->cipso = sizeof(struct iphdr); 1810 kfree(buf); 1811 buf = NULL; 1812 1813 sk_inet = inet_sk(sk); 1814 if (sk_inet->is_icsk) { 1815 sk_conn = inet_csk(sk); 1816 if (sk_inet->opt) 1817 sk_conn->icsk_ext_hdr_len -= sk_inet->opt->optlen; 1818 sk_conn->icsk_ext_hdr_len += opt->optlen; 1819 sk_conn->icsk_sync_mss(sk, sk_conn->icsk_pmtu_cookie); 1820 } 1821 opt = xchg(&sk_inet->opt, opt); 1822 kfree(opt); 1823 1824 return 0; 1825 1826socket_setattr_failure: 1827 kfree(buf); 1828 kfree(opt); 1829 return ret_val; 1830} 1831 1832/** 1833 * cipso_v4_sock_getattr - Get the security attributes from a sock 1834 * @sk: the sock 1835 * @secattr: the security attributes 1836 * 1837 * Description: 1838 * Query @sk to see if there is a CIPSO option attached to the sock and if 1839 * there is return the CIPSO security attributes in @secattr. This function 1840 * requires that @sk be locked, or privately held, but it does not do any 1841 * locking itself. Returns zero on success and negative values on failure. 1842 * 1843 */ 1844int cipso_v4_sock_getattr(struct sock *sk, struct netlbl_lsm_secattr *secattr) 1845{ 1846 int ret_val = -ENOMSG; 1847 struct inet_sock *sk_inet; 1848 unsigned char *cipso_ptr; 1849 u32 doi; 1850 struct cipso_v4_doi *doi_def; 1851 1852 sk_inet = inet_sk(sk); 1853 if (sk_inet->opt == NULL || sk_inet->opt->cipso == 0) 1854 return -ENOMSG; 1855 cipso_ptr = sk_inet->opt->__data + sk_inet->opt->cipso - 1856 sizeof(struct iphdr); 1857 ret_val = cipso_v4_cache_check(cipso_ptr, cipso_ptr[1], secattr); 1858 if (ret_val == 0) 1859 return ret_val; 1860 1861 doi = ntohl(*(__be32 *)&cipso_ptr[2]); 1862 rcu_read_lock(); 1863 doi_def = cipso_v4_doi_search(doi); 1864 if (doi_def == NULL) { 1865 rcu_read_unlock(); 1866 return -ENOMSG; 1867 } 1868 1869 /* XXX - This code assumes only one tag per CIPSO option which isn't 1870 * really a good assumption to make but since we only support the MAC 1871 * tags right now it is a safe assumption. */ 1872 switch (cipso_ptr[6]) { 1873 case CIPSO_V4_TAG_RBITMAP: 1874 ret_val = cipso_v4_parsetag_rbm(doi_def, 1875 &cipso_ptr[6], 1876 secattr); 1877 break; 1878 case CIPSO_V4_TAG_ENUM: 1879 ret_val = cipso_v4_parsetag_enum(doi_def, 1880 &cipso_ptr[6], 1881 secattr); 1882 break; 1883 case CIPSO_V4_TAG_RANGE: 1884 ret_val = cipso_v4_parsetag_rng(doi_def, 1885 &cipso_ptr[6], 1886 secattr); 1887 break; 1888 } 1889 rcu_read_unlock(); 1890 1891 return ret_val; 1892} 1893 1894/** 1895 * cipso_v4_socket_getattr - Get the security attributes from a socket 1896 * @sock: the socket 1897 * @secattr: the security attributes 1898 * 1899 * Description: 1900 * Query @sock to see if there is a CIPSO option attached to the socket and if 1901 * there is return the CIPSO security attributes in @secattr. Returns zero on 1902 * success and negative values on failure. 1903 * 1904 */ 1905int cipso_v4_socket_getattr(const struct socket *sock, 1906 struct netlbl_lsm_secattr *secattr) 1907{ 1908 int ret_val; 1909 1910 lock_sock(sock->sk); 1911 ret_val = cipso_v4_sock_getattr(sock->sk, secattr); 1912 release_sock(sock->sk); 1913 1914 return ret_val; 1915} 1916 1917/** 1918 * cipso_v4_skbuff_getattr - Get the security attributes from the CIPSO option 1919 * @skb: the packet 1920 * @secattr: the security attributes 1921 * 1922 * Description: 1923 * Parse the given packet's CIPSO option and return the security attributes. 1924 * Returns zero on success and negative values on failure. 1925 * 1926 */ 1927int cipso_v4_skbuff_getattr(const struct sk_buff *skb, 1928 struct netlbl_lsm_secattr *secattr) 1929{ 1930 int ret_val = -ENOMSG; 1931 unsigned char *cipso_ptr; 1932 u32 doi; 1933 struct cipso_v4_doi *doi_def; 1934 1935 cipso_ptr = CIPSO_V4_OPTPTR(skb); 1936 if (cipso_v4_cache_check(cipso_ptr, cipso_ptr[1], secattr) == 0) 1937 return 0; 1938 1939 doi = ntohl(*(__be32 *)&cipso_ptr[2]); 1940 rcu_read_lock(); 1941 doi_def = cipso_v4_doi_search(doi); 1942 if (doi_def == NULL) 1943 goto skbuff_getattr_return; 1944 1945 /* XXX - This code assumes only one tag per CIPSO option which isn't 1946 * really a good assumption to make but since we only support the MAC 1947 * tags right now it is a safe assumption. */ 1948 switch (cipso_ptr[6]) { 1949 case CIPSO_V4_TAG_RBITMAP: 1950 ret_val = cipso_v4_parsetag_rbm(doi_def, 1951 &cipso_ptr[6], 1952 secattr); 1953 break; 1954 case CIPSO_V4_TAG_ENUM: 1955 ret_val = cipso_v4_parsetag_enum(doi_def, 1956 &cipso_ptr[6], 1957 secattr); 1958 break; 1959 case CIPSO_V4_TAG_RANGE: 1960 ret_val = cipso_v4_parsetag_rng(doi_def, 1961 &cipso_ptr[6], 1962 secattr); 1963 break; 1964 } 1965 1966skbuff_getattr_return: 1967 rcu_read_unlock(); 1968 return ret_val; 1969} 1970 1971/* 1972 * Setup Functions 1973 */ 1974 1975/** 1976 * cipso_v4_init - Initialize the CIPSO module 1977 * 1978 * Description: 1979 * Initialize the CIPSO module and prepare it for use. Returns zero on success 1980 * and negative values on failure. 1981 * 1982 */ 1983static int __init cipso_v4_init(void) 1984{ 1985 int ret_val; 1986 1987 ret_val = cipso_v4_cache_init(); 1988 if (ret_val != 0) 1989 panic("Failed to initialize the CIPSO/IPv4 cache (%d)\n", 1990 ret_val); 1991 1992 return 0; 1993} 1994 1995subsys_initcall(cipso_v4_init);