diff options
| author | Paul Moore <pmoore@redhat.com> | 2013-08-02 14:45:08 -0400 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2013-08-02 19:57:01 -0400 |
| commit | 6a8b7f0c85f1f42eb8b6e68ef3d5ba8020d8e272 (patch) | |
| tree | 2097e9baf7e2af21a6cc80206df4f3c58c8a4840 | |
| parent | 5f671d6b4ec3e6d66c2a868738af2cdea09e7509 (diff) | |
netlabel: use domain based selectors when address based selectors are not available
NetLabel has the ability to selectively assign network security labels
to outbound traffic based on either the LSM's "domain" (different for
each LSM), the network destination, or a combination of both. Depending
on the type of traffic, local or forwarded, and the type of traffic
selector, domain or address based, different hooks are used to label the
traffic; the goal being minimal overhead.
Unfortunately, there is a bug such that a system using NetLabel domain
based traffic selectors does not correctly label outbound local traffic
that is not assigned to a socket. The issue is that in these cases
the associated NetLabel hook only looks at the address based selectors
and not the domain based selectors. This patch corrects this by
checking both the domain and address based selectors so that the correct
labeling is applied, regardless of the configuration type.
In order to acomplish this fix, this patch also simplifies some of the
NetLabel domainhash structures to use a more common outbound traffic
mapping type: struct netlbl_dommap_def. This simplifies some of the code
in this patch and paves the way for further simplifications in the
future.
Signed-off-by: Paul Moore <pmoore@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
| -rw-r--r-- | net/netlabel/netlabel_cipso_v4.c | 4 | ||||
| -rw-r--r-- | net/netlabel/netlabel_domainhash.c | 104 | ||||
| -rw-r--r-- | net/netlabel/netlabel_domainhash.h | 46 | ||||
| -rw-r--r-- | net/netlabel/netlabel_kapi.c | 88 | ||||
| -rw-r--r-- | net/netlabel/netlabel_mgmt.c | 44 | ||||
| -rw-r--r-- | net/netlabel/netlabel_unlabeled.c | 2 |
6 files changed, 130 insertions, 158 deletions
diff --git a/net/netlabel/netlabel_cipso_v4.c b/net/netlabel/netlabel_cipso_v4.c index c15042f987bd..a1100640495d 100644 --- a/net/netlabel/netlabel_cipso_v4.c +++ b/net/netlabel/netlabel_cipso_v4.c | |||
| @@ -691,8 +691,8 @@ static int netlbl_cipsov4_remove_cb(struct netlbl_dom_map *entry, void *arg) | |||
| 691 | { | 691 | { |
| 692 | struct netlbl_domhsh_walk_arg *cb_arg = arg; | 692 | struct netlbl_domhsh_walk_arg *cb_arg = arg; |
| 693 | 693 | ||
| 694 | if (entry->type == NETLBL_NLTYPE_CIPSOV4 && | 694 | if (entry->def.type == NETLBL_NLTYPE_CIPSOV4 && |
| 695 | entry->type_def.cipsov4->doi == cb_arg->doi) | 695 | entry->def.cipso->doi == cb_arg->doi) |
| 696 | return netlbl_domhsh_remove_entry(entry, cb_arg->audit_info); | 696 | return netlbl_domhsh_remove_entry(entry, cb_arg->audit_info); |
| 697 | 697 | ||
| 698 | return 0; | 698 | return 0; |
diff --git a/net/netlabel/netlabel_domainhash.c b/net/netlabel/netlabel_domainhash.c index 6bb1d42f0fac..85d842e6e431 100644 --- a/net/netlabel/netlabel_domainhash.c +++ b/net/netlabel/netlabel_domainhash.c | |||
| @@ -84,15 +84,15 @@ static void netlbl_domhsh_free_entry(struct rcu_head *entry) | |||
| 84 | #endif /* IPv6 */ | 84 | #endif /* IPv6 */ |
| 85 | 85 | ||
| 86 | ptr = container_of(entry, struct netlbl_dom_map, rcu); | 86 | ptr = container_of(entry, struct netlbl_dom_map, rcu); |
| 87 | if (ptr->type == NETLBL_NLTYPE_ADDRSELECT) { | 87 | if (ptr->def.type == NETLBL_NLTYPE_ADDRSELECT) { |
| 88 | netlbl_af4list_foreach_safe(iter4, tmp4, | 88 | netlbl_af4list_foreach_safe(iter4, tmp4, |
| 89 | &ptr->type_def.addrsel->list4) { | 89 | &ptr->def.addrsel->list4) { |
| 90 | netlbl_af4list_remove_entry(iter4); | 90 | netlbl_af4list_remove_entry(iter4); |
| 91 | kfree(netlbl_domhsh_addr4_entry(iter4)); | 91 | kfree(netlbl_domhsh_addr4_entry(iter4)); |
| 92 | } | 92 | } |
| 93 | #if IS_ENABLED(CONFIG_IPV6) | 93 | #if IS_ENABLED(CONFIG_IPV6) |
| 94 | netlbl_af6list_foreach_safe(iter6, tmp6, | 94 | netlbl_af6list_foreach_safe(iter6, tmp6, |
| 95 | &ptr->type_def.addrsel->list6) { | 95 | &ptr->def.addrsel->list6) { |
| 96 | netlbl_af6list_remove_entry(iter6); | 96 | netlbl_af6list_remove_entry(iter6); |
| 97 | kfree(netlbl_domhsh_addr6_entry(iter6)); | 97 | kfree(netlbl_domhsh_addr6_entry(iter6)); |
| 98 | } | 98 | } |
| @@ -213,21 +213,21 @@ static void netlbl_domhsh_audit_add(struct netlbl_dom_map *entry, | |||
| 213 | if (addr4 != NULL) { | 213 | if (addr4 != NULL) { |
| 214 | struct netlbl_domaddr4_map *map4; | 214 | struct netlbl_domaddr4_map *map4; |
| 215 | map4 = netlbl_domhsh_addr4_entry(addr4); | 215 | map4 = netlbl_domhsh_addr4_entry(addr4); |
| 216 | type = map4->type; | 216 | type = map4->def.type; |
| 217 | cipsov4 = map4->type_def.cipsov4; | 217 | cipsov4 = map4->def.cipso; |
| 218 | netlbl_af4list_audit_addr(audit_buf, 0, NULL, | 218 | netlbl_af4list_audit_addr(audit_buf, 0, NULL, |
| 219 | addr4->addr, addr4->mask); | 219 | addr4->addr, addr4->mask); |
| 220 | #if IS_ENABLED(CONFIG_IPV6) | 220 | #if IS_ENABLED(CONFIG_IPV6) |
| 221 | } else if (addr6 != NULL) { | 221 | } else if (addr6 != NULL) { |
| 222 | struct netlbl_domaddr6_map *map6; | 222 | struct netlbl_domaddr6_map *map6; |
| 223 | map6 = netlbl_domhsh_addr6_entry(addr6); | 223 | map6 = netlbl_domhsh_addr6_entry(addr6); |
| 224 | type = map6->type; | 224 | type = map6->def.type; |
| 225 | netlbl_af6list_audit_addr(audit_buf, 0, NULL, | 225 | netlbl_af6list_audit_addr(audit_buf, 0, NULL, |
| 226 | &addr6->addr, &addr6->mask); | 226 | &addr6->addr, &addr6->mask); |
| 227 | #endif /* IPv6 */ | 227 | #endif /* IPv6 */ |
| 228 | } else { | 228 | } else { |
| 229 | type = entry->type; | 229 | type = entry->def.type; |
| 230 | cipsov4 = entry->type_def.cipsov4; | 230 | cipsov4 = entry->def.cipso; |
| 231 | } | 231 | } |
| 232 | switch (type) { | 232 | switch (type) { |
| 233 | case NETLBL_NLTYPE_UNLABELED: | 233 | case NETLBL_NLTYPE_UNLABELED: |
| @@ -265,26 +265,25 @@ static int netlbl_domhsh_validate(const struct netlbl_dom_map *entry) | |||
| 265 | if (entry == NULL) | 265 | if (entry == NULL) |
| 266 | return -EINVAL; | 266 | return -EINVAL; |
| 267 | 267 | ||
| 268 | switch (entry->type) { | 268 | switch (entry->def.type) { |
| 269 | case NETLBL_NLTYPE_UNLABELED: | 269 | case NETLBL_NLTYPE_UNLABELED: |
| 270 | if (entry->type_def.cipsov4 != NULL || | 270 | if (entry->def.cipso != NULL || entry->def.addrsel != NULL) |
| 271 | entry->type_def.addrsel != NULL) | ||
| 272 | return -EINVAL; | 271 | return -EINVAL; |
| 273 | break; | 272 | break; |
| 274 | case NETLBL_NLTYPE_CIPSOV4: | 273 | case NETLBL_NLTYPE_CIPSOV4: |
| 275 | if (entry->type_def.cipsov4 == NULL) | 274 | if (entry->def.cipso == NULL) |
| 276 | return -EINVAL; | 275 | return -EINVAL; |
| 277 | break; | 276 | break; |
| 278 | case NETLBL_NLTYPE_ADDRSELECT: | 277 | case NETLBL_NLTYPE_ADDRSELECT: |
| 279 | netlbl_af4list_foreach(iter4, &entry->type_def.addrsel->list4) { | 278 | netlbl_af4list_foreach(iter4, &entry->def.addrsel->list4) { |
| 280 | map4 = netlbl_domhsh_addr4_entry(iter4); | 279 | map4 = netlbl_domhsh_addr4_entry(iter4); |
| 281 | switch (map4->type) { | 280 | switch (map4->def.type) { |
| 282 | case NETLBL_NLTYPE_UNLABELED: | 281 | case NETLBL_NLTYPE_UNLABELED: |
| 283 | if (map4->type_def.cipsov4 != NULL) | 282 | if (map4->def.cipso != NULL) |
| 284 | return -EINVAL; | 283 | return -EINVAL; |
| 285 | break; | 284 | break; |
| 286 | case NETLBL_NLTYPE_CIPSOV4: | 285 | case NETLBL_NLTYPE_CIPSOV4: |
| 287 | if (map4->type_def.cipsov4 == NULL) | 286 | if (map4->def.cipso == NULL) |
| 288 | return -EINVAL; | 287 | return -EINVAL; |
| 289 | break; | 288 | break; |
| 290 | default: | 289 | default: |
| @@ -292,9 +291,9 @@ static int netlbl_domhsh_validate(const struct netlbl_dom_map *entry) | |||
| 292 | } | 291 | } |
| 293 | } | 292 | } |
| 294 | #if IS_ENABLED(CONFIG_IPV6) | 293 | #if IS_ENABLED(CONFIG_IPV6) |
| 295 | netlbl_af6list_foreach(iter6, &entry->type_def.addrsel->list6) { | 294 | netlbl_af6list_foreach(iter6, &entry->def.addrsel->list6) { |
| 296 | map6 = netlbl_domhsh_addr6_entry(iter6); | 295 | map6 = netlbl_domhsh_addr6_entry(iter6); |
| 297 | switch (map6->type) { | 296 | switch (map6->def.type) { |
| 298 | case NETLBL_NLTYPE_UNLABELED: | 297 | case NETLBL_NLTYPE_UNLABELED: |
| 299 | break; | 298 | break; |
| 300 | default: | 299 | default: |
| @@ -402,32 +401,31 @@ int netlbl_domhsh_add(struct netlbl_dom_map *entry, | |||
| 402 | rcu_assign_pointer(netlbl_domhsh_def, entry); | 401 | rcu_assign_pointer(netlbl_domhsh_def, entry); |
| 403 | } | 402 | } |
| 404 | 403 | ||
| 405 | if (entry->type == NETLBL_NLTYPE_ADDRSELECT) { | 404 | if (entry->def.type == NETLBL_NLTYPE_ADDRSELECT) { |
| 406 | netlbl_af4list_foreach_rcu(iter4, | 405 | netlbl_af4list_foreach_rcu(iter4, |
| 407 | &entry->type_def.addrsel->list4) | 406 | &entry->def.addrsel->list4) |
| 408 | netlbl_domhsh_audit_add(entry, iter4, NULL, | 407 | netlbl_domhsh_audit_add(entry, iter4, NULL, |
| 409 | ret_val, audit_info); | 408 | ret_val, audit_info); |
| 410 | #if IS_ENABLED(CONFIG_IPV6) | 409 | #if IS_ENABLED(CONFIG_IPV6) |
| 411 | netlbl_af6list_foreach_rcu(iter6, | 410 | netlbl_af6list_foreach_rcu(iter6, |
| 412 | &entry->type_def.addrsel->list6) | 411 | &entry->def.addrsel->list6) |
| 413 | netlbl_domhsh_audit_add(entry, NULL, iter6, | 412 | netlbl_domhsh_audit_add(entry, NULL, iter6, |
| 414 | ret_val, audit_info); | 413 | ret_val, audit_info); |
| 415 | #endif /* IPv6 */ | 414 | #endif /* IPv6 */ |
| 416 | } else | 415 | } else |
| 417 | netlbl_domhsh_audit_add(entry, NULL, NULL, | 416 | netlbl_domhsh_audit_add(entry, NULL, NULL, |
| 418 | ret_val, audit_info); | 417 | ret_val, audit_info); |
| 419 | } else if (entry_old->type == NETLBL_NLTYPE_ADDRSELECT && | 418 | } else if (entry_old->def.type == NETLBL_NLTYPE_ADDRSELECT && |
| 420 | entry->type == NETLBL_NLTYPE_ADDRSELECT) { | 419 | entry->def.type == NETLBL_NLTYPE_ADDRSELECT) { |
| 421 | struct list_head *old_list4; | 420 | struct list_head *old_list4; |
| 422 | struct list_head *old_list6; | 421 | struct list_head *old_list6; |
| 423 | 422 | ||
