/src/selinux/libsepol/src/kernel_to_common.c
Line | Count | Source (jump to first uncovered line) |
1 | | #include <stdio.h> |
2 | | #include <stdlib.h> |
3 | | #include <stdarg.h> |
4 | | #include <string.h> |
5 | | #include <sys/types.h> |
6 | | #include <unistd.h> |
7 | | |
8 | | #include <arpa/inet.h> |
9 | | #include <netinet/in.h> |
10 | | #ifndef IPPROTO_DCCP |
11 | | #define IPPROTO_DCCP 33 |
12 | | #endif |
13 | | #ifndef IPPROTO_SCTP |
14 | | #define IPPROTO_SCTP 132 |
15 | | #endif |
16 | | |
17 | | #include <sepol/policydb/ebitmap.h> |
18 | | #include <sepol/policydb/hashtab.h> |
19 | | #include <sepol/policydb/symtab.h> |
20 | | |
21 | | #include "debug.h" |
22 | | #include "private.h" |
23 | | #include "kernel_to_common.h" |
24 | | |
25 | | |
26 | | void sepol_indent(FILE *out, int indent) |
27 | 4.98k | { |
28 | 4.98k | if (fprintf(out, "%*s", indent * 4, "") < 0) { |
29 | 0 | ERR(NULL, "Failed to write to output"); |
30 | 0 | } |
31 | 4.98k | } |
32 | | |
33 | | void sepol_printf(FILE *out, const char *fmt, ...) |
34 | 124k | { |
35 | 124k | va_list argptr; |
36 | 124k | va_start(argptr, fmt); |
37 | 124k | if (vfprintf(out, fmt, argptr) < 0) { |
38 | 0 | ERR(NULL, "Failed to write to output"); |
39 | 0 | } |
40 | 124k | va_end(argptr); |
41 | 124k | } |
42 | | |
43 | | char *create_str(const char *fmt, ...) |
44 | 38.5k | { |
45 | 38.5k | char *str; |
46 | 38.5k | va_list vargs; |
47 | 38.5k | int rc; |
48 | | |
49 | 38.5k | va_start(vargs, fmt); |
50 | 38.5k | rc = vasprintf(&str, fmt, vargs); |
51 | 38.5k | va_end(vargs); |
52 | | |
53 | 38.5k | if (rc == -1) |
54 | 0 | return NULL; |
55 | | |
56 | 38.5k | return str; |
57 | 38.5k | } |
58 | | |
59 | | int strs_init(struct strs **strs, size_t size) |
60 | 103k | { |
61 | 103k | struct strs *new; |
62 | | |
63 | 103k | if (size == 0) { |
64 | 10.9k | size = 1; |
65 | 10.9k | } |
66 | | |
67 | 103k | *strs = NULL; |
68 | | |
69 | 103k | new = malloc(sizeof(struct strs)); |
70 | 103k | if (!new) { |
71 | 0 | ERR(NULL, "Out of memory"); |
72 | 0 | return -1; |
73 | 0 | } |
74 | | |
75 | 103k | new->list = calloc(size, sizeof(char *)); |
76 | 103k | if (!new->list) { |
77 | 0 | ERR(NULL, "Out of memory"); |
78 | 0 | free(new); |
79 | 0 | return -1; |
80 | 0 | } |
81 | | |
82 | 103k | new->num = 0; |
83 | 103k | new->size = size; |
84 | | |
85 | 103k | *strs = new; |
86 | | |
87 | 103k | return 0; |
88 | 103k | } |
89 | | |
90 | | void strs_destroy(struct strs **strs) |
91 | 105k | { |
92 | 105k | if (!strs || !*strs) { |
93 | 1.55k | return; |
94 | 1.55k | } |
95 | | |
96 | 103k | free((*strs)->list); |
97 | 103k | (*strs)->list = NULL; |
98 | 103k | (*strs)->num = 0; |
99 | 103k | (*strs)->size = 0; |
100 | 103k | free(*strs); |
101 | 103k | *strs = NULL; |
102 | 103k | } |
103 | | |
104 | | void strs_free_all(struct strs *strs) |
105 | 52.3k | { |
106 | 52.3k | if (!strs) { |
107 | 0 | return; |
108 | 0 | } |
109 | | |
110 | 82.6k | while (strs->num > 0) { |
111 | 30.3k | strs->num--; |
112 | 30.3k | free(strs->list[strs->num]); |
113 | 30.3k | } |
114 | 52.3k | } |
115 | | |
116 | | int strs_add(struct strs *strs, char *s) |
117 | 60.4k | { |
118 | 60.4k | if (strs->num + 1 > strs->size) { |
119 | 180 | char **new; |
120 | 180 | size_t i = strs->size; |
121 | 180 | strs->size *= 2; |
122 | 180 | new = reallocarray(strs->list, strs->size, sizeof(char *)); |
123 | 180 | if (!new) { |
124 | 0 | ERR(NULL, "Out of memory"); |
125 | 0 | return -1; |
126 | 0 | } |
127 | 180 | strs->list = new; |
128 | 180 | memset(&strs->list[i], 0, sizeof(char *)*(strs->size-i)); |
129 | 180 | } |
130 | | |
131 | 60.4k | strs->list[strs->num] = s; |
132 | 60.4k | strs->num++; |
133 | | |
134 | 60.4k | return 0; |
135 | 60.4k | } |
136 | | |
137 | | int strs_create_and_add(struct strs *strs, const char *fmt, ...) |
138 | 18.9k | { |
139 | 18.9k | char *str; |
140 | 18.9k | va_list vargs; |
141 | 18.9k | int rc; |
142 | | |
143 | 18.9k | va_start(vargs, fmt); |
144 | 18.9k | rc = vasprintf(&str, fmt, vargs); |
145 | 18.9k | va_end(vargs); |
146 | | |
147 | 18.9k | if (rc == -1) |
148 | 0 | goto exit; |
149 | | |
150 | 18.9k | rc = strs_add(strs, str); |
151 | 18.9k | if (rc != 0) { |
152 | 0 | free(str); |
153 | 0 | goto exit; |
154 | 0 | } |
155 | | |
156 | 18.9k | return 0; |
157 | | |
158 | 0 | exit: |
159 | 0 | return rc; |
160 | 18.9k | } |
161 | | |
162 | | char *strs_remove_last(struct strs *strs) |
163 | 23.4k | { |
164 | 23.4k | if (strs->num == 0) { |
165 | 0 | return NULL; |
166 | 0 | } |
167 | 23.4k | strs->num--; |
168 | 23.4k | return strs->list[strs->num]; |
169 | 23.4k | } |
170 | | |
171 | | int strs_add_at_index(struct strs *strs, char *s, size_t index) |
172 | 7.26k | { |
173 | 7.26k | if (index >= strs->size) { |
174 | 0 | char **new; |
175 | 0 | size_t i = strs->size; |
176 | 0 | while (index >= strs->size) { |
177 | 0 | strs->size *= 2; |
178 | 0 | } |
179 | 0 | new = reallocarray(strs->list, strs->size, sizeof(char *)); |
180 | 0 | if (!new) { |
181 | 0 | ERR(NULL, "Out of memory"); |
182 | 0 | return -1; |
183 | 0 | } |
184 | 0 | strs->list = new; |
185 | 0 | memset(&strs->list[i], 0, sizeof(char *)*(strs->size - i)); |
186 | 0 | } |
187 | | |
188 | 7.26k | strs->list[index] = s; |
189 | 7.26k | if (index >= strs->num) { |
190 | 3.52k | strs->num = index+1; |
191 | 3.52k | } |
192 | | |
193 | 7.26k | return 0; |
194 | 7.26k | } |
195 | | |
196 | | char *strs_read_at_index(struct strs *strs, size_t index) |
197 | 26.8k | { |
198 | 26.8k | if (index >= strs->num) { |
199 | 0 | return NULL; |
200 | 0 | } |
201 | | |
202 | 26.8k | return strs->list[index]; |
203 | 26.8k | } |
204 | | |
205 | | static int strs_cmp(const void *a, const void *b) |
206 | 135k | { |
207 | 135k | char *const *aa = a; |
208 | 135k | char *const *bb = b; |
209 | 135k | return strcmp(*aa,*bb); |
210 | 135k | } |
211 | | |
212 | | void strs_sort(struct strs *strs) |
213 | 70.5k | { |
214 | 70.5k | if (strs->num == 0) { |
215 | 58.6k | return; |
216 | 58.6k | } |
217 | 11.8k | qsort(strs->list, strs->num, sizeof(char *), strs_cmp); |
218 | 11.8k | } |
219 | | |
220 | | unsigned strs_num_items(const struct strs *strs) |
221 | 56.4k | { |
222 | 56.4k | return strs->num; |
223 | 56.4k | } |
224 | | |
225 | | size_t strs_len_items(const struct strs *strs) |
226 | 2.13k | { |
227 | 2.13k | unsigned i; |
228 | 2.13k | size_t len = 0; |
229 | | |
230 | 7.12k | for (i=0; i<strs->num; i++) { |
231 | 4.99k | if (!strs->list[i]) continue; |
232 | 4.99k | len += strlen(strs->list[i]); |
233 | 4.99k | } |
234 | | |
235 | 2.13k | return len; |
236 | 2.13k | } |
237 | | |
238 | | char *strs_to_str(const struct strs *strs) |
239 | 2.10k | { |
240 | 2.10k | char *str = NULL; |
241 | 2.10k | size_t len = 0; |
242 | 2.10k | char *p; |
243 | 2.10k | unsigned i; |
244 | 2.10k | int rc; |
245 | | |
246 | 2.10k | if (strs->num == 0) { |
247 | 0 | goto exit; |
248 | 0 | } |
249 | | |
250 | | /* strs->num added because either ' ' or '\0' follows each item */ |
251 | 2.10k | len = strs_len_items(strs) + strs->num; |
252 | 2.10k | str = malloc(len); |
253 | 2.10k | if (!str) { |
254 | 0 | ERR(NULL, "Out of memory"); |
255 | 0 | goto exit; |
256 | 0 | } |
257 | | |
258 | 2.10k | p = str; |
259 | 7.04k | for (i=0; i<strs->num; i++) { |
260 | 4.93k | if (!strs->list[i]) continue; |
261 | 4.93k | len = strlen(strs->list[i]); |
262 | 4.93k | rc = snprintf(p, len+1, "%s", strs->list[i]); |
263 | 4.93k | if (rc < 0 || rc > (int)len) { |
264 | 0 | free(str); |
265 | 0 | str = NULL; |
266 | 0 | goto exit; |
267 | 0 | } |
268 | 4.93k | p += len; |
269 | 4.93k | if (i < strs->num - 1) { |
270 | 2.83k | *p++ = ' '; |
271 | 2.83k | } |
272 | 4.93k | } |
273 | | |
274 | 2.10k | *p = '\0'; |
275 | | |
276 | 2.10k | exit: |
277 | 2.10k | return str; |
278 | 2.10k | } |
279 | | |
280 | | void strs_write_each(const struct strs *strs, FILE *out) |
281 | 27.5k | { |
282 | 27.5k | unsigned i; |
283 | | |
284 | 49.8k | for (i=0; i<strs->num; i++) { |
285 | 22.3k | if (!strs->list[i]) { |
286 | 1.74k | continue; |
287 | 1.74k | } |
288 | 20.5k | sepol_printf(out, "%s\n",strs->list[i]); |
289 | 20.5k | } |
290 | 27.5k | } |
291 | | |
292 | | void strs_write_each_indented(const struct strs *strs, FILE *out, int indent) |
293 | 22.6k | { |
294 | 22.6k | unsigned i; |
295 | | |
296 | 27.2k | for (i=0; i<strs->num; i++) { |
297 | 4.62k | if (!strs->list[i]) { |
298 | 0 | continue; |
299 | 0 | } |
300 | 4.62k | sepol_indent(out, indent); |
301 | 4.62k | sepol_printf(out, "%s\n",strs->list[i]); |
302 | 4.62k | } |
303 | 22.6k | } |
304 | | |
305 | | int hashtab_ordered_to_strs(char *key, void *data, void *args) |
306 | 3.93k | { |
307 | 3.93k | struct strs *strs = (struct strs *)args; |
308 | 3.93k | symtab_datum_t *datum = data; |
309 | | |
310 | 3.93k | return strs_add_at_index(strs, key, datum->value-1); |
311 | 3.93k | } |
312 | | |
313 | | int ebitmap_to_strs(const struct ebitmap *map, struct strs *strs, char **val_to_name) |
314 | 1.86k | { |
315 | 1.86k | struct ebitmap_node *node; |
316 | 1.86k | uint32_t i; |
317 | 1.86k | int rc; |
318 | | |
319 | 119k | ebitmap_for_each_positive_bit(map, node, i) { |
320 | 2.02k | if (!val_to_name[i]) |
321 | 0 | continue; |
322 | | |
323 | 2.02k | rc = strs_add(strs, val_to_name[i]); |
324 | 2.02k | if (rc != 0) { |
325 | 0 | return -1; |
326 | 0 | } |
327 | 2.02k | } |
328 | | |
329 | 1.86k | return 0; |
330 | 1.86k | } |
331 | | |
332 | | char *ebitmap_to_str(const struct ebitmap *map, char **val_to_name, int sort) |
333 | 929 | { |
334 | 929 | struct strs *strs; |
335 | 929 | char *str = NULL; |
336 | 929 | int rc; |
337 | | |
338 | 929 | rc = strs_init(&strs, 32); |
339 | 929 | if (rc != 0) { |
340 | 0 | goto exit; |
341 | 0 | } |
342 | | |
343 | 929 | rc = ebitmap_to_strs(map, strs, val_to_name); |
344 | 929 | if (rc != 0) { |
345 | 0 | goto exit; |
346 | 0 | } |
347 | | |
348 | 929 | if (sort) { |
349 | 929 | strs_sort(strs); |
350 | 929 | } |
351 | | |
352 | 929 | str = strs_to_str(strs); |
353 | | |
354 | 929 | exit: |
355 | 929 | strs_destroy(&strs); |
356 | | |
357 | 929 | return str; |
358 | 929 | } |
359 | | |
360 | | int strs_stack_init(struct strs **stack) |
361 | 18.5k | { |
362 | 18.5k | return strs_init(stack, STACK_SIZE); |
363 | 18.5k | } |
364 | | |
365 | | void strs_stack_destroy(struct strs **stack) |
366 | 18.5k | { |
367 | 18.5k | return strs_destroy(stack); |
368 | 18.5k | } |
369 | | |
370 | | int strs_stack_push(struct strs *stack, char *s) |
371 | 23.4k | { |
372 | 23.4k | return strs_add(stack, s); |
373 | 23.4k | } |
374 | | |
375 | | char *strs_stack_pop(struct strs *stack) |
376 | 23.4k | { |
377 | 23.4k | return strs_remove_last(stack); |
378 | 23.4k | } |
379 | | |
380 | | int strs_stack_empty(const struct strs *stack) |
381 | 18.5k | { |
382 | 18.5k | return strs_num_items(stack) == 0; |
383 | 18.5k | } |
384 | | |
385 | | static int compare_ranges(uint64_t l1, uint64_t h1, uint64_t l2, uint64_t h2) |
386 | 0 | { |
387 | 0 | uint64_t d1, d2; |
388 | |
|
389 | 0 | d1 = h1-l1; |
390 | 0 | d2 = h2-l2; |
391 | |
|
392 | 0 | if (d1 < d2) { |
393 | 0 | return -1; |
394 | 0 | } else if (d1 > d2) { |
395 | 0 | return 1; |
396 | 0 | } else { |
397 | 0 | if (l1 < l2) { |
398 | 0 | return -1; |
399 | 0 | } else if (l1 > l2) { |
400 | 0 | return 1; |
401 | 0 | } |
402 | 0 | } |
403 | | |
404 | 0 | return 0; |
405 | 0 | } |
406 | | |
407 | | static int fsuse_data_cmp(const void *a, const void *b) |
408 | 44 | { |
409 | 44 | struct ocontext *const *aa = a; |
410 | 44 | struct ocontext *const *bb = b; |
411 | | |
412 | 44 | if ((*aa)->v.behavior != (*bb)->v.behavior) { |
413 | 16 | if ((*aa)->v.behavior < (*bb)->v.behavior) { |
414 | 12 | return -1; |
415 | 12 | } else { |
416 | 4 | return 1; |
417 | 4 | } |
418 | 16 | } |
419 | | |
420 | 28 | return strcmp((*aa)->u.name, (*bb)->u.name); |
421 | 44 | } |
422 | | |
423 | | static int portcon_data_cmp(const void *a, const void *b) |
424 | 0 | { |
425 | 0 | struct ocontext *const *aa = a; |
426 | 0 | struct ocontext *const *bb = b; |
427 | 0 | int rc; |
428 | |
|
429 | 0 | rc = compare_ranges((*aa)->u.port.low_port, (*aa)->u.port.high_port, |
430 | 0 | (*bb)->u.port.low_port, (*bb)->u.port.high_port); |
431 | 0 | if (rc == 0) { |
432 | 0 | if ((*aa)->u.port.protocol < (*bb)->u.port.protocol) { |
433 | 0 | rc = -1; |
434 | 0 | } else if ((*aa)->u.port.protocol > (*bb)->u.port.protocol) { |
435 | 0 | rc = 1; |
436 | 0 | } |
437 | 0 | } |
438 | |
|
439 | 0 | return rc; |
440 | 0 | } |
441 | | |
442 | | static int netif_data_cmp(const void *a, const void *b) |
443 | 0 | { |
444 | | /* keep in sync with cil_post.c:cil_post_netifcon_compare() */ |
445 | 0 | const struct ocontext *const *aa = a; |
446 | 0 | const struct ocontext *const *bb = b; |
447 | 0 | const char *a_name = (*aa)->u.name; |
448 | 0 | const char *b_name = (*bb)->u.name; |
449 | 0 | size_t a_stem = strcspn(a_name, "*?"); |
450 | 0 | size_t b_stem = strcspn(b_name, "*?"); |
451 | 0 | size_t a_len = strlen(a_name); |
452 | 0 | size_t b_len = strlen(b_name); |
453 | 0 | int a_iswildcard = a_stem != a_len; |
454 | 0 | int b_iswildcard = b_stem != b_len; |
455 | 0 | int rc; |
456 | | |
457 | | /* order non-wildcards first */ |
458 | 0 | rc = spaceship_cmp(a_iswildcard, b_iswildcard); |
459 | 0 | if (rc) |
460 | 0 | return rc; |
461 | | |
462 | | /* order non-wildcards alphabetically */ |
463 | 0 | if (!a_iswildcard) |
464 | 0 | return strcmp(a_name, b_name); |
465 | | |
466 | | /* order by decreasing stem length */ |
467 | 0 | rc = spaceship_cmp(a_stem, b_stem); |
468 | 0 | if (rc) |
469 | 0 | return -rc; |
470 | | |
471 | | /* order '?' (0x3f) before '*' (0x2A) */ |
472 | 0 | rc = spaceship_cmp(a_name[a_stem], b_name[b_stem]); |
473 | 0 | if (rc) |
474 | 0 | return -rc; |
475 | | |
476 | | /* order alphabetically */ |
477 | 0 | return strcmp(a_name, b_name); |
478 | 0 | } |
479 | | |
480 | | static int node_data_cmp(const void *a, const void *b) |
481 | 0 | { |
482 | 0 | struct ocontext *const *aa = a; |
483 | 0 | struct ocontext *const *bb = b; |
484 | 0 | int rc; |
485 | |
|
486 | 0 | rc = memcmp(&(*aa)->u.node.mask, &(*bb)->u.node.mask, sizeof((*aa)->u.node.mask)); |
487 | 0 | if (rc > 0) { |
488 | 0 | return -1; |
489 | 0 | } else if (rc < 0) { |
490 | 0 | return 1; |
491 | 0 | } |
492 | | |
493 | 0 | return memcmp(&(*aa)->u.node.addr, &(*bb)->u.node.addr, sizeof((*aa)->u.node.addr)); |
494 | 0 | } |
495 | | |
496 | | static int node6_data_cmp(const void *a, const void *b) |
497 | 0 | { |
498 | 0 | struct ocontext *const *aa = a; |
499 | 0 | struct ocontext *const *bb = b; |
500 | 0 | int rc; |
501 | |
|
502 | 0 | rc = memcmp(&(*aa)->u.node6.mask, &(*bb)->u.node6.mask, sizeof((*aa)->u.node6.mask)); |
503 | 0 | if (rc > 0) { |
504 | 0 | return -1; |
505 | 0 | } else if (rc < 0) { |
506 | 0 | return 1; |
507 | 0 | } |
508 | | |
509 | 0 | return memcmp(&(*aa)->u.node6.addr, &(*bb)->u.node6.addr, sizeof((*aa)->u.node6.addr)); |
510 | 0 | } |
511 | | |
512 | | static int ibpkey_data_cmp(const void *a, const void *b) |
513 | 0 | { |
514 | 0 | int rc; |
515 | 0 | struct ocontext *const *aa = a; |
516 | 0 | struct ocontext *const *bb = b; |
517 | |
|
518 | 0 | rc = (*aa)->u.ibpkey.subnet_prefix - (*bb)->u.ibpkey.subnet_prefix; |
519 | 0 | if (rc) |
520 | 0 | return rc; |
521 | | |
522 | 0 | return compare_ranges((*aa)->u.ibpkey.low_pkey, (*aa)->u.ibpkey.high_pkey, |
523 | 0 | (*bb)->u.ibpkey.low_pkey, (*bb)->u.ibpkey.high_pkey); |
524 | 0 | } |
525 | | |
526 | | static int ibendport_data_cmp(const void *a, const void *b) |
527 | 0 | { |
528 | 0 | int rc; |
529 | 0 | struct ocontext *const *aa = a; |
530 | 0 | struct ocontext *const *bb = b; |
531 | |
|
532 | 0 | rc = strcmp((*aa)->u.ibendport.dev_name, (*bb)->u.ibendport.dev_name); |
533 | 0 | if (rc) |
534 | 0 | return rc; |
535 | | |
536 | 0 | return spaceship_cmp((*aa)->u.ibendport.port, (*bb)->u.ibendport.port); |
537 | 0 | } |
538 | | |
539 | | static int pirq_data_cmp(const void *a, const void *b) |
540 | 0 | { |
541 | 0 | struct ocontext *const *aa = a; |
542 | 0 | struct ocontext *const *bb = b; |
543 | |
|
544 | 0 | if ((*aa)->u.pirq < (*bb)->u.pirq) { |
545 | 0 | return -1; |
546 | 0 | } else if ((*aa)->u.pirq > (*bb)->u.pirq) { |
547 | 0 | return 1; |
548 | 0 | } |
549 | | |
550 | 0 | return 0; |
551 | 0 | } |
552 | | |
553 | | static int ioport_data_cmp(const void *a, const void *b) |
554 | 0 | { |
555 | 0 | struct ocontext *const *aa = a; |
556 | 0 | struct ocontext *const *bb = b; |
557 | |
|
558 | 0 | return compare_ranges((*aa)->u.ioport.low_ioport, (*aa)->u.ioport.high_ioport, |
559 | 0 | (*bb)->u.ioport.low_ioport, (*bb)->u.ioport.high_ioport); |
560 | 0 | } |
561 | | |
562 | | static int iomem_data_cmp(const void *a, const void *b) |
563 | 0 | { |
564 | 0 | struct ocontext *const *aa = a; |
565 | 0 | struct ocontext *const *bb = b; |
566 | |
|
567 | 0 | return compare_ranges((*aa)->u.iomem.low_iomem, (*aa)->u.iomem.high_iomem, |
568 | 0 | (*bb)->u.iomem.low_iomem, (*bb)->u.iomem.high_iomem); |
569 | 0 | } |
570 | | |
571 | | static int pcid_data_cmp(const void *a, const void *b) |
572 | 0 | { |
573 | 0 | struct ocontext *const *aa = a; |
574 | 0 | struct ocontext *const *bb = b; |
575 | |
|
576 | 0 | if ((*aa)->u.device < (*bb)->u.device) { |
577 | 0 | return -1; |
578 | 0 | } else if ((*aa)->u.device > (*bb)->u.device) { |
579 | 0 | return 1; |
580 | 0 | } |
581 | | |
582 | 0 | return 0; |
583 | 0 | } |
584 | | |
585 | | static int dtree_data_cmp(const void *a, const void *b) |
586 | 0 | { |
587 | 0 | struct ocontext *const *aa = a; |
588 | 0 | struct ocontext *const *bb = b; |
589 | |
|
590 | 0 | return strcmp((*aa)->u.name, (*bb)->u.name); |
591 | 0 | } |
592 | | |
593 | | static int sort_ocontext_data(struct ocontext **ocons, int (*cmp)(const void *, const void *)) |
594 | 17.3k | { |
595 | 17.3k | struct ocontext *ocon; |
596 | 17.3k | struct ocontext **data; |
597 | 17.3k | unsigned i, num; |
598 | | |
599 | 17.3k | num = 0; |
600 | 17.4k | for (ocon = *ocons; ocon != NULL; ocon = ocon->next) { |
601 | 116 | num++; |
602 | 116 | } |
603 | | |
604 | 17.3k | if (num == 0) { |
605 | 17.2k | return 0; |
606 | 17.2k | } |
607 | | |
608 | 72 | data = calloc(num, sizeof(*data)); |
609 | 72 | if (!data) { |
610 | 0 | ERR(NULL, "Out of memory"); |
611 | 0 | return -1; |
612 | 0 | } |
613 | | |
614 | 72 | i = 0; |
615 | 188 | for (ocon = *ocons; ocon != NULL; ocon = ocon->next) { |
616 | 116 | data[i] = ocon; |
617 | 116 | i++; |
618 | 116 | } |
619 | | |
620 | 72 | qsort(data, num, sizeof(*data), cmp); |
621 | | |
622 | 72 | *ocons = data[0]; |
623 | 116 | for (i=1; i < num; i++) { |
624 | 44 | data[i-1]->next = data[i]; |
625 | 44 | } |
626 | 72 | data[num-1]->next = NULL; |
627 | | |
628 | 72 | free(data); |
629 | | |
630 | 72 | return 0; |
631 | 72 | } |
632 | | |
633 | | int sort_ocontexts(struct policydb *pdb) |
634 | 2.49k | { |
635 | 2.49k | int rc = 0; |
636 | | |
637 | 2.49k | if (pdb->target_platform == SEPOL_TARGET_SELINUX) { |
638 | 2.45k | rc = sort_ocontext_data(&pdb->ocontexts[5], fsuse_data_cmp); |
639 | 2.45k | if (rc != 0) { |
640 | 0 | goto exit; |
641 | 0 | } |
642 | | |
643 | 2.45k | rc = sort_ocontext_data(&pdb->ocontexts[2], portcon_data_cmp); |
644 | 2.45k | if (rc != 0) { |
645 | 0 | goto exit; |
646 | 0 | } |
647 | | |
648 | 2.45k | rc = sort_ocontext_data(&pdb->ocontexts[3], netif_data_cmp); |
649 | 2.45k | if (rc != 0) { |
650 | 0 | goto exit; |
651 | 0 | } |
652 | | |
653 | 2.45k | rc = sort_ocontext_data(&pdb->ocontexts[4], node_data_cmp); |
654 | 2.45k | if (rc != 0) { |
655 | 0 | goto exit; |
656 | 0 | } |
657 | | |
658 | 2.45k | rc = sort_ocontext_data(&pdb->ocontexts[6], node6_data_cmp); |
659 | 2.45k | if (rc != 0) { |
660 | 0 | goto exit; |
661 | 0 | } |
662 | | |
663 | 2.45k | rc = sort_ocontext_data(&pdb->ocontexts[OCON_IBPKEY], ibpkey_data_cmp); |
664 | 2.45k | if (rc != 0) { |
665 | 0 | goto exit; |
666 | 0 | } |
667 | | |
668 | 2.45k | rc = sort_ocontext_data(&pdb->ocontexts[OCON_IBENDPORT], ibendport_data_cmp); |
669 | 2.45k | if (rc != 0) { |
670 | 0 | goto exit; |
671 | 0 | } |
672 | 2.45k | } else if (pdb->target_platform == SEPOL_TARGET_XEN) { |
673 | 38 | rc = sort_ocontext_data(&pdb->ocontexts[1], pirq_data_cmp); |
674 | 38 | if (rc != 0) { |
675 | 0 | goto exit; |
676 | 0 | } |
677 | | |
678 | 38 | rc = sort_ocontext_data(&pdb->ocontexts[2], ioport_data_cmp); |
679 | 38 | if (rc != 0) { |
680 | 0 | goto exit; |
681 | 0 | } |
682 | | |
683 | 38 | rc = sort_ocontext_data(&pdb->ocontexts[3], iomem_data_cmp); |
684 | 38 | if (rc != 0) { |
685 | 0 | goto exit; |
686 | 0 | } |
687 | | |
688 | 38 | rc = sort_ocontext_data(&pdb->ocontexts[4], pcid_data_cmp); |
689 | 38 | if (rc != 0) { |
690 | 0 | goto exit; |
691 | 0 | } |
692 | | |
693 | 38 | rc = sort_ocontext_data(&pdb->ocontexts[5], dtree_data_cmp); |
694 | 38 | if (rc != 0) { |
695 | 0 | goto exit; |
696 | 0 | } |
697 | 38 | } |
698 | | |
699 | 2.49k | exit: |
700 | 2.49k | if (rc != 0) { |
701 | 0 | ERR(NULL, "Error sorting ocontexts"); |
702 | 0 | } |
703 | | |
704 | 2.49k | return rc; |
705 | 2.49k | } |