2 * Implementation of the extensible bitmap type.
4 * Author : Stephen Smalley, <sds@epoch.ncsc.mil>
7 * Updated: Hewlett-Packard <paul@paul-moore.com>
9 * Added support to import/export the NetLabel category bitmap
11 * (c) Copyright Hewlett-Packard Development Company, L.P., 2006
14 * Updated: KaiGai Kohei <kaigai@ak.jp.nec.com>
15 * Applied standard bit operations to improve bitmap scanning.
18 #include <linux/kernel.h>
19 #include <linux/slab.h>
20 #include <linux/errno.h>
21 #include <net/netlabel.h>
25 #define BITS_PER_U64 (sizeof(u64) * 8)
27 int ebitmap_cmp(struct ebitmap
*e1
, struct ebitmap
*e2
)
29 struct ebitmap_node
*n1
, *n2
;
31 if (e1
->highbit
!= e2
->highbit
)
37 (n1
->startbit
== n2
->startbit
) &&
38 !memcmp(n1
->maps
, n2
->maps
, EBITMAP_SIZE
/ 8)) {
49 int ebitmap_cpy(struct ebitmap
*dst
, struct ebitmap
*src
)
51 struct ebitmap_node
*n
, *new, *prev
;
57 new = kzalloc(sizeof(*new), GFP_ATOMIC
);
62 new->startbit
= n
->startbit
;
63 memcpy(new->maps
, n
->maps
, EBITMAP_SIZE
/ 8);
73 dst
->highbit
= src
->highbit
;
77 #ifdef CONFIG_NETLABEL
79 * ebitmap_netlbl_export - Export an ebitmap into a NetLabel category bitmap
80 * @ebmap: the ebitmap to export
81 * @catmap: the NetLabel category bitmap
84 * Export a SELinux extensibile bitmap into a NetLabel category bitmap.
85 * Returns zero on success, negative values on error.
88 int ebitmap_netlbl_export(struct ebitmap
*ebmap
,
89 struct netlbl_lsm_catmap
**catmap
)
91 struct ebitmap_node
*e_iter
= ebmap
->node
;
103 netlbl_catmap_free(*catmap
);
107 offset
= e_iter
->startbit
;
108 for (iter
= 0; iter
< EBITMAP_UNIT_NUMS
; iter
++) {
109 e_map
= e_iter
->maps
[iter
];
111 rc
= netlbl_catmap_setlong(catmap
,
116 goto netlbl_export_failure
;
118 offset
+= EBITMAP_UNIT_SIZE
;
120 e_iter
= e_iter
->next
;
125 netlbl_export_failure
:
126 netlbl_catmap_free(*catmap
);
131 * ebitmap_netlbl_import - Import a NetLabel category bitmap into an ebitmap
132 * @ebmap: the ebitmap to import
133 * @catmap: the NetLabel category bitmap
136 * Import a NetLabel category bitmap into a SELinux extensibile bitmap.
137 * Returns zero on success, negative values on error.
140 int ebitmap_netlbl_import(struct ebitmap
*ebmap
,
141 struct netlbl_lsm_catmap
*catmap
)
144 struct ebitmap_node
*e_iter
= NULL
;
145 struct ebitmap_node
*e_prev
= NULL
;
147 unsigned long bitmap
;
150 rc
= netlbl_catmap_getlong(catmap
, &offset
, &bitmap
);
152 goto netlbl_import_failure
;
153 if (offset
== (u32
)-1)
156 /* don't waste ebitmap space if the netlabel bitmap is empty */
158 offset
+= EBITMAP_UNIT_SIZE
;
162 if (e_iter
== NULL
||
163 offset
>= e_iter
->startbit
+ EBITMAP_SIZE
) {
165 e_iter
= kzalloc(sizeof(*e_iter
), GFP_ATOMIC
);
167 goto netlbl_import_failure
;
168 e_iter
->startbit
= offset
& ~(EBITMAP_SIZE
- 1);
170 ebmap
->node
= e_iter
;
172 e_prev
->next
= e_iter
;
173 ebmap
->highbit
= e_iter
->startbit
+ EBITMAP_SIZE
;
176 /* offset will always be aligned to an unsigned long */
177 idx
= EBITMAP_NODE_INDEX(e_iter
, offset
);
178 e_iter
->maps
[idx
] = bitmap
;
181 offset
+= EBITMAP_UNIT_SIZE
;
184 /* NOTE: we should never reach this return */
187 netlbl_import_failure
:
188 ebitmap_destroy(ebmap
);
191 #endif /* CONFIG_NETLABEL */
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
198 int ebitmap_contains(struct ebitmap
*e1
, struct ebitmap
*e2
, u32 last_e2bit
)
200 struct ebitmap_node
*n1
, *n2
;
203 if (e1
->highbit
< e2
->highbit
)
209 while (n1
&& n2
&& (n1
->startbit
<= n2
->startbit
)) {
210 if (n1
->startbit
< n2
->startbit
) {
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
+
219 if (lastsetbit
> last_e2bit
)
224 if ((n1
->maps
[i
] & n2
->maps
[i
]) != n2
->maps
[i
])
239 int ebitmap_get_bit(struct ebitmap
*e
, unsigned long bit
)
241 struct ebitmap_node
*n
;
243 if (e
->highbit
< bit
)
247 while (n
&& (n
->startbit
<= bit
)) {
248 if ((n
->startbit
+ EBITMAP_SIZE
) > bit
)
249 return ebitmap_node_get_bit(n
, bit
);
256 int ebitmap_set_bit(struct ebitmap
*e
, unsigned long bit
, int value
)
258 struct ebitmap_node
*n
, *prev
, *new;
262 while (n
&& n
->startbit
<= bit
) {
263 if ((n
->startbit
+ EBITMAP_SIZE
) > bit
) {
265 ebitmap_node_set_bit(n
, bit
);
269 ebitmap_node_clr_bit(n
, bit
);
271 s
= find_first_bit(n
->maps
, EBITMAP_SIZE
);
272 if (s
< EBITMAP_SIZE
)
275 /* drop this node from the bitmap */
278 * this was the highest map
282 e
->highbit
= prev
->startbit
288 prev
->next
= n
->next
;
302 new = kzalloc(sizeof(*new), GFP_ATOMIC
);
306 new->startbit
= bit
- (bit
% EBITMAP_SIZE
);
307 ebitmap_node_set_bit(new, bit
);
310 /* this node will be the highest map within the bitmap */
311 e
->highbit
= new->startbit
+ EBITMAP_SIZE
;
314 new->next
= prev
->next
;
324 void ebitmap_destroy(struct ebitmap
*e
)
326 struct ebitmap_node
*n
, *temp
;
343 int ebitmap_read(struct ebitmap
*e
, void *fp
)
345 struct ebitmap_node
*n
= NULL
;
346 u32 mapunit
, count
, startbit
, index
;
353 rc
= next_entry(buf
, fp
, sizeof buf
);
357 mapunit
= le32_to_cpu(buf
[0]);
358 e
->highbit
= le32_to_cpu(buf
[1]);
359 count
= le32_to_cpu(buf
[2]);
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
);
368 /* round up e->highbit */
369 e
->highbit
+= EBITMAP_SIZE
- 1;
370 e
->highbit
-= (e
->highbit
% EBITMAP_SIZE
);
377 for (i
= 0; i
< count
; i
++) {
378 rc
= next_entry(&startbit
, fp
, sizeof(u32
));
380 printk(KERN_ERR
"SELinux: ebitmap: truncated map\n");
383 startbit
= le32_to_cpu(startbit
);
385 if (startbit
& (mapunit
- 1)) {
386 printk(KERN_ERR
"SELinux: ebitmap start bit (%d) is "
387 "not a multiple of the map unit size (%u)\n",
391 if (startbit
> e
->highbit
- mapunit
) {
392 printk(KERN_ERR
"SELinux: ebitmap start bit (%d) is "
393 "beyond the end of the bitmap (%u)\n",
394 startbit
, (e
->highbit
- mapunit
));
398 if (!n
|| startbit
>= n
->startbit
+ EBITMAP_SIZE
) {
399 struct ebitmap_node
*tmp
;
400 tmp
= kzalloc(sizeof(*tmp
), GFP_KERNEL
);
403 "SELinux: ebitmap: out of memory\n");
408 tmp
->startbit
= startbit
- (startbit
% EBITMAP_SIZE
);
414 } else if (startbit
<= n
->startbit
) {
415 printk(KERN_ERR
"SELinux: ebitmap: start bit %d"
416 " comes after start bit %d\n",
417 startbit
, n
->startbit
);
421 rc
= next_entry(&map
, fp
, sizeof(u64
));
423 printk(KERN_ERR
"SELinux: ebitmap: truncated map\n");
426 map
= le64_to_cpu(map
);
428 index
= (startbit
- n
->startbit
) / EBITMAP_UNIT_SIZE
;
430 n
->maps
[index
++] = map
& (-1UL);
431 map
= EBITMAP_SHIFT_UNIT_SIZE(map
);
445 int ebitmap_write(struct ebitmap
*e
, void *fp
)
447 struct ebitmap_node
*n
;
451 int bit
, last_bit
, last_startbit
, rc
;
453 buf
[0] = cpu_to_le32(BITS_PER_U64
);
458 ebitmap_for_each_positive_bit(e
, n
, bit
) {
459 if (rounddown(bit
, (int)BITS_PER_U64
) > last_startbit
) {
461 last_startbit
= rounddown(bit
, BITS_PER_U64
);
463 last_bit
= roundup(bit
+ 1, BITS_PER_U64
);
465 buf
[1] = cpu_to_le32(last_bit
);
466 buf
[2] = cpu_to_le32(count
);
468 rc
= put_entry(buf
, sizeof(u32
), 3, fp
);
473 last_startbit
= INT_MIN
;
474 ebitmap_for_each_positive_bit(e
, n
, bit
) {
475 if (rounddown(bit
, (int)BITS_PER_U64
) > last_startbit
) {
478 /* this is the very first bit */
480 last_startbit
= rounddown(bit
, BITS_PER_U64
);
481 map
= (u64
)1 << (bit
- last_startbit
);
485 /* write the last node */
486 buf
[0] = cpu_to_le32(last_startbit
);
487 rc
= put_entry(buf
, sizeof(u32
), 1, fp
);
491 buf64
[0] = cpu_to_le64(map
);
492 rc
= put_entry(buf64
, sizeof(u64
), 1, fp
);
496 /* set up for the next node */
498 last_startbit
= rounddown(bit
, BITS_PER_U64
);
500 map
|= (u64
)1 << (bit
- last_startbit
);
502 /* write the last node */
506 /* write the last node */
507 buf
[0] = cpu_to_le32(last_startbit
);
508 rc
= put_entry(buf
, sizeof(u32
), 1, fp
);
512 buf64
[0] = cpu_to_le64(map
);
513 rc
= put_entry(buf64
, sizeof(u64
), 1, fp
);