]> nv-tegra.nvidia Code Review - linux-2.6.git/blob - security/selinux/ss/ebitmap.c
NetLabel: better error handling involving mls_export_cat()
[linux-2.6.git] / security / selinux / ss / ebitmap.c
1 /*
2  * Implementation of the extensible bitmap type.
3  *
4  * Author : Stephen Smalley, <sds@epoch.ncsc.mil>
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
14 #include <linux/kernel.h>
15 #include <linux/slab.h>
16 #include <linux/errno.h>
17 #include "ebitmap.h"
18 #include "policydb.h"
19
20 int ebitmap_cmp(struct ebitmap *e1, struct ebitmap *e2)
21 {
22         struct ebitmap_node *n1, *n2;
23
24         if (e1->highbit != e2->highbit)
25                 return 0;
26
27         n1 = e1->node;
28         n2 = e2->node;
29         while (n1 && n2 &&
30                (n1->startbit == n2->startbit) &&
31                (n1->map == n2->map)) {
32                 n1 = n1->next;
33                 n2 = n2->next;
34         }
35
36         if (n1 || n2)
37                 return 0;
38
39         return 1;
40 }
41
42 int ebitmap_cpy(struct ebitmap *dst, struct ebitmap *src)
43 {
44         struct ebitmap_node *n, *new, *prev;
45
46         ebitmap_init(dst);
47         n = src->node;
48         prev = NULL;
49         while (n) {
50                 new = kzalloc(sizeof(*new), GFP_ATOMIC);
51                 if (!new) {
52                         ebitmap_destroy(dst);
53                         return -ENOMEM;
54                 }
55                 new->startbit = n->startbit;
56                 new->map = n->map;
57                 new->next = NULL;
58                 if (prev)
59                         prev->next = new;
60                 else
61                         dst->node = new;
62                 prev = new;
63                 n = n->next;
64         }
65
66         dst->highbit = src->highbit;
67         return 0;
68 }
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         if (src->highbit == 0) {
97                 *dst = NULL;
98                 *dst_len = 0;
99                 return 0;
100         }
101
102         bitmap_len = src->highbit / 8;
103         if (src->highbit % 7)
104                 bitmap_len += 1;
105
106         bitmap = kzalloc((bitmap_len & ~(sizeof(MAPTYPE) - 1)) +
107                          sizeof(MAPTYPE),
108                          GFP_ATOMIC);
109         if (bitmap == NULL)
110                 return -ENOMEM;
111
112         iter_node = src->node;
113         do {
114                 bitmap_byte = iter_node->startbit / 8;
115                 bitmask = 0x80;
116                 node_val = iter_node->map;
117                 do {
118                         if (bitmask == 0) {
119                                 bitmap_byte++;
120                                 bitmask = 0x80;
121                         }
122                         if (node_val & (MAPTYPE)0x01)
123                                 bitmap[bitmap_byte] |= bitmask;
124                         node_val >>= 1;
125                         bitmask >>= 1;
126                 } while (node_val > 0);
127                 iter_node = iter_node->next;
128         } while (iter_node);
129
130         *dst = bitmap;
131         *dst_len = bitmap_len;
132         return 0;
133 }
134
135 /**
136  * ebitmap_import - Import an unsigned char bitmap string into an ebitmap
137  * @src: the bitmap string
138  * @src_len: the bitmap length in bytes
139  * @dst: the empty ebitmap
140  *
141  * Description:
142  * This function takes a little endian bitmap string in src and imports it into
143  * the ebitmap pointed to by dst.  Returns zero on success, negative values on
144  * failure.
145  *
146  */
147 int ebitmap_import(const unsigned char *src,
148                    size_t src_len,
149                    struct ebitmap *dst)
150 {
151         size_t src_off = 0;
152         size_t node_limit;
153         struct ebitmap_node *node_new;
154         struct ebitmap_node *node_last = NULL;
155         u32 i_byte;
156         u32 i_bit;
157         unsigned char src_byte;
158
159         while (src_off < src_len) {
160                 if (src_len - src_off >= sizeof(MAPTYPE)) {
161                         if (*(MAPTYPE *)&src[src_off] == 0) {
162                                 src_off += sizeof(MAPTYPE);
163                                 continue;
164                         }
165                         node_limit = sizeof(MAPTYPE);
166                 } else {
167                         for (src_byte = 0, i_byte = src_off;
168                              i_byte < src_len && src_byte == 0;
169                              i_byte++)
170                                 src_byte |= src[i_byte];
171                         if (src_byte == 0)
172                                 break;
173                         node_limit = src_len - src_off;
174                 }
175
176                 node_new = kzalloc(sizeof(*node_new), GFP_ATOMIC);
177                 if (unlikely(node_new == NULL)) {
178                         ebitmap_destroy(dst);
179                         return -ENOMEM;
180                 }
181                 node_new->startbit = src_off * 8;
182                 for (i_byte = 0; i_byte < node_limit; i_byte++) {
183                         src_byte = src[src_off++];
184                         for (i_bit = i_byte * 8; src_byte != 0; i_bit++) {
185                                 if (src_byte & 0x80)
186                                         node_new->map |= MAPBIT << i_bit;
187                                 src_byte <<= 1;
188                         }
189                 }
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         }
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
206 int ebitmap_contains(struct ebitmap *e1, struct ebitmap *e2)
207 {
208         struct ebitmap_node *n1, *n2;
209
210         if (e1->highbit < e2->highbit)
211                 return 0;
212
213         n1 = e1->node;
214         n2 = e2->node;
215         while (n1 && n2 && (n1->startbit <= n2->startbit)) {
216                 if (n1->startbit < n2->startbit) {
217                         n1 = n1->next;
218                         continue;
219                 }
220                 if ((n1->map & n2->map) != n2->map)
221                         return 0;
222
223                 n1 = n1->next;
224                 n2 = n2->next;
225         }
226
227         if (n2)
228                 return 0;
229
230         return 1;
231 }
232
233 int ebitmap_get_bit(struct ebitmap *e, unsigned long bit)
234 {
235         struct ebitmap_node *n;
236
237         if (e->highbit < bit)
238                 return 0;
239
240         n = e->node;
241         while (n && (n->startbit <= bit)) {
242                 if ((n->startbit + MAPSIZE) > bit) {
243                         if (n->map & (MAPBIT << (bit - n->startbit)))
244                                 return 1;
245                         else
246                                 return 0;
247                 }
248                 n = n->next;
249         }
250
251         return 0;
252 }
253
254 int ebitmap_set_bit(struct ebitmap *e, unsigned long bit, int value)
255 {
256         struct ebitmap_node *n, *prev, *new;
257
258         prev = NULL;
259         n = e->node;
260         while (n && n->startbit <= bit) {
261                 if ((n->startbit + MAPSIZE) > bit) {
262                         if (value) {
263                                 n->map |= (MAPBIT << (bit - n->startbit));
264                         } else {
265                                 n->map &= ~(MAPBIT << (bit - n->startbit));
266                                 if (!n->map) {
267                                         /* drop this node from the bitmap */
268
269                                         if (!n->next) {
270                                                 /*
271                                                  * this was the highest map
272                                                  * within the bitmap
273                                                  */
274                                                 if (prev)
275                                                         e->highbit = prev->startbit + MAPSIZE;
276                                                 else
277                                                         e->highbit = 0;
278                                         }
279                                         if (prev)
280                                                 prev->next = n->next;
281                                         else
282                                                 e->node = n->next;
283
284                                         kfree(n);
285                                 }
286                         }
287                         return 0;
288                 }
289                 prev = n;
290                 n = n->next;
291         }
292
293         if (!value)
294                 return 0;
295
296         new = kzalloc(sizeof(*new), GFP_ATOMIC);
297         if (!new)
298                 return -ENOMEM;
299
300         new->startbit = bit & ~(MAPSIZE - 1);
301         new->map = (MAPBIT << (bit - new->startbit));
302
303         if (!n)
304                 /* this node will be the highest map within the bitmap */
305                 e->highbit = new->startbit + MAPSIZE;
306
307         if (prev) {
308                 new->next = prev->next;
309                 prev->next = new;
310         } else {
311                 new->next = e->node;
312                 e->node = new;
313         }
314
315         return 0;
316 }
317
318 void ebitmap_destroy(struct ebitmap *e)
319 {
320         struct ebitmap_node *n, *temp;
321
322         if (!e)
323                 return;
324
325         n = e->node;
326         while (n) {
327                 temp = n;
328                 n = n->next;
329                 kfree(temp);
330         }
331
332         e->highbit = 0;
333         e->node = NULL;
334         return;
335 }
336
337 int ebitmap_read(struct ebitmap *e, void *fp)
338 {
339         int rc;
340         struct ebitmap_node *n, *l;
341         __le32 buf[3];
342         u32 mapsize, count, i;
343         __le64 map;
344
345         ebitmap_init(e);
346
347         rc = next_entry(buf, fp, sizeof buf);
348         if (rc < 0)
349                 goto out;
350
351         mapsize = le32_to_cpu(buf[0]);
352         e->highbit = le32_to_cpu(buf[1]);
353         count = le32_to_cpu(buf[2]);
354
355         if (mapsize != MAPSIZE) {
356                 printk(KERN_ERR "security: ebitmap: map size %u does not "
357                        "match my size %Zd (high bit was %d)\n", mapsize,
358                        MAPSIZE, e->highbit);
359                 goto bad;
360         }
361         if (!e->highbit) {
362                 e->node = NULL;
363                 goto ok;
364         }
365         if (e->highbit & (MAPSIZE - 1)) {
366                 printk(KERN_ERR "security: ebitmap: high bit (%d) is not a "
367                        "multiple of the map size (%Zd)\n", e->highbit, MAPSIZE);
368                 goto bad;
369         }
370         l = NULL;
371         for (i = 0; i < count; i++) {
372                 rc = next_entry(buf, fp, sizeof(u32));
373                 if (rc < 0) {
374                         printk(KERN_ERR "security: ebitmap: truncated map\n");
375                         goto bad;
376                 }
377                 n = kzalloc(sizeof(*n), GFP_KERNEL);
378                 if (!n) {
379                         printk(KERN_ERR "security: ebitmap: out of memory\n");
380                         rc = -ENOMEM;
381                         goto bad;
382                 }
383
384                 n->startbit = le32_to_cpu(buf[0]);
385
386                 if (n->startbit & (MAPSIZE - 1)) {
387                         printk(KERN_ERR "security: ebitmap start bit (%d) is "
388                                "not a multiple of the map size (%Zd)\n",
389                                n->startbit, MAPSIZE);
390                         goto bad_free;
391                 }
392                 if (n->startbit > (e->highbit - MAPSIZE)) {
393                         printk(KERN_ERR "security: ebitmap start bit (%d) is "
394                                "beyond the end of the bitmap (%Zd)\n",
395                                n->startbit, (e->highbit - MAPSIZE));
396                         goto bad_free;
397                 }
398                 rc = next_entry(&map, fp, sizeof(u64));
399                 if (rc < 0) {
400                         printk(KERN_ERR "security: ebitmap: truncated map\n");
401                         goto bad_free;
402                 }
403                 n->map = le64_to_cpu(map);
404
405                 if (!n->map) {
406                         printk(KERN_ERR "security: ebitmap: null map in "
407                                "ebitmap (startbit %d)\n", n->startbit);
408                         goto bad_free;
409                 }
410                 if (l) {
411                         if (n->startbit <= l->startbit) {
412                                 printk(KERN_ERR "security: ebitmap: start "
413                                        "bit %d comes after start bit %d\n",
414                                        n->startbit, l->startbit);
415                                 goto bad_free;
416                         }
417                         l->next = n;
418                 } else
419                         e->node = n;
420
421                 l = n;
422         }
423
424 ok:
425         rc = 0;
426 out:
427         return rc;
428 bad_free:
429         kfree(n);
430 bad:
431         if (!rc)
432                 rc = -EINVAL;
433         ebitmap_destroy(e);
434         goto out;
435 }