Merge branch 'next' of git://git.infradead.org/users/pcmoore/selinux into next
authorJames Morris <james.l.morris@oracle.com>
Sat, 2 Aug 2014 12:58:02 +0000 (22:58 +1000)
committerJames Morris <james.l.morris@oracle.com>
Sat, 2 Aug 2014 12:58:02 +0000 (22:58 +1000)
include/net/netlabel.h
net/ipv4/cipso_ipv4.c
net/netlabel/netlabel_kapi.c
security/selinux/ss/ebitmap.c
security/selinux/ss/ebitmap.h
security/smack/smack_access.c
security/smack/smack_lsm.c
security/smack/smackfs.c

index 4fe018c48ed9fc796545e172cba8e2cea62f21ff..a4fc39bb3e4fc1eedd7fc6be183be96a734d941e 100644 (file)
@@ -139,7 +139,7 @@ struct netlbl_lsm_cache {
 };
 
 /**
- * struct netlbl_lsm_secattr_catmap - NetLabel LSM secattr category bitmap
+ * struct netlbl_lsm_catmap - NetLabel LSM secattr category bitmap
  * @startbit: the value of the lowest order bit in the bitmap
  * @bitmap: the category bitmap
  * @next: pointer to the next bitmap "node" or NULL
@@ -162,10 +162,10 @@ struct netlbl_lsm_cache {
 #define NETLBL_CATMAP_SIZE              (NETLBL_CATMAP_MAPSIZE * \
                                         NETLBL_CATMAP_MAPCNT)
 #define NETLBL_CATMAP_BIT               (NETLBL_CATMAP_MAPTYPE)0x01
-struct netlbl_lsm_secattr_catmap {
+struct netlbl_lsm_catmap {
        u32 startbit;
        NETLBL_CATMAP_MAPTYPE bitmap[NETLBL_CATMAP_MAPCNT];
-       struct netlbl_lsm_secattr_catmap *next;
+       struct netlbl_lsm_catmap *next;
 };
 
 /**
@@ -209,7 +209,7 @@ struct netlbl_lsm_secattr {
        struct netlbl_lsm_cache *cache;
        struct {
                struct {
-                       struct netlbl_lsm_secattr_catmap *cat;
+                       struct netlbl_lsm_catmap *cat;
                        u32 lvl;
                } mls;
                u32 secid;
@@ -258,7 +258,7 @@ static inline void netlbl_secattr_cache_free(struct netlbl_lsm_cache *cache)
 }
 
 /**
- * netlbl_secattr_catmap_alloc - Allocate a LSM secattr catmap
+ * netlbl_catmap_alloc - Allocate a LSM secattr catmap
  * @flags: memory allocation flags
  *
  * Description:
@@ -266,30 +266,28 @@ static inline void netlbl_secattr_cache_free(struct netlbl_lsm_cache *cache)
  * on failure.
  *
  */
-static inline struct netlbl_lsm_secattr_catmap *netlbl_secattr_catmap_alloc(
-                                                                  gfp_t flags)
+static inline struct netlbl_lsm_catmap *netlbl_catmap_alloc(gfp_t flags)
 {
-       return kzalloc(sizeof(struct netlbl_lsm_secattr_catmap), flags);
+       return kzalloc(sizeof(struct netlbl_lsm_catmap), flags);
 }
 
 /**
- * netlbl_secattr_catmap_free - Free a LSM secattr catmap
+ * netlbl_catmap_free - Free a LSM secattr catmap
  * @catmap: the category bitmap
  *
  * Description:
  * Free a LSM secattr catmap.
  *
  */
-static inline void netlbl_secattr_catmap_free(
-                                     struct netlbl_lsm_secattr_catmap *catmap)
+static inline void netlbl_catmap_free(struct netlbl_lsm_catmap *catmap)
 {
-       struct netlbl_lsm_secattr_catmap *iter;
+       struct netlbl_lsm_catmap *iter;
 
-       do {
+       while (catmap) {
                iter = catmap;
                catmap = catmap->next;
                kfree(iter);
-       } while (catmap);
+       }
 }
 
 /**
@@ -321,7 +319,7 @@ static inline void netlbl_secattr_destroy(struct netlbl_lsm_secattr *secattr)
        if (secattr->flags & NETLBL_SECATTR_CACHE)
                netlbl_secattr_cache_free(secattr->cache);
        if (secattr->flags & NETLBL_SECATTR_MLS_CAT)
-               netlbl_secattr_catmap_free(secattr->attr.mls.cat);
+               netlbl_catmap_free(secattr->attr.mls.cat);
 }
 
 /**
@@ -390,17 +388,22 @@ int netlbl_cfg_cipsov4_map_add(u32 doi,
 /*
  * LSM security attribute operations
  */
-int netlbl_secattr_catmap_walk(struct netlbl_lsm_secattr_catmap *catmap,
-                              u32 offset);
-int netlbl_secattr_catmap_walk_rng(struct netlbl_lsm_secattr_catmap *catmap,
-                                  u32 offset);
-int netlbl_secattr_catmap_setbit(struct netlbl_lsm_secattr_catmap *catmap,
-                                u32 bit,
-                                gfp_t flags);
-int netlbl_secattr_catmap_setrng(struct netlbl_lsm_secattr_catmap *catmap,
-                                u32 start,
-                                u32 end,
-                                gfp_t flags);
+int netlbl_catmap_walk(struct netlbl_lsm_catmap *catmap, u32 offset);
+int netlbl_catmap_walkrng(struct netlbl_lsm_catmap *catmap, u32 offset);
+int netlbl_catmap_getlong(struct netlbl_lsm_catmap *catmap,
+                         u32 *offset,
+                         unsigned long *bitmap);
+int netlbl_catmap_setbit(struct netlbl_lsm_catmap **catmap,
+                        u32 bit,
+                        gfp_t flags);
+int netlbl_catmap_setrng(struct netlbl_lsm_catmap **catmap,
+                        u32 start,
+                        u32 end,
+                        gfp_t flags);
+int netlbl_catmap_setlong(struct netlbl_lsm_catmap **catmap,
+                         u32 offset,
+                         unsigned long bitmap,
+                         gfp_t flags);
 
 /*
  * LSM protocol operations (NetLabel LSM/kernel API)
@@ -492,30 +495,39 @@ static inline int netlbl_cfg_cipsov4_map_add(u32 doi,
 {
        return -ENOSYS;
 }
-static inline int netlbl_secattr_catmap_walk(
-                                     struct netlbl_lsm_secattr_catmap *catmap,
-                                     u32 offset)
+static inline int netlbl_catmap_walk(struct netlbl_lsm_catmap *catmap,
+                                    u32 offset)
 {
        return -ENOENT;
 }
-static inline int netlbl_secattr_catmap_walk_rng(
-                                     struct netlbl_lsm_secattr_catmap *catmap,
-                                     u32 offset)
+static inline int netlbl_catmap_walkrng(struct netlbl_lsm_catmap *catmap,
+                                       u32 offset)
 {
        return -ENOENT;
 }
-static inline int netlbl_secattr_catmap_setbit(
-                                     struct netlbl_lsm_secattr_catmap *catmap,
-                                     u32 bit,
-                                     gfp_t flags)
+static inline int netlbl_catmap_getlong(struct netlbl_lsm_catmap *catmap,
+                                       u32 *offset,
+                                       unsigned long *bitmap)
 {
        return 0;
 }
-static inline int netlbl_secattr_catmap_setrng(
-                                     struct netlbl_lsm_secattr_catmap *catmap,
-                                     u32 start,
-                                     u32 end,
-                                     gfp_t flags)
+static inline int netlbl_catmap_setbit(struct netlbl_lsm_catmap **catmap,
+                                      u32 bit,
+                                      gfp_t flags)
+{
+       return 0;
+}
+static inline int netlbl_catmap_setrng(struct netlbl_lsm_catmap **catmap,
+                                      u32 start,
+                                      u32 end,
+                                      gfp_t flags)
+{
+       return 0;
+}
+static int netlbl_catmap_setlong(struct netlbl_lsm_catmap **catmap,
+                                u32 offset,
+                                unsigned long bitmap,
+                                gfp_t flags)
 {
        return 0;
 }
index 69e77c8ff285c74a3743cd10b95cfd04a45bf687..05b708bbdb0dedd34a04d99b16391a6b2ca4a30c 100644 (file)
@@ -890,8 +890,8 @@ static int cipso_v4_map_cat_rbm_hton(const struct cipso_v4_doi *doi_def,
        }
 
        for (;;) {
-               host_spot = netlbl_secattr_catmap_walk(secattr->attr.mls.cat,
-                                                      host_spot + 1);
+               host_spot = netlbl_catmap_walk(secattr->attr.mls.cat,
+                                              host_spot + 1);
                if (host_spot < 0)
                        break;
 
@@ -973,7 +973,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->attr.mls.cat,
+               ret_val = netlbl_catmap_setbit(&secattr->attr.mls.cat,
                                                       host_spot,
                                                       GFP_ATOMIC);
                if (ret_val != 0)
@@ -1039,8 +1039,7 @@ 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->attr.mls.cat,
-                                                cat + 1);
+               cat = netlbl_catmap_walk(secattr->attr.mls.cat, cat + 1);
                if (cat < 0)
                        break;
                if ((cat_iter + 2) > net_cat_len)
@@ -1075,9 +1074,9 @@ 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->attr.mls.cat,
-                               get_unaligned_be16(&net_cat[iter]),
-                               GFP_ATOMIC);
+               ret_val = netlbl_catmap_setbit(&secattr->attr.mls.cat,
+                                            get_unaligned_be16(&net_cat[iter]),
+                                            GFP_ATOMIC);
                if (ret_val != 0)
                        return ret_val;
        }
@@ -1155,8 +1154,7 @@ static int cipso_v4_map_cat_rng_hton(const struct cipso_v4_doi *doi_def,
                return -ENOSPC;
 
        for (;;) {
-               iter = netlbl_secattr_catmap_walk(secattr->attr.mls.cat,
-                                                 iter + 1);
+               iter = netlbl_catmap_walk(secattr->attr.mls.cat, iter + 1);
                if (iter < 0)
                        break;
                cat_size += (iter == 0 ? 0 : sizeof(u16));
@@ -1164,8 +1162,7 @@ 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->attr.mls.cat,
-                                                     iter);
+               iter = netlbl_catmap_walkrng(secattr->attr.mls.cat, iter);
                if (iter < 0)
                        return -EFAULT;
                cat_size += sizeof(u16);
@@ -1217,10 +1214,10 @@ 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->attr.mls.cat,
-                                                      cat_low,
-                                                      cat_high,
-                                                      GFP_ATOMIC);
+               ret_val = netlbl_catmap_setrng(&secattr->attr.mls.cat,
+                                              cat_low,
+                                              cat_high,
+                                              GFP_ATOMIC);
                if (ret_val != 0)
                        return ret_val;
        }
@@ -1335,16 +1332,12 @@ static int cipso_v4_parsetag_rbm(const struct cipso_v4_doi *doi_def,
        secattr->flags |= NETLBL_SECATTR_MLS_LVL;
 
        if (tag_len > 4) {
-               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,
                                                    &tag[4],
                                                    tag_len - 4,
                                                    secattr);
                if (ret_val != 0) {
-                       netlbl_secattr_catmap_free(secattr->attr.mls.cat);
+                       netlbl_catmap_free(secattr->attr.mls.cat);
                        return ret_val;
                }
 
@@ -1430,16 +1423,12 @@ static int cipso_v4_parsetag_enum(const struct cipso_v4_doi *doi_def,
        secattr->flags |= NETLBL_SECATTR_MLS_LVL;
 
        if (tag_len > 4) {
-               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,
                                                     &tag[4],
                                                     tag_len - 4,
                                                     secattr);
                if (ret_val != 0) {
-                       netlbl_secattr_catmap_free(secattr->attr.mls.cat);
+                       netlbl_catmap_free(secattr->attr.mls.cat);
                        return ret_val;
                }
 
@@ -1524,16 +1513,12 @@ static int cipso_v4_parsetag_rng(const struct cipso_v4_doi *doi_def,
        secattr->flags |= NETLBL_SECATTR_MLS_LVL;
 
        if (tag_len > 4) {
-               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,
                                                    &tag[4],
                                                    tag_len - 4,
                                                    secattr);
                if (ret_val != 0) {
-                       netlbl_secattr_catmap_free(secattr->attr.mls.cat);
+                       netlbl_catmap_free(secattr->attr.mls.cat);
                        return ret_val;
                }
 
index 3045a964f39c82152574ef4479e01a0254c88f5a..05ea4a4cc0ac8d58af0b7eed95dc76ad8d2e22c5 100644 (file)
@@ -405,8 +405,72 @@ out_entry:
  * Security Attribute Functions
  */
 
+#define _CM_F_NONE     0x00000000
+#define _CM_F_ALLOC    0x00000001
+#define _CM_F_WALK     0x00000002
+
 /**
- * netlbl_secattr_catmap_walk - Walk a LSM secattr catmap looking for a bit
+ * _netlbl_catmap_getnode - Get a individual node from a catmap
+ * @catmap: pointer to the category bitmap
+ * @offset: the requested offset
+ * @cm_flags: catmap flags, see _CM_F_*
+ * @gfp_flags: memory allocation flags
+ *
+ * Description:
+ * Iterate through the catmap looking for the node associated with @offset.
+ * If the _CM_F_ALLOC flag is set in @cm_flags and there is no associated node,
+ * one will be created and inserted into the catmap.  If the _CM_F_WALK flag is
+ * set in @cm_flags and there is no associated node, the next highest node will
+ * be returned.  Returns a pointer to the node on success, NULL on failure.
+ *
+ */
+static struct netlbl_lsm_catmap *_netlbl_catmap_getnode(
+                                            struct netlbl_lsm_catmap **catmap,
+                                            u32 offset,
+                                            unsigned int cm_flags,
+                                            gfp_t gfp_flags)
+{
+       struct netlbl_lsm_catmap *iter = *catmap;
+       struct netlbl_lsm_catmap *prev = NULL;
+
+       if (iter == NULL)
+               goto catmap_getnode_alloc;
+       if (offset < iter->startbit)
+               goto catmap_getnode_walk;
+       while (iter && offset >= (iter->startbit + NETLBL_CATMAP_SIZE)) {
+               prev = iter;
+               iter = iter->next;
+       }
+       if (iter == NULL || offset < iter->startbit)
+               goto catmap_getnode_walk;
+
+       return iter;
+
+catmap_getnode_walk:
+       if (cm_flags & _CM_F_WALK)
+               return iter;
+catmap_getnode_alloc:
+       if (!(cm_flags & _CM_F_ALLOC))
+               return NULL;
+
+       iter = netlbl_catmap_alloc(gfp_flags);
+       if (iter == NULL)
+               return NULL;
+       iter->startbit = offset & ~(NETLBL_CATMAP_SIZE - 1);
+
+       if (prev == NULL) {
+               iter->next = *catmap;
+               *catmap = iter;
+       } else {
+               iter->next = prev->next;
+               prev->next = iter;
+       }
+
+       return iter;
+}
+
+/**
+ * netlbl_catmap_walk - Walk a LSM secattr catmap looking for a bit
  * @catmap: the category bitmap
  * @offset: the offset to start searching at, in bits
  *
@@ -415,54 +479,51 @@ out_entry:
  * returns the spot of the first set bit or -ENOENT if no bits are set.
  *
  */
-int netlbl_secattr_catmap_walk(struct netlbl_lsm_secattr_catmap *catmap,
-                              u32 offset)
+int netlbl_catmap_walk(struct netlbl_lsm_catmap *catmap, u32 offset)
 {
-       struct netlbl_lsm_secattr_catmap *iter = catmap;
-       u32 node_idx;
-       u32 node_bit;
+       struct netlbl_lsm_catmap *iter = catmap;
+       u32 idx;
+       u32 bit;
        NETLBL_CATMAP_MAPTYPE bitmap;
 
+       iter = _netlbl_catmap_getnode(&catmap, offset, _CM_F_WALK, 0);
+       if (iter == NULL)
+               return -ENOENT;
        if (offset > iter->startbit) {
-               while (offset >= (iter->startbit + NETLBL_CATMAP_SIZE)) {
-                       iter = iter->next;
-                       if (iter == NULL)
-                               return -ENOENT;
-               }
-               node_idx = (offset - iter->startbit) / NETLBL_CATMAP_MAPSIZE;
-               node_bit = offset - iter->startbit -
-                          (NETLBL_CATMAP_MAPSIZE * node_idx);
+               offset -= iter->startbit;
+               idx = offset / NETLBL_CATMAP_MAPSIZE;
+               bit = offset % NETLBL_CATMAP_MAPSIZE;
        } else {
-               node_idx = 0;
-               node_bit = 0;
+               idx = 0;
+               bit = 0;
        }
-       bitmap = iter->bitmap[node_idx] >> node_bit;
+       bitmap = iter->bitmap[idx] >> bit;
 
        for (;;) {
                if (bitmap != 0) {
                        while ((bitmap & NETLBL_CATMAP_BIT) == 0) {
                                bitmap >>= 1;
-                               node_bit++;
+                               bit++;
                        }
                        return iter->startbit +
-                               (NETLBL_CATMAP_MAPSIZE * node_idx) + node_bit;
+                              (NETLBL_CATMAP_MAPSIZE * idx) + bit;
                }
-               if (++node_idx >= NETLBL_CATMAP_MAPCNT) {
+               if (++idx >= NETLBL_CATMAP_MAPCNT) {
                        if (iter->next != NULL) {
                                iter = iter->next;
-                               node_idx = 0;
+                               idx = 0;
                        } else
                                return -ENOENT;
                }
-               bitmap = iter->bitmap[node_idx];
-               node_bit = 0;
+               bitmap = iter->bitmap[idx];
+               bit = 0;
        }
 
        return -ENOENT;
 }
 
 /**
- * netlbl_secattr_catmap_walk_rng - Find the end of a string of set bits
+ * netlbl_catmap_walkrng - Find the end of a string of set bits
  * @catmap: the category bitmap
  * @offset: the offset to start searching at, in bits
  *
@@ -472,57 +533,105 @@ int netlbl_secattr_catmap_walk(struct netlbl_lsm_secattr_catmap *catmap,
  * the end of the bitmap.
  *
  */
-int netlbl_secattr_catmap_walk_rng(struct netlbl_lsm_secattr_catmap *catmap,
-                                  u32 offset)
+int netlbl_catmap_walkrng(struct netlbl_lsm_catmap *catmap, u32 offset)
 {
-       struct netlbl_lsm_secattr_catmap *iter = catmap;
-       u32 node_idx;
-       u32 node_bit;
+       struct netlbl_lsm_catmap *iter;
+       struct netlbl_lsm_catmap *prev = NULL;
+       u32 idx;
+       u32 bit;
        NETLBL_CATMAP_MAPTYPE bitmask;
        NETLBL_CATMAP_MAPTYPE bitmap;
 
+       iter = _netlbl_catmap_getnode(&catmap, offset, _CM_F_WALK, 0);
+       if (iter == NULL)
+               return -ENOENT;
        if (offset > iter->startbit) {
-               while (offset >= (iter->startbit + NETLBL_CATMAP_SIZE)) {
-                       iter = iter->next;
-                       if (iter == NULL)
-                               return -ENOENT;
-               }
-               node_idx = (offset - iter->startbit) / NETLBL_CATMAP_MAPSIZE;
-               node_bit = offset - iter->startbit -
-                          (NETLBL_CATMAP_MAPSIZE * node_idx);
+               offset -= iter->startbit;
+               idx = offset / NETLBL_CATMAP_MAPSIZE;
+               bit = offset % NETLBL_CATMAP_MAPSIZE;
        } else {
-               node_idx = 0;
-               node_bit = 0;
+               idx = 0;
+               bit = 0;
        }
-       bitmask = NETLBL_CATMAP_BIT << node_bit;
+       bitmask = NETLBL_CATMAP_BIT << bit;
 
        for (;;) {
-               bitmap = iter->bitmap[node_idx];
+               bitmap = iter->bitmap[idx];
                while (bitmask != 0 && (bitmap & bitmask) != 0) {
                        bitmask <<= 1;
-                       node_bit++;
+                       bit++;
                }
 
-               if (bitmask != 0)
+               if (prev && idx == 0 && bit == 0)
+                       return prev->startbit + NETLBL_CATMAP_SIZE - 1;
+               else if (bitmask != 0)
                        return iter->startbit +
-                               (NETLBL_CATMAP_MAPSIZE * node_idx) +
-                               node_bit - 1;
-               else if (++node_idx >= NETLBL_CATMAP_MAPCNT) {
+                               (NETLBL_CATMAP_MAPSIZE * idx) + bit - 1;
+               else if (++idx >= NETLBL_CATMAP_MAPCNT) {
                        if (iter->next == NULL)
-                               return iter->startbit + NETLBL_CATMAP_SIZE - 1;
+                               return iter->startbit + NETLBL_CATMAP_SIZE - 1;
+                       prev = iter;
                        iter = iter->next;
-                       node_idx = 0;
+                       idx = 0;
                }
                bitmask = NETLBL_CATMAP_BIT;
-               node_bit = 0;
+               bit = 0;
        }
 
        return -ENOENT;
 }
 
 /**
- * netlbl_secattr_catmap_setbit - Set a bit in a LSM secattr catmap
- * @catmap: the category bitmap
+ * netlbl_catmap_getlong - Export an unsigned long bitmap
+ * @catmap: pointer to the category bitmap
+ * @offset: pointer to the requested offset
+ * @bitmap: the exported bitmap
+ *
+ * Description:
+ * Export a bitmap with an offset greater than or equal to @offset and return
+ * it in @bitmap.  The @offset must be aligned to an unsigned long and will be
+ * updated on return if different from what was requested; if the catmap is
+ * empty at the requested offset and beyond, the @offset is set to (u32)-1.
+ * Returns zero on sucess, negative values on failure.
+ *
+ */
+int netlbl_catmap_getlong(struct netlbl_lsm_catmap *catmap,
+                         u32 *offset,
+                         unsigned long *bitmap)
+{
+       struct netlbl_lsm_catmap *iter;
+       u32 off = *offset;
+       u32 idx;
+
+       /* only allow aligned offsets */
+       if ((off & (BITS_PER_LONG - 1)) != 0)
+               return -EINVAL;
+
+       if (off < catmap->startbit) {
+               off = catmap->startbit;
+               *offset = off;
+       }
+       iter = _netlbl_catmap_getnode(&catmap, off, _CM_F_NONE, 0);
+       if (iter == NULL) {
+               *offset = (u32)-1;
+               return 0;
+       }
+
+       if (off < iter->startbit) {
+               off = iter->startbit;
+               *offset = off;
+       } else
+               off -= iter->startbit;
+
+       idx = off / NETLBL_CATMAP_MAPSIZE;
+       *bitmap = iter->bitmap[idx] >> (off % NETLBL_CATMAP_SIZE);
+
+       return 0;
+}
+
+/**
+ * netlbl_catmap_setbit - Set a bit in a LSM secattr catmap
+ * @catmap: pointer to the category bitmap
  * @bit: the bit to set
  * @flags: memory allocation flags
  *
@@ -531,36 +640,27 @@ int netlbl_secattr_catmap_walk_rng(struct netlbl_lsm_secattr_catmap *catmap,
  * negative values on failure.
  *
  */
-int netlbl_secattr_catmap_setbit(struct netlbl_lsm_secattr_catmap *catmap,
-                                u32 bit,
-                                gfp_t flags)
+int netlbl_catmap_setbit(struct netlbl_lsm_catmap **catmap,
+                        u32 bit,
+                        gfp_t flags)
 {
-       struct netlbl_lsm_secattr_catmap *iter = catmap;
-       u32 node_bit;
-       u32 node_idx;
+       struct netlbl_lsm_catmap *iter;
+       u32 idx;
 
-       while (iter->next != NULL &&
-              bit >= (iter->startbit + NETLBL_CATMAP_SIZE))
-               iter = iter->next;
-       if (bit >= (iter->startbit + NETLBL_CATMAP_SIZE)) {
-               iter->next = netlbl_secattr_catmap_alloc(flags);
-               if (iter->next == NULL)
-                       return -ENOMEM;
-               iter = iter->next;
-               iter->startbit = bit & ~(NETLBL_CATMAP_SIZE - 1);
-       }
+       iter = _netlbl_catmap_getnode(catmap, bit, _CM_F_ALLOC, flags);
+       if (iter == NULL)
+               return -ENOMEM;
 
-       /* gcc always rounds to zero when doing integer division */
-       node_idx = (bit - iter->startbit) / NETLBL_CATMAP_MAPSIZE;
-       node_bit = bit - iter->startbit - (NETLBL_CATMAP_MAPSIZE * node_idx);
-       iter->bitmap[node_idx] |= NETLBL_CATMAP_BIT << node_bit;
+       bit -= iter->startbit;
+       idx = bit / NETLBL_CATMAP_MAPSIZE;
+       iter->bitmap[idx] |= NETLBL_CATMAP_BIT << (bit % NETLBL_CATMAP_MAPSIZE);
 
        return 0;
 }
 
 /**
- * netlbl_secattr_catmap_setrng - Set a range of bits in a LSM secattr catmap
- * @catmap: the category bitmap
+ * netlbl_catmap_setrng - Set a range of bits in a LSM secattr catmap
+ * @catmap: pointer to the category bitmap
  * @start: the starting bit
  * @end: the last bit in the string
  * @flags: memory allocation flags
@@ -570,36 +670,63 @@ int netlbl_secattr_catmap_setbit(struct netlbl_lsm_secattr_catmap *catmap,
  * on success, negative values on failure.
  *
  */
-int netlbl_secattr_catmap_setrng(struct netlbl_lsm_secattr_catmap *catmap,
-                                u32 start,
-                                u32 end,
-                                gfp_t flags)
+int netlbl_catmap_setrng(struct netlbl_lsm_catmap **catmap,
+                        u32 start,
+                        u32 end,
+                        gfp_t flags)
 {
-       int ret_val = 0;
-       struct netlbl_lsm_secattr_catmap *iter = catmap;
-       u32 iter_max_spot;
-       u32 spot;
-
-       /* XXX - This could probably be made a bit faster by combining writes
-        * to the catmap instead of setting a single bit each time, but for
-        * right now skipping to the start of the range in the catmap should
-        * be a nice improvement over calling the individual setbit function
-        * repeatedly from a loop. */
-
-       while (iter->next != NULL &&
-              start >= (iter->startbit + NETLBL_CATMAP_SIZE))
-               iter = iter->next;
-       iter_max_spot = iter->startbit + NETLBL_CATMAP_SIZE;
-
-       for (spot = start; spot <= end && ret_val == 0; spot++) {
-               if (spot >= iter_max_spot && iter->next != NULL) {
-                       iter = iter->next;
-                       iter_max_spot = iter->startbit + NETLBL_CATMAP_SIZE;
-               }
-               ret_val = netlbl_secattr_catmap_setbit(iter, spot, flags);
+       int rc = 0;
+       u32 spot = start;
+
+       while (rc == 0 && spot <= end) {
+               if (((spot & (BITS_PER_LONG - 1)) != 0) &&
+                   ((end - spot) > BITS_PER_LONG)) {
+                       rc = netlbl_catmap_setlong(catmap,
+                                                  spot,
+                                                  (unsigned long)-1,
+                                                  flags);
+                       spot += BITS_PER_LONG;
+               } else
+                       rc = netlbl_catmap_setbit(catmap, spot++, flags);
        }
 
-       return ret_val;
+       return rc;
+}
+
+/**
+ * netlbl_catmap_setlong - Import an unsigned long bitmap
+ * @catmap: pointer to the category bitmap
+ * @offset: offset to the start of the imported bitmap
+ * @bitmap: the bitmap to import
+ * @flags: memory allocation flags
+ *
+ * Description:
+ * Import the bitmap specified in @bitmap into @catmap, using the offset
+ * in @offset.  The offset must be aligned to an unsigned long.  Returns zero
+ * on success, negative values on failure.
+ *
+ */
+int netlbl_catmap_setlong(struct netlbl_lsm_catmap **catmap,
+                         u32 offset,
+                         unsigned long bitmap,
+                         gfp_t flags)
+{
+       struct netlbl_lsm_catmap *iter;
+       u32 idx;
+
+       /* only allow aligned offsets */
+       if ((offset & (BITS_PER_LONG - 1)) != 0)
+               return -EINVAL;
+
+       iter = _netlbl_catmap_getnode(catmap, offset, _CM_F_ALLOC, flags);
+       if (iter == NULL)
+               return -ENOMEM;
+
+       offset -= iter->startbit;
+       idx = offset / NETLBL_CATMAP_MAPSIZE;
+       iter->bitmap[idx] |= bitmap << (offset % NETLBL_CATMAP_MAPSIZE);
+
+       return 0;
 }
 
 /*
index 820313a04d49bf4c4a8bc0f04ea01514ff184a64..afe6a269ec177897d3a8851ae2e3cddf19688bce 100644 (file)
@@ -86,51 +86,36 @@ int ebitmap_cpy(struct ebitmap *dst, struct ebitmap *src)
  *
  */
 int ebitmap_netlbl_export(struct ebitmap *ebmap,
-                         struct netlbl_lsm_secattr_catmap **catmap)
+                         struct netlbl_lsm_catmap **catmap)
 {
        struct ebitmap_node *e_iter = ebmap->node;
-       struct netlbl_lsm_secattr_catmap *c_iter;
-       u32 cmap_idx, cmap_sft;
-       int i;
-
-       /* NetLabel's NETLBL_CATMAP_MAPTYPE is defined as an array of u64,
-        * however, it is not always compatible with an array of unsigned long
-        * in ebitmap_node.
-        * In addition, you should pay attention the following implementation
-        * assumes unsigned long has a width equal with or less than 64-bit.
-        */
+       unsigned long e_map;
+       u32 offset;
+       unsigned int iter;
+       int rc;
 
        if (e_iter == NULL) {
                *catmap = NULL;
                return 0;
        }
 
-       c_iter = netlbl_secattr_catmap_alloc(GFP_ATOMIC);
-       if (c_iter == NULL)
-               return -ENOMEM;
-       *catmap = c_iter;
-       c_iter->startbit = e_iter->startbit & ~(NETLBL_CATMAP_SIZE - 1);
+       if (*catmap != NULL)
+               netlbl_catmap_free(*catmap);
+       *catmap = NULL;
 
        while (e_iter) {
-               for (i = 0; i < EBITMAP_UNIT_NUMS; i++) {
-                       unsigned int delta, e_startbit, c_endbit;
-
-                       e_startbit = e_iter->startbit + i * EBITMAP_UNIT_SIZE;
-                       c_endbit = c_iter->startbit + NETLBL_CATMAP_SIZE;
-                       if (e_startbit >= c_endbit) {
-                               c_iter->next
-                                 = netlbl_secattr_catmap_alloc(GFP_ATOMIC);
-                               if (c_iter->next == NULL)
+               offset = e_iter->startbit;
+               for (iter = 0; iter < EBITMAP_UNIT_NUMS; iter++) {
+                       e_map = e_iter->maps[iter];
+                       if (e_map != 0) {
+                               rc = netlbl_catmap_setlong(catmap,
+                                                          offset,
+                                                          e_map,
+                                                          GFP_ATOMIC);
+                               if (rc != 0)
                                        goto netlbl_export_failure;
-                               c_iter = c_iter->next;
-                               c_iter->startbit
-                                 = e_startbit & ~(NETLBL_CATMAP_SIZE - 1);
                        }
-                       delta = e_startbit - c_iter->startbit;
-                       cmap_idx = delta / NETLBL_CATMAP_MAPSIZE;
-                       cmap_sft = delta % NETLBL_CATMAP_MAPSIZE;
-                       c_iter->bitmap[cmap_idx]
-                               |= e_iter->maps[i] << cmap_sft;
+                       offset += EBITMAP_UNIT_SIZE;
                }
                e_iter = e_iter->next;
        }
@@ -138,7 +123,7 @@ int ebitmap_netlbl_export(struct ebitmap *ebmap,
        return 0;
 
 netlbl_export_failure:
-       netlbl_secattr_catmap_free(*catmap);
+       netlbl_catmap_free(*catmap);
        return -ENOMEM;
 }
 
@@ -153,58 +138,44 @@ netlbl_export_failure:
  *
  */
 int ebitmap_netlbl_import(struct ebitmap *ebmap,
-                         struct netlbl_lsm_secattr_catmap *catmap)
+                         struct netlbl_lsm_catmap *catmap)
 {
+       int rc;
        struct ebitmap_node *e_iter = NULL;
-       struct ebitmap_node *emap_prev = NULL;
-       struct netlbl_lsm_secattr_catmap *c_iter = catmap;
-       u32 c_idx, c_pos, e_idx, e_sft;
-
-       /* NetLabel's NETLBL_CATMAP_MAPTYPE is defined as an array of u64,
-        * however, it is not always compatible with an array of unsigned long
-        * in ebitmap_node.
-        * In addition, you should pay attention the following implementation
-        * assumes unsigned long has a width equal with or less than 64-bit.
-        */
-
-       do {
-               for (c_idx = 0; c_idx < NETLBL_CATMAP_MAPCNT; c_idx++) {
-                       unsigned int delta;
-                       u64 map = c_iter->bitmap[c_idx];
-
-                       if (!map)
-                               continue;
+       struct ebitmap_node *e_prev = NULL;
+       u32 offset = 0, idx;
+       unsigned long bitmap;
+
+       for (;;) {
+               rc = netlbl_catmap_getlong(catmap, &offset, &bitmap);
+               if (rc < 0)
+                       goto netlbl_import_failure;
+               if (offset == (u32)-1)
+                       return 0;
 
-                       c_pos = c_iter->startbit
-                               + c_idx * NETLBL_CATMAP_MAPSIZE;
-                       if (!e_iter
-                           || c_pos >= e_iter->startbit + EBITMAP_SIZE) {
-                               e_iter = kzalloc(sizeof(*e_iter), GFP_ATOMIC);
-                               if (!e_iter)
-                                       goto netlbl_import_failure;
-                               e_iter->startbit
-                                       = c_pos - (c_pos % EBITMAP_SIZE);
-                               if (emap_prev == NULL)
-                                       ebmap->node = e_iter;
-                               else
-                                       emap_prev->next = e_iter;
-                               emap_prev = e_iter;
-                       }
-                       delta = c_pos - e_iter->startbit;
-                       e_idx = delta / EBITMAP_UNIT_SIZE;
-                       e_sft = delta % EBITMAP_UNIT_SIZE;
-                       while (map) {
-                               e_iter->maps[e_idx++] |= map & (-1UL);
-                               map = EBITMAP_SHIFT_UNIT_SIZE(map);
-                       }
+               if (e_iter == NULL ||
+                   offset >= e_iter->startbit + EBITMAP_SIZE) {
+                       e_prev = e_iter;
+                       e_iter = kzalloc(sizeof(*e_iter), GFP_ATOMIC);
+                       if (e_iter == NULL)
+                               goto netlbl_import_failure;
+                       e_iter->startbit = offset & ~(EBITMAP_SIZE - 1);
+                       if (e_prev == NULL)
+                               ebmap->node = e_iter;
+                       else
+                               e_prev->next = e_iter;
+                       ebmap->highbit = e_iter->startbit + EBITMAP_SIZE;
                }
-               c_iter = c_iter->next;
-       } while (c_iter);
-       if (e_iter != NULL)
-               ebmap->highbit = e_iter->startbit + EBITMAP_SIZE;
-       else
-               ebitmap_destroy(ebmap);
 
+               /* offset will always be aligned to an unsigned long */
+               idx = EBITMAP_NODE_INDEX(e_iter, offset);
+               e_iter->maps[idx] = bitmap;
+
+               /* next */
+               offset += EBITMAP_UNIT_SIZE;
+       }
+
+       /* NOTE: we should never reach this return */
        return 0;
 
 netlbl_import_failure:
index 712c8a7b8e8b879d3835b5ee3650b66baa46e106..9637b8c71085b2ea7d4e7505c6c83df9226fe16a 100644 (file)
@@ -132,17 +132,17 @@ int ebitmap_write(struct ebitmap *e, void *fp);
 
 #ifdef CONFIG_NETLABEL
 int ebitmap_netlbl_export(struct ebitmap *ebmap,
-                         struct netlbl_lsm_secattr_catmap **catmap);
+                         struct netlbl_lsm_catmap **catmap);
 int ebitmap_netlbl_import(struct ebitmap *ebmap,
-                         struct netlbl_lsm_secattr_catmap *catmap);
+                         struct netlbl_lsm_catmap *catmap);
 #else
 static inline int ebitmap_netlbl_export(struct ebitmap *ebmap,
-                               struct netlbl_lsm_secattr_catmap **catmap)
+                                       struct netlbl_lsm_catmap **catmap)
 {
        return -ENOMEM;
 }
 static inline int ebitmap_netlbl_import(struct ebitmap *ebmap,
-                               struct netlbl_lsm_secattr_catmap *catmap)
+                                       struct netlbl_lsm_catmap *catmap)
 {
        return -ENOMEM;
 }
index c062e9467b62f91cb2b975f271de60755d66248c..f97d0842e6217a3578caa85730c95ce6b5683087 100644 (file)
@@ -457,19 +457,16 @@ int smk_netlbl_mls(int level, char *catset, struct netlbl_lsm_secattr *sap,
 
        sap->flags |= NETLBL_SECATTR_MLS_CAT;
        sap->attr.mls.lvl = level;
-       sap->attr.mls.cat = netlbl_secattr_catmap_alloc(GFP_ATOMIC);
-       if (!sap->attr.mls.cat)
-               return -ENOMEM;
-       sap->attr.mls.cat->startbit = 0;
+       sap->attr.mls.cat = NULL;
 
        for (cat = 1, cp = catset, byte = 0; byte < len; cp++, byte++)
                for (m = 0x80; m != 0; m >>= 1, cat++) {
                        if ((m & *cp) == 0)
                                continue;
-                       rc = netlbl_secattr_catmap_setbit(sap->attr.mls.cat,
-                                                         cat, GFP_ATOMIC);
+                       rc = netlbl_catmap_setbit(&sap->attr.mls.cat,
+                                                 cat, GFP_ATOMIC);
                        if (rc < 0) {
-                               netlbl_secattr_catmap_free(sap->attr.mls.cat);
+                               netlbl_catmap_free(sap->attr.mls.cat);
                                return rc;
                        }
                }
index f2c30801ce413224bade6b1ba3f34fb676fd2e80..e6ab307ce86e2fc1d1d04d35d2869fe1385ea724 100644 (file)
@@ -3209,9 +3209,9 @@ static struct smack_known *smack_from_secattr(struct netlbl_lsm_secattr *sap,
                                break;
                        }
                        for (acat = -1, kcat = -1; acat == kcat; ) {
-                               acat = netlbl_secattr_catmap_walk(
-                                       sap->attr.mls.cat, acat + 1);
-                               kcat = netlbl_secattr_catmap_walk(
+                               acat = netlbl_catmap_walk(sap->attr.mls.cat,
+                                                         acat + 1);
+                               kcat = netlbl_catmap_walk(
                                        skp->smk_netlabel.attr.mls.cat,
                                        kcat + 1);
                                if (acat < 0 || kcat < 0)
index 32b248820840e76b7db365730f12a2f9eb7b29d0..3c720ff105917dcedbfda26c7814f8cc8716fa8f 100644 (file)
@@ -787,7 +787,7 @@ static int cipso_seq_show(struct seq_file *s, void *v)
        struct list_head  *list = v;
        struct smack_known *skp =
                 list_entry(list, struct smack_known, list);
-       struct netlbl_lsm_secattr_catmap *cmp = skp->smk_netlabel.attr.mls.cat;
+       struct netlbl_lsm_catmap *cmp = skp->smk_netlabel.attr.mls.cat;
        char sep = '/';
        int i;
 
@@ -804,8 +804,8 @@ static int cipso_seq_show(struct seq_file *s, void *v)
 
        seq_printf(s, "%s %3d", skp->smk_known, skp->smk_netlabel.attr.mls.lvl);
 
-       for (i = netlbl_secattr_catmap_walk(cmp, 0); i >= 0;
-            i = netlbl_secattr_catmap_walk(cmp, i + 1)) {
+       for (i = netlbl_catmap_walk(cmp, 0); i >= 0;
+            i = netlbl_catmap_walk(cmp, i + 1)) {
                seq_printf(s, "%c%d", sep, i);
                sep = ',';
        }
@@ -926,7 +926,7 @@ static ssize_t smk_set_cipso(struct file *file, const char __user *buf,
 
        rc = smk_netlbl_mls(maplevel, mapcatset, &ncats, SMK_CIPSOLEN);
        if (rc >= 0) {
-               netlbl_secattr_catmap_free(skp->smk_netlabel.attr.mls.cat);
+               netlbl_catmap_free(skp->smk_netlabel.attr.mls.cat);
                skp->smk_netlabel.attr.mls.cat = ncats.attr.mls.cat;
                skp->smk_netlabel.attr.mls.lvl = ncats.attr.mls.lvl;
                rc = count;
@@ -976,14 +976,14 @@ static int cipso2_seq_show(struct seq_file *s, void *v)
        struct list_head  *list = v;
        struct smack_known *skp =
                 list_entry(list, struct smack_known, list);
-       struct netlbl_lsm_secattr_catmap *cmp = skp->smk_netlabel.attr.mls.cat;
+       struct netlbl_lsm_catmap *cmp = skp->smk_netlabel.attr.mls.cat;
        char sep = '/';
        int i;
 
        seq_printf(s, "%s %3d", skp->smk_known, skp->smk_netlabel.attr.mls.lvl);
 
-       for (i = netlbl_secattr_catmap_walk(cmp, 0); i >= 0;
-            i = netlbl_secattr_catmap_walk(cmp, i + 1)) {
+       for (i = netlbl_catmap_walk(cmp, 0); i >= 0;
+            i = netlbl_catmap_walk(cmp, i + 1)) {
                seq_printf(s, "%c%d", sep, i);
                sep = ',';
        }