diff options
Diffstat (limited to 'net/netlabel/netlabel_kapi.c')
| -rw-r--r-- | net/netlabel/netlabel_kapi.c | 272 |
1 files changed, 192 insertions, 80 deletions
diff --git a/net/netlabel/netlabel_kapi.c b/net/netlabel/netlabel_kapi.c index 39793a1a93aa..b32eceb3ab0d 100644 --- a/net/netlabel/netlabel_kapi.c +++ b/net/netlabel/netlabel_kapi.c | |||
| @@ -10,7 +10,7 @@ | |||
| 10 | */ | 10 | */ |
| 11 | 11 | ||
| 12 | /* | 12 | /* |
| 13 | * (c) Copyright Hewlett-Packard Development Company, L.P., 2006 | 13 | * (c) Copyright Hewlett-Packard Development Company, L.P., 2006, 2008 |
| 14 | * | 14 | * |
| 15 | * This program is free software; you can redistribute it and/or modify | 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 | 16 | * it under the terms of the GNU General Public License as published by |
| @@ -82,7 +82,7 @@ int netlbl_cfg_unlbl_add_map(const char *domain, | |||
| 82 | 82 | ||
| 83 | entry = kzalloc(sizeof(*entry), GFP_ATOMIC); | 83 | entry = kzalloc(sizeof(*entry), GFP_ATOMIC); |
| 84 | if (entry == NULL) | 84 | if (entry == NULL) |
| 85 | goto cfg_unlbl_add_map_failure; | 85 | return -ENOMEM; |
| 86 | if (domain != NULL) { | 86 | if (domain != NULL) { |
| 87 | entry->domain = kstrdup(domain, GFP_ATOMIC); | 87 | entry->domain = kstrdup(domain, GFP_ATOMIC); |
| 88 | if (entry->domain == NULL) | 88 | if (entry->domain == NULL) |
| @@ -104,49 +104,6 @@ cfg_unlbl_add_map_failure: | |||
| 104 | } | 104 | } |
| 105 | 105 | ||
| 106 | /** | 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 | 107 | * netlbl_cfg_cipsov4_add_map - Add a new CIPSOv4 DOI definition and mapping |
| 151 | * @doi_def: the DOI definition | 108 | * @doi_def: the DOI definition |
| 152 | * @domain: the domain mapping to add | 109 | * @domain: the domain mapping to add |
| @@ -164,58 +121,71 @@ int netlbl_cfg_cipsov4_add_map(struct cipso_v4_doi *doi_def, | |||
| 164 | struct netlbl_audit *audit_info) | 121 | struct netlbl_audit *audit_info) |
| 165 | { | 122 | { |
| 166 | int ret_val = -ENOMEM; | 123 | int ret_val = -ENOMEM; |
| 124 | u32 doi; | ||
| 125 | u32 doi_type; | ||
| 167 | struct netlbl_dom_map *entry; | 126 | struct netlbl_dom_map *entry; |
| 127 | const char *type_str; | ||
| 128 | struct audit_buffer *audit_buf; | ||
| 129 | |||
| 130 | doi = doi_def->doi; | ||
| 131 | doi_type = doi_def->type; | ||
| 168 | 132 | ||
| 169 | entry = kzalloc(sizeof(*entry), GFP_ATOMIC); | 133 | entry = kzalloc(sizeof(*entry), GFP_ATOMIC); |
| 170 | if (entry == NULL) | 134 | if (entry == NULL) |
| 171 | goto cfg_cipsov4_add_map_failure; | 135 | return -ENOMEM; |
| 172 | if (domain != NULL) { | 136 | if (domain != NULL) { |
| 173 | entry->domain = kstrdup(domain, GFP_ATOMIC); | 137 | entry->domain = kstrdup(domain, GFP_ATOMIC); |
| 174 | if (entry->domain == NULL) | 138 | if (entry->domain == NULL) |
| 175 | goto cfg_cipsov4_add_map_failure; | 139 | goto cfg_cipsov4_add_map_failure; |
| 176 | } | 140 | } |
| 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 | 141 | ||
| 184 | rcu_read_lock(); | 142 | ret_val = cipso_v4_doi_add(doi_def); |
| 185 | ret_val = netlbl_cfg_cipsov4_add(doi_def, audit_info); | ||
| 186 | if (ret_val != 0) | 143 | if (ret_val != 0) |
| 187 | goto cfg_cipsov4_add_map_failure_unlock; | 144 | goto cfg_cipsov4_add_map_failure_remove_doi; |
| 145 | entry->type = NETLBL_NLTYPE_CIPSOV4; | ||
| 146 | entry->type_def.cipsov4 = cipso_v4_doi_getdef(doi); | ||
| 147 | if (entry->type_def.cipsov4 == NULL) { | ||
| 148 | ret_val = -ENOENT; | ||
| 149 | goto cfg_cipsov4_add_map_failure_remove_doi; | ||
| 150 | } | ||
| 188 | ret_val = netlbl_domhsh_add(entry, audit_info); | 151 | ret_val = netlbl_domhsh_add(entry, audit_info); |
| 189 | if (ret_val != 0) | 152 | if (ret_val != 0) |
| 190 | goto cfg_cipsov4_add_map_failure_remove_doi; | 153 | goto cfg_cipsov4_add_map_failure_release_doi; |
| 191 | rcu_read_unlock(); | ||
| 192 | 154 | ||
| 193 | return 0; | 155 | cfg_cipsov4_add_map_return: |
| 156 | audit_buf = netlbl_audit_start_common(AUDIT_MAC_CIPSOV4_ADD, | ||
| 157 | audit_info); | ||
| 158 | if (audit_buf != NULL) { | ||
| 159 | switch (doi_type) { | ||
| 160 | case CIPSO_V4_MAP_TRANS: | ||
| 161 | type_str = "trans"; | ||
| 162 | break; | ||
| 163 | case CIPSO_V4_MAP_PASS: | ||
| 164 | type_str = "pass"; | ||
| 165 | break; | ||
| 166 | case CIPSO_V4_MAP_LOCAL: | ||
| 167 | type_str = "local"; | ||
| 168 | break; | ||
| 169 | default: | ||
| 170 | type_str = "(unknown)"; | ||
| 171 | } | ||
| 172 | audit_log_format(audit_buf, | ||
| 173 | " cipso_doi=%u cipso_type=%s res=%u", | ||
| 174 | doi, type_str, ret_val == 0 ? 1 : 0); | ||
| 175 | audit_log_end(audit_buf); | ||
| 176 | } | ||
| 194 | 177 | ||
| 178 | return ret_val; | ||
| 179 | |||
| 180 | cfg_cipsov4_add_map_failure_release_doi: | ||
| 181 | cipso_v4_doi_putdef(doi_def); | ||
| 195 | cfg_cipsov4_add_map_failure_remove_doi: | 182 | cfg_cipsov4_add_map_failure_remove_doi: |
| 196 | cipso_v4_doi_remove(doi_def->doi, audit_info, netlbl_cipsov4_doi_free); | 183 | cipso_v4_doi_remove(doi, audit_info); |
| 197 | cfg_cipsov4_add_map_failure_unlock: | ||
| 198 | rcu_read_unlock(); | ||
| 199 | cfg_cipsov4_add_map_failure: | 184 | cfg_cipsov4_add_map_failure: |
| 200 | if (entry != NULL) | 185 | if (entry != NULL) |
| 201 | kfree(entry->domain); | 186 | kfree(entry->domain); |
| 202 | kfree(entry); | 187 | kfree(entry); |
| 203 | return ret_val; | 188 | goto cfg_cipsov4_add_map_return; |
| 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 | } | 189 | } |
| 220 | 190 | ||
| 221 | /* | 191 | /* |
| @@ -452,7 +422,9 @@ int netlbl_enabled(void) | |||
| 452 | * Attach the correct label to the given socket using the security attributes | 422 | * Attach the correct label to the given socket using the security attributes |
| 453 | * specified in @secattr. This function requires exclusive access to @sk, | 423 | * 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. | 424 | * which means it either needs to be in the process of being created or locked. |
| 455 | * Returns zero on success, negative values on failure. | 425 | * Returns zero on success, -EDESTADDRREQ if the domain is configured to use |
| 426 | * network address selectors (can't blindly label the socket), and negative | ||
| 427 | * values on all other failures. | ||
| 456 | * | 428 | * |
| 457 | */ | 429 | */ |
| 458 | int netlbl_sock_setattr(struct sock *sk, | 430 | int netlbl_sock_setattr(struct sock *sk, |
| @@ -466,6 +438,9 @@ int netlbl_sock_setattr(struct sock *sk, | |||
| 466 | if (dom_entry == NULL) | 438 | if (dom_entry == NULL) |
| 467 | goto socket_setattr_return; | 439 | goto socket_setattr_return; |
| 468 | switch (dom_entry->type) { | 440 | switch (dom_entry->type) { |
| 441 | case NETLBL_NLTYPE_ADDRSELECT: | ||
| 442 | ret_val = -EDESTADDRREQ; | ||
| 443 | break; | ||
| 469 | case NETLBL_NLTYPE_CIPSOV4: | 444 | case NETLBL_NLTYPE_CIPSOV4: |
| 470 | ret_val = cipso_v4_sock_setattr(sk, | 445 | ret_val = cipso_v4_sock_setattr(sk, |
| 471 | dom_entry->type_def.cipsov4, | 446 | dom_entry->type_def.cipsov4, |
| @@ -484,6 +459,20 @@ socket_setattr_return: | |||
| 484 | } | 459 | } |
| 485 | 460 | ||
| 486 | /** | 461 | /** |
| 462 | * netlbl_sock_delattr - Delete all the NetLabel labels on a socket | ||
| 463 | * @sk: the socket | ||
| 464 | * | ||
| 465 | * Description: | ||
| 466 | * Remove all the NetLabel labeling from @sk. The caller is responsible for | ||
| 467 | * ensuring that @sk is locked. | ||
| 468 | * | ||
| 469 | */ | ||
| 470 | void netlbl_sock_delattr(struct sock *sk) | ||
| 471 | { | ||
| 472 | cipso_v4_sock_delattr(sk); | ||
| 473 | } | ||
| 474 | |||
| 475 | /** | ||
| 487 | * netlbl_sock_getattr - Determine the security attributes of a sock | 476 | * netlbl_sock_getattr - Determine the security attributes of a sock |
| 488 | * @sk: the sock | 477 | * @sk: the sock |
| 489 | * @secattr: the security attributes | 478 | * @secattr: the security attributes |
| @@ -501,6 +490,128 @@ int netlbl_sock_getattr(struct sock *sk, struct netlbl_lsm_secattr *secattr) | |||
| 501 | } | 490 | } |
| 502 | 491 | ||
| 503 | /** | 492 | /** |
| 493 | * netlbl_conn_setattr - Label a connected socket using the correct protocol | ||
| 494 | * @sk: the socket to label | ||
| 495 | * @addr: the destination address | ||
| 496 | * @secattr: the security attributes | ||
| 497 | * | ||
| 498 | * Description: | ||
| 499 | * Attach the correct label to the given connected socket using the security | ||
| 500 | * attributes specified in @secattr. The caller is responsible for ensuring | ||
| 501 | * that @sk is locked. Returns zero on success, negative values on failure. | ||
| 502 | * | ||
| 503 | */ | ||
| 504 | int netlbl_conn_setattr(struct sock *sk, | ||
| 505 | struct sockaddr *addr, | ||
| 506 | const struct netlbl_lsm_secattr *secattr) | ||
| 507 | { | ||
| 508 | int ret_val; | ||
| 509 | struct sockaddr_in *addr4; | ||
| 510 | struct netlbl_domaddr4_map *af4_entry; | ||
| 511 | |||
| 512 | rcu_read_lock(); | ||
| 513 | switch (addr->sa_family) { | ||
| 514 | case AF_INET: | ||
| 515 | addr4 = (struct sockaddr_in *)addr; | ||
| 516 | af4_entry = netlbl_domhsh_getentry_af4(secattr->domain, | ||
| 517 | addr4->sin_addr.s_addr); | ||
| 518 | if (af4_entry == NULL) { | ||
| 519 | ret_val = -ENOENT; | ||
| 520 | goto conn_setattr_return; | ||
| 521 | } | ||
| 522 | switch (af4_entry->type) { | ||
| 523 | case NETLBL_NLTYPE_CIPSOV4: | ||
| 524 | ret_val = cipso_v4_sock_setattr(sk, | ||
| 525 | af4_entry->type_def.cipsov4, | ||
| 526 | secattr); | ||
| 527 | break; | ||
| 528 | case NETLBL_NLTYPE_UNLABELED: | ||
| 529 | /* just delete the protocols we support for right now | ||
| 530 | * but we could remove other protocols if needed */ | ||
| 531 | cipso_v4_sock_delattr(sk); | ||
| 532 | ret_val = 0; | ||
| 533 | break; | ||
| 534 | default: | ||
| 535 | ret_val = -ENOENT; | ||
| 536 | } | ||
| 537 | break; | ||
| 538 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
| 539 | case AF_INET6: | ||
| 540 | /* since we don't support any IPv6 labeling protocols right | ||
| 541 | * now we can optimize everything away until we do */ | ||
| 542 | ret_val = 0; | ||
| 543 | break; | ||
| 544 | #endif /* IPv6 */ | ||
| 545 | default: | ||
| 546 | ret_val = 0; | ||
| 547 | } | ||
| 548 | |||
| 549 | conn_setattr_return: | ||
| 550 | rcu_read_unlock(); | ||
| 551 | return ret_val; | ||
| 552 | } | ||
| 553 | |||
| 554 | /** | ||
| 555 | * netlbl_skbuff_setattr - Label a packet using the correct protocol | ||
| 556 | * @skb: the packet | ||
| 557 | * @family: protocol family | ||
| 558 | * @secattr: the security attributes | ||
| 559 | * | ||
| 560 | * Description: | ||
| 561 | * Attach the correct label to the given packet using the security attributes | ||
| 562 | * specified in @secattr. Returns zero on success, negative values on failure. | ||
| 563 | * | ||
| 564 | */ | ||
| 565 | int netlbl_skbuff_setattr(struct sk_buff *skb, | ||
| 566 | u16 family, | ||
| 567 | const struct netlbl_lsm_secattr *secattr) | ||
| 568 | { | ||
| 569 | int ret_val; | ||
| 570 | struct iphdr *hdr4; | ||
| 571 | struct netlbl_domaddr4_map *af4_entry; | ||
| 572 | |||
| 573 | rcu_read_lock(); | ||
| 574 | switch (family) { | ||
| 575 | case AF_INET: | ||
| 576 | hdr4 = ip_hdr(skb); | ||
| 577 | af4_entry = netlbl_domhsh_getentry_af4(secattr->domain, | ||
| 578 | hdr4->daddr); | ||
| 579 | if (af4_entry == NULL) { | ||
| 580 | ret_val = -ENOENT; | ||
| 581 | goto skbuff_setattr_return; | ||
| 582 | } | ||
| 583 | switch (af4_entry->type) { | ||
| 584 | case NETLBL_NLTYPE_CIPSOV4: | ||
| 585 | ret_val = cipso_v4_skbuff_setattr(skb, | ||
| 586 | af4_entry->type_def.cipsov4, | ||
| 587 | secattr); | ||
| 588 | break; | ||
| 589 | case NETLBL_NLTYPE_UNLABELED: | ||
| 590 | /* just delete the protocols we support for right now | ||
| 591 | * but we could remove other protocols if needed */ | ||
| 592 | ret_val = cipso_v4_skbuff_delattr(skb); | ||
| 593 | break; | ||
| 594 | default: | ||
| 595 | ret_val = -ENOENT; | ||
| 596 | } | ||
| 597 | break; | ||
| 598 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
| 599 | case AF_INET6: | ||
| 600 | /* since we don't support any IPv6 labeling protocols right | ||
| 601 | * now we can optimize everything away until we do */ | ||
| 602 | ret_val = 0; | ||
| 603 | break; | ||
| 604 | #endif /* IPv6 */ | ||
| 605 | default: | ||
| 606 | ret_val = 0; | ||
| 607 | } | ||
| 608 | |||
| 609 | skbuff_setattr_return: | ||
| 610 | rcu_read_unlock(); | ||
| 611 | return ret_val; | ||
| 612 | } | ||
| 613 | |||
| 614 | /** | ||
| 504 | * netlbl_skbuff_getattr - Determine the security attributes of a packet | 615 | * netlbl_skbuff_getattr - Determine the security attributes of a packet |
| 505 | * @skb: the packet | 616 | * @skb: the packet |
| 506 | * @family: protocol family | 617 | * @family: protocol family |
| @@ -528,6 +639,7 @@ int netlbl_skbuff_getattr(const struct sk_buff *skb, | |||
| 528 | * netlbl_skbuff_err - Handle a LSM error on a sk_buff | 639 | * netlbl_skbuff_err - Handle a LSM error on a sk_buff |
| 529 | * @skb: the packet | 640 | * @skb: the packet |
| 530 | * @error: the error code | 641 | * @error: the error code |
| 642 | * @gateway: true if host is acting as a gateway, false otherwise | ||
| 531 | * | 643 | * |
| 532 | * Description: | 644 | * Description: |
| 533 | * Deal with a LSM problem when handling the packet in @skb, typically this is | 645 | * Deal with a LSM problem when handling the packet in @skb, typically this is |
| @@ -535,10 +647,10 @@ int netlbl_skbuff_getattr(const struct sk_buff *skb, | |||
| 535 | * according to the packet's labeling protocol. | 647 | * according to the packet's labeling protocol. |
| 536 | * | 648 | * |
| 537 | */ | 649 | */ |
| 538 | void netlbl_skbuff_err(struct sk_buff *skb, int error) | 650 | void netlbl_skbuff_err(struct sk_buff *skb, int error, int gateway) |
| 539 | { | 651 | { |
| 540 | if (CIPSO_V4_OPTEXIST(skb)) | 652 | if (CIPSO_V4_OPTEXIST(skb)) |
| 541 | cipso_v4_error(skb, error, 0); | 653 | cipso_v4_error(skb, error, gateway); |
| 542 | } | 654 | } |
| 543 | 655 | ||
| 544 | /** | 656 | /** |
