diff options
Diffstat (limited to 'security/selinux/ss/ebitmap.c')
-rw-r--r-- | security/selinux/ss/ebitmap.c | 144 |
1 files changed, 144 insertions, 0 deletions
diff --git a/security/selinux/ss/ebitmap.c b/security/selinux/ss/ebitmap.c index 47024a6e1844..4b915eb60c45 100644 --- a/security/selinux/ss/ebitmap.c +++ b/security/selinux/ss/ebitmap.c | |||
@@ -3,6 +3,14 @@ | |||
3 | * | 3 | * |
4 | * Author : Stephen Smalley, <sds@epoch.ncsc.mil> | 4 | * Author : Stephen Smalley, <sds@epoch.ncsc.mil> |
5 | */ | 5 | */ |
6 | /* | ||
7 | * Updated: Hewlett-Packard <paul.moore@hp.com> | ||
8 | * | ||
9 | * Added ebitmap_export() and ebitmap_import() | ||
10 | * | ||
11 | * (c) Copyright Hewlett-Packard Development Company, L.P., 2006 | ||
12 | */ | ||
13 | |||
6 | #include <linux/kernel.h> | 14 | #include <linux/kernel.h> |
7 | #include <linux/slab.h> | 15 | #include <linux/slab.h> |
8 | #include <linux/errno.h> | 16 | #include <linux/errno.h> |
@@ -59,6 +67,142 @@ int ebitmap_cpy(struct ebitmap *dst, struct ebitmap *src) | |||
59 | return 0; | 67 | return 0; |
60 | } | 68 | } |
61 | 69 | ||
70 | /** | ||
71 | * ebitmap_export - Export an ebitmap to a unsigned char bitmap string | ||
72 | * @src: the ebitmap to export | ||
73 | * @dst: the resulting bitmap string | ||
74 | * @dst_len: length of dst in bytes | ||
75 | * | ||
76 | * Description: | ||
77 | * Allocate a buffer at least src->highbit bits long and export the extensible | ||
78 | * bitmap into the buffer. The bitmap string will be in little endian format, | ||
79 | * i.e. LSB first. The value returned in dst_len may not the true size of the | ||
80 | * buffer as the length of the buffer is rounded up to a multiple of MAPTYPE. | ||
81 | * The caller must free the buffer when finished. Returns zero on success, | ||
82 | * negative values on failure. | ||
83 | * | ||
84 | */ | ||
85 | int ebitmap_export(const struct ebitmap *src, | ||
86 | unsigned char **dst, | ||
87 | size_t *dst_len) | ||
88 | { | ||
89 | size_t bitmap_len; | ||
90 | unsigned char *bitmap; | ||
91 | struct ebitmap_node *iter_node; | ||
92 | MAPTYPE node_val; | ||
93 | size_t bitmap_byte; | ||
94 | unsigned char bitmask; | ||
95 | |||
96 | bitmap_len = src->highbit / 8; | ||
97 | if (src->highbit % 7) | ||
98 | bitmap_len += 1; | ||
99 | if (bitmap_len == 0) | ||
100 | return -EINVAL; | ||
101 | |||
102 | bitmap = kzalloc((bitmap_len & ~(sizeof(MAPTYPE) - 1)) + | ||
103 | sizeof(MAPTYPE), | ||
104 | GFP_ATOMIC); | ||
105 | if (bitmap == NULL) | ||
106 | return -ENOMEM; | ||
107 | |||
108 | iter_node = src->node; | ||
109 | do { | ||
110 | bitmap_byte = iter_node->startbit / 8; | ||
111 | bitmask = 0x80; | ||
112 | node_val = iter_node->map; | ||
113 | do { | ||
114 | if (bitmask == 0) { | ||
115 | bitmap_byte++; | ||
116 | bitmask = 0x80; | ||
117 | } | ||
118 | if (node_val & (MAPTYPE)0x01) | ||
119 | bitmap[bitmap_byte] |= bitmask; | ||
120 | node_val >>= 1; | ||
121 | bitmask >>= 1; | ||
122 | } while (node_val > 0); | ||
123 | iter_node = iter_node->next; | ||
124 | } while (iter_node); | ||
125 | |||
126 | *dst = bitmap; | ||
127 | *dst_len = bitmap_len; | ||
128 | return 0; | ||
129 | } | ||
130 | |||
131 | /** | ||
132 | * ebitmap_import - Import an unsigned char bitmap string into an ebitmap | ||
133 | * @src: the bitmap string | ||
134 | * @src_len: the bitmap length in bytes | ||
135 | * @dst: the empty ebitmap | ||
136 | * | ||
137 | * Description: | ||
138 | * This function takes a little endian bitmap string in src and imports it into | ||
139 | * the ebitmap pointed to by dst. Returns zero on success, negative values on | ||
140 | * failure. | ||
141 | * | ||
142 | */ | ||
143 | int ebitmap_import(const unsigned char *src, | ||
144 | size_t src_len, | ||
145 | struct ebitmap *dst) | ||
146 | { | ||
147 | size_t src_off = 0; | ||
148 | struct ebitmap_node *node_new; | ||
149 | struct ebitmap_node *node_last = NULL; | ||
150 | size_t iter; | ||
151 | size_t iter_bit; | ||
152 | size_t iter_limit; | ||
153 | unsigned char src_byte; | ||
154 | |||
155 | do { | ||
156 | iter_limit = src_len - src_off; | ||
157 | if (iter_limit >= sizeof(MAPTYPE)) { | ||
158 | if (*(MAPTYPE *)&src[src_off] == 0) { | ||
159 | src_off += sizeof(MAPTYPE); | ||
160 | continue; | ||
161 | } | ||
162 | iter_limit = sizeof(MAPTYPE); | ||
163 | } else { | ||
164 | iter = src_off; | ||
165 | src_byte = 0; | ||
166 | do { | ||
167 | src_byte |= src[iter++]; | ||
168 | } while (iter < src_len && src_byte == 0); | ||
169 | if (src_byte == 0) | ||
170 | break; | ||
171 | } | ||
172 | |||
173 | node_new = kzalloc(sizeof(*node_new), GFP_ATOMIC); | ||
174 | if (unlikely(node_new == NULL)) { | ||
175 | ebitmap_destroy(dst); | ||
176 | return -ENOMEM; | ||
177 | } | ||
178 | node_new->startbit = src_off * 8; | ||
179 | iter = 0; | ||
180 | do { | ||
181 | src_byte = src[src_off++]; | ||
182 | iter_bit = iter++ * 8; | ||
183 | while (src_byte != 0) { | ||
184 | if (src_byte & 0x80) | ||
185 | node_new->map |= MAPBIT << iter_bit; | ||
186 | iter_bit++; | ||
187 | src_byte <<= 1; | ||
188 | } | ||
189 | } while (iter < iter_limit); | ||
190 | |||
191 | if (node_last != NULL) | ||
192 | node_last->next = node_new; | ||
193 | else | ||
194 | dst->node = node_new; | ||
195 | node_last = node_new; | ||
196 | } while (src_off < src_len); | ||
197 | |||
198 | if (likely(node_last != NULL)) | ||
199 | dst->highbit = node_last->startbit + MAPSIZE; | ||
200 | else | ||
201 | ebitmap_init(dst); | ||
202 | |||
203 | return 0; | ||
204 | } | ||
205 | |||
62 | int ebitmap_contains(struct ebitmap *e1, struct ebitmap *e2) | 206 | int ebitmap_contains(struct ebitmap *e1, struct ebitmap *e2) |
63 | { | 207 | { |
64 | struct ebitmap_node *n1, *n2; | 208 | struct ebitmap_node *n1, *n2; |