]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - security/selinux/ss/ebitmap.c
Merge tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi
[karo-tx-linux.git] / security / selinux / ss / ebitmap.c
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: