2 * Implementation of the extensible bitmap type.
4 * Author : Stephen Smalley, <sds@epoch.ncsc.mil>
7 * Updated: Hewlett-Packard <paul.moore@hp.com>
9 * Added support to import/export the NetLabel category bitmap
11 * (c) Copyright Hewlett-Packard Development Company, L.P., 2006
14 #include <linux/kernel.h>
15 #include <linux/slab.h>
16 #include <linux/errno.h>
17 #include <net/netlabel.h>
21 int ebitmap_cmp(struct ebitmap
*e1
, struct ebitmap
*e2
)
23 struct ebitmap_node
*n1
, *n2
;
25 if (e1
->highbit
!= e2
->highbit
)
31 (n1
->startbit
== n2
->startbit
) &&
32 (n1
->map
== n2
->map
)) {
43 int ebitmap_cpy(struct ebitmap
*dst
, struct ebitmap
*src
)
45 struct ebitmap_node
*n
, *new, *prev
;
51 new = kzalloc(sizeof(*new), GFP_ATOMIC
);
56 new->startbit
= n
->startbit
;
67 dst
->highbit
= src
->highbit
;
71 #ifdef CONFIG_NETLABEL
73 * ebitmap_netlbl_export - Export an ebitmap into a NetLabel category bitmap
74 * @ebmap: the ebitmap to export
75 * @catmap: the NetLabel category bitmap
78 * Export a SELinux extensibile bitmap into a NetLabel category bitmap.
79 * Returns zero on success, negative values on error.
82 int ebitmap_netlbl_export(struct ebitmap
*ebmap
,
83 struct netlbl_lsm_secattr_catmap
**catmap
)
85 struct ebitmap_node
*e_iter
= ebmap
->node
;
86 struct netlbl_lsm_secattr_catmap
*c_iter
;
89 /* This function is a much simpler because SELinux's MAPTYPE happens
90 * to be the same as NetLabel's NETLBL_CATMAP_MAPTYPE, if MAPTYPE is
91 * changed from a u64 this function will most likely need to be changed
92 * as well. It's not ideal but I think the tradeoff in terms of
93 * neatness and speed is worth it. */
100 c_iter
= netlbl_secattr_catmap_alloc(GFP_ATOMIC
);
104 c_iter
->startbit
= e_iter
->startbit
& ~(NETLBL_CATMAP_SIZE
- 1);
106 while (e_iter
!= NULL
) {
107 if (e_iter
->startbit
>=
108 (c_iter
->startbit
+ NETLBL_CATMAP_SIZE
)) {
109 c_iter
->next
= netlbl_secattr_catmap_alloc(GFP_ATOMIC
);
110 if (c_iter
->next
== NULL
)
111 goto netlbl_export_failure
;
112 c_iter
= c_iter
->next
;
113 c_iter
->startbit
= e_iter
->startbit
&
114 ~(NETLBL_CATMAP_SIZE
- 1);
116 cmap_idx
= (e_iter
->startbit
- c_iter
->startbit
) /
117 NETLBL_CATMAP_MAPSIZE
;
118 c_iter
->bitmap
[cmap_idx
] = e_iter
->map
;
119 e_iter
= e_iter
->next
;
124 netlbl_export_failure
:
125 netlbl_secattr_catmap_free(*catmap
);
130 * ebitmap_netlbl_import - Import a NetLabel category bitmap into an ebitmap
131 * @ebmap: the ebitmap to export
132 * @catmap: the NetLabel category bitmap
135 * Import a NetLabel category bitmap into a SELinux extensibile bitmap.
136 * Returns zero on success, negative values on error.
139 int ebitmap_netlbl_import(struct ebitmap
*ebmap
,
140 struct netlbl_lsm_secattr_catmap
*catmap
)
142 struct ebitmap_node
*e_iter
= NULL
;
143 struct ebitmap_node
*emap_prev
= NULL
;
144 struct netlbl_lsm_secattr_catmap
*c_iter
= catmap
;
147 /* This function is a much simpler because SELinux's MAPTYPE happens
148 * to be the same as NetLabel's NETLBL_CATMAP_MAPTYPE, if MAPTYPE is
149 * changed from a u64 this function will most likely need to be changed
150 * as well. It's not ideal but I think the tradeoff in terms of
151 * neatness and speed is worth it. */
154 for (c_idx
= 0; c_idx
< NETLBL_CATMAP_MAPCNT
; c_idx
++) {
155 if (c_iter
->bitmap
[c_idx
] == 0)
158 e_iter
= kzalloc(sizeof(*e_iter
), GFP_ATOMIC
);
160 goto netlbl_import_failure
;
161 if (emap_prev
== NULL
)
162 ebmap
->node
= e_iter
;
164 emap_prev
->next
= e_iter
;
167 e_iter
->startbit
= c_iter
->startbit
+
168 NETLBL_CATMAP_MAPSIZE
* c_idx
;
169 e_iter
->map
= c_iter
->bitmap
[c_idx
];
171 c_iter
= c_iter
->next
;
172 } while (c_iter
!= NULL
);
174 ebmap
->highbit
= e_iter
->startbit
+ MAPSIZE
;
176 ebitmap_destroy(ebmap
);
180 netlbl_import_failure
:
181 ebitmap_destroy(ebmap
);
184 #endif /* CONFIG_NETLABEL */
186 int ebitmap_contains(struct ebitmap
*e1
, struct ebitmap
*e2
)
188 struct ebitmap_node
*n1
, *n2
;
190 if (e1
->highbit
< e2
->highbit
)
195 while (n1
&& n2
&& (n1
->startbit
<= n2
->startbit
)) {
196 if (n1
->startbit
< n2
->startbit
) {
200 if ((n1
->map
& n2
->map
) != n2
->map
)
213 int ebitmap_get_bit(struct ebitmap
*e
, unsigned long bit
)
215 struct ebitmap_node
*n
;
217 if (e
->highbit
< bit
)
221 while (n
&& (n
->startbit
<= bit
)) {
222 if ((n
->startbit
+ MAPSIZE
) > bit
) {
223 if (n
->map
& (MAPBIT
<< (bit
- n
->startbit
)))
234 int ebitmap_set_bit(struct ebitmap
*e
, unsigned long bit
, int value
)
236 struct ebitmap_node
*n
, *prev
, *new;
240 while (n
&& n
->startbit
<= bit
) {
241 if ((n
->startbit
+ MAPSIZE
) > bit
) {
243 n
->map
|= (MAPBIT
<< (bit
- n
->startbit
));
245 n
->map
&= ~(MAPBIT
<< (bit
- n
->startbit
));
247 /* drop this node from the bitmap */
251 * this was the highest map
255 e
->highbit
= prev
->startbit
+ MAPSIZE
;
260 prev
->next
= n
->next
;
276 new = kzalloc(sizeof(*new), GFP_ATOMIC
);
280 new->startbit
= bit
& ~(MAPSIZE
- 1);
281 new->map
= (MAPBIT
<< (bit
- new->startbit
));
284 /* this node will be the highest map within the bitmap */
285 e
->highbit
= new->startbit
+ MAPSIZE
;
288 new->next
= prev
->next
;
298 void ebitmap_destroy(struct ebitmap
*e
)
300 struct ebitmap_node
*n
, *temp
;
317 int ebitmap_read(struct ebitmap
*e
, void *fp
)
320 struct ebitmap_node
*n
, *l
;
322 u32 mapsize
, count
, i
;
327 rc
= next_entry(buf
, fp
, sizeof buf
);
331 mapsize
= le32_to_cpu(buf
[0]);
332 e
->highbit
= le32_to_cpu(buf
[1]);
333 count
= le32_to_cpu(buf
[2]);
335 if (mapsize
!= MAPSIZE
) {
336 printk(KERN_ERR
"security: ebitmap: map size %u does not "
337 "match my size %Zd (high bit was %d)\n", mapsize
,
338 MAPSIZE
, e
->highbit
);
345 if (e
->highbit
& (MAPSIZE
- 1)) {
346 printk(KERN_ERR
"security: ebitmap: high bit (%d) is not a "
347 "multiple of the map size (%Zd)\n", e
->highbit
, MAPSIZE
);
351 for (i
= 0; i
< count
; i
++) {
352 rc
= next_entry(buf
, fp
, sizeof(u32
));
354 printk(KERN_ERR
"security: ebitmap: truncated map\n");
357 n
= kzalloc(sizeof(*n
), GFP_KERNEL
);
359 printk(KERN_ERR
"security: ebitmap: out of memory\n");
364 n
->startbit
= le32_to_cpu(buf
[0]);
366 if (n
->startbit
& (MAPSIZE
- 1)) {
367 printk(KERN_ERR
"security: ebitmap start bit (%d) is "
368 "not a multiple of the map size (%Zd)\n",
369 n
->startbit
, MAPSIZE
);
372 if (n
->startbit
> (e
->highbit
- MAPSIZE
)) {
373 printk(KERN_ERR
"security: ebitmap start bit (%d) is "
374 "beyond the end of the bitmap (%Zd)\n",
375 n
->startbit
, (e
->highbit
- MAPSIZE
));
378 rc
= next_entry(&map
, fp
, sizeof(u64
));
380 printk(KERN_ERR
"security: ebitmap: truncated map\n");
383 n
->map
= le64_to_cpu(map
);
386 printk(KERN_ERR
"security: ebitmap: null map in "
387 "ebitmap (startbit %d)\n", n
->startbit
);
391 if (n
->startbit
<= l
->startbit
) {
392 printk(KERN_ERR
"security: ebitmap: start "
393 "bit %d comes after start bit %d\n",
394 n
->startbit
, l
->startbit
);