xref: /openbmc/linux/security/selinux/ss/ebitmap.c (revision 5b5e0928)
1 /*
2  * Implementation of the extensible bitmap type.
3  *
4  * Author : Stephen Smalley, <sds@epoch.ncsc.mil>
5  */
6 /*
7  * Updated: Hewlett-Packard <paul@paul-moore.com>
8  *
9  *      Added support to import/export the NetLabel category bitmap
10  *
11  * (c) Copyright Hewlett-Packard Development Company, L.P., 2006
12  */
13 /*
14  * Updated: KaiGai Kohei <kaigai@ak.jp.nec.com>
15  *      Applied standard bit operations to improve bitmap scanning.
16  */
17 
18 #include <linux/kernel.h>
19 #include <linux/slab.h>
20 #include <linux/errno.h>
21 #include <net/netlabel.h>
22 #include "ebitmap.h"
23 #include "policydb.h"
24 
25 #define BITS_PER_U64	(sizeof(u64) * 8)
26 
27 int ebitmap_cmp(struct ebitmap *e1, struct ebitmap *e2)
28 {
29 	struct ebitmap_node *n1, *n2;
30 
31 	if (e1->highbit != e2->highbit)
32 		return 0;
33 
34 	n1 = e1->node;
35 	n2 = e2->node;
36 	while (n1 && n2 &&
37 	       (n1->startbit == n2->startbit) &&
38 	       !memcmp(n1->maps, n2->maps, EBITMAP_SIZE / 8)) {
39 		n1 = n1->next;
40 		n2 = n2->next;
41 	}
42 
43 	if (n1 || n2)
44 		return 0;
45 
46 	return 1;
47 }
48 
49 int ebitmap_cpy(struct ebitmap *dst, struct ebitmap *src)
50 {
51 	struct ebitmap_node *n, *new, *prev;
52 
53 	ebitmap_init(dst);
54 	n = src->node;
55 	prev = NULL;
56 	while (n) {
57 		new = kzalloc(sizeof(*new), GFP_ATOMIC);
58 		if (!new) {
59 			ebitmap_destroy(dst);
60 			return -ENOMEM;
61 		}
62 		new->startbit = n->startbit;
63 		memcpy(new->maps, n->maps, EBITMAP_SIZE / 8);
64 		new->next = NULL;
65 		if (prev)
66 			prev->next = new;
67 		else
68 			dst->node = new;
69 		prev = new;
70 		n = n->next;
71 	}
72 
73 	dst->highbit = src->highbit;
74 	return 0;
75 }
76 
77 #ifdef CONFIG_NETLABEL
78 /**
79  * ebitmap_netlbl_export - Export an ebitmap into a NetLabel category bitmap
80  * @ebmap: the ebitmap to export
81  * @catmap: the NetLabel category bitmap
82  *
83  * Description:
84  * Export a SELinux extensibile bitmap into a NetLabel category bitmap.
85  * Returns zero on success, negative values on error.
86  *
87  */
88 int ebitmap_netlbl_export(struct ebitmap *ebmap,
89 			  struct netlbl_lsm_catmap **catmap)
90 {
91 	struct ebitmap_node *e_iter = ebmap->node;
92 	unsigned long e_map;
93 	u32 offset;
94 	unsigned int iter;
95 	int rc;
96 
97 	if (e_iter == NULL) {
98 		*catmap = NULL;
99 		return 0;
100 	}
101 
102 	if (*catmap != NULL)
103 		netlbl_catmap_free(*catmap);
104 	*catmap = NULL;
105 
106 	while (e_iter) {
107 		offset = e_iter->startbit;
108 		for (iter = 0; iter < EBITMAP_UNIT_NUMS; iter++) {
109 			e_map = e_iter->maps[iter];
110 			if (e_map != 0) {
111 				rc = netlbl_catmap_setlong(catmap,
112 							   offset,
113 							   e_map,
114 							   GFP_ATOMIC);
115 				if (rc != 0)
116 					goto netlbl_export_failure;
117 			}
118 			offset += EBITMAP_UNIT_SIZE;
119 		}
120 		e_iter = e_iter->next;
121 	}
122 
123 	return 0;
124 
125 netlbl_export_failure:
126 	netlbl_catmap_free(*catmap);
127 	return -ENOMEM;
128 }
129 
130 /**
131  * ebitmap_netlbl_import - Import a NetLabel category bitmap into an ebitmap
132  * @ebmap: the ebitmap to import
133  * @catmap: the NetLabel category bitmap
134  *
135  * Description:
136  * Import a NetLabel category bitmap into a SELinux extensibile bitmap.
137  * Returns zero on success, negative values on error.
138  *
139  */
140 int ebitmap_netlbl_import(struct ebitmap *ebmap,
141 			  struct netlbl_lsm_catmap *catmap)
142 {
143 	int rc;
144 	struct ebitmap_node *e_iter = NULL;
145 	struct ebitmap_node *e_prev = NULL;
146 	u32 offset = 0, idx;
147 	unsigned long bitmap;
148 
149 	for (;;) {
150 		rc = netlbl_catmap_getlong(catmap, &offset, &bitmap);
151 		if (rc < 0)
152 			goto netlbl_import_failure;
153 		if (offset == (u32)-1)
154 			return 0;
155 
156 		/* don't waste ebitmap space if the netlabel bitmap is empty */
157 		if (bitmap == 0) {
158 			offset += EBITMAP_UNIT_SIZE;
159 			continue;
160 		}
161 
162 		if (e_iter == NULL ||
163 		    offset >= e_iter->startbit + EBITMAP_SIZE) {
164 			e_prev = e_iter;
165 			e_iter = kzalloc(sizeof(*e_iter), GFP_ATOMIC);
166 			if (e_iter == NULL)
167 				goto netlbl_import_failure;
168 			e_iter->startbit = offset - (offset % EBITMAP_SIZE);
169 			if (e_prev == NULL)
170 				ebmap->node = e_iter;
171 			else
172 				e_prev->next = e_iter;
173 			ebmap->highbit = e_iter->startbit + EBITMAP_SIZE;
174 		}
175 
176 		/* offset will always be aligned to an unsigned long */
177 		idx = EBITMAP_NODE_INDEX(e_iter, offset);
178 		e_iter->maps[idx] = bitmap;
179 
180 		/* next */
181 		offset += EBITMAP_UNIT_SIZE;
182 	}
183 
184 	/* NOTE: we should never reach this return */
185 	return 0;
186 
187 netlbl_import_failure:
188 	ebitmap_destroy(ebmap);
189 	return -ENOMEM;
190 }
191 #endif /* CONFIG_NETLABEL */
192 
193 /*
194  * Check to see if all the bits set in e2 are also set in e1. Optionally,
195  * if last_e2bit is non-zero, the highest set bit in e2 cannot exceed
196  * last_e2bit.
197  */
198 int ebitmap_contains(struct ebitmap *e1, struct ebitmap *e2, u32 last_e2bit)
199 {
200 	struct ebitmap_node *n1, *n2;
201 	int i;
202 
203 	if (e1->highbit < e2->highbit)
204 		return 0;
205 
206 	n1 = e1->node;
207 	n2 = e2->node;
208 
209 	while (n1 && n2 && (n1->startbit <= n2->startbit)) {
210 		if (n1->startbit < n2->startbit) {
211 			n1 = n1->next;
212 			continue;
213 		}
214 		for (i = EBITMAP_UNIT_NUMS - 1; (i >= 0) && !n2->maps[i]; )
215 			i--;	/* Skip trailing NULL map entries */
216 		if (last_e2bit && (i >= 0)) {
217 			u32 lastsetbit = n2->startbit + i * EBITMAP_UNIT_SIZE +
218 					 __fls(n2->maps[i]);
219 			if (lastsetbit > last_e2bit)
220 				return 0;
221 		}
222 
223 		while (i >= 0) {
224 			if ((n1->maps[i] & n2->maps[i]) != n2->maps[i])
225 				return 0;
226 			i--;
227 		}
228 
229 		n1 = n1->next;
230 		n2 = n2->next;
231 	}
232 
233 	if (n2)
234 		return 0;
235 
236 	return 1;
237 }
238 
239 int ebitmap_get_bit(struct ebitmap *e, unsigned long bit)
240 {
241 	struct ebitmap_node *n;
242 
243 	if (e->highbit < bit)
244 		return 0;
245 
246 	n = e->node;
247 	while (n && (n->startbit <= bit)) {
248 		if ((n->startbit + EBITMAP_SIZE) > bit)
249 			return ebitmap_node_get_bit(n, bit);
250 		n = n->next;
251 	}
252 
253 	return 0;
254 }
255 
256 int ebitmap_set_bit(struct ebitmap *e, unsigned long bit, int value)
257 {
258 	struct ebitmap_node *n, *prev, *new;
259 
260 	prev = NULL;
261 	n = e->node;
262 	while (n && n->startbit <= bit) {
263 		if ((n->startbit + EBITMAP_SIZE) > bit) {
264 			if (value) {
265 				ebitmap_node_set_bit(n, bit);
266 			} else {
267 				unsigned int s;
268 
269 				ebitmap_node_clr_bit(n, bit);
270 
271 				s = find_first_bit(n->maps, EBITMAP_SIZE);
272 				if (s < EBITMAP_SIZE)
273 					return 0;
274 
275 				/* drop this node from the bitmap */
276 				if (!n->next) {
277 					/*
278 					 * this was the highest map
279 					 * within the bitmap
280 					 */
281 					if (prev)
282 						e->highbit = prev->startbit
283 							     + EBITMAP_SIZE;
284 					else
285 						e->highbit = 0;
286 				}
287 				if (prev)
288 					prev->next = n->next;
289 				else
290 					e->node = n->next;
291 				kfree(n);
292 			}
293 			return 0;
294 		}
295 		prev = n;
296 		n = n->next;
297 	}
298 
299 	if (!value)
300 		return 0;
301 
302 	new = kzalloc(sizeof(*new), GFP_ATOMIC);
303 	if (!new)
304 		return -ENOMEM;
305 
306 	new->startbit = bit - (bit % EBITMAP_SIZE);
307 	ebitmap_node_set_bit(new, bit);
308 
309 	if (!n)
310 		/* this node will be the highest map within the bitmap */
311 		e->highbit = new->startbit + EBITMAP_SIZE;
312 
313 	if (prev) {
314 		new->next = prev->next;
315 		prev->next = new;
316 	} else {
317 		new->next = e->node;
318 		e->node = new;
319 	}
320 
321 	return 0;
322 }
323 
324 void ebitmap_destroy(struct ebitmap *e)
325 {
326 	struct ebitmap_node *n, *temp;
327 
328 	if (!e)
329 		return;
330 
331 	n = e->node;
332 	while (n) {
333 		temp = n;
334 		n = n->next;
335 		kfree(temp);
336 	}
337 
338 	e->highbit = 0;
339 	e->node = NULL;
340 	return;
341 }
342 
343 int ebitmap_read(struct ebitmap *e, void *fp)
344 {
345 	struct ebitmap_node *n = NULL;
346 	u32 mapunit, count, startbit, index;
347 	u64 map;
348 	__le32 buf[3];
349 	int rc, i;
350 
351 	ebitmap_init(e);
352 
353 	rc = next_entry(buf, fp, sizeof buf);
354 	if (rc < 0)
355 		goto out;
356 
357 	mapunit = le32_to_cpu(buf[0]);
358 	e->highbit = le32_to_cpu(buf[1]);
359 	count = le32_to_cpu(buf[2]);
360 
361 	if (mapunit != BITS_PER_U64) {
362 		printk(KERN_ERR "SELinux: ebitmap: map size %u does not "
363 		       "match my size %zd (high bit was %d)\n",
364 		       mapunit, BITS_PER_U64, e->highbit);
365 		goto bad;
366 	}
367 
368 	/* round up e->highbit */
369 	e->highbit += EBITMAP_SIZE - 1;
370 	e->highbit -= (e->highbit % EBITMAP_SIZE);
371 
372 	if (!e->highbit) {
373 		e->node = NULL;
374 		goto ok;
375 	}
376 
377 	if (e->highbit && !count)
378 		goto bad;
379 
380 	for (i = 0; i < count; i++) {
381 		rc = next_entry(&startbit, fp, sizeof(u32));
382 		if (rc < 0) {
383 			printk(KERN_ERR "SELinux: ebitmap: truncated map\n");
384 			goto bad;
385 		}
386 		startbit = le32_to_cpu(startbit);
387 
388 		if (startbit & (mapunit - 1)) {
389 			printk(KERN_ERR "SELinux: ebitmap start bit (%d) is "
390 			       "not a multiple of the map unit size (%u)\n",
391 			       startbit, mapunit);
392 			goto bad;
393 		}
394 		if (startbit > e->highbit - mapunit) {
395 			printk(KERN_ERR "SELinux: ebitmap start bit (%d) is "
396 			       "beyond the end of the bitmap (%u)\n",
397 			       startbit, (e->highbit - mapunit));
398 			goto bad;
399 		}
400 
401 		if (!n || startbit >= n->startbit + EBITMAP_SIZE) {
402 			struct ebitmap_node *tmp;
403 			tmp = kzalloc(sizeof(*tmp), GFP_KERNEL);
404 			if (!tmp) {
405 				printk(KERN_ERR
406 				       "SELinux: ebitmap: out of memory\n");
407 				rc = -ENOMEM;
408 				goto bad;
409 			}
410 			/* round down */
411 			tmp->startbit = startbit - (startbit % EBITMAP_SIZE);
412 			if (n)
413 				n->next = tmp;
414 			else
415 				e->node = tmp;
416 			n = tmp;
417 		} else if (startbit <= n->startbit) {
418 			printk(KERN_ERR "SELinux: ebitmap: start bit %d"
419 			       " comes after start bit %d\n",
420 			       startbit, n->startbit);
421 			goto bad;
422 		}
423 
424 		rc = next_entry(&map, fp, sizeof(u64));
425 		if (rc < 0) {
426 			printk(KERN_ERR "SELinux: ebitmap: truncated map\n");
427 			goto bad;
428 		}
429 		map = le64_to_cpu(map);
430 
431 		index = (startbit - n->startbit) / EBITMAP_UNIT_SIZE;
432 		while (map) {
433 			n->maps[index++] = map & (-1UL);
434 			map = EBITMAP_SHIFT_UNIT_SIZE(map);
435 		}
436 	}
437 ok:
438 	rc = 0;
439 out:
440 	return rc;
441 bad:
442 	if (!rc)
443 		rc = -EINVAL;
444 	ebitmap_destroy(e);
445 	goto out;
446 }
447 
448 int ebitmap_write(struct ebitmap *e, void *fp)
449 {
450 	struct ebitmap_node *n;
451 	u32 count;
452 	__le32 buf[3];
453 	u64 map;
454 	int bit, last_bit, last_startbit, rc;
455 
456 	buf[0] = cpu_to_le32(BITS_PER_U64);
457 
458 	count = 0;
459 	last_bit = 0;
460 	last_startbit = -1;
461 	ebitmap_for_each_positive_bit(e, n, bit) {
462 		if (rounddown(bit, (int)BITS_PER_U64) > last_startbit) {
463 			count++;
464 			last_startbit = rounddown(bit, BITS_PER_U64);
465 		}
466 		last_bit = roundup(bit + 1, BITS_PER_U64);
467 	}
468 	buf[1] = cpu_to_le32(last_bit);
469 	buf[2] = cpu_to_le32(count);
470 
471 	rc = put_entry(buf, sizeof(u32), 3, fp);
472 	if (rc)
473 		return rc;
474 
475 	map = 0;
476 	last_startbit = INT_MIN;
477 	ebitmap_for_each_positive_bit(e, n, bit) {
478 		if (rounddown(bit, (int)BITS_PER_U64) > last_startbit) {
479 			__le64 buf64[1];
480 
481 			/* this is the very first bit */
482 			if (!map) {
483 				last_startbit = rounddown(bit, BITS_PER_U64);
484 				map = (u64)1 << (bit - last_startbit);
485 				continue;
486 			}
487 
488 			/* write the last node */
489 			buf[0] = cpu_to_le32(last_startbit);
490 			rc = put_entry(buf, sizeof(u32), 1, fp);
491 			if (rc)
492 				return rc;
493 
494 			buf64[0] = cpu_to_le64(map);
495 			rc = put_entry(buf64, sizeof(u64), 1, fp);
496 			if (rc)
497 				return rc;
498 
499 			/* set up for the next node */
500 			map = 0;
501 			last_startbit = rounddown(bit, BITS_PER_U64);
502 		}
503 		map |= (u64)1 << (bit - last_startbit);
504 	}
505 	/* write the last node */
506 	if (map) {
507 		__le64 buf64[1];
508 
509 		/* write the last node */
510 		buf[0] = cpu_to_le32(last_startbit);
511 		rc = put_entry(buf, sizeof(u32), 1, fp);
512 		if (rc)
513 			return rc;
514 
515 		buf64[0] = cpu_to_le64(map);
516 		rc = put_entry(buf64, sizeof(u64), 1, fp);
517 		if (rc)
518 			return rc;
519 	}
520 	return 0;
521 }
522