1 /* 2 * NetLabel Kernel API 3 * 4 * This file defines the kernel API for the NetLabel system. The NetLabel 5 * system manages static and dynamic label mappings for network protocols such 6 * as CIPSO and RIPSO. 7 * 8 * Author: Paul Moore <paul.moore@hp.com> 9 * 10 */ 11 12 /* 13 * (c) Copyright Hewlett-Packard Development Company, L.P., 2006 14 * 15 * This program is free software; you can redistribute it and/or modify 16 * it under the terms of the GNU General Public License as published by 17 * the Free Software Foundation; either version 2 of the License, or 18 * (at your option) any later version. 19 * 20 * This program is distributed in the hope that it will be useful, 21 * but WITHOUT ANY WARRANTY; without even the implied warranty of 22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 23 * the GNU General Public License for more details. 24 * 25 * You should have received a copy of the GNU General Public License 26 * along with this program; if not, write to the Free Software 27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 28 * 29 */ 30 31 #include <linux/init.h> 32 #include <linux/types.h> 33 #include <linux/audit.h> 34 #include <net/ip.h> 35 #include <net/netlabel.h> 36 #include <net/cipso_ipv4.h> 37 #include <asm/bug.h> 38 #include <asm/atomic.h> 39 40 #include "netlabel_domainhash.h" 41 #include "netlabel_unlabeled.h" 42 #include "netlabel_cipso_v4.h" 43 #include "netlabel_user.h" 44 #include "netlabel_mgmt.h" 45 46 /* 47 * Configuration Functions 48 */ 49 50 /** 51 * netlbl_cfg_map_del - Remove a NetLabel/LSM domain mapping 52 * @domain: the domain mapping to remove 53 * @audit_info: NetLabel audit information 54 * 55 * Description: 56 * Removes a NetLabel/LSM domain mapping. A @domain value of NULL causes the 57 * default domain mapping to be removed. Returns zero on success, negative 58 * values on failure. 59 * 60 */ 61 int netlbl_cfg_map_del(const char *domain, struct netlbl_audit *audit_info) 62 { 63 return netlbl_domhsh_remove(domain, audit_info); 64 } 65 66 /** 67 * netlbl_cfg_unlbl_add_map - Add an unlabeled NetLabel/LSM domain mapping 68 * @domain: the domain mapping to add 69 * @audit_info: NetLabel audit information 70 * 71 * Description: 72 * Adds a new unlabeled NetLabel/LSM domain mapping. A @domain value of NULL 73 * causes a new default domain mapping to be added. Returns zero on success, 74 * negative values on failure. 75 * 76 */ 77 int netlbl_cfg_unlbl_add_map(const char *domain, 78 struct netlbl_audit *audit_info) 79 { 80 int ret_val = -ENOMEM; 81 struct netlbl_dom_map *entry; 82 83 entry = kzalloc(sizeof(*entry), GFP_ATOMIC); 84 if (entry == NULL) 85 goto cfg_unlbl_add_map_failure; 86 if (domain != NULL) { 87 entry->domain = kstrdup(domain, GFP_ATOMIC); 88 if (entry->domain == NULL) 89 goto cfg_unlbl_add_map_failure; 90 } 91 entry->type = NETLBL_NLTYPE_UNLABELED; 92 93 ret_val = netlbl_domhsh_add(entry, audit_info); 94 if (ret_val != 0) 95 goto cfg_unlbl_add_map_failure; 96 97 return 0; 98 99 cfg_unlbl_add_map_failure: 100 if (entry != NULL) 101 kfree(entry->domain); 102 kfree(entry); 103 return ret_val; 104 } 105 106 /** 107 * netlbl_cfg_cipsov4_add - Add a new CIPSOv4 DOI definition 108 * @doi_def: the DOI definition 109 * @audit_info: NetLabel audit information 110 * 111 * Description: 112 * Add a new CIPSOv4 DOI definition to the NetLabel subsystem. Returns zero on 113 * success, negative values on failure. 114 * 115 */ 116 int netlbl_cfg_cipsov4_add(struct cipso_v4_doi *doi_def, 117 struct netlbl_audit *audit_info) 118 { 119 int ret_val; 120 const char *type_str; 121 struct audit_buffer *audit_buf; 122 123 ret_val = cipso_v4_doi_add(doi_def); 124 125 audit_buf = netlbl_audit_start_common(AUDIT_MAC_CIPSOV4_ADD, 126 audit_info); 127 if (audit_buf != NULL) { 128 switch (doi_def->type) { 129 case CIPSO_V4_MAP_STD: 130 type_str = "std"; 131 break; 132 case CIPSO_V4_MAP_PASS: 133 type_str = "pass"; 134 break; 135 default: 136 type_str = "(unknown)"; 137 } 138 audit_log_format(audit_buf, 139 " cipso_doi=%u cipso_type=%s res=%u", 140 doi_def->doi, 141 type_str, 142 ret_val == 0 ? 1 : 0); 143 audit_log_end(audit_buf); 144 } 145 146 return ret_val; 147 } 148 149 /** 150 * netlbl_cfg_cipsov4_add_map - Add a new CIPSOv4 DOI definition and mapping 151 * @doi_def: the DOI definition 152 * @domain: the domain mapping to add 153 * @audit_info: NetLabel audit information 154 * 155 * Description: 156 * Add a new CIPSOv4 DOI definition and NetLabel/LSM domain mapping for this 157 * new DOI definition to the NetLabel subsystem. A @domain value of NULL adds 158 * a new default domain mapping. Returns zero on success, negative values on 159 * failure. 160 * 161 */ 162 int netlbl_cfg_cipsov4_add_map(struct cipso_v4_doi *doi_def, 163 const char *domain, 164 struct netlbl_audit *audit_info) 165 { 166 int ret_val = -ENOMEM; 167 struct netlbl_dom_map *entry; 168 169 entry = kzalloc(sizeof(*entry), GFP_ATOMIC); 170 if (entry == NULL) 171 goto cfg_cipsov4_add_map_failure; 172 if (domain != NULL) { 173 entry->domain = kstrdup(domain, GFP_ATOMIC); 174 if (entry->domain == NULL) 175 goto cfg_cipsov4_add_map_failure; 176 } 177 entry->type = NETLBL_NLTYPE_CIPSOV4; 178 entry->type_def.cipsov4 = doi_def; 179 180 /* Grab a RCU read lock here so nothing happens to the doi_def variable 181 * between adding it to the CIPSOv4 protocol engine and adding a 182 * domain mapping for it. */ 183 184 rcu_read_lock(); 185 ret_val = netlbl_cfg_cipsov4_add(doi_def, audit_info); 186 if (ret_val != 0) 187 goto cfg_cipsov4_add_map_failure_unlock; 188 ret_val = netlbl_domhsh_add(entry, audit_info); 189 if (ret_val != 0) 190 goto cfg_cipsov4_add_map_failure_remove_doi; 191 rcu_read_unlock(); 192 193 return 0; 194 195 cfg_cipsov4_add_map_failure_remove_doi: 196 cipso_v4_doi_remove(doi_def->doi, audit_info, netlbl_cipsov4_doi_free); 197 cfg_cipsov4_add_map_failure_unlock: 198 rcu_read_unlock(); 199 cfg_cipsov4_add_map_failure: 200 if (entry != NULL) 201 kfree(entry->domain); 202 kfree(entry); 203 return ret_val; 204 } 205 206 /** 207 * netlbl_cfg_cipsov4_del - Removean existing CIPSOv4 DOI definition 208 * @doi: the CIPSO DOI value 209 * @audit_info: NetLabel audit information 210 * 211 * Description: 212 * Removes an existing CIPSOv4 DOI definition from the NetLabel subsystem. 213 * Returns zero on success, negative values on failure. 214 * 215 */ 216 int netlbl_cfg_cipsov4_del(u32 doi, struct netlbl_audit *audit_info) 217 { 218 return cipso_v4_doi_remove(doi, audit_info, netlbl_cipsov4_doi_free); 219 } 220 221 /* 222 * Security Attribute Functions 223 */ 224 225 /** 226 * netlbl_secattr_catmap_walk - Walk a LSM secattr catmap looking for a bit 227 * @catmap: the category bitmap 228 * @offset: the offset to start searching at, in bits 229 * 230 * Description: 231 * This function walks a LSM secattr category bitmap starting at @offset and 232 * returns the spot of the first set bit or -ENOENT if no bits are set. 233 * 234 */ 235 int netlbl_secattr_catmap_walk(struct netlbl_lsm_secattr_catmap *catmap, 236 u32 offset) 237 { 238 struct netlbl_lsm_secattr_catmap *iter = catmap; 239 u32 node_idx; 240 u32 node_bit; 241 NETLBL_CATMAP_MAPTYPE bitmap; 242 243 if (offset > iter->startbit) { 244 while (offset >= (iter->startbit + NETLBL_CATMAP_SIZE)) { 245 iter = iter->next; 246 if (iter == NULL) 247 return -ENOENT; 248 } 249 node_idx = (offset - iter->startbit) / NETLBL_CATMAP_MAPSIZE; 250 node_bit = offset - iter->startbit - 251 (NETLBL_CATMAP_MAPSIZE * node_idx); 252 } else { 253 node_idx = 0; 254 node_bit = 0; 255 } 256 bitmap = iter->bitmap[node_idx] >> node_bit; 257 258 for (;;) { 259 if (bitmap != 0) { 260 while ((bitmap & NETLBL_CATMAP_BIT) == 0) { 261 bitmap >>= 1; 262 node_bit++; 263 } 264 return iter->startbit + 265 (NETLBL_CATMAP_MAPSIZE * node_idx) + node_bit; 266 } 267 if (++node_idx >= NETLBL_CATMAP_MAPCNT) { 268 if (iter->next != NULL) { 269 iter = iter->next; 270 node_idx = 0; 271 } else 272 return -ENOENT; 273 } 274 bitmap = iter->bitmap[node_idx]; 275 node_bit = 0; 276 } 277 278 return -ENOENT; 279 } 280 281 /** 282 * netlbl_secattr_catmap_walk_rng - Find the end of a string of set bits 283 * @catmap: the category bitmap 284 * @offset: the offset to start searching at, in bits 285 * 286 * Description: 287 * This function walks a LSM secattr category bitmap starting at @offset and 288 * returns the spot of the first cleared bit or -ENOENT if the offset is past 289 * the end of the bitmap. 290 * 291 */ 292 int netlbl_secattr_catmap_walk_rng(struct netlbl_lsm_secattr_catmap *catmap, 293 u32 offset) 294 { 295 struct netlbl_lsm_secattr_catmap *iter = catmap; 296 u32 node_idx; 297 u32 node_bit; 298 NETLBL_CATMAP_MAPTYPE bitmask; 299 NETLBL_CATMAP_MAPTYPE bitmap; 300 301 if (offset > iter->startbit) { 302 while (offset >= (iter->startbit + NETLBL_CATMAP_SIZE)) { 303 iter = iter->next; 304 if (iter == NULL) 305 return -ENOENT; 306 } 307 node_idx = (offset - iter->startbit) / NETLBL_CATMAP_MAPSIZE; 308 node_bit = offset - iter->startbit - 309 (NETLBL_CATMAP_MAPSIZE * node_idx); 310 } else { 311 node_idx = 0; 312 node_bit = 0; 313 } 314 bitmask = NETLBL_CATMAP_BIT << node_bit; 315 316 for (;;) { 317 bitmap = iter->bitmap[node_idx]; 318 while (bitmask != 0 && (bitmap & bitmask) != 0) { 319 bitmask <<= 1; 320 node_bit++; 321 } 322 323 if (bitmask != 0) 324 return iter->startbit + 325 (NETLBL_CATMAP_MAPSIZE * node_idx) + 326 node_bit - 1; 327 else if (++node_idx >= NETLBL_CATMAP_MAPCNT) { 328 if (iter->next == NULL) 329 return iter->startbit + NETLBL_CATMAP_SIZE - 1; 330 iter = iter->next; 331 node_idx = 0; 332 } 333 bitmask = NETLBL_CATMAP_BIT; 334 node_bit = 0; 335 } 336 337 return -ENOENT; 338 } 339 340 /** 341 * netlbl_secattr_catmap_setbit - Set a bit in a LSM secattr catmap 342 * @catmap: the category bitmap 343 * @bit: the bit to set 344 * @flags: memory allocation flags 345 * 346 * Description: 347 * Set the bit specified by @bit in @catmap. Returns zero on success, 348 * negative values on failure. 349 * 350 */ 351 int netlbl_secattr_catmap_setbit(struct netlbl_lsm_secattr_catmap *catmap, 352 u32 bit, 353 gfp_t flags) 354 { 355 struct netlbl_lsm_secattr_catmap *iter = catmap; 356 u32 node_bit; 357 u32 node_idx; 358 359 while (iter->next != NULL && 360 bit >= (iter->startbit + NETLBL_CATMAP_SIZE)) 361 iter = iter->next; 362 if (bit >= (iter->startbit + NETLBL_CATMAP_SIZE)) { 363 iter->next = netlbl_secattr_catmap_alloc(flags); 364 if (iter->next == NULL) 365 return -ENOMEM; 366 iter = iter->next; 367 iter->startbit = bit & ~(NETLBL_CATMAP_SIZE - 1); 368 } 369 370 /* gcc always rounds to zero when doing integer division */ 371 node_idx = (bit - iter->startbit) / NETLBL_CATMAP_MAPSIZE; 372 node_bit = bit - iter->startbit - (NETLBL_CATMAP_MAPSIZE * node_idx); 373 iter->bitmap[node_idx] |= NETLBL_CATMAP_BIT << node_bit; 374 375 return 0; 376 } 377 378 /** 379 * netlbl_secattr_catmap_setrng - Set a range of bits in a LSM secattr catmap 380 * @catmap: the category bitmap 381 * @start: the starting bit 382 * @end: the last bit in the string 383 * @flags: memory allocation flags 384 * 385 * Description: 386 * Set a range of bits, starting at @start and ending with @end. Returns zero 387 * on success, negative values on failure. 388 * 389 */ 390 int netlbl_secattr_catmap_setrng(struct netlbl_lsm_secattr_catmap *catmap, 391 u32 start, 392 u32 end, 393 gfp_t flags) 394 { 395 int ret_val = 0; 396 struct netlbl_lsm_secattr_catmap *iter = catmap; 397 u32 iter_max_spot; 398 u32 spot; 399 400 /* XXX - This could probably be made a bit faster by combining writes 401 * to the catmap instead of setting a single bit each time, but for 402 * right now skipping to the start of the range in the catmap should 403 * be a nice improvement over calling the individual setbit function 404 * repeatedly from a loop. */ 405 406 while (iter->next != NULL && 407 start >= (iter->startbit + NETLBL_CATMAP_SIZE)) 408 iter = iter->next; 409 iter_max_spot = iter->startbit + NETLBL_CATMAP_SIZE; 410 411 for (spot = start; spot <= end && ret_val == 0; spot++) { 412 if (spot >= iter_max_spot && iter->next != NULL) { 413 iter = iter->next; 414 iter_max_spot = iter->startbit + NETLBL_CATMAP_SIZE; 415 } 416 ret_val = netlbl_secattr_catmap_setbit(iter, spot, GFP_ATOMIC); 417 } 418 419 return ret_val; 420 } 421 422 /* 423 * LSM Functions 424 */ 425 426 /** 427 * netlbl_enabled - Determine if the NetLabel subsystem is enabled 428 * 429 * Description: 430 * The LSM can use this function to determine if it should use NetLabel 431 * security attributes in it's enforcement mechanism. Currently, NetLabel is 432 * considered to be enabled when it's configuration contains a valid setup for 433 * at least one labeled protocol (i.e. NetLabel can understand incoming 434 * labeled packets of at least one type); otherwise NetLabel is considered to 435 * be disabled. 436 * 437 */ 438 int netlbl_enabled(void) 439 { 440 /* At some point we probably want to expose this mechanism to the user 441 * as well so that admins can toggle NetLabel regardless of the 442 * configuration */ 443 return (atomic_read(&netlabel_mgmt_protocount) > 0); 444 } 445 446 /** 447 * netlbl_socket_setattr - Label a socket using the correct protocol 448 * @sk: the socket to label 449 * @secattr: the security attributes 450 * 451 * Description: 452 * Attach the correct label to the given socket using the security attributes 453 * specified in @secattr. This function requires exclusive access to @sk, 454 * which means it either needs to be in the process of being created or locked. 455 * Returns zero on success, negative values on failure. 456 * 457 */ 458 int netlbl_sock_setattr(struct sock *sk, 459 const struct netlbl_lsm_secattr *secattr) 460 { 461 int ret_val = -ENOENT; 462 struct netlbl_dom_map *dom_entry; 463 464 rcu_read_lock(); 465 dom_entry = netlbl_domhsh_getentry(secattr->domain); 466 if (dom_entry == NULL) 467 goto socket_setattr_return; 468 switch (dom_entry->type) { 469 case NETLBL_NLTYPE_CIPSOV4: 470 ret_val = cipso_v4_sock_setattr(sk, 471 dom_entry->type_def.cipsov4, 472 secattr); 473 break; 474 case NETLBL_NLTYPE_UNLABELED: 475 ret_val = 0; 476 break; 477 default: 478 ret_val = -ENOENT; 479 } 480 481 socket_setattr_return: 482 rcu_read_unlock(); 483 return ret_val; 484 } 485 486 /** 487 * netlbl_sock_getattr - Determine the security attributes of a sock 488 * @sk: the sock 489 * @secattr: the security attributes 490 * 491 * Description: 492 * Examines the given sock to see if any NetLabel style labeling has been 493 * applied to the sock, if so it parses the socket label and returns the 494 * security attributes in @secattr. Returns zero on success, negative values 495 * on failure. 496 * 497 */ 498 int netlbl_sock_getattr(struct sock *sk, struct netlbl_lsm_secattr *secattr) 499 { 500 return cipso_v4_sock_getattr(sk, secattr); 501 } 502 503 /** 504 * netlbl_skbuff_getattr - Determine the security attributes of a packet 505 * @skb: the packet 506 * @family: protocol family 507 * @secattr: the security attributes 508 * 509 * Description: 510 * Examines the given packet to see if a recognized form of packet labeling 511 * is present, if so it parses the packet label and returns the security 512 * attributes in @secattr. Returns zero on success, negative values on 513 * failure. 514 * 515 */ 516 int netlbl_skbuff_getattr(const struct sk_buff *skb, 517 u16 family, 518 struct netlbl_lsm_secattr *secattr) 519 { 520 if (CIPSO_V4_OPTEXIST(skb) && 521 cipso_v4_skbuff_getattr(skb, secattr) == 0) 522 return 0; 523 524 return netlbl_unlabel_getattr(skb, family, secattr); 525 } 526 527 /** 528 * netlbl_skbuff_err - Handle a LSM error on a sk_buff 529 * @skb: the packet 530 * @error: the error code 531 * 532 * Description: 533 * Deal with a LSM problem when handling the packet in @skb, typically this is 534 * a permission denied problem (-EACCES). The correct action is determined 535 * according to the packet's labeling protocol. 536 * 537 */ 538 void netlbl_skbuff_err(struct sk_buff *skb, int error) 539 { 540 if (CIPSO_V4_OPTEXIST(skb)) 541 cipso_v4_error(skb, error, 0); 542 } 543 544 /** 545 * netlbl_cache_invalidate - Invalidate all of the NetLabel protocol caches 546 * 547 * Description: 548 * For all of the NetLabel protocols that support some form of label mapping 549 * cache, invalidate the cache. Returns zero on success, negative values on 550 * error. 551 * 552 */ 553 void netlbl_cache_invalidate(void) 554 { 555 cipso_v4_cache_invalidate(); 556 } 557 558 /** 559 * netlbl_cache_add - Add an entry to a NetLabel protocol cache 560 * @skb: the packet 561 * @secattr: the packet's security attributes 562 * 563 * Description: 564 * Add the LSM security attributes for the given packet to the underlying 565 * NetLabel protocol's label mapping cache. Returns zero on success, negative 566 * values on error. 567 * 568 */ 569 int netlbl_cache_add(const struct sk_buff *skb, 570 const struct netlbl_lsm_secattr *secattr) 571 { 572 if ((secattr->flags & NETLBL_SECATTR_CACHE) == 0) 573 return -ENOMSG; 574 575 if (CIPSO_V4_OPTEXIST(skb)) 576 return cipso_v4_cache_add(skb, secattr); 577 578 return -ENOMSG; 579 } 580 581 /* 582 * Setup Functions 583 */ 584 585 /** 586 * netlbl_init - Initialize NetLabel 587 * 588 * Description: 589 * Perform the required NetLabel initialization before first use. 590 * 591 */ 592 static int __init netlbl_init(void) 593 { 594 int ret_val; 595 596 printk(KERN_INFO "NetLabel: Initializing\n"); 597 printk(KERN_INFO "NetLabel: domain hash size = %u\n", 598 (1 << NETLBL_DOMHSH_BITSIZE)); 599 printk(KERN_INFO "NetLabel: protocols =" 600 " UNLABELED" 601 " CIPSOv4" 602 "\n"); 603 604 ret_val = netlbl_domhsh_init(NETLBL_DOMHSH_BITSIZE); 605 if (ret_val != 0) 606 goto init_failure; 607 608 ret_val = netlbl_unlabel_init(NETLBL_UNLHSH_BITSIZE); 609 if (ret_val != 0) 610 goto init_failure; 611 612 ret_val = netlbl_netlink_init(); 613 if (ret_val != 0) 614 goto init_failure; 615 616 ret_val = netlbl_unlabel_defconf(); 617 if (ret_val != 0) 618 goto init_failure; 619 printk(KERN_INFO "NetLabel: unlabeled traffic allowed by default\n"); 620 621 return 0; 622 623 init_failure: 624 panic("NetLabel: failed to initialize properly (%d)\n", ret_val); 625 } 626 627 subsys_initcall(netlbl_init); 628