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_secattr_catmap
**catmap
)
91 struct ebitmap_node
*e_iter
= ebmap
->node
;
92 struct netlbl_lsm_secattr_catmap
*c_iter
;
93 u32 cmap_idx
, cmap_sft
;
96 /* NetLabel's NETLBL_CATMAP_MAPTYPE is defined as an array of u64,
97 * however, it is not always compatible with an array of unsigned long
99 * In addition, you should pay attention the following implementation
100 * assumes unsigned long has a width equal with or less than 64-bit.
103 if (e_iter
== NULL
) {
108 c_iter
= netlbl_secattr_catmap_alloc(GFP_ATOMIC
);
112 c_iter
->startbit
= e_iter
->startbit
& ~(NETLBL_CATMAP_SIZE
- 1);
115 for (i
= 0; i
< EBITMAP_UNIT_NUMS
; i
++) {
116 unsigned int delta
, e_startbit
, c_endbit
;
118 e_startbit
= e_iter
->startbit
+ i
* EBITMAP_UNIT_SIZE
;
119 c_endbit
= c_iter
->startbit
+ NETLBL_CATMAP_SIZE
;
120 if (e_startbit
>= c_endbit
) {
122 = netlbl_secattr_catmap_alloc(GFP_ATOMIC
);
123 if (c_iter
->next
== NULL
)
124 goto netlbl_export_failure
;
125 c_iter
= c_iter
->next
;
127 = e_startbit
& ~(NETLBL_CATMAP_SIZE
- 1);
129 delta
= e_startbit
- c_iter
->startbit
;
130 cmap_idx
= delta
/ NETLBL_CATMAP_MAPSIZE
;
131 cmap_sft
= delta
% NETLBL_CATMAP_MAPSIZE
;
132 c_iter
->bitmap
[cmap_idx
]
133 |= e_iter
->maps
[i
] << cmap_sft
;
135 e_iter
= e_iter
->next
;
140 netlbl_export_failure
:
141 netlbl_secattr_catmap_free(*catmap
);
146 * ebitmap_netlbl_import - Import a NetLabel category bitmap into an ebitmap
147 * @ebmap: the ebitmap to import
148 * @catmap: the NetLabel category bitmap
151 * Import a NetLabel category bitmap into a SELinux extensibile bitmap.
152 * Returns zero on success, negative values on error.
155 int ebitmap_netlbl_import(struct ebitmap
*ebmap
,
156 struct netlbl_lsm_secattr_catmap
*catmap
)
158 struct ebitmap_node
*e_iter
= NULL
;
159 struct ebitmap_node
*emap_prev
= NULL
;
160 struct netlbl_lsm_secattr_catmap
*c_iter
= catmap
;
161 u32 c_idx
, c_pos
, e_idx
, e_sft
;
163 /* NetLabel's NETLBL_CATMAP_MAPTYPE is defined as an array of u64,
164 * however, it is not always compatible with an array of unsigned long
166 * In addition, you should pay attention the following implementation
167 * assumes unsigned long has a width equal with or less than 64-bit.
171 for (c_idx
= 0; c_idx
< NETLBL_CATMAP_MAPCNT
; c_idx
++) {
173 u64 map
= c_iter
->bitmap
[c_idx
];
178 c_pos
= c_iter
->startbit
179 + c_idx
* NETLBL_CATMAP_MAPSIZE
;
181 || c_pos
>= e_iter
->startbit
+ EBITMAP_SIZE
) {
182 e_iter
= kzalloc(sizeof(*e_iter
), GFP_ATOMIC
);
184 goto netlbl_import_failure
;
186 = c_pos
- (c_pos
% EBITMAP_SIZE
);
187 if (emap_prev
== NULL
)
188 ebmap
->node
= e_iter
;
190 emap_prev
->next
= e_iter
;
193 delta
= c_pos
- e_iter
->startbit
;
194 e_idx
= delta
/ EBITMAP_UNIT_SIZE
;
195 e_sft
= delta
% EBITMAP_UNIT_SIZE
;
197 e_iter
->maps
[e_idx
++] |= map
& (-1UL);
198 map
= EBITMAP_SHIFT_UNIT_SIZE(map
);
201 c_iter
= c_iter
->next
;
204 ebmap
->highbit
= e_iter
->startbit
+ EBITMAP_SIZE
;
206 ebitmap_destroy(ebmap
);
210 netlbl_import_failure
:
211 ebitmap_destroy(ebmap
);
214 #endif /* CONFIG_NETLABEL */
216 int ebitmap_contains(struct ebitmap
*e1
, struct ebitmap
*e2
)
218 struct ebitmap_node
*n1
, *n2
;
221 if (e1
->highbit
< e2
->highbit
)
226 while (n1
&& n2
&& (n1
->startbit
<= n2
->startbit
)) {
227 if (n1
->startbit
< n2
->startbit
) {
231 for (i
= 0; i
< EBITMAP_UNIT_NUMS
; i
++) {
232 if ((n1
->maps
[i
] & n2
->maps
[i
]) != n2
->maps
[i
])
246 int ebitmap_get_bit(struct ebitmap
*e
, unsigned long bit
)
248 struct ebitmap_node
*n
;
250 if (e
->highbit
< bit
)
254 while (n
&& (n
->startbit
<= bit
)) {
255 if ((n
->startbit
+ EBITMAP_SIZE
) > bit
)
256 return ebitmap_node_get_bit(n
, bit
);
263 int ebitmap_set_bit(struct ebitmap
*e
, unsigned long bit
, int value
)
265 struct ebitmap_node
*n
, *prev
, *new;
269 while (n
&& n
->startbit
<= bit
) {
270 if ((n
->startbit
+ EBITMAP_SIZE
) > bit
) {
272 ebitmap_node_set_bit(n
, bit
);
276 ebitmap_node_clr_bit(n
, bit
);
278 s
= find_first_bit(n
->maps
, EBITMAP_SIZE
);
279 if (s
< EBITMAP_SIZE
)
282 /* drop this node from the bitmap */
285 * this was the highest map
289 e
->highbit
= prev
->startbit
295 prev
->next
= n
->next
;
309 new = kzalloc(sizeof(*new), GFP_ATOMIC
);
313 new->startbit
= bit
- (bit
% EBITMAP_SIZE
);
314 ebitmap_node_set_bit(new, bit
);
317 /* this node will be the highest map within the bitmap */
318 e
->highbit
= new->startbit
+ EBITMAP_SIZE
;
321 new->next
= prev
->next
;
331 void ebitmap_destroy(struct ebitmap
*e
)
333 struct ebitmap_node
*n
, *temp
;
350 int ebitmap_read(struct ebitmap
*e
, void *fp
)
352 struct ebitmap_node
*n
= NULL
;
353 u32 mapunit
, count
, startbit
, index
;
360 rc
= next_entry(buf
, fp
, sizeof buf
);
364 mapunit
= le32_to_cpu(buf
[0]);
365 e
->highbit
= le32_to_cpu(buf
[1]);
366 count
= le32_to_cpu(buf
[2]);
368 if (mapunit
!= BITS_PER_U64
) {
369 printk(KERN_ERR
"SELinux: ebitmap: map size %u does not "
370 "match my size %Zd (high bit was %d)\n",
371 mapunit
, BITS_PER_U64
, e
->highbit
);
375 /* round up e->highbit */
376 e
->highbit
+= EBITMAP_SIZE
- 1;
377 e
->highbit
-= (e
->highbit
% EBITMAP_SIZE
);
384 for (i
= 0; i
< count
; i
++) {
385 rc
= next_entry(&startbit
, fp
, sizeof(u32
));
387 printk(KERN_ERR
"SELinux: ebitmap: truncated map\n");
390 startbit
= le32_to_cpu(startbit
);
392 if (startbit
& (mapunit
- 1)) {
393 printk(KERN_ERR
"SELinux: ebitmap start bit (%d) is "
394 "not a multiple of the map unit size (%u)\n",
398 if (startbit
> e
->highbit
- mapunit
) {
399 printk(KERN_ERR
"SELinux: ebitmap start bit (%d) is "
400 "beyond the end of the bitmap (%u)\n",
401 startbit
, (e
->highbit
- mapunit
));
405 if (!n
|| startbit
>= n
->startbit
+ EBITMAP_SIZE
) {
406 struct ebitmap_node
*tmp
;
407 tmp
= kzalloc(sizeof(*tmp
), GFP_KERNEL
);
410 "SELinux: ebitmap: out of memory\n");
415 tmp
->startbit
= startbit
- (startbit
% EBITMAP_SIZE
);
421 } else if (startbit
<= n
->startbit
) {
422 printk(KERN_ERR
"SELinux: ebitmap: start bit %d"
423 " comes after start bit %d\n",
424 startbit
, n
->startbit
);
428 rc
= next_entry(&map
, fp
, sizeof(u64
));
430 printk(KERN_ERR
"SELinux: ebitmap: truncated map\n");
433 map
= le64_to_cpu(map
);
435 index
= (startbit
- n
->startbit
) / EBITMAP_UNIT_SIZE
;
437 n
->maps
[index
++] = map
& (-1UL);
438 map
= EBITMAP_SHIFT_UNIT_SIZE(map
);
452 int ebitmap_write(struct ebitmap
*e
, void *fp
)
454 struct ebitmap_node
*n
;
458 int bit
, last_bit
, last_startbit
, rc
;
460 buf
[0] = cpu_to_le32(BITS_PER_U64
);
465 ebitmap_for_each_positive_bit(e
, n
, bit
) {
466 if (rounddown(bit
, (int)BITS_PER_U64
) > last_startbit
) {
468 last_startbit
= rounddown(bit
, BITS_PER_U64
);
470 last_bit
= roundup(bit
+ 1, BITS_PER_U64
);
472 buf
[1] = cpu_to_le32(last_bit
);
473 buf
[2] = cpu_to_le32(count
);
475 rc
= put_entry(buf
, sizeof(u32
), 3, fp
);
480 last_startbit
= INT_MIN
;
481 ebitmap_for_each_positive_bit(e
, n
, bit
) {
482 if (rounddown(bit
, (int)BITS_PER_U64
) > last_startbit
) {
485 /* this is the very first bit */
487 last_startbit
= rounddown(bit
, BITS_PER_U64
);
488 map
= (u64
)1 << (bit
- last_startbit
);
492 /* write the last node */
493 buf
[0] = cpu_to_le32(last_startbit
);
494 rc
= put_entry(buf
, sizeof(u32
), 1, fp
);
498 buf64
[0] = cpu_to_le64(map
);
499 rc
= put_entry(buf64
, sizeof(u64
), 1, fp
);
503 /* set up for the next node */
505 last_startbit
= rounddown(bit
, BITS_PER_U64
);
507 map
|= (u64
)1 << (bit
- last_startbit
);
509 /* write the last node */
513 /* write the last node */
514 buf
[0] = cpu_to_le32(last_startbit
);
515 rc
= put_entry(buf
, sizeof(u32
), 1, fp
);
519 buf64
[0] = cpu_to_le64(map
);
520 rc
= put_entry(buf64
, sizeof(u64
), 1, fp
);