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 if (e_iter
== NULL
||
157 offset
>= e_iter
->startbit
+ EBITMAP_SIZE
) {
159 e_iter
= kzalloc(sizeof(*e_iter
), GFP_ATOMIC
);
161 goto netlbl_import_failure
;
162 e_iter
->startbit
= offset
& ~(EBITMAP_SIZE
- 1);
164 ebmap
->node
= e_iter
;
166 e_prev
->next
= e_iter
;
167 ebmap
->highbit
= e_iter
->startbit
+ EBITMAP_SIZE
;
170 /* offset will always be aligned to an unsigned long */
171 idx
= EBITMAP_NODE_INDEX(e_iter
, offset
);
172 e_iter
->maps
[idx
] = bitmap
;
175 offset
+= EBITMAP_UNIT_SIZE
;
178 /* NOTE: we should never reach this return */
181 netlbl_import_failure
:
182 ebitmap_destroy(ebmap
);
185 #endif /* CONFIG_NETLABEL */
188 * Check to see if all the bits set in e2 are also set in e1. Optionally,
189 * if last_e2bit is non-zero, the highest set bit in e2 cannot exceed
192 int ebitmap_contains(struct ebitmap
*e1
, struct ebitmap
*e2
, u32 last_e2bit
)
194 struct ebitmap_node
*n1
, *n2
;
197 if (e1
->highbit
< e2
->highbit
)
203 while (n1
&& n2
&& (n1
->startbit
<= n2
->startbit
)) {
204 if (n1
->startbit
< n2
->startbit
) {
208 for (i
= EBITMAP_UNIT_NUMS
- 1; (i
>= 0) && !n2
->maps
[i
]; )
209 i
--; /* Skip trailing NULL map entries */
210 if (last_e2bit
&& (i
>= 0)) {
211 u32 lastsetbit
= n2
->startbit
+ i
* EBITMAP_UNIT_SIZE
+
213 if (lastsetbit
> last_e2bit
)
218 if ((n1
->maps
[i
] & n2
->maps
[i
]) != n2
->maps
[i
])
233 int ebitmap_get_bit(struct ebitmap
*e
, unsigned long bit
)
235 struct ebitmap_node
*n
;
237 if (e
->highbit
< bit
)
241 while (n
&& (n
->startbit
<= bit
)) {
242 if ((n
->startbit
+ EBITMAP_SIZE
) > bit
)
243 return ebitmap_node_get_bit(n
, bit
);
250 int ebitmap_set_bit(struct ebitmap
*e
, unsigned long bit
, int value
)
252 struct ebitmap_node
*n
, *prev
, *new;
256 while (n
&& n
->startbit
<= bit
) {
257 if ((n
->startbit
+ EBITMAP_SIZE
) > bit
) {
259 ebitmap_node_set_bit(n
, bit
);
263 ebitmap_node_clr_bit(n
, bit
);
265 s
= find_first_bit(n
->maps
, EBITMAP_SIZE
);
266 if (s
< EBITMAP_SIZE
)
269 /* drop this node from the bitmap */
272 * this was the highest map
276 e
->highbit
= prev
->startbit
282 prev
->next
= n
->next
;
296 new = kzalloc(sizeof(*new), GFP_ATOMIC
);
300 new->startbit
= bit
- (bit
% EBITMAP_SIZE
);
301 ebitmap_node_set_bit(new, bit
);
304 /* this node will be the highest map within the bitmap */
305 e
->highbit
= new->startbit
+ EBITMAP_SIZE
;
308 new->next
= prev
->next
;
318 void ebitmap_destroy(struct ebitmap
*e
)
320 struct ebitmap_node
*n
, *temp
;
337 int ebitmap_read(struct ebitmap
*e
, void *fp
)
339 struct ebitmap_node
*n
= NULL
;
340 u32 mapunit
, count
, startbit
, index
;
347 rc
= next_entry(buf
, fp
, sizeof buf
);
351 mapunit
= le32_to_cpu(buf
[0]);
352 e
->highbit
= le32_to_cpu(buf
[1]);
353 count
= le32_to_cpu(buf
[2]);
355 if (mapunit
!= BITS_PER_U64
) {
356 printk(KERN_ERR
"SELinux: ebitmap: map size %u does not "
357 "match my size %Zd (high bit was %d)\n",
358 mapunit
, BITS_PER_U64
, e
->highbit
);
362 /* round up e->highbit */
363 e
->highbit
+= EBITMAP_SIZE
- 1;
364 e
->highbit
-= (e
->highbit
% EBITMAP_SIZE
);
371 for (i
= 0; i
< count
; i
++) {
372 rc
= next_entry(&startbit
, fp
, sizeof(u32
));
374 printk(KERN_ERR
"SELinux: ebitmap: truncated map\n");
377 startbit
= le32_to_cpu(startbit
);
379 if (startbit
& (mapunit
- 1)) {
380 printk(KERN_ERR
"SELinux: ebitmap start bit (%d) is "
381 "not a multiple of the map unit size (%u)\n",
385 if (startbit
> e
->highbit
- mapunit
) {
386 printk(KERN_ERR
"SELinux: ebitmap start bit (%d) is "
387 "beyond the end of the bitmap (%u)\n",
388 startbit
, (e
->highbit
- mapunit
));
392 if (!n
|| startbit
>= n
->startbit
+ EBITMAP_SIZE
) {
393 struct ebitmap_node
*tmp
;
394 tmp
= kzalloc(sizeof(*tmp
), GFP_KERNEL
);
397 "SELinux: ebitmap: out of memory\n");
402 tmp
->startbit
= startbit
- (startbit
% EBITMAP_SIZE
);
408 } else if (startbit
<= n
->startbit
) {
409 printk(KERN_ERR
"SELinux: ebitmap: start bit %d"
410 " comes after start bit %d\n",
411 startbit
, n
->startbit
);
415 rc
= next_entry(&map
, fp
, sizeof(u64
));
417 printk(KERN_ERR
"SELinux: ebitmap: truncated map\n");
420 map
= le64_to_cpu(map
);
422 index
= (startbit
- n
->startbit
) / EBITMAP_UNIT_SIZE
;
424 n
->maps
[index
++] = map
& (-1UL);
425 map
= EBITMAP_SHIFT_UNIT_SIZE(map
);
439 int ebitmap_write(struct ebitmap
*e
, void *fp
)
441 struct ebitmap_node
*n
;
445 int bit
, last_bit
, last_startbit
, rc
;
447 buf
[0] = cpu_to_le32(BITS_PER_U64
);
452 ebitmap_for_each_positive_bit(e
, n
, bit
) {
453 if (rounddown(bit
, (int)BITS_PER_U64
) > last_startbit
) {
455 last_startbit
= rounddown(bit
, BITS_PER_U64
);
457 last_bit
= roundup(bit
+ 1, BITS_PER_U64
);
459 buf
[1] = cpu_to_le32(last_bit
);
460 buf
[2] = cpu_to_le32(count
);
462 rc
= put_entry(buf
, sizeof(u32
), 3, fp
);
467 last_startbit
= INT_MIN
;
468 ebitmap_for_each_positive_bit(e
, n
, bit
) {
469 if (rounddown(bit
, (int)BITS_PER_U64
) > last_startbit
) {
472 /* this is the very first bit */
474 last_startbit
= rounddown(bit
, BITS_PER_U64
);
475 map
= (u64
)1 << (bit
- last_startbit
);
479 /* write the last node */
480 buf
[0] = cpu_to_le32(last_startbit
);
481 rc
= put_entry(buf
, sizeof(u32
), 1, fp
);
485 buf64
[0] = cpu_to_le64(map
);
486 rc
= put_entry(buf64
, sizeof(u64
), 1, fp
);
490 /* set up for the next node */
492 last_startbit
= rounddown(bit
, BITS_PER_U64
);
494 map
|= (u64
)1 << (bit
- last_startbit
);
496 /* write the last node */
500 /* write the last node */
501 buf
[0] = cpu_to_le32(last_startbit
);
502 rc
= put_entry(buf
, sizeof(u32
), 1, fp
);
506 buf64
[0] = cpu_to_le64(map
);
507 rc
= put_entry(buf64
, sizeof(u64
), 1, fp
);