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 | /** |