aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/cipso_ipv4.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv4/cipso_ipv4.c')
-rw-r--r--net/ipv4/cipso_ipv4.c47
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
48struct cipso_v4_domhsh_entry { 49struct 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 */
194static void cipso_v4_cache_entry_free(struct cipso_v4_map_cache_entry *entry) 196static 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) {