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 */
217 * Check to see if all the bits set in e2 are also set in e1. Optionally,
218 * if last_e2bit is non-zero, the highest set bit in e2 cannot exceed
221 int ebitmap_contains(struct ebitmap
*e1
, struct ebitmap
*e2
, u32 last_e2bit
)
223 struct ebitmap_node
*n1
, *n2
;
226 if (e1
->highbit
< e2
->highbit
)
232 while (n1
&& n2
&& (n1
->startbit
<= n2
->startbit
)) {
233 if (n1
->startbit
< n2
->startbit
) {
237 for (i
= EBITMAP_UNIT_NUMS
- 1; (i
>= 0) && !n2
->maps
[i
]; )
238 i
--; /* Skip trailing NULL map entries */
239 if (last_e2bit
&& (i
>= 0)) {
240 u32 lastsetbit
= n2
->startbit
+ i
* EBITMAP_UNIT_SIZE
+
242 if (lastsetbit
> last_e2bit
)
247 if ((n1
->maps
[i
] & n2
->maps
[i
]) != n2
->maps
[i
])
262 int ebitmap_get_bit(struct ebitmap
*e
, unsigned long bit
)
264 struct ebitmap_node
*n
;
266 if (e
->highbit
< bit
)
270 while (n
&& (n
->startbit
<= bit
)) {
271 if ((n
->startbit
+ EBITMAP_SIZE
) > bit
)
272 return ebitmap_node_get_bit(n
, bit
);
279 int ebitmap_set_bit(struct ebitmap
*e
, unsigned long bit
, int value
)
281 struct ebitmap_node
*n
, *prev
, *new;
285 while (n
&& n
->startbit
<= bit
) {
286 if ((n
->startbit
+ EBITMAP_SIZE
) > bit
) {
288 ebitmap_node_set_bit(n
, bit
);
292 ebitmap_node_clr_bit(n
, bit
);
294 s
= find_first_bit(n
->maps
, EBITMAP_SIZE
);
295 if (s
< EBITMAP_SIZE
)
298 /* drop this node from the bitmap */
301 * this was the highest map
305 e
->highbit
= prev
->startbit
311 prev
->next
= n
->next
;
325 new = kzalloc(sizeof(*new), GFP_ATOMIC
);
329 new->startbit
= bit
- (bit
% EBITMAP_SIZE
);
330 ebitmap_node_set_bit(new, bit
);
333 /* this node will be the highest map within the bitmap */
334 e
->highbit
= new->startbit
+ EBITMAP_SIZE
;
337 new->next
= prev
->next
;
347 void ebitmap_destroy(struct ebitmap
*e
)
349 struct ebitmap_node
*n
, *temp
;
366 int ebitmap_read(struct ebitmap
*e
, void *fp
)
368 struct ebitmap_node
*n
= NULL
;
369 u32 mapunit
, count
, startbit
, index
;
376 rc
= next_entry(buf
, fp
, sizeof buf
);
380 mapunit
= le32_to_cpu(buf
[0]);
381 e
->highbit
= le32_to_cpu(buf
[1]);
382 count
= le32_to_cpu(buf
[2]);
384 if (mapunit
!= BITS_PER_U64
) {
385 printk(KERN_ERR
"SELinux: ebitmap: map size %u does not "
386 "match my size %Zd (high bit was %d)\n",
387 mapunit
, BITS_PER_U64
, e
->highbit
);
391 /* round up e->highbit */
392 e
->highbit
+= EBITMAP_SIZE
- 1;
393 e
->highbit
-= (e
->highbit
% EBITMAP_SIZE
);
400 for (i
= 0; i
< count
; i
++) {
401 rc
= next_entry(&startbit
, fp
, sizeof(u32
));
403 printk(KERN_ERR
"SELinux: ebitmap: truncated map\n");
406 startbit
= le32_to_cpu(startbit
);
408 if (startbit
& (mapunit
- 1)) {
409 printk(KERN_ERR
"SELinux: ebitmap start bit (%d) is "
410 "not a multiple of the map unit size (%u)\n",
414 if (startbit
> e
->highbit
- mapunit
) {
415 printk(KERN_ERR
"SELinux: ebitmap start bit (%d) is "
416 "beyond the end of the bitmap (%u)\n",
417 startbit
, (e
->highbit
- mapunit
));
421 if (!n
|| startbit
>= n
->startbit
+ EBITMAP_SIZE
) {
422 struct ebitmap_node
*tmp
;
423 tmp
= kzalloc(sizeof(*tmp
), GFP_KERNEL
);
426 "SELinux: ebitmap: out of memory\n");
431 tmp
->startbit
= startbit
- (startbit
% EBITMAP_SIZE
);
437 } else if (startbit
<= n
->startbit
) {
438 printk(KERN_ERR
"SELinux: ebitmap: start bit %d"
439 " comes after start bit %d\n",
440 startbit
, n
->startbit
);
444 rc
= next_entry(&map
, fp
, sizeof(u64
));
446 printk(KERN_ERR
"SELinux: ebitmap: truncated map\n");
449 map
= le64_to_cpu(map
);
451 index
= (startbit
- n
->startbit
) / EBITMAP_UNIT_SIZE
;
453 n
->maps
[index
++] = map
& (-1UL);
454 map
= EBITMAP_SHIFT_UNIT_SIZE(map
);
468 int ebitmap_write(struct ebitmap
*e
, void *fp
)
470 struct ebitmap_node
*n
;
474 int bit
, last_bit
, last_startbit
, rc
;
476 buf
[0] = cpu_to_le32(BITS_PER_U64
);
481 ebitmap_for_each_positive_bit(e
, n
, bit
) {
482 if (rounddown(bit
, (int)BITS_PER_U64
) > last_startbit
) {
484 last_startbit
= rounddown(bit
, BITS_PER_U64
);
486 last_bit
= roundup(bit
+ 1, BITS_PER_U64
);
488 buf
[1] = cpu_to_le32(last_bit
);
489 buf
[2] = cpu_to_le32(count
);
491 rc
= put_entry(buf
, sizeof(u32
), 3, fp
);
496 last_startbit
= INT_MIN
;
497 ebitmap_for_each_positive_bit(e
, n
, bit
) {
498 if (rounddown(bit
, (int)BITS_PER_U64
) > last_startbit
) {
501 /* this is the very first bit */
503 last_startbit
= rounddown(bit
, BITS_PER_U64
);
504 map
= (u64
)1 << (bit
- last_startbit
);
508 /* write the last node */
509 buf
[0] = cpu_to_le32(last_startbit
);
510 rc
= put_entry(buf
, sizeof(u32
), 1, fp
);
514 buf64
[0] = cpu_to_le64(map
);
515 rc
= put_entry(buf64
, sizeof(u64
), 1, fp
);
519 /* set up for the next node */
521 last_startbit
= rounddown(bit
, BITS_PER_U64
);
523 map
|= (u64
)1 << (bit
- last_startbit
);
525 /* write the last node */
529 /* write the last node */
530 buf
[0] = cpu_to_le32(last_startbit
);
531 rc
= put_entry(buf
, sizeof(u32
), 1, fp
);
535 buf64
[0] = cpu_to_le64(map
);
536 rc
= put_entry(buf64
, sizeof(u64
), 1, fp
);