summaryrefslogtreecommitdiffstats
path: root/security/selinux/ss/ebitmap.c
diff options
context:
space:
mode:
authorJeff Garzik <jeff@garzik.org>2006-09-24 07:52:47 +0200
committerJeff Garzik <jeff@garzik.org>2006-09-24 07:52:47 +0200
commit23930fa1cebfea6f79881c588ccd1b0781e49e3f (patch)
tree36d29e3f83661c4f5f45b6f74ac0d5f9886867a8 /security/selinux/ss/ebitmap.c
parent[libata] Delete pata_it8172 driver (diff)
parentMerge master.kernel.org:/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6 (diff)
downloadlinux-23930fa1cebfea6f79881c588ccd1b0781e49e3f.tar.xz
linux-23930fa1cebfea6f79881c588ccd1b0781e49e3f.zip
Merge branch 'master' into upstream
Diffstat (limited to 'security/selinux/ss/ebitmap.c')
-rw-r--r--security/selinux/ss/ebitmap.c140
1 files changed, 140 insertions, 0 deletions
diff --git a/security/selinux/ss/ebitmap.c b/security/selinux/ss/ebitmap.c
index 47024a6e1844..cfed1d30fa6a 100644
--- a/security/selinux/ss/ebitmap.c
+++ b/security/selinux/ss/ebitmap.c
@@ -3,6 +3,14 @@
*
* Author : Stephen Smalley, <sds@epoch.ncsc.mil>
*/
+/*
+ * Updated: Hewlett-Packard <paul.moore@hp.com>
+ *
+ * Added ebitmap_export() and ebitmap_import()
+ *
+ * (c) Copyright Hewlett-Packard Development Company, L.P., 2006
+ */
+
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/errno.h>
@@ -59,6 +67,138 @@ int ebitmap_cpy(struct ebitmap *dst, struct ebitmap *src)
return 0;
}
+/**
+ * ebitmap_export - Export an ebitmap to a unsigned char bitmap string
+ * @src: the ebitmap to export
+ * @dst: the resulting bitmap string
+ * @dst_len: length of dst in bytes
+ *
+ * Description:
+ * Allocate a buffer at least src->highbit bits long and export the extensible
+ * bitmap into the buffer. The bitmap string will be in little endian format,
+ * i.e. LSB first. The value returned in dst_len may not the true size of the
+ * buffer as the length of the buffer is rounded up to a multiple of MAPTYPE.
+ * The caller must free the buffer when finished. Returns zero on success,
+ * negative values on failure.
+ *
+ */
+int ebitmap_export(const struct ebitmap *src,
+ unsigned char **dst,
+ size_t *dst_len)
+{
+ size_t bitmap_len;
+ unsigned char *bitmap;
+ struct ebitmap_node *iter_node;
+ MAPTYPE node_val;
+ size_t bitmap_byte;
+ unsigned char bitmask;
+
+ bitmap_len = src->highbit / 8;
+ if (src->highbit % 7)
+ bitmap_len += 1;
+ if (bitmap_len == 0)
+ return -EINVAL;
+
+ bitmap = kzalloc((bitmap_len & ~(sizeof(MAPTYPE) - 1)) +
+ sizeof(MAPTYPE),
+ GFP_ATOMIC);
+ if (bitmap == NULL)
+ return -ENOMEM;
+
+ iter_node = src->node;
+ do {
+ bitmap_byte = iter_node->startbit / 8;
+ bitmask = 0x80;
+ node_val = iter_node->map;
+ do {
+ if (bitmask == 0) {
+ bitmap_byte++;
+ bitmask = 0x80;
+ }
+ if (node_val & (MAPTYPE)0x01)
+ bitmap[bitmap_byte] |= bitmask;
+ node_val >>= 1;
+ bitmask >>= 1;
+ } while (node_val > 0);
+ iter_node = iter_node->next;
+ } while (iter_node);
+
+ *dst = bitmap;
+ *dst_len = bitmap_len;
+ return 0;
+}
+
+/**
+ * ebitmap_import - Import an unsigned char bitmap string into an ebitmap
+ * @src: the bitmap string
+ * @src_len: the bitmap length in bytes
+ * @dst: the empty ebitmap
+ *
+ * Description:
+ * This function takes a little endian bitmap string in src and imports it into
+ * the ebitmap pointed to by dst. Returns zero on success, negative values on
+ * failure.
+ *
+ */
+int ebitmap_import(const unsigned char *src,
+ size_t src_len,
+ struct ebitmap *dst)
+{
+ size_t src_off = 0;
+ size_t node_limit;
+ struct ebitmap_node *node_new;
+ struct ebitmap_node *node_last = NULL;
+ u32 i_byte;
+ u32 i_bit;
+ unsigned char src_byte;
+
+ while (src_off < src_len) {
+ if (src_len - src_off >= sizeof(MAPTYPE)) {
+ if (*(MAPTYPE *)&src[src_off] == 0) {
+ src_off += sizeof(MAPTYPE);
+ continue;
+ }
+ node_limit = sizeof(MAPTYPE);
+ } else {
+ for (src_byte = 0, i_byte = src_off;
+ i_byte < src_len && src_byte == 0;
+ i_byte++)
+ src_byte |= src[i_byte];
+ if (src_byte == 0)
+ break;
+ node_limit = src_len - src_off;
+ }
+
+ node_new = kzalloc(sizeof(*node_new), GFP_ATOMIC);
+ if (unlikely(node_new == NULL)) {
+ ebitmap_destroy(dst);
+ return -ENOMEM;
+ }
+ node_new->startbit = src_off * 8;
+ for (i_byte = 0; i_byte < node_limit; i_byte++) {
+ src_byte = src[src_off++];
+ for (i_bit = i_byte * 8; src_byte != 0; i_bit++) {
+ if (src_byte & 0x80)
+ node_new->map |= MAPBIT << i_bit;
+ src_byte <<= 1;
+ }
+ }
+
+ if (node_last != NULL)
+ node_last->next = node_new;
+ else
+ dst->node = node_new;
+ node_last = node_new;
+ }
+
+ if (likely(node_last != NULL))
+ dst->highbit = node_last->startbit + MAPSIZE;
+ else
+ ebitmap_init(dst);
+
+ return 0;
+}
+
int ebitmap_contains(struct ebitmap *e1, struct ebitmap *e2)
{
struct ebitmap_node *n1, *n2;