diff options
Diffstat (limited to 'net/ipv4/cipso_ipv4.c')
| -rw-r--r-- | net/ipv4/cipso_ipv4.c | 47 |
1 files changed, 27 insertions, 20 deletions
diff --git a/net/ipv4/cipso_ipv4.c b/net/ipv4/cipso_ipv4.c index a8e2e879a647..6460233407c7 100644 --- a/net/ipv4/cipso_ipv4.c +++ b/net/ipv4/cipso_ipv4.c | |||
| @@ -43,6 +43,7 @@ | |||
| 43 | #include <net/tcp.h> | 43 | #include <net/tcp.h> |
| 44 | #include <net/netlabel.h> | 44 | #include <net/netlabel.h> |
| 45 | #include <net/cipso_ipv4.h> | 45 | #include <net/cipso_ipv4.h> |
| 46 | #include <asm/atomic.h> | ||
| 46 | #include <asm/bug.h> | 47 | #include <asm/bug.h> |
| 47 | 48 | ||
| 48 | struct cipso_v4_domhsh_entry { | 49 | struct cipso_v4_domhsh_entry { |
| @@ -79,7 +80,7 @@ struct cipso_v4_map_cache_entry { | |||
| 79 | unsigned char *key; | 80 | unsigned char *key; |
| 80 | size_t key_len; | 81 | size_t key_len; |
| 81 | 82 | ||
| 82 | struct netlbl_lsm_cache lsm_data; | 83 | struct netlbl_lsm_cache *lsm_data; |
| 83 | 84 | ||
| 84 | u32 activity; | 85 | u32 activity; |
| 85 | struct list_head list; | 86 | struct list_head list; |
| @@ -188,13 +189,14 @@ static void cipso_v4_doi_domhsh_free(struct rcu_head *entry) | |||
| 188 | * @entry: the entry to free | 189 | * @entry: the entry to free |
| 189 | * | 190 | * |
| 190 | * Description: | 191 | * Description: |
| 191 | * This function frees the memory associated with a cache entry. | 192 | * This function frees the memory associated with a cache entry including the |
| 193 | * LSM cache data if there are no longer any users, i.e. reference count == 0. | ||
| 192 | * | 194 | * |
| 193 | */ | 195 | */ |
| 194 | static void cipso_v4_cache_entry_free(struct cipso_v4_map_cache_entry *entry) | 196 | static void cipso_v4_cache_entry_free(struct cipso_v4_map_cache_entry *entry) |
| 195 | { | 197 | { |
| 196 | if (entry->lsm_data.free) | 198 | if (entry->lsm_data) |
| 197 | entry->lsm_data.free(entry->lsm_data.data); | 199 | netlbl_secattr_cache_free(entry->lsm_data); |
| 198 | kfree(entry->key); | 200 | kfree(entry->key); |
| 199 | kfree(entry); | 201 | kfree(entry); |
| 200 | } | 202 | } |
| @@ -315,8 +317,8 @@ static int cipso_v4_cache_check(const unsigned char *key, | |||
| 315 | entry->key_len == key_len && | 317 | entry->key_len == key_len && |
| 316 | memcmp(entry->key, key, key_len) == 0) { | 318 | memcmp(entry->key, key, key_len) == 0) { |
| 317 | entry->activity += 1; | 319 | entry->activity += 1; |
| 318 | secattr->cache.free = entry->lsm_data.free; | 320 | atomic_inc(&entry->lsm_data->refcount); |
| 319 | secattr->cache.data = entry->lsm_data.data; | 321 | secattr->cache = entry->lsm_data; |
| 320 | if (prev_entry == NULL) { | 322 | if (prev_entry == NULL) { |
| 321 | spin_unlock_bh(&cipso_v4_cache[bkt].lock); | 323 | spin_unlock_bh(&cipso_v4_cache[bkt].lock); |
| 322 | return 0; | 324 | return 0; |
| @@ -383,8 +385,8 @@ int cipso_v4_cache_add(const struct sk_buff *skb, | |||
| 383 | memcpy(entry->key, cipso_ptr, cipso_ptr_len); | 385 | memcpy(entry->key, cipso_ptr, cipso_ptr_len); |
| 384 | entry->key_len = cipso_ptr_len; | 386 | entry->key_len = cipso_ptr_len; |
| 385 | entry->hash = cipso_v4_map_cache_hash(cipso_ptr, cipso_ptr_len); | 387 | entry->hash = cipso_v4_map_cache_hash(cipso_ptr, cipso_ptr_len); |
| 386 | entry->lsm_data.free = secattr->cache.free; | 388 | atomic_inc(&secattr->cache->refcount); |
| 387 | entry->lsm_data.data = secattr->cache.data; | 389 | entry->lsm_data = secattr->cache; |
| 388 | 390 | ||
| 389 | bkt = entry->hash & (CIPSO_V4_CACHE_BUCKETBITS - 1); | 391 | bkt = entry->hash & (CIPSO_V4_CACHE_BUCKETBITS - 1); |
| 390 | spin_lock_bh(&cipso_v4_cache[bkt].lock); | 392 | spin_lock_bh(&cipso_v4_cache[bkt].lock); |
| @@ -771,13 +773,15 @@ static int cipso_v4_map_cat_rbm_valid(const struct cipso_v4_doi *doi_def, | |||
| 771 | { | 773 | { |
| 772 | int cat = -1; | 774 | int cat = -1; |
| 773 | u32 bitmap_len_bits = bitmap_len * 8; | 775 | u32 bitmap_len_bits = bitmap_len * 8; |
| 774 | u32 cipso_cat_size = doi_def->map.std->cat.cipso_size; | 776 | u32 cipso_cat_size; |
| 775 | u32 *cipso_array = doi_def->map.std->cat.cipso; | 777 | u32 *cipso_array; |
| 776 | 778 | ||
| 777 | switch (doi_def->type) { | 779 | switch (doi_def->type) { |
| 778 | case CIPSO_V4_MAP_PASS: | 780 | case CIPSO_V4_MAP_PASS: |
| 779 | return 0; | 781 | return 0; |
| 780 | case CIPSO_V4_MAP_STD: | 782 | case CIPSO_V4_MAP_STD: |
| 783 | cipso_cat_size = doi_def->map.std->cat.cipso_size; | ||
| 784 | cipso_array = doi_def->map.std->cat.cipso; | ||
| 781 | for (;;) { | 785 | for (;;) { |
| 782 | cat = cipso_v4_bitmap_walk(bitmap, | 786 | cat = cipso_v4_bitmap_walk(bitmap, |
| 783 | bitmap_len_bits, | 787 | bitmap_len_bits, |
| @@ -823,19 +827,21 @@ static int cipso_v4_map_cat_rbm_hton(const struct cipso_v4_doi *doi_def, | |||
| 823 | u32 net_spot_max = 0; | 827 | u32 net_spot_max = 0; |
| 824 | u32 host_clen_bits = host_cat_len * 8; | 828 | u32 host_clen_bits = host_cat_len * 8; |
| 825 | u32 net_clen_bits = net_cat_len * 8; | 829 | u32 net_clen_bits = net_cat_len * 8; |
| 826 | u32 host_cat_size = doi_def->map.std->cat.local_size; | 830 | u32 host_cat_size; |
| 827 | u32 *host_cat_array = doi_def->map.std->cat.local; | 831 | u32 *host_cat_array; |
| 828 | 832 | ||
| 829 | switch (doi_def->type) { | 833 | switch (doi_def->type) { |
| 830 | case CIPSO_V4_MAP_PASS: | 834 | case CIPSO_V4_MAP_PASS: |
| 831 | net_spot_max = host_cat_len - 1; | 835 | net_spot_max = host_cat_len; |
| 832 | while (net_spot_max > 0 && host_cat[net_spot_max] == 0) | 836 | while (net_spot_max > 0 && host_cat[net_spot_max - 1] == 0) |
| 833 | net_spot_max--; | 837 | net_spot_max--; |
| 834 | if (net_spot_max > net_cat_len) | 838 | if (net_spot_max > net_cat_len) |
| 835 | return -EINVAL; | 839 | return -EINVAL; |
| 836 | memcpy(net_cat, host_cat, net_spot_max); | 840 | memcpy(net_cat, host_cat, net_spot_max); |
| 837 | return net_spot_max; | 841 | return net_spot_max; |
| 838 | case CIPSO_V4_MAP_STD: | 842 | case CIPSO_V4_MAP_STD: |
| 843 | host_cat_size = doi_def->map.std->cat.local_size; | ||
| 844 | host_cat_array = doi_def->map.std->cat.local; | ||
| 839 | for (;;) { | 845 | for (;;) { |
| 840 | host_spot = cipso_v4_bitmap_walk(host_cat, | 846 | host_spot = cipso_v4_bitmap_walk(host_cat, |
| 841 | host_clen_bits, | 847 | host_clen_bits, |
| @@ -891,8 +897,8 @@ static int cipso_v4_map_cat_rbm_ntoh(const struct cipso_v4_doi *doi_def, | |||
| 891 | int net_spot = -1; | 897 | int net_spot = -1; |
| 892 | u32 net_clen_bits = net_cat_len * 8; | 898 | u32 net_clen_bits = net_cat_len * 8; |
| 893 | u32 host_clen_bits = host_cat_len * 8; | 899 | u32 host_clen_bits = host_cat_len * 8; |
| 894 | u32 net_cat_size = doi_def->map.std->cat.cipso_size; | 900 | u32 net_cat_size; |
| 895 | u32 *net_cat_array = doi_def->map.std->cat.cipso; | 901 | u32 *net_cat_array; |
| 896 | 902 | ||
| 897 | switch (doi_def->type) { | 903 | switch (doi_def->type) { |
| 898 | case CIPSO_V4_MAP_PASS: | 904 | case CIPSO_V4_MAP_PASS: |
| @@ -901,6 +907,8 @@ static int cipso_v4_map_cat_rbm_ntoh(const struct cipso_v4_doi *doi_def, | |||
| 901 | memcpy(host_cat, net_cat, net_cat_len); | 907 | memcpy(host_cat, net_cat, net_cat_len); |
| 902 | return net_cat_len; | 908 | return net_cat_len; |
| 903 | case CIPSO_V4_MAP_STD: | 909 | case CIPSO_V4_MAP_STD: |
| 910 | net_cat_size = doi_def->map.std->cat.cipso_size; | ||
| 911 | net_cat_array = doi_def->map.std->cat.cipso; | ||
| 904 | for (;;) { | 912 | for (;;) { |
| 905 | net_spot = cipso_v4_bitmap_walk(net_cat, | 913 | net_spot = cipso_v4_bitmap_walk(net_cat, |
| 906 | net_clen_bits, | 914 | net_clen_bits, |
| @@ -1299,7 +1307,8 @@ int cipso_v4_socket_setattr(const struct socket *sock, | |||
| 1299 | 1307 | ||
| 1300 | /* We can't use ip_options_get() directly because it makes a call to | 1308 | /* We can't use ip_options_get() directly because it makes a call to |
| 1301 | * ip_options_get_alloc() which allocates memory with GFP_KERNEL and | 1309 | * ip_options_get_alloc() which allocates memory with GFP_KERNEL and |
| 1302 | * we can't block here. */ | 1310 | * we won't always have CAP_NET_RAW even though we _always_ want to |
| 1311 | * set the IPOPT_CIPSO option. */ | ||
| 1303 | opt_len = (buf_len + 3) & ~3; | 1312 | opt_len = (buf_len + 3) & ~3; |
| 1304 | opt = kzalloc(sizeof(*opt) + opt_len, GFP_ATOMIC); | 1313 | opt = kzalloc(sizeof(*opt) + opt_len, GFP_ATOMIC); |
| 1305 | if (opt == NULL) { | 1314 | if (opt == NULL) { |
| @@ -1309,11 +1318,9 @@ int cipso_v4_socket_setattr(const struct socket *sock, | |||
| 1309 | memcpy(opt->__data, buf, buf_len); | 1318 | memcpy(opt->__data, buf, buf_len); |
| 1310 | opt->optlen = opt_len; | 1319 | opt->optlen = opt_len; |
| 1311 | opt->is_data = 1; | 1320 | opt->is_data = 1; |
| 1321 | opt->cipso = sizeof(struct iphdr); | ||
| 1312 | kfree(buf); | 1322 | kfree(buf); |
| 1313 | buf = NULL; | 1323 | buf = NULL; |
| 1314 | ret_val = ip_options_compile(opt, NULL); | ||
| 1315 | if (ret_val != 0) | ||
| 1316 | goto socket_setattr_failure; | ||
| 1317 | 1324 | ||
| 1318 | sk_inet = inet_sk(sk); | 1325 | sk_inet = inet_sk(sk); |
| 1319 | if (sk_inet->is_icsk) { | 1326 | if (sk_inet->is_icsk) { |
