]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - net/ipv4/cipso_ipv4.c
[TCP]: TCP_DEFER_ACCEPT updates - process as established
[linux-2.6-omap-h63xx.git] / net / ipv4 / cipso_ipv4.c
index ab56a052ce31cb53e873df670a4afdc8dc68972a..8cd357f41283504f98e55d7a3ffe2d9090dbcd38 100644 (file)
@@ -63,7 +63,7 @@ struct cipso_v4_domhsh_entry {
  * probably be turned into a hash table or something similar so we
  * can do quick lookups. */
 static DEFINE_SPINLOCK(cipso_v4_doi_list_lock);
-static struct list_head cipso_v4_doi_list = LIST_HEAD_INIT(cipso_v4_doi_list);
+static LIST_HEAD(cipso_v4_doi_list);
 
 /* Label mapping cache */
 int cipso_v4_cache_enabled = 1;
@@ -348,6 +348,7 @@ static int cipso_v4_cache_check(const unsigned char *key,
                        atomic_inc(&entry->lsm_data->refcount);
                        secattr->cache = entry->lsm_data;
                        secattr->flags |= NETLBL_SECATTR_CACHE;
+                       secattr->type = NETLBL_NLTYPE_CIPSOV4;
                        if (prev_entry == NULL) {
                                spin_unlock_bh(&cipso_v4_cache[bkt].lock);
                                return 0;
@@ -504,22 +505,16 @@ int cipso_v4_doi_add(struct cipso_v4_doi *doi_def)
        INIT_RCU_HEAD(&doi_def->rcu);
        INIT_LIST_HEAD(&doi_def->dom_list);
 
-       rcu_read_lock();
-       if (cipso_v4_doi_search(doi_def->doi) != NULL)
-               goto doi_add_failure_rlock;
        spin_lock(&cipso_v4_doi_list_lock);
        if (cipso_v4_doi_search(doi_def->doi) != NULL)
-               goto doi_add_failure_slock;
+               goto doi_add_failure;
        list_add_tail_rcu(&doi_def->list, &cipso_v4_doi_list);
        spin_unlock(&cipso_v4_doi_list_lock);
-       rcu_read_unlock();
 
        return 0;
 
-doi_add_failure_slock:
+doi_add_failure:
        spin_unlock(&cipso_v4_doi_list_lock);
-doi_add_failure_rlock:
-       rcu_read_unlock();
        return -EEXIST;
 }
 
@@ -543,29 +538,23 @@ int cipso_v4_doi_remove(u32 doi,
        struct cipso_v4_doi *doi_def;
        struct cipso_v4_domhsh_entry *dom_iter;
 
-       rcu_read_lock();
-       if (cipso_v4_doi_search(doi) != NULL) {
-               spin_lock(&cipso_v4_doi_list_lock);
-               doi_def = cipso_v4_doi_search(doi);
-               if (doi_def == NULL) {
-                       spin_unlock(&cipso_v4_doi_list_lock);
-                       rcu_read_unlock();
-                       return -ENOENT;
-               }
+       spin_lock(&cipso_v4_doi_list_lock);
+       doi_def = cipso_v4_doi_search(doi);
+       if (doi_def != NULL) {
                doi_def->valid = 0;
                list_del_rcu(&doi_def->list);
                spin_unlock(&cipso_v4_doi_list_lock);
+               rcu_read_lock();
                list_for_each_entry_rcu(dom_iter, &doi_def->dom_list, list)
                        if (dom_iter->valid)
-                               netlbl_domhsh_remove(dom_iter->domain,
-                                                    audit_info);
-               cipso_v4_cache_invalidate();
+                               netlbl_cfg_map_del(dom_iter->domain,
+                                                  audit_info);
                rcu_read_unlock();
-
+               cipso_v4_cache_invalidate();
                call_rcu(&doi_def->rcu, callback);
                return 0;
        }
-       rcu_read_unlock();
+       spin_unlock(&cipso_v4_doi_list_lock);
 
        return -ENOENT;
 }
@@ -653,22 +642,19 @@ int cipso_v4_doi_domhsh_add(struct cipso_v4_doi *doi_def, const char *domain)
        new_dom->valid = 1;
        INIT_RCU_HEAD(&new_dom->rcu);
 
-       rcu_read_lock();
        spin_lock(&cipso_v4_doi_list_lock);
-       list_for_each_entry_rcu(iter, &doi_def->dom_list, list)
+       list_for_each_entry(iter, &doi_def->dom_list, list)
                if (iter->valid &&
                    ((domain != NULL && iter->domain != NULL &&
                      strcmp(iter->domain, domain) == 0) ||
                     (domain == NULL && iter->domain == NULL))) {
                        spin_unlock(&cipso_v4_doi_list_lock);
-                       rcu_read_unlock();
                        kfree(new_dom->domain);
                        kfree(new_dom);
                        return -EEXIST;
                }
        list_add_tail_rcu(&new_dom->list, &doi_def->dom_list);
        spin_unlock(&cipso_v4_doi_list_lock);
-       rcu_read_unlock();
 
        return 0;
 }
@@ -689,9 +675,8 @@ int cipso_v4_doi_domhsh_remove(struct cipso_v4_doi *doi_def,
 {
        struct cipso_v4_domhsh_entry *iter;
 
-       rcu_read_lock();
        spin_lock(&cipso_v4_doi_list_lock);
-       list_for_each_entry_rcu(iter, &doi_def->dom_list, list)
+       list_for_each_entry(iter, &doi_def->dom_list, list)
                if (iter->valid &&
                    ((domain != NULL && iter->domain != NULL &&
                      strcmp(iter->domain, domain) == 0) ||
@@ -699,13 +684,10 @@ int cipso_v4_doi_domhsh_remove(struct cipso_v4_doi *doi_def,
                        iter->valid = 0;
                        list_del_rcu(&iter->list);
                        spin_unlock(&cipso_v4_doi_list_lock);
-                       rcu_read_unlock();
                        call_rcu(&iter->rcu, cipso_v4_doi_domhsh_free);
-
                        return 0;
                }
        spin_unlock(&cipso_v4_doi_list_lock);
-       rcu_read_unlock();
 
        return -ENOENT;
 }
@@ -884,7 +866,7 @@ static int cipso_v4_map_cat_rbm_hton(const struct cipso_v4_doi *doi_def,
        }
 
        for (;;) {
-               host_spot = netlbl_secattr_catmap_walk(secattr->mls_cat,
+               host_spot = netlbl_secattr_catmap_walk(secattr->attr.mls.cat,
                                                       host_spot + 1);
                if (host_spot < 0)
                        break;
@@ -967,7 +949,7 @@ static int cipso_v4_map_cat_rbm_ntoh(const struct cipso_v4_doi *doi_def,
                                return -EPERM;
                        break;
                }
-               ret_val = netlbl_secattr_catmap_setbit(secattr->mls_cat,
+               ret_val = netlbl_secattr_catmap_setbit(secattr->attr.mls.cat,
                                                       host_spot,
                                                       GFP_ATOMIC);
                if (ret_val != 0)
@@ -1033,7 +1015,8 @@ static int cipso_v4_map_cat_enum_hton(const struct cipso_v4_doi *doi_def,
        u32 cat_iter = 0;
 
        for (;;) {
-               cat = netlbl_secattr_catmap_walk(secattr->mls_cat, cat + 1);
+               cat = netlbl_secattr_catmap_walk(secattr->attr.mls.cat,
+                                                cat + 1);
                if (cat < 0)
                        break;
                if ((cat_iter + 2) > net_cat_len)
@@ -1068,7 +1051,7 @@ static int cipso_v4_map_cat_enum_ntoh(const struct cipso_v4_doi *doi_def,
        u32 iter;
 
        for (iter = 0; iter < net_cat_len; iter += 2) {
-               ret_val = netlbl_secattr_catmap_setbit(secattr->mls_cat,
+               ret_val = netlbl_secattr_catmap_setbit(secattr->attr.mls.cat,
                                ntohs(get_unaligned((__be16 *)&net_cat[iter])),
                                GFP_ATOMIC);
                if (ret_val != 0)
@@ -1149,7 +1132,8 @@ static int cipso_v4_map_cat_rng_hton(const struct cipso_v4_doi *doi_def,
                return -ENOSPC;
 
        for (;;) {
-               iter = netlbl_secattr_catmap_walk(secattr->mls_cat, iter + 1);
+               iter = netlbl_secattr_catmap_walk(secattr->attr.mls.cat,
+                                                 iter + 1);
                if (iter < 0)
                        break;
                cat_size += (iter == 0 ? 0 : sizeof(u16));
@@ -1157,7 +1141,8 @@ static int cipso_v4_map_cat_rng_hton(const struct cipso_v4_doi *doi_def,
                        return -ENOSPC;
                array[array_cnt++] = iter;
 
-               iter = netlbl_secattr_catmap_walk_rng(secattr->mls_cat, iter);
+               iter = netlbl_secattr_catmap_walk_rng(secattr->attr.mls.cat,
+                                                     iter);
                if (iter < 0)
                        return -EFAULT;
                cat_size += sizeof(u16);
@@ -1210,7 +1195,7 @@ static int cipso_v4_map_cat_rng_ntoh(const struct cipso_v4_doi *doi_def,
                else
                        cat_low = 0;
 
-               ret_val = netlbl_secattr_catmap_setrng(secattr->mls_cat,
+               ret_val = netlbl_secattr_catmap_setrng(secattr->attr.mls.cat,
                                                       cat_low,
                                                       cat_high,
                                                       GFP_ATOMIC);
@@ -1270,7 +1255,9 @@ static int cipso_v4_gentag_rbm(const struct cipso_v4_doi *doi_def,
        if ((secattr->flags & NETLBL_SECATTR_MLS_LVL) == 0)
                return -EPERM;
 
-       ret_val = cipso_v4_map_lvl_hton(doi_def, secattr->mls_lvl, &level);
+       ret_val = cipso_v4_map_lvl_hton(doi_def,
+                                       secattr->attr.mls.lvl,
+                                       &level);
        if (ret_val != 0)
                return ret_val;
 
@@ -1322,12 +1309,13 @@ static int cipso_v4_parsetag_rbm(const struct cipso_v4_doi *doi_def,
        ret_val = cipso_v4_map_lvl_ntoh(doi_def, tag[3], &level);
        if (ret_val != 0)
                return ret_val;
-       secattr->mls_lvl = level;
+       secattr->attr.mls.lvl = level;
        secattr->flags |= NETLBL_SECATTR_MLS_LVL;
 
        if (tag_len > 4) {
-               secattr->mls_cat = netlbl_secattr_catmap_alloc(GFP_ATOMIC);
-               if (secattr->mls_cat == NULL)
+               secattr->attr.mls.cat =
+                                      netlbl_secattr_catmap_alloc(GFP_ATOMIC);
+               if (secattr->attr.mls.cat == NULL)
                        return -ENOMEM;
 
                ret_val = cipso_v4_map_cat_rbm_ntoh(doi_def,
@@ -1335,7 +1323,7 @@ static int cipso_v4_parsetag_rbm(const struct cipso_v4_doi *doi_def,
                                                    tag_len - 4,
                                                    secattr);
                if (ret_val != 0) {
-                       netlbl_secattr_catmap_free(secattr->mls_cat);
+                       netlbl_secattr_catmap_free(secattr->attr.mls.cat);
                        return ret_val;
                }
 
@@ -1369,7 +1357,9 @@ static int cipso_v4_gentag_enum(const struct cipso_v4_doi *doi_def,
        if (!(secattr->flags & NETLBL_SECATTR_MLS_LVL))
                return -EPERM;
 
-       ret_val = cipso_v4_map_lvl_hton(doi_def, secattr->mls_lvl, &level);
+       ret_val = cipso_v4_map_lvl_hton(doi_def,
+                                       secattr->attr.mls.lvl,
+                                       &level);
        if (ret_val != 0)
                return ret_val;
 
@@ -1415,12 +1405,13 @@ static int cipso_v4_parsetag_enum(const struct cipso_v4_doi *doi_def,
        ret_val = cipso_v4_map_lvl_ntoh(doi_def, tag[3], &level);
        if (ret_val != 0)
                return ret_val;
-       secattr->mls_lvl = level;
+       secattr->attr.mls.lvl = level;
        secattr->flags |= NETLBL_SECATTR_MLS_LVL;
 
        if (tag_len > 4) {
-               secattr->mls_cat = netlbl_secattr_catmap_alloc(GFP_ATOMIC);
-               if (secattr->mls_cat == NULL)
+               secattr->attr.mls.cat =
+                                      netlbl_secattr_catmap_alloc(GFP_ATOMIC);
+               if (secattr->attr.mls.cat == NULL)
                        return -ENOMEM;
 
                ret_val = cipso_v4_map_cat_enum_ntoh(doi_def,
@@ -1428,7 +1419,7 @@ static int cipso_v4_parsetag_enum(const struct cipso_v4_doi *doi_def,
                                                     tag_len - 4,
                                                     secattr);
                if (ret_val != 0) {
-                       netlbl_secattr_catmap_free(secattr->mls_cat);
+                       netlbl_secattr_catmap_free(secattr->attr.mls.cat);
                        return ret_val;
                }
 
@@ -1462,7 +1453,9 @@ static int cipso_v4_gentag_rng(const struct cipso_v4_doi *doi_def,
        if (!(secattr->flags & NETLBL_SECATTR_MLS_LVL))
                return -EPERM;
 
-       ret_val = cipso_v4_map_lvl_hton(doi_def, secattr->mls_lvl, &level);
+       ret_val = cipso_v4_map_lvl_hton(doi_def,
+                                       secattr->attr.mls.lvl,
+                                       &level);
        if (ret_val != 0)
                return ret_val;
 
@@ -1507,12 +1500,13 @@ static int cipso_v4_parsetag_rng(const struct cipso_v4_doi *doi_def,
        ret_val = cipso_v4_map_lvl_ntoh(doi_def, tag[3], &level);
        if (ret_val != 0)
                return ret_val;
-       secattr->mls_lvl = level;
+       secattr->attr.mls.lvl = level;
        secattr->flags |= NETLBL_SECATTR_MLS_LVL;
 
        if (tag_len > 4) {
-               secattr->mls_cat = netlbl_secattr_catmap_alloc(GFP_ATOMIC);
-               if (secattr->mls_cat == NULL)
+               secattr->attr.mls.cat =
+                                      netlbl_secattr_catmap_alloc(GFP_ATOMIC);
+               if (secattr->attr.mls.cat == NULL)
                        return -ENOMEM;
 
                ret_val = cipso_v4_map_cat_rng_ntoh(doi_def,
@@ -1520,7 +1514,7 @@ static int cipso_v4_parsetag_rng(const struct cipso_v4_doi *doi_def,
                                                    tag_len - 4,
                                                    secattr);
                if (ret_val != 0) {
-                       netlbl_secattr_catmap_free(secattr->mls_cat);
+                       netlbl_secattr_catmap_free(secattr->attr.mls.cat);
                        return ret_val;
                }
 
@@ -1831,67 +1825,76 @@ socket_setattr_failure:
 }
 
 /**
- * cipso_v4_sock_getattr - Get the security attributes from a sock
- * @sk: the sock
+ * cipso_v4_getattr - Helper function for the cipso_v4_*_getattr functions
+ * @cipso: the CIPSO v4 option
  * @secattr: the security attributes
  *
  * Description:
- * Query @sk to see if there is a CIPSO option attached to the sock and if
- * there is return the CIPSO security attributes in @secattr.  This function
- * requires that @sk be locked, or privately held, but it does not do any
- * locking itself.  Returns zero on success and negative values on failure.
+ * Inspect @cipso and return the security attributes in @secattr.  Returns zero
+ * on success and negative values on failure.
  *
  */
-int cipso_v4_sock_getattr(struct sock *sk, struct netlbl_lsm_secattr *secattr)
+static int cipso_v4_getattr(const unsigned char *cipso,
+                           struct netlbl_lsm_secattr *secattr)
 {
        int ret_val = -ENOMSG;
-       struct inet_sock *sk_inet;
-       unsigned char *cipso_ptr;
        u32 doi;
        struct cipso_v4_doi *doi_def;
 
-       sk_inet = inet_sk(sk);
-       if (sk_inet->opt == NULL || sk_inet->opt->cipso == 0)
-               return -ENOMSG;
-       cipso_ptr = sk_inet->opt->__data + sk_inet->opt->cipso -
-               sizeof(struct iphdr);
-       ret_val = cipso_v4_cache_check(cipso_ptr, cipso_ptr[1], secattr);
-       if (ret_val == 0)
-               return ret_val;
+       if (cipso_v4_cache_check(cipso, cipso[1], secattr) == 0)
+               return 0;
 
-       doi = ntohl(get_unaligned((__be32 *)&cipso_ptr[2]));
+       doi = ntohl(get_unaligned((__be32 *)&cipso[2]));
        rcu_read_lock();
        doi_def = cipso_v4_doi_search(doi);
-       if (doi_def == NULL) {
-               rcu_read_unlock();
-               return -ENOMSG;
-       }
-
+       if (doi_def == NULL)
+               goto getattr_return;
        /* XXX - This code assumes only one tag per CIPSO option which isn't
         * really a good assumption to make but since we only support the MAC
         * tags right now it is a safe assumption. */
-       switch (cipso_ptr[6]) {
+       switch (cipso[6]) {
        case CIPSO_V4_TAG_RBITMAP:
-               ret_val = cipso_v4_parsetag_rbm(doi_def,
-                                               &cipso_ptr[6],
-                                               secattr);
+               ret_val = cipso_v4_parsetag_rbm(doi_def, &cipso[6], secattr);
                break;
        case CIPSO_V4_TAG_ENUM:
-               ret_val = cipso_v4_parsetag_enum(doi_def,
-                                                &cipso_ptr[6],
-                                                secattr);
+               ret_val = cipso_v4_parsetag_enum(doi_def, &cipso[6], secattr);
                break;
        case CIPSO_V4_TAG_RANGE:
-               ret_val = cipso_v4_parsetag_rng(doi_def,
-                                               &cipso_ptr[6],
-                                               secattr);
+               ret_val = cipso_v4_parsetag_rng(doi_def, &cipso[6], secattr);
                break;
        }
-       rcu_read_unlock();
+       if (ret_val == 0)
+               secattr->type = NETLBL_NLTYPE_CIPSOV4;
 
+getattr_return:
+       rcu_read_unlock();
        return ret_val;
 }
 
+/**
+ * cipso_v4_sock_getattr - Get the security attributes from a sock
+ * @sk: the sock
+ * @secattr: the security attributes
+ *
+ * Description:
+ * Query @sk to see if there is a CIPSO option attached to the sock and if
+ * there is return the CIPSO security attributes in @secattr.  This function
+ * requires that @sk be locked, or privately held, but it does not do any
+ * locking itself.  Returns zero on success and negative values on failure.
+ *
+ */
+int cipso_v4_sock_getattr(struct sock *sk, struct netlbl_lsm_secattr *secattr)
+{
+       struct ip_options *opt;
+
+       opt = inet_sk(sk)->opt;
+       if (opt == NULL || opt->cipso == 0)
+               return -ENOMSG;
+
+       return cipso_v4_getattr(opt->__data + opt->cipso - sizeof(struct iphdr),
+                               secattr);
+}
+
 /**
  * cipso_v4_skbuff_getattr - Get the security attributes from the CIPSO option
  * @skb: the packet
@@ -1905,45 +1908,7 @@ int cipso_v4_sock_getattr(struct sock *sk, struct netlbl_lsm_secattr *secattr)
 int cipso_v4_skbuff_getattr(const struct sk_buff *skb,
                            struct netlbl_lsm_secattr *secattr)
 {
-       int ret_val = -ENOMSG;
-       unsigned char *cipso_ptr;
-       u32 doi;
-       struct cipso_v4_doi *doi_def;
-
-       cipso_ptr = CIPSO_V4_OPTPTR(skb);
-       if (cipso_v4_cache_check(cipso_ptr, cipso_ptr[1], secattr) == 0)
-               return 0;
-
-       doi = ntohl(get_unaligned((__be32 *)&cipso_ptr[2]));
-       rcu_read_lock();
-       doi_def = cipso_v4_doi_search(doi);
-       if (doi_def == NULL)
-               goto skbuff_getattr_return;
-
-       /* XXX - This code assumes only one tag per CIPSO option which isn't
-        * really a good assumption to make but since we only support the MAC
-        * tags right now it is a safe assumption. */
-       switch (cipso_ptr[6]) {
-       case CIPSO_V4_TAG_RBITMAP:
-               ret_val = cipso_v4_parsetag_rbm(doi_def,
-                                               &cipso_ptr[6],
-                                               secattr);
-               break;
-       case CIPSO_V4_TAG_ENUM:
-               ret_val = cipso_v4_parsetag_enum(doi_def,
-                                                &cipso_ptr[6],
-                                                secattr);
-               break;
-       case CIPSO_V4_TAG_RANGE:
-               ret_val = cipso_v4_parsetag_rng(doi_def,
-                                               &cipso_ptr[6],
-                                               secattr);
-               break;
-       }
-
-skbuff_getattr_return:
-       rcu_read_unlock();
-       return ret_val;
+       return cipso_v4_getattr(CIPSO_V4_OPTPTR(skb), secattr);
 }
 
 /*