/src/selinux/libsepol/src/ebitmap.c
Line | Count | Source |
1 | | |
2 | | /* Author : Stephen Smalley, <stephen.smalley.work@gmail.com> */ |
3 | | |
4 | | /* FLASK */ |
5 | | |
6 | | /* |
7 | | * Implementation of the extensible bitmap type. |
8 | | */ |
9 | | |
10 | | #include <stdlib.h> |
11 | | |
12 | | #include <sepol/policydb/ebitmap.h> |
13 | | #include <sepol/policydb/policydb.h> |
14 | | |
15 | | #include "debug.h" |
16 | | #include "private.h" |
17 | | |
18 | | int ebitmap_or(ebitmap_t *dst, const ebitmap_t *e1, const ebitmap_t *e2) |
19 | 1.83M | { |
20 | 1.83M | const ebitmap_node_t *n1, *n2; |
21 | 1.83M | ebitmap_node_t *new = NULL, **prev; |
22 | | |
23 | 1.83M | ebitmap_init(dst); |
24 | | |
25 | 1.83M | prev = &dst->node; |
26 | 1.83M | n1 = e1->node; |
27 | 1.83M | n2 = e2->node; |
28 | 6.82M | while (n1 || n2) { |
29 | 4.98M | new = (ebitmap_node_t *)malloc(sizeof(ebitmap_node_t)); |
30 | 4.98M | if (!new) { |
31 | 0 | ebitmap_destroy(dst); |
32 | 0 | return -ENOMEM; |
33 | 0 | } |
34 | 4.98M | if (n1 && n2 && n1->startbit == n2->startbit) { |
35 | 865k | new->startbit = n1->startbit; |
36 | 865k | new->map = n1->map | n2->map; |
37 | 865k | n1 = n1->next; |
38 | 865k | n2 = n2->next; |
39 | 4.12M | } else if (!n2 || (n1 && n1->startbit < n2->startbit)) { |
40 | 635k | new->startbit = n1->startbit; |
41 | 635k | new->map = n1->map; |
42 | 635k | n1 = n1->next; |
43 | 3.48M | } else { |
44 | 3.48M | new->startbit = n2->startbit; |
45 | 3.48M | new->map = n2->map; |
46 | 3.48M | n2 = n2->next; |
47 | 3.48M | } |
48 | | |
49 | 4.98M | new->next = NULL; |
50 | | |
51 | 4.98M | *prev = new; |
52 | 4.98M | prev = &new->next; |
53 | 4.98M | } |
54 | | |
55 | 1.83M | dst->highbit = (e1->highbit > e2->highbit) ? e1->highbit : e2->highbit; |
56 | 1.83M | return 0; |
57 | 1.83M | } |
58 | | |
59 | | int ebitmap_union(ebitmap_t *dst, const ebitmap_t *e1) |
60 | 1.48M | { |
61 | 1.48M | ebitmap_t tmp; |
62 | | |
63 | 1.48M | if (ebitmap_or(&tmp, dst, e1)) |
64 | 0 | return -1; |
65 | 1.48M | ebitmap_destroy(dst); |
66 | 1.48M | dst->node = tmp.node; |
67 | 1.48M | dst->highbit = tmp.highbit; |
68 | | |
69 | 1.48M | return 0; |
70 | 1.48M | } |
71 | | |
72 | | int ebitmap_and(ebitmap_t *dst, const ebitmap_t *e1, const ebitmap_t *e2) |
73 | 3.60M | { |
74 | 3.60M | const ebitmap_node_t *n1, *n2; |
75 | 3.60M | ebitmap_node_t *new = NULL, **prev; |
76 | | |
77 | 3.60M | ebitmap_init(dst); |
78 | | |
79 | 3.60M | prev = &dst->node; |
80 | 3.60M | n1 = e1->node; |
81 | 3.60M | n2 = e2->node; |
82 | 12.4M | while (n1 && n2) { |
83 | 8.84M | if (n1->startbit == n2->startbit) { |
84 | 6.36M | if (n1->map & n2->map) { |
85 | 5.15M | new = malloc(sizeof(ebitmap_node_t)); |
86 | 5.15M | if (!new) { |
87 | 0 | ebitmap_destroy(dst); |
88 | 0 | return -ENOMEM; |
89 | 0 | } |
90 | 5.15M | new->startbit = n1->startbit; |
91 | 5.15M | new->map = n1->map & n2->map; |
92 | 5.15M | new->next = NULL; |
93 | | |
94 | 5.15M | *prev = new; |
95 | 5.15M | prev = &new->next; |
96 | 5.15M | } |
97 | | |
98 | 6.36M | n1 = n1->next; |
99 | 6.36M | n2 = n2->next; |
100 | 6.36M | } else if (n1->startbit > n2->startbit) { |
101 | 313k | n2 = n2->next; |
102 | 2.17M | } else { |
103 | 2.17M | n1 = n1->next; |
104 | 2.17M | } |
105 | 8.84M | } |
106 | | |
107 | 3.60M | if (new) |
108 | 2.59M | dst->highbit = new->startbit + MAPSIZE; |
109 | | |
110 | 3.60M | return 0; |
111 | 3.60M | } |
112 | | |
113 | | int ebitmap_xor(ebitmap_t *dst, const ebitmap_t *e1, const ebitmap_t *e2) |
114 | 2.13k | { |
115 | 2.13k | const ebitmap_node_t *n1, *n2; |
116 | 2.13k | ebitmap_node_t *new = NULL, **prev; |
117 | 2.13k | uint32_t startbit; |
118 | 2.13k | MAPTYPE map; |
119 | | |
120 | 2.13k | ebitmap_init(dst); |
121 | | |
122 | 2.13k | prev = &dst->node; |
123 | 2.13k | n1 = e1->node; |
124 | 2.13k | n2 = e2->node; |
125 | 44.8k | while (n1 || n2) { |
126 | 42.7k | if (n1 && n2 && n1->startbit == n2->startbit) { |
127 | 2.97k | startbit = n1->startbit; |
128 | 2.97k | map = n1->map ^ n2->map; |
129 | 2.97k | n1 = n1->next; |
130 | 2.97k | n2 = n2->next; |
131 | 39.7k | } else if (!n2 || (n1 && n1->startbit < n2->startbit)) { |
132 | 24.4k | startbit = n1->startbit; |
133 | 24.4k | map = n1->map; |
134 | 24.4k | n1 = n1->next; |
135 | 24.4k | } else { |
136 | 15.2k | startbit = n2->startbit; |
137 | 15.2k | map = n2->map; |
138 | 15.2k | n2 = n2->next; |
139 | 15.2k | } |
140 | | |
141 | 42.7k | if (map != 0) { |
142 | 41.2k | new = malloc(sizeof(ebitmap_node_t)); |
143 | 41.2k | if (!new) { |
144 | 0 | ebitmap_destroy(dst); |
145 | 0 | return -ENOMEM; |
146 | 0 | } |
147 | 41.2k | new->startbit = startbit; |
148 | 41.2k | new->map = map; |
149 | 41.2k | new->next = NULL; |
150 | | |
151 | 41.2k | *prev = new; |
152 | 41.2k | prev = &new->next; |
153 | 41.2k | } |
154 | 42.7k | } |
155 | | |
156 | 2.13k | if (new) |
157 | 1.87k | dst->highbit = new->startbit + MAPSIZE; |
158 | | |
159 | 2.13k | return 0; |
160 | 2.13k | } |
161 | | |
162 | | int ebitmap_not(ebitmap_t *dst, const ebitmap_t *e1, unsigned int maxbit) |
163 | 171k | { |
164 | 171k | const ebitmap_node_t *n; |
165 | 171k | ebitmap_node_t *new = NULL, **prev; |
166 | 171k | uint32_t startbit, cur_startbit; |
167 | 171k | MAPTYPE map; |
168 | | |
169 | 171k | ebitmap_init(dst); |
170 | | |
171 | 171k | prev = &dst->node; |
172 | 171k | n = e1->node; |
173 | 2.19M | for (cur_startbit = 0; cur_startbit < maxbit; cur_startbit += MAPSIZE) { |
174 | 2.01M | if (n && n->startbit == cur_startbit) { |
175 | 637k | startbit = n->startbit; |
176 | 637k | map = ~n->map; |
177 | | |
178 | 637k | n = n->next; |
179 | 1.38M | } else { |
180 | 1.38M | startbit = cur_startbit; |
181 | 1.38M | map = ~((MAPTYPE)0); |
182 | 1.38M | } |
183 | | |
184 | 2.01M | if (maxbit - cur_startbit < MAPSIZE) |
185 | 37.5k | map &= (((MAPTYPE)1) << (maxbit - cur_startbit)) - 1; |
186 | | |
187 | 2.01M | if (map != 0) { |
188 | 1.63M | new = malloc(sizeof(ebitmap_node_t)); |
189 | 1.63M | if (!new) { |
190 | 0 | ebitmap_destroy(dst); |
191 | 0 | return -ENOMEM; |
192 | 0 | } |
193 | | |
194 | 1.63M | new->startbit = startbit; |
195 | 1.63M | new->map = map; |
196 | 1.63M | new->next = NULL; |
197 | | |
198 | 1.63M | *prev = new; |
199 | 1.63M | prev = &new->next; |
200 | 1.63M | } |
201 | 2.01M | } |
202 | | |
203 | 171k | if (new) |
204 | 169k | dst->highbit = new->startbit + MAPSIZE; |
205 | | |
206 | 171k | return 0; |
207 | 171k | } |
208 | | |
209 | | int ebitmap_andnot(ebitmap_t *dst, const ebitmap_t *e1, const ebitmap_t *e2, |
210 | | unsigned int maxbit) |
211 | 132k | { |
212 | 132k | int rc; |
213 | 132k | ebitmap_t e3; |
214 | 132k | ebitmap_init(dst); |
215 | 132k | rc = ebitmap_not(&e3, e2, maxbit); |
216 | 132k | if (rc < 0) |
217 | 0 | return rc; |
218 | 132k | rc = ebitmap_and(dst, e1, &e3); |
219 | 132k | ebitmap_destroy(&e3); |
220 | 132k | if (rc < 0) |
221 | 0 | return rc; |
222 | 132k | return 0; |
223 | 132k | } |
224 | | |
225 | | unsigned int ebitmap_cardinality(const ebitmap_t *e1) |
226 | 2.29M | { |
227 | 2.29M | unsigned int count = 0; |
228 | 2.29M | const ebitmap_node_t *n; |
229 | | |
230 | 6.38M | for (n = e1->node; n; n = n->next) { |
231 | 4.09M | count += __builtin_popcountll(n->map); |
232 | 4.09M | } |
233 | 2.29M | return count; |
234 | 2.29M | } |
235 | | |
236 | | int ebitmap_hamming_distance(const ebitmap_t *e1, const ebitmap_t *e2) |
237 | 0 | { |
238 | 0 | int rc; |
239 | 0 | ebitmap_t tmp; |
240 | 0 | int distance; |
241 | 0 | if (ebitmap_cmp(e1, e2)) |
242 | 0 | return 0; |
243 | 0 | rc = ebitmap_xor(&tmp, e1, e2); |
244 | 0 | if (rc < 0) |
245 | 0 | return -1; |
246 | 0 | distance = ebitmap_cardinality(&tmp); |
247 | 0 | ebitmap_destroy(&tmp); |
248 | 0 | return distance; |
249 | 0 | } |
250 | | |
251 | | int ebitmap_cmp(const ebitmap_t *e1, const ebitmap_t *e2) |
252 | 18.7M | { |
253 | 18.7M | const ebitmap_node_t *n1, *n2; |
254 | | |
255 | 18.7M | if (e1->highbit != e2->highbit) |
256 | 2.90M | return 0; |
257 | | |
258 | 15.8M | n1 = e1->node; |
259 | 15.8M | n2 = e2->node; |
260 | 46.1M | while (n1 && n2 && (n1->startbit == n2->startbit) && |
261 | 41.6M | (n1->map == n2->map)) { |
262 | 30.2M | n1 = n1->next; |
263 | 30.2M | n2 = n2->next; |
264 | 30.2M | } |
265 | | |
266 | 15.8M | if (n1 || n2) |
267 | 11.5M | return 0; |
268 | | |
269 | 4.27M | return 1; |
270 | 15.8M | } |
271 | | |
272 | | int ebitmap_cpy(ebitmap_t *dst, const ebitmap_t *src) |
273 | 397k | { |
274 | 397k | const ebitmap_node_t *n; |
275 | 397k | ebitmap_node_t *new = NULL, **prev; |
276 | | |
277 | 397k | ebitmap_init(dst); |
278 | 397k | n = src->node; |
279 | 397k | prev = &dst->node; |
280 | 2.09M | while (n) { |
281 | 1.69M | new = (ebitmap_node_t *)malloc(sizeof(ebitmap_node_t)); |
282 | 1.69M | if (!new) { |
283 | 0 | ebitmap_destroy(dst); |
284 | 0 | return -ENOMEM; |
285 | 0 | } |
286 | 1.69M | new->startbit = n->startbit; |
287 | 1.69M | new->map = n->map; |
288 | 1.69M | new->next = NULL; |
289 | | |
290 | 1.69M | *prev = new; |
291 | 1.69M | prev = &new->next; |
292 | | |
293 | 1.69M | n = n->next; |
294 | 1.69M | } |
295 | | |
296 | 397k | dst->highbit = src->highbit; |
297 | 397k | return 0; |
298 | 397k | } |
299 | | |
300 | | int ebitmap_contains(const ebitmap_t *e1, const ebitmap_t *e2) |
301 | 21.9M | { |
302 | 21.9M | const ebitmap_node_t *n1, *n2; |
303 | | |
304 | 21.9M | if (e1->highbit < e2->highbit) |
305 | 5.90M | return 0; |
306 | | |
307 | 16.0M | n1 = e1->node; |
308 | 16.0M | n2 = e2->node; |
309 | 29.0M | while (n1 && n2 && (n1->startbit <= n2->startbit)) { |
310 | 13.2M | if (n1->startbit < n2->startbit) { |
311 | 609k | n1 = n1->next; |
312 | 609k | continue; |
313 | 609k | } |
314 | 12.6M | if ((n1->map & n2->map) != n2->map) |
315 | 188k | return 0; |
316 | | |
317 | 12.4M | n1 = n1->next; |
318 | 12.4M | n2 = n2->next; |
319 | 12.4M | } |
320 | | |
321 | 15.8M | if (n2) |
322 | 4.77M | return 0; |
323 | | |
324 | 11.0M | return 1; |
325 | 15.8M | } |
326 | | |
327 | | int ebitmap_match_any(const ebitmap_t *e1, const ebitmap_t *e2) |
328 | 19.7M | { |
329 | 19.7M | const ebitmap_node_t *n1 = e1->node; |
330 | 19.7M | const ebitmap_node_t *n2 = e2->node; |
331 | | |
332 | 43.9M | while (n1 && n2) { |
333 | 27.7M | if (n1->startbit < n2->startbit) { |
334 | 11.7M | n1 = n1->next; |
335 | 16.0M | } else if (n2->startbit < n1->startbit) { |
336 | 8.39M | n2 = n2->next; |
337 | 8.39M | } else { |
338 | 7.65M | if (n1->map & n2->map) { |
339 | 3.62M | return 1; |
340 | 3.62M | } |
341 | 4.02M | n1 = n1->next; |
342 | 4.02M | n2 = n2->next; |
343 | 4.02M | } |
344 | 27.7M | } |
345 | | |
346 | 16.1M | return 0; |
347 | 19.7M | } |
348 | | |
349 | | int ebitmap_get_bit(const ebitmap_t *e, unsigned int bit) |
350 | 30.8M | { |
351 | 30.8M | const ebitmap_node_t *n; |
352 | | |
353 | 30.8M | if (e->highbit < bit) |
354 | 5.76M | return 0; |
355 | | |
356 | 25.0M | n = e->node; |
357 | 2.39G | while (n && (n->startbit <= bit)) { |
358 | 2.39G | if ((n->startbit + MAPSIZE) > bit) { |
359 | 20.0M | if (n->map & (MAPBIT << (bit - n->startbit))) |
360 | 16.3M | return 1; |
361 | 3.70M | else |
362 | 3.70M | return 0; |
363 | 20.0M | } |
364 | 2.37G | n = n->next; |
365 | 2.37G | } |
366 | | |
367 | 4.99M | return 0; |
368 | 25.0M | } |
369 | | |
370 | | int ebitmap_set_bit(ebitmap_t *e, unsigned int bit, int value) |
371 | 22.8M | { |
372 | 22.8M | ebitmap_node_t *n, *prev, *new; |
373 | 22.8M | uint32_t startbit = bit & ~(MAPSIZE - 1); |
374 | 22.8M | uint32_t highbit = startbit + MAPSIZE; |
375 | | |
376 | 22.8M | if (highbit == 0) { |
377 | 12 | ERR(NULL, "bitmap overflow, bit 0x%x", bit); |
378 | 12 | return -EINVAL; |
379 | 12 | } |
380 | | |
381 | 22.8M | prev = NULL; |
382 | 22.8M | n = e->node; |
383 | 457M | while (n && n->startbit <= bit) { |
384 | 450M | if ((n->startbit + MAPSIZE) > bit) { |
385 | 15.8M | if (value) { |
386 | 15.7M | n->map |= (MAPBIT << (bit - n->startbit)); |
387 | 15.7M | } else { |
388 | 118k | n->map &= ~(MAPBIT << (bit - n->startbit)); |
389 | 118k | if (!n->map) { |
390 | | /* drop this node from the bitmap */ |
391 | | |
392 | 4.08k | if (!n->next) { |
393 | | /* |
394 | | * this was the highest map |
395 | | * within the bitmap |
396 | | */ |
397 | 3.16k | if (prev) |
398 | 2.60k | e->highbit = |
399 | 2.60k | prev->startbit + |
400 | 2.60k | MAPSIZE; |
401 | 562 | else |
402 | 562 | e->highbit = 0; |
403 | 3.16k | } |
404 | 4.08k | if (prev) |
405 | 3.37k | prev->next = n->next; |
406 | 713 | else |
407 | 713 | e->node = n->next; |
408 | | |
409 | 4.08k | free(n); |
410 | 4.08k | } |
411 | 118k | } |
412 | 15.8M | return 0; |
413 | 15.8M | } |
414 | 434M | prev = n; |
415 | 434M | n = n->next; |
416 | 434M | } |
417 | | |
418 | 7.01M | if (!value) |
419 | 1.88k | return 0; |
420 | | |
421 | 7.01M | new = (ebitmap_node_t *)malloc(sizeof(ebitmap_node_t)); |
422 | 7.01M | if (!new) |
423 | 0 | return -ENOMEM; |
424 | | |
425 | 7.01M | new->startbit = startbit; |
426 | 7.01M | new->map = (MAPBIT << (bit - new->startbit)); |
427 | | |
428 | 7.01M | if (!n) { |
429 | | /* this node will be the highest map within the bitmap */ |
430 | 6.96M | e->highbit = highbit; |
431 | 6.96M | } |
432 | | |
433 | 7.01M | if (prev) { |
434 | 164k | new->next = prev->next; |
435 | 164k | prev->next = new; |
436 | 6.85M | } else { |
437 | 6.85M | new->next = e->node; |
438 | 6.85M | e->node = new; |
439 | 6.85M | } |
440 | | |
441 | 7.01M | return 0; |
442 | 7.01M | } |
443 | | |
444 | | int ebitmap_init_range(ebitmap_t *e, unsigned int minbit, unsigned int maxbit) |
445 | 60.5k | { |
446 | 60.5k | ebitmap_node_t *new = NULL, **prev; |
447 | 60.5k | uint32_t minstartbit = minbit & ~(MAPSIZE - 1); |
448 | 60.5k | uint32_t maxstartbit = maxbit & ~(MAPSIZE - 1); |
449 | 60.5k | uint32_t minhighbit = minstartbit + MAPSIZE; |
450 | 60.5k | uint32_t maxhighbit = maxstartbit + MAPSIZE; |
451 | 60.5k | uint32_t startbit; |
452 | 60.5k | MAPTYPE mask; |
453 | | |
454 | 60.5k | ebitmap_init(e); |
455 | | |
456 | 60.5k | if (minbit > maxbit) |
457 | 707 | return -EINVAL; |
458 | | |
459 | 59.8k | if (minhighbit == 0 || maxhighbit == 0) |
460 | 32 | return -EOVERFLOW; |
461 | | |
462 | 59.8k | prev = &e->node; |
463 | | |
464 | 448k | for (startbit = minstartbit; startbit <= maxstartbit; |
465 | 388k | startbit += MAPSIZE) { |
466 | 388k | new = malloc(sizeof(ebitmap_node_t)); |
467 | 388k | if (!new) |
468 | 0 | return -ENOMEM; |
469 | | |
470 | 388k | new->next = NULL; |
471 | 388k | new->startbit = startbit; |
472 | | |
473 | 388k | if (startbit != minstartbit && startbit != maxstartbit) { |
474 | 314k | new->map = ~((MAPTYPE)0); |
475 | 314k | } else if (startbit != maxstartbit) { |
476 | 13.9k | new->map = ~((MAPTYPE)0) << (minbit - startbit); |
477 | 59.8k | } else if (startbit != minstartbit) { |
478 | 13.9k | new->map = ~((MAPTYPE)0) >> |
479 | 13.9k | (MAPSIZE - (maxbit - startbit + 1)); |
480 | 45.8k | } else { |
481 | 45.8k | mask = ~((MAPTYPE)0) >> |
482 | 45.8k | (MAPSIZE - (maxbit - minbit + 1)); |
483 | 45.8k | new->map = (mask << (minbit - startbit)); |
484 | 45.8k | } |
485 | | |
486 | 388k | *prev = new; |
487 | 388k | prev = &new->next; |
488 | 388k | } |
489 | | |
490 | 59.8k | e->highbit = maxhighbit; |
491 | | |
492 | 59.8k | return 0; |
493 | 59.8k | } |
494 | | |
495 | | unsigned int ebitmap_highest_set_bit(const ebitmap_t *e) |
496 | 205k | { |
497 | 205k | const ebitmap_node_t *n; |
498 | 205k | MAPTYPE map; |
499 | 205k | unsigned int pos = 0; |
500 | | |
501 | 205k | n = e->node; |
502 | 205k | if (!n) |
503 | 1.50k | return 0; |
504 | | |
505 | 204k | while (n->next) |
506 | 82 | n = n->next; |
507 | | |
508 | 204k | map = n->map; |
509 | 3.89M | while (map >>= 1) |
510 | 3.68M | pos++; |
511 | | |
512 | 204k | return n->startbit + pos; |
513 | 205k | } |
514 | | |
515 | | void ebitmap_destroy(ebitmap_t *e) |
516 | 40.0M | { |
517 | 40.0M | ebitmap_node_t *n, *temp; |
518 | | |
519 | 40.0M | if (!e) |
520 | 50.6k | return; |
521 | | |
522 | 40.0M | n = e->node; |
523 | 61.0M | while (n) { |
524 | 20.9M | temp = n; |
525 | 20.9M | n = n->next; |
526 | 20.9M | free(temp); |
527 | 20.9M | } |
528 | | |
529 | 40.0M | e->highbit = 0; |
530 | 40.0M | e->node = NULL; |
531 | 40.0M | return; |
532 | 40.0M | } |
533 | | |
534 | | int ebitmap_read(ebitmap_t *e, void *fp) |
535 | 574k | { |
536 | 574k | int rc; |
537 | 574k | ebitmap_node_t *n, *l; |
538 | 574k | uint32_t buf[3], mapsize, count, i; |
539 | 574k | uint64_t map; |
540 | | |
541 | 574k | ebitmap_init(e); |
542 | | |
543 | 574k | rc = next_entry(buf, fp, sizeof(uint32_t) * 3); |
544 | 574k | if (rc < 0) |
545 | 666 | goto bad; |
546 | | |
547 | 574k | mapsize = le32_to_cpu(buf[0]); |
548 | 574k | e->highbit = le32_to_cpu(buf[1]); |
549 | 574k | count = le32_to_cpu(buf[2]); |
550 | | |
551 | 574k | if (mapsize != MAPSIZE) { |
552 | 304 | ERR(NULL, |
553 | 304 | "security: ebitmap: map size %d does not match my size %zu (high bit was %d)", |
554 | 304 | mapsize, MAPSIZE, e->highbit); |
555 | 304 | goto bad; |
556 | 304 | } |
557 | 573k | if (!e->highbit) { |
558 | 485k | e->node = NULL; |
559 | 485k | goto ok; |
560 | 485k | } |
561 | 88.5k | if (e->highbit & (MAPSIZE - 1)) { |
562 | 36 | ERR(NULL, |
563 | 36 | "security: ebitmap: high bit (%d) is not a multiple of the map size (%zu)", |
564 | 36 | e->highbit, MAPSIZE); |
565 | 36 | goto bad; |
566 | 36 | } |
567 | | |
568 | 88.5k | if (e->highbit && !count) |
569 | 7 | goto bad; |
570 | | |
571 | 88.4k | l = NULL; |
572 | 178k | for (i = 0; i < count; i++) { |
573 | 90.1k | rc = next_entry(buf, fp, sizeof(uint32_t)); |
574 | 90.1k | if (rc < 0) { |
575 | 271 | ERR(NULL, "security: ebitmap: truncated map"); |
576 | 271 | goto bad; |
577 | 271 | } |
578 | 89.8k | n = (ebitmap_node_t *)malloc(sizeof(ebitmap_node_t)); |
579 | 89.8k | if (!n) { |
580 | 0 | ERR(NULL, "security: ebitmap: out of memory"); |
581 | 0 | rc = -ENOMEM; |
582 | 0 | goto bad; |
583 | 0 | } |
584 | 89.8k | memset(n, 0, sizeof(ebitmap_node_t)); |
585 | | |
586 | 89.8k | n->startbit = le32_to_cpu(buf[0]); |
587 | | |
588 | 89.8k | if (n->startbit & (MAPSIZE - 1)) { |
589 | 7 | ERR(NULL, |
590 | 7 | "security: ebitmap start bit (%d) is not a multiple of the map size (%zu)", |
591 | 7 | n->startbit, MAPSIZE); |
592 | 7 | goto bad_free; |
593 | 7 | } |
594 | 89.8k | if (n->startbit > (e->highbit - MAPSIZE)) { |
595 | 11 | ERR(NULL, |
596 | 11 | "security: ebitmap start bit (%d) is beyond the end of the bitmap (%zu)", |
597 | 11 | n->startbit, (e->highbit - MAPSIZE)); |
598 | 11 | goto bad_free; |
599 | 11 | } |
600 | 89.8k | rc = next_entry(&map, fp, sizeof(uint64_t)); |
601 | 89.8k | if (rc < 0) { |
602 | 70 | ERR(NULL, "security: ebitmap: truncated map"); |
603 | 70 | goto bad_free; |
604 | 70 | } |
605 | 89.7k | n->map = le64_to_cpu(map); |
606 | | |
607 | 89.7k | if (!n->map) { |
608 | 5 | ERR(NULL, |
609 | 5 | "security: ebitmap: null map in ebitmap (startbit %d)", |
610 | 5 | n->startbit); |
611 | 5 | goto bad_free; |
612 | 5 | } |
613 | 89.7k | if (l) { |
614 | 1.47k | if (n->startbit <= l->startbit) { |
615 | 32 | ERR(NULL, |
616 | 32 | "security: ebitmap: start bit %d comes after start bit %d", |
617 | 32 | n->startbit, l->startbit); |
618 | 32 | goto bad_free; |
619 | 32 | } |
620 | 1.44k | l->next = n; |
621 | 1.44k | } else |
622 | 88.3k | e->node = n; |
623 | | |
624 | 89.7k | l = n; |
625 | 89.7k | } |
626 | 88.1k | if (count && l->startbit + MAPSIZE != e->highbit) { |
627 | 79 | ERR(NULL, |
628 | 79 | "security: ebitmap: high bit %u has not the expected value %zu", |
629 | 79 | e->highbit, l->startbit + MAPSIZE); |
630 | 79 | goto bad; |
631 | 79 | } |
632 | | |
633 | 573k | ok: |
634 | 573k | rc = 0; |
635 | 574k | out: |
636 | 574k | return rc; |
637 | 125 | bad_free: |
638 | 125 | free(n); |
639 | 1.48k | bad: |
640 | 1.48k | if (!rc) |
641 | 481 | rc = -EINVAL; |
642 | 1.48k | ebitmap_destroy(e); |
643 | 1.48k | goto out; |
644 | 125 | } |
645 | | |
646 | | /* FLASK */ |