1 #include <stdarg.h>
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include <inttypes.h>
6 #include <sys/types.h>
7 #include <unistd.h>
8
9 #include <arpa/inet.h>
10 #include <errno.h>
11 #include <netinet/in.h>
12 #ifndef IPPROTO_DCCP
13 #define IPPROTO_DCCP 33
14 #endif
15 #ifndef IPPROTO_SCTP
16 #define IPPROTO_SCTP 132
17 #endif
18
19 #include <sepol/kernel_to_cil.h>
20 #include <sepol/policydb/avtab.h>
21 #include <sepol/policydb/conditional.h>
22 #include <sepol/policydb/hashtab.h>
23 #include <sepol/policydb/polcaps.h>
24 #include <sepol/policydb/policydb.h>
25 #include <sepol/policydb/services.h>
26 #include <sepol/policydb/util.h>
27
28 #include "kernel_to_common.h"
29
30
cond_expr_to_str(struct policydb *pdb, struct cond_expr *expr)31 static char *cond_expr_to_str(struct policydb *pdb, struct cond_expr *expr)
32 {
33 struct cond_expr *curr;
34 struct strs *stack;
35 char *new_val;
36 char *str = NULL;
37 int rc;
38
39 rc = strs_stack_init(&stack);
40 if (rc != 0) {
41 goto exit;
42 }
43
44 for (curr = expr; curr != NULL; curr = curr->next) {
45 if (curr->expr_type == COND_BOOL) {
46 char *val1 = pdb->p_bool_val_to_name[curr->bool - 1];
47 new_val = create_str("%s", 1, val1);
48 } else {
49 const char *op;
50 uint32_t num_params;
51 char *val1 = NULL;
52 char *val2 = NULL;
53
54 switch(curr->expr_type) {
55 case COND_NOT: op = "not"; num_params = 1; break;
56 case COND_OR: op = "or"; num_params = 2; break;
57 case COND_AND: op = "and"; num_params = 2; break;
58 case COND_XOR: op = "xor"; num_params = 2; break;
59 case COND_EQ: op = "eq"; num_params = 2; break;
60 case COND_NEQ: op = "neq"; num_params = 2; break;
61 default:
62 sepol_log_err("Unknown conditional operator: %i",
63 curr->expr_type);
64 goto exit;
65 }
66
67 if (num_params == 2) {
68 val2 = strs_stack_pop(stack);
69 if (!val2) {
70 sepol_log_err("Invalid conditional expression");
71 goto exit;
72 }
73 }
74 val1 = strs_stack_pop(stack);
75 if (!val1) {
76 sepol_log_err("Invalid conditional expression");
77 free(val2);
78 goto exit;
79 }
80 if (num_params == 2) {
81 new_val = create_str("(%s %s %s)", 3, op, val1, val2);
82 free(val2);
83 } else {
84 new_val = create_str("(%s %s)", 2, op, val1);
85 }
86 free(val1);
87 }
88 if (!new_val) {
89 sepol_log_err("Invalid conditional expression");
90 goto exit;
91 }
92 rc = strs_stack_push(stack, new_val);
93 if (rc != 0) {
94 sepol_log_err("Out of memory");
95 goto exit;
96 }
97 }
98
99 new_val = strs_stack_pop(stack);
100 if (!new_val || !strs_stack_empty(stack)) {
101 sepol_log_err("Invalid conditional expression");
102 goto exit;
103 }
104
105 str = new_val;
106
107 strs_stack_destroy(&stack);
108 return str;
109
110 exit:
111 if (stack) {
112 while ((new_val = strs_stack_pop(stack)) != NULL) {
113 free(new_val);
114 }
115 strs_stack_destroy(&stack);
116 }
117
118 return NULL;
119 }
120
constraint_expr_to_str(struct policydb *pdb, struct constraint_expr *expr, int *use_mls)121 static char *constraint_expr_to_str(struct policydb *pdb, struct constraint_expr *expr, int *use_mls)
122 {
123 struct constraint_expr *curr;
124 struct strs *stack = NULL;
125 char *new_val = NULL;
126 const char *op;
127 char *str = NULL;
128 int rc;
129
130 *use_mls = 0;
131
132 rc = strs_stack_init(&stack);
133 if (rc != 0) {
134 goto exit;
135 }
136
137 for (curr = expr; curr; curr = curr->next) {
138 if (curr->expr_type == CEXPR_ATTR || curr->expr_type == CEXPR_NAMES) {
139 const char *attr1 = NULL;
140 const char *attr2 = NULL;
141
142 switch (curr->op) {
143 case CEXPR_EQ: op = "eq"; break;
144 case CEXPR_NEQ: op = "neq"; break;
145 case CEXPR_DOM: op = "dom"; break;
146 case CEXPR_DOMBY: op = "domby"; break;
147 case CEXPR_INCOMP: op = "incomp"; break;
148 default:
149 sepol_log_err("Unknown constraint operator: %i", curr->op);
150 goto exit;
151 }
152
153 switch (curr->attr) {
154 case CEXPR_USER: attr1 ="u1"; attr2 ="u2"; break;
155 case CEXPR_USER | CEXPR_TARGET: attr1 ="u2"; attr2 =""; break;
156 case CEXPR_USER | CEXPR_XTARGET: attr1 ="u3"; attr2 =""; break;
157 case CEXPR_ROLE: attr1 ="r1"; attr2 ="r2"; break;
158 case CEXPR_ROLE | CEXPR_TARGET: attr1 ="r2"; attr2 =""; break;
159 case CEXPR_ROLE | CEXPR_XTARGET: attr1 ="r3"; attr2 =""; break;
160 case CEXPR_TYPE: attr1 ="t1"; attr2 ="t2"; break;
161 case CEXPR_TYPE | CEXPR_TARGET: attr1 ="t2"; attr2 =""; break;
162 case CEXPR_TYPE | CEXPR_XTARGET: attr1 ="t3"; attr2 =""; break;
163 case CEXPR_L1L2: attr1 ="l1"; attr2 ="l2"; break;
164 case CEXPR_L1H2: attr1 ="l1"; attr2 ="h2"; break;
165 case CEXPR_H1L2: attr1 ="h1"; attr2 ="l2"; break;
166 case CEXPR_H1H2: attr1 ="h1"; attr2 ="h2"; break;
167 case CEXPR_L1H1: attr1 ="l1"; attr2 ="h1"; break;
168 case CEXPR_L2H2: attr1 ="l2"; attr2 ="h2"; break;
169 default:
170 sepol_log_err("Unknown constraint attribute: %i",
171 curr->attr);
172 goto exit;
173 }
174
175 if (curr->attr >= CEXPR_XTARGET) {
176 *use_mls = 1;
177 }
178
179 if (curr->expr_type == CEXPR_ATTR) {
180 new_val = create_str("(%s %s %s)", 3, op, attr1, attr2);
181 } else {
182 char *names = NULL;
183 if (curr->attr & CEXPR_TYPE) {
184 struct type_set *ts = curr->type_names;
185 names = ebitmap_to_str(&ts->types, pdb->p_type_val_to_name, 1);
186 } else if (curr->attr & CEXPR_USER) {
187 names = ebitmap_to_str(&curr->names, pdb->p_user_val_to_name, 1);
188 } else if (curr->attr & CEXPR_ROLE) {
189 names = ebitmap_to_str(&curr->names, pdb->p_role_val_to_name, 1);
190 }
191 if (!names) {
192 names = strdup("NO_IDENTIFIER");
193 if (!names) {
194 sepol_log_err("Out of memory");
195 goto exit;
196 }
197 }
198 if (strchr(names, ' ')) {
199 new_val = create_str("(%s %s (%s))", 3, op, attr1, names);
200 } else {
201 new_val = create_str("(%s %s %s)", 3, op, attr1, names);
202 }
203 free(names);
204 }
205 } else {
206 uint32_t num_params;
207 char *val1 = NULL;
208 char *val2 = NULL;
209
210 switch (curr->expr_type) {
211 case CEXPR_NOT: op = "not"; num_params = 1; break;
212 case CEXPR_AND: op = "and"; num_params = 2; break;
213 case CEXPR_OR: op = "or"; num_params = 2; break;
214 default:
215 sepol_log_err("Unknown constraint expression type: %i",
216 curr->expr_type);
217 goto exit;
218 }
219
220 if (num_params == 2) {
221 val2 = strs_stack_pop(stack);
222 if (!val2) {
223 sepol_log_err("Invalid constraint expression");
224 goto exit;
225 }
226 }
227 val1 = strs_stack_pop(stack);
228 if (!val1) {
229 sepol_log_err("Invalid constraint expression");
230 goto exit;
231 }
232
233 if (num_params == 2) {
234 new_val = create_str("(%s %s %s)", 3, op, val1, val2);
235 free(val2);
236 } else {
237 new_val = create_str("(%s %s)", 2, op, val1);
238 }
239 free(val1);
240 }
241 if (!new_val) {
242 goto exit;
243 }
244 rc = strs_stack_push(stack, new_val);
245 if (rc != 0) {
246 sepol_log_err("Out of memory");
247 goto exit;
248 }
249 }
250
251 new_val = strs_stack_pop(stack);
252 if (!new_val || !strs_stack_empty(stack)) {
253 sepol_log_err("Invalid constraint expression");
254 goto exit;
255 }
256
257 str = new_val;
258
259 strs_stack_destroy(&stack);
260
261 return str;
262
263 exit:
264 if (stack) {
265 while ((new_val = strs_stack_pop(stack)) != NULL) {
266 free(new_val);
267 }
268 strs_stack_destroy(&stack);
269 }
270
271 return NULL;
272 }
273
class_constraint_rules_to_strs(struct policydb *pdb, char *classkey, class_datum_t *class, struct constraint_node *constraint_rules, struct strs *mls_list, struct strs *non_mls_list)274 static int class_constraint_rules_to_strs(struct policydb *pdb, char *classkey,
275 class_datum_t *class,
276 struct constraint_node *constraint_rules,
277 struct strs *mls_list,
278 struct strs *non_mls_list)
279 {
280 int rc = 0;
281 struct constraint_node *curr;
282 char *expr = NULL;
283 int is_mls;
284 char *perms;
285 const char *key_word;
286 struct strs *strs;
287
288 for (curr = constraint_rules; curr != NULL; curr = curr->next) {
289 if (curr->permissions == 0) {
290 continue;
291 }
292 expr = constraint_expr_to_str(pdb, curr->expr, &is_mls);
293 if (!expr) {
294 rc = -1;
295 goto exit;
296 }
297
298 perms = sepol_av_to_string(pdb, class->s.value, curr->permissions);
299
300 if (is_mls) {
301 key_word = "mlsconstrain";
302 strs = mls_list;
303 } else {
304 key_word = "constrain";
305 strs = non_mls_list;
306 }
307
308 rc = strs_create_and_add(strs, "(%s (%s (%s)) %s)", 4, key_word, classkey, perms+1, expr);
309 free(expr);
310 if (rc != 0) {
311 goto exit;
312 }
313 }
314
315 return 0;
316 exit:
317 sepol_log_err("Error gathering constraint rules\n");
318 return rc;
319 }
320
class_validatetrans_rules_to_strs(struct policydb *pdb, char *classkey, struct constraint_node *validatetrans_rules, struct strs *mls_list, struct strs *non_mls_list)321 static int class_validatetrans_rules_to_strs(struct policydb *pdb, char *classkey,
322 struct constraint_node *validatetrans_rules,
323 struct strs *mls_list,
324 struct strs *non_mls_list)
325 {
326 struct constraint_node *curr;
327 char *expr = NULL;
328 int is_mls;
329 const char *key_word;
330 struct strs *strs;
331 int rc = 0;
332
333 for (curr = validatetrans_rules; curr != NULL; curr = curr->next) {
334 expr = constraint_expr_to_str(pdb, curr->expr, &is_mls);
335 if (!expr) {
336 rc = -1;
337 goto exit;
338 }
339
340 if (is_mls) {
341 key_word = "mlsvalidatetrans";
342 strs = mls_list;
343 } else {
344 key_word = "validatetrans";
345 strs = non_mls_list;
346 }
347
348 rc = strs_create_and_add(strs, "(%s %s %s)", 3, key_word, classkey, expr);
349 free(expr);
350 if (rc != 0) {
351 goto exit;
352 }
353 }
354
355 exit:
356 return rc;
357 }
358
constraint_rules_to_strs(struct policydb *pdb, struct strs *mls_strs, struct strs *non_mls_strs)359 static int constraint_rules_to_strs(struct policydb *pdb, struct strs *mls_strs, struct strs *non_mls_strs)
360 {
361 class_datum_t *class;
362 char *name;
363 unsigned i;
364 int rc = 0;
365
366 for (i=0; i < pdb->p_classes.nprim; i++) {
367 class = pdb->class_val_to_struct[i];
368 if (!class) continue;
369 if (class->constraints) {
370 name = pdb->p_class_val_to_name[i];
371 rc = class_constraint_rules_to_strs(pdb, name, class, class->constraints, mls_strs, non_mls_strs);
372 if (rc != 0) {
373 goto exit;
374 }
375 }
376 }
377
378 strs_sort(mls_strs);
379 strs_sort(non_mls_strs);
380
381 exit:
382 return rc;
383 }
384
validatetrans_rules_to_strs(struct policydb *pdb, struct strs *mls_strs, struct strs *non_mls_strs)385 static int validatetrans_rules_to_strs(struct policydb *pdb, struct strs *mls_strs, struct strs *non_mls_strs)
386 {
387 class_datum_t *class;
388 char *name;
389 unsigned i;
390 int rc = 0;
391
392 for (i=0; i < pdb->p_classes.nprim; i++) {
393 class = pdb->class_val_to_struct[i];
394 if (!class) continue;
395 if (class->validatetrans) {
396 name = pdb->p_class_val_to_name[i];
397 rc = class_validatetrans_rules_to_strs(pdb, name, class->validatetrans, mls_strs, non_mls_strs);
398 if (rc != 0) {
399 goto exit;
400 }
401 }
402 }
403
404 strs_sort(mls_strs);
405 strs_sort(non_mls_strs);
406
407 exit:
408 return rc;
409 }
410
write_handle_unknown_to_cil(FILE *out, struct policydb *pdb)411 static int write_handle_unknown_to_cil(FILE *out, struct policydb *pdb)
412 {
413 const char *action;
414
415 switch (pdb->handle_unknown) {
416 case SEPOL_DENY_UNKNOWN:
417 action = "deny";
418 break;
419 case SEPOL_REJECT_UNKNOWN:
420 action = "reject";
421 break;
422 case SEPOL_ALLOW_UNKNOWN:
423 action = "allow";
424 break;
425 default:
426 sepol_log_err("Unknown value for handle-unknown: %i", pdb->handle_unknown);
427 return -1;
428 }
429
430 sepol_printf(out, "(handleunknown %s)\n", action);
431
432 return 0;
433 }
434
class_or_common_perms_to_str(symtab_t *permtab)435 static char *class_or_common_perms_to_str(symtab_t *permtab)
436 {
437 struct strs *strs;
438 char *perms = NULL;
439 int rc;
440
441 rc = strs_init(&strs, permtab->nprim);
442 if (rc != 0) {
443 goto exit;
444 }
445
446 rc = hashtab_map(permtab->table, hashtab_ordered_to_strs, strs);
447 if (rc != 0) {
448 goto exit;
449 }
450
451 if (strs_num_items(strs) > 0) {
452 perms = strs_to_str(strs);
453 }
454
455 exit:
456 strs_destroy(&strs);
457
458 return perms;
459 }
460
write_class_decl_rules_to_cil(FILE *out, struct policydb *pdb)461 static int write_class_decl_rules_to_cil(FILE *out, struct policydb *pdb)
462 {
463 class_datum_t *class;
464 common_datum_t *common;
465 int *used;
466 char *name, *perms;
467 unsigned i;
468 int rc = 0;
469
470 /* class */
471 for (i=0; i < pdb->p_classes.nprim; i++) {
472 class = pdb->class_val_to_struct[i];
473 if (!class) continue;
474 name = pdb->p_class_val_to_name[i];
475 perms = class_or_common_perms_to_str(&class->permissions);
476 if (perms) {
477 sepol_printf(out, "(class %s (%s))\n", name, perms);
478 free(perms);
479 } else {
480 sepol_printf(out, "(class %s ())\n", name);
481 }
482 }
483
484 /* classorder */
485 sepol_printf(out, "(classorder (");
486 name = NULL;
487 for (i=0; i < pdb->p_classes.nprim; i++) {
488 if (name) {
489 sepol_printf(out, "%s ", name);
490 }
491 name = pdb->p_class_val_to_name[i];
492 }
493 if (name) {
494 sepol_printf(out, "%s", name);
495 }
496 sepol_printf(out, "))\n");
497
498 /* classcommon */
499 for (i=0; i < pdb->p_classes.nprim; i++) {
500 class = pdb->class_val_to_struct[i];
501 if (!class) continue;
502 name = pdb->p_class_val_to_name[i];
503 if (class->comkey != NULL) {
504 sepol_printf(out, "(classcommon %s %s)\n", name, class->comkey);
505 }
506 }
507
508 /* common */
509 used = calloc(pdb->p_commons.nprim, sizeof(*used));
510 if (!used) {
511 sepol_log_err("Out of memory");
512 rc = -1;
513 goto exit;
514 }
515 for (i=0; i < pdb->p_classes.nprim; i++) {
516 class = pdb->class_val_to_struct[i];
517 if (!class) continue;
518 name = class->comkey;
519 if (name != NULL) {
520 common = hashtab_search(pdb->p_commons.table, name);
521 if (!common) {
522 rc = -1;
523 free(used);
524 goto exit;
525 }
526 /* Only write common rule once */
527 if (!used[common->s.value-1]) {
528 perms = class_or_common_perms_to_str(&common->permissions);
529 if (!perms) {
530 rc = -1;
531 free(perms);
532 free(used);
533 goto exit;
534 }
535
536 sepol_printf(out, "(common %s (%s))\n", name, perms);
537 free(perms);
538 used[common->s.value-1] = 1;
539 }
540 }
541 }
542 free(used);
543
544 exit:
545 if (rc != 0) {
546 sepol_log_err("Error writing class rules to CIL\n");
547 }
548
549 return rc;
550 }
551
write_sids_to_cil(FILE *out, const char *const *sid_to_str, unsigned num_sids, struct ocontext *isids)552 static int write_sids_to_cil(FILE *out, const char *const *sid_to_str,
553 unsigned num_sids, struct ocontext *isids)
554 {
555 struct ocontext *isid;
556 struct strs *strs;
557 char *sid;
558 char *prev;
559 char unknown[18];
560 unsigned i;
561 int rc;
562
563 rc = strs_init(&strs, num_sids+1);
564 if (rc != 0) {
565 goto exit;
566 }
567
568 for (isid = isids; isid != NULL; isid = isid->next) {
569 i = isid->sid[0];
570 if (i < num_sids) {
571 sid = (char *)sid_to_str[i];
572 } else {
573 snprintf(unknown, 18, "%s%u", "UNKNOWN", i);
574 sid = strdup(unknown);
575 if (!sid) {
576 sepol_log_err("Out of memory");
577 rc = -1;
578 goto exit;
579 }
580 }
581 rc = strs_add_at_index(strs, sid, i);
582 if (rc != 0) {
583 goto exit;
584 }
585 }
586
587 for (i=0; i<strs_num_items(strs); i++) {
588 sid = strs_read_at_index(strs, i);
589 if (!sid) {
590 continue;
591 }
592 sepol_printf(out, "(sid %s)\n", sid);
593 }
594
595 sepol_printf(out, "(sidorder (");
596 prev = NULL;
597 for (i=0; i<strs_num_items(strs); i++) {
598 sid = strs_read_at_index(strs, i);
599 if (!sid) {
600 continue;
601 }
602 if (prev) {
603 sepol_printf(out, "%s ", prev);
604 }
605 prev = sid;
606 }
607 if (prev) {
608 sepol_printf(out, "%s", prev);
609 }
610 sepol_printf(out, "))\n");
611
612 exit:
613 for (i=num_sids; i<strs_num_items(strs); i++) {
614 sid = strs_read_at_index(strs, i);
615 free(sid);
616 }
617 strs_destroy(&strs);
618 if (rc != 0) {
619 sepol_log_err("Error writing sid rules to CIL\n");
620 }
621
622 return rc;
623 }
624
write_sid_decl_rules_to_cil(FILE *out, struct policydb *pdb)625 static int write_sid_decl_rules_to_cil(FILE *out, struct policydb *pdb)
626 {
627 int rc = 0;
628
629 if (pdb->target_platform == SEPOL_TARGET_SELINUX) {
630 rc = write_sids_to_cil(out, selinux_sid_to_str, SELINUX_SID_SZ,
631 pdb->ocontexts[0]);
632 } else if (pdb->target_platform == SEPOL_TARGET_XEN) {
633 rc = write_sids_to_cil(out, xen_sid_to_str, XEN_SID_SZ,
634 pdb->ocontexts[0]);
635 } else {
636 sepol_log_err("Unknown target platform: %i", pdb->target_platform);
637 rc = -1;
638 }
639
640 return rc;
641 }
642
write_default_user_to_cil(FILE *out, char *class_name, class_datum_t *class)643 static int write_default_user_to_cil(FILE *out, char *class_name, class_datum_t *class)
644 {
645 const char *dft;
646
647 switch (class->default_user) {
648 case DEFAULT_SOURCE:
649 dft = "source";
650 break;
651 case DEFAULT_TARGET:
652 dft = "target";
653 break;
654 default:
655 sepol_log_err("Unknown default role value: %i", class->default_user);
656 return -1;
657 }
658 sepol_printf(out, "(defaultuser %s %s)\n", class_name, dft);
659
660 return 0;
661 }
662
write_default_role_to_cil(FILE *out, char *class_name, class_datum_t *class)663 static int write_default_role_to_cil(FILE *out, char *class_name, class_datum_t *class)
664 {
665 const char *dft;
666
667 switch (class->default_role) {
668 case DEFAULT_SOURCE:
669 dft = "source";
670 break;
671 case DEFAULT_TARGET:
672 dft = "target";
673 break;
674 default:
675 sepol_log_err("Unknown default role value: %i", class->default_role);
676 return -1;
677 }
678 sepol_printf(out, "(defaultrole %s %s)\n", class_name, dft);
679
680 return 0;
681 }
682
write_default_type_to_cil(FILE *out, char *class_name, class_datum_t *class)683 static int write_default_type_to_cil(FILE *out, char *class_name, class_datum_t *class)
684 {
685 const char *dft;
686
687 switch (class->default_type) {
688 case DEFAULT_SOURCE:
689 dft = "source";
690 break;
691 case DEFAULT_TARGET:
692 dft = "target";
693 break;
694 default:
695 sepol_log_err("Unknown default type value: %i", class->default_type);
696 return -1;
697 }
698 sepol_printf(out, "(defaulttype %s %s)\n", class_name, dft);
699
700 return 0;
701 }
702
write_default_range_to_cil(FILE *out, char *class_name, class_datum_t *class)703 static int write_default_range_to_cil(FILE *out, char *class_name, class_datum_t *class)
704 {
705 const char *dft;
706
707 switch (class->default_range) {
708 case DEFAULT_SOURCE_LOW:
709 dft = "source low";
710 break;
711 case DEFAULT_SOURCE_HIGH:
712 dft = "source high";
713 break;
714 case DEFAULT_SOURCE_LOW_HIGH:
715 dft = "source low-high";
716 break;
717 case DEFAULT_TARGET_LOW:
718 dft = "target low";
719 break;
720 case DEFAULT_TARGET_HIGH:
721 dft = "target high";
722 break;
723 case DEFAULT_TARGET_LOW_HIGH:
724 dft = "target low-high";
725 break;
726 case DEFAULT_GLBLUB:
727 dft = "glblub";
728 break;
729 default:
730 sepol_log_err("Unknown default type value: %i", class->default_range);
731 return -1;
732 }
733 sepol_printf(out, "(defaultrange %s %s)\n", class_name, dft);
734
735 return 0;
736 }
737
write_default_rules_to_cil(FILE *out, struct policydb *pdb)738 static int write_default_rules_to_cil(FILE *out, struct policydb *pdb)
739 {
740 class_datum_t *class;
741 unsigned i;
742 int rc = 0;
743
744 /* default_user */
745 for (i=0; i < pdb->p_classes.nprim; i++) {
746 class = pdb->class_val_to_struct[i];
747 if (!class) continue;
748 if (class->default_user != 0) {
749 rc = write_default_user_to_cil(out, pdb->p_class_val_to_name[i], class);
750 if (rc != 0) {
751 goto exit;
752 }
753 }
754 }
755
756 /* default_role */
757 for (i=0; i < pdb->p_classes.nprim; i++) {
758 class = pdb->class_val_to_struct[i];
759 if (!class) continue;
760 if (class->default_role != 0) {
761 rc = write_default_role_to_cil(out, pdb->p_class_val_to_name[i], class);
762 if (rc != 0) {
763 goto exit;
764 }
765 }
766 }
767
768 /* default_type */
769 for (i=0; i < pdb->p_classes.nprim; i++) {
770 class = pdb->class_val_to_struct[i];
771 if (!class) continue;
772 if (class->default_type != 0) {
773 rc = write_default_type_to_cil(out, pdb->p_class_val_to_name[i], class);
774 if (rc != 0) {
775 goto exit;
776 }
777 }
778 }
779
780 if (!pdb->mls) {
781 return 0;
782 }
783
784 /* default_range */
785 for (i=0; i < pdb->p_classes.nprim; i++) {
786 class = pdb->class_val_to_struct[i];
787 if (!class) continue;
788 if (class->default_range) {
789 rc = write_default_range_to_cil(out, pdb->p_class_val_to_name[i], class);
790 if (rc != 0) {
791 goto exit;
792 }
793 }
794 }
795
796 exit:
797 if (rc != 0) {
798 sepol_log_err("Error writing default rules to CIL\n");
799 }
800
801 return rc;
802 }
803
write_default_mls_level(FILE *out)804 static void write_default_mls_level(FILE *out)
805 {
806 sepol_printf(out, "(sensitivity s0)\n");
807 sepol_printf(out, "(sensitivityorder (s0))\n");
808 sepol_printf(out, "(level %s (s0))\n", DEFAULT_LEVEL);
809 }
810
map_count_sensitivity_aliases(__attribute__((unused)) char *key, void *data, void *args)811 static int map_count_sensitivity_aliases(__attribute__((unused)) char *key, void *data, void *args)
812 {
813 level_datum_t *sens = data;
814 unsigned *count = args;
815
816 if (sens->isalias)
817 (*count)++;
818
819 return SEPOL_OK;
820 }
821
map_sensitivity_aliases_to_strs(char *key, void *data, void *args)822 static int map_sensitivity_aliases_to_strs(char *key, void *data, void *args)
823 {
824 level_datum_t *sens = data;
825 struct strs *strs = args;
826 int rc = 0;
827
828 if (sens->isalias) {
829 rc = strs_add(strs, key);
830 }
831
832 return rc;
833 }
834
write_sensitivity_rules_to_cil(FILE *out, struct policydb *pdb)835 static int write_sensitivity_rules_to_cil(FILE *out, struct policydb *pdb)
836 {
837 level_datum_t *level;
838 char *prev, *name, *actual;
839 struct strs *strs = NULL;
840 unsigned i, num = 0;
841 int rc = 0;
842
843 /* sensitivities */
844 for (i=0; i < pdb->p_levels.nprim; i++) {
845 name = pdb->p_sens_val_to_name[i];
846 sepol_printf(out, "(sensitivity %s)\n", name);
847 }
848
849 /* sensitivityorder */
850 sepol_printf(out, "(sensitivityorder (");
851 prev = NULL;
852 for (i=0; i < pdb->p_levels.nprim; i++) {
853 name = pdb->p_sens_val_to_name[i];
854 if (prev) {
855 sepol_printf(out, "%s ", prev);
856 }
857 prev = name;
858 }
859 if (prev) {
860 sepol_printf(out, "%s", prev);
861 }
862 sepol_printf(out, "))\n");
863
864 rc = hashtab_map(pdb->p_levels.table, map_count_sensitivity_aliases, &num);
865 if (rc != 0) {
866 goto exit;
867 }
868
869 if (num == 0) {
870 /* No aliases, so skip sensitivity alias rules */
871 rc = 0;
872 goto exit;
873 }
874
875 rc = strs_init(&strs, num);
876 if (rc != 0) {
877 goto exit;
878 }
879
880 rc = hashtab_map(pdb->p_levels.table, map_sensitivity_aliases_to_strs, strs);
881 if (rc != 0) {
882 goto exit;
883 }
884
885 strs_sort(strs);
886
887 /* sensitivity aliases */
888 for (i=0; i < num; i++) {
889 name = strs_read_at_index(strs, i);
890 sepol_printf(out, "(sensitivityalias %s)\n", name);
891 }
892
893 /* sensitivity aliases to actual */
894 for (i=0; i < num; i++) {
895 name = strs_read_at_index(strs, i);
896 level = hashtab_search(pdb->p_levels.table, name);
897 if (!level) {
898 rc = -1;
899 goto exit;
900 }
901 actual = pdb->p_sens_val_to_name[level->level->sens - 1];
902 sepol_printf(out, "(sensitivityaliasactual %s %s)\n", name, actual);
903 }
904
905 exit:
906 strs_destroy(&strs);
907
908 if (rc != 0) {
909 sepol_log_err("Error writing sensitivity rules to CIL\n");
910 }
911
912 return rc;
913 }
914
map_count_category_aliases(__attribute__((unused)) char *key, void *data, void *args)915 static int map_count_category_aliases(__attribute__((unused)) char *key, void *data, void *args)
916 {
917 cat_datum_t *cat = data;
918 unsigned *count = args;
919
920 if (cat->isalias)
921 (*count)++;
922
923 return SEPOL_OK;
924 }
925
map_category_aliases_to_strs(char *key, void *data, void *args)926 static int map_category_aliases_to_strs(char *key, void *data, void *args)
927 {
928 cat_datum_t *cat = data;
929 struct strs *strs = args;
930 int rc = 0;
931
932 if (cat->isalias) {
933 rc = strs_add(strs, key);
934 }
935
936 return rc;
937 }
938
write_category_rules_to_cil(FILE *out, struct policydb *pdb)939 static int write_category_rules_to_cil(FILE *out, struct policydb *pdb)
940 {
941 cat_datum_t *cat;
942 char *prev, *name, *actual;
943 struct strs *strs = NULL;
944 unsigned i, num = 0;
945 int rc = 0;
946
947 /* categories */
948 for (i=0; i < pdb->p_cats.nprim; i++) {
949 name = pdb->p_cat_val_to_name[i];
950 sepol_printf(out, "(category %s)\n", name);
951 }
952
953 /* categoryorder */
954 sepol_printf(out, "(categoryorder (");
955 prev = NULL;
956 for (i=0; i < pdb->p_cats.nprim; i++) {
957 name = pdb->p_cat_val_to_name[i];
958 if (prev) {
959 sepol_printf(out, "%s ", prev);
960 }
961 prev = name;
962 }
963 if (prev) {
964 sepol_printf(out, "%s", prev);
965 }
966 sepol_printf(out, "))\n");
967
968 rc = hashtab_map(pdb->p_cats.table, map_count_category_aliases, &num);
969 if (rc != 0) {
970 goto exit;
971 }
972
973 if (num == 0) {
974 /* No aliases, so skip category alias rules */
975 rc = 0;
976 goto exit;
977 }
978
979 rc = strs_init(&strs, num);
980 if (rc != 0) {
981 goto exit;
982 }
983
984 rc = hashtab_map(pdb->p_cats.table, map_category_aliases_to_strs, strs);
985 if (rc != 0) {
986 goto exit;
987 }
988
989 strs_sort(strs);
990
991 /* category aliases */
992 for (i=0; i < num; i++) {
993 name = strs_read_at_index(strs, i);
994 sepol_printf(out, "(categoryalias %s)\n", name);
995 }
996
997 /* category aliases to actual */
998 for (i=0; i < num; i++) {
999 name = strs_read_at_index(strs, i);
1000 cat = hashtab_search(pdb->p_cats.table, name);
1001 if (!cat) {
1002 rc = -1;
1003 goto exit;
1004 }
1005 actual = pdb->p_cat_val_to_name[cat->s.value - 1];
1006 sepol_printf(out, "(categoryaliasactual %s %s)\n", name, actual);
1007 }
1008
1009 exit:
1010 strs_destroy(&strs);
1011
1012 if (rc != 0) {
1013 sepol_log_err("Error writing category rules to CIL\n");
1014 }
1015
1016 return rc;
1017 }
1018
cats_ebitmap_len(struct ebitmap *cats, char **val_to_name)1019 static size_t cats_ebitmap_len(struct ebitmap *cats, char **val_to_name)
1020 {
1021 struct ebitmap_node *node;
1022 uint32_t i, start, range;
1023 size_t len = 0;
1024
1025 range = 0;
1026 ebitmap_for_each_positive_bit(cats, node, i) {
1027 if (range == 0)
1028 start = i;
1029
1030 range++;
1031
1032 if (ebitmap_get_bit(cats, i+1))
1033 continue;
1034
1035 len += strlen(val_to_name[start]);
1036 if (range > 2) {
1037 len += strlen(val_to_name[i-1]) + strlen("(range ) ");
1038 } else if (range == 2) {
1039 len += strlen(val_to_name[i-1]) + 2;
1040 } else if (range == 1) {
1041 len += 1;
1042 }
1043
1044 range = 0;
1045 }
1046
1047 if (len > 0) {
1048 len += 2; /* For '(' and ')'. '\0' overwrites last ' ' */
1049 }
1050
1051 return len;
1052 }
1053
cats_ebitmap_to_str(struct ebitmap *cats, char **val_to_name)1054 static char *cats_ebitmap_to_str(struct ebitmap *cats, char **val_to_name)
1055 {
1056 struct ebitmap_node *node;
1057 uint32_t i, start, range;
1058 char *catsbuf = NULL, *p;
1059 int len, remaining;
1060
1061 remaining = (int)cats_ebitmap_len(cats, val_to_name);
1062 if (remaining == 0) {
1063 goto exit;
1064 }
1065 catsbuf = malloc(remaining);
1066 if (!catsbuf) {
1067 goto exit;
1068 }
1069
1070 p = catsbuf;
1071
1072 *p++ = '(';
1073 remaining--;
1074
1075 range = 0;
1076 ebitmap_for_each_positive_bit(cats, node, i) {
1077 if (range == 0)
1078 start = i;
1079
1080 range++;
1081
1082 if (ebitmap_get_bit(cats, i+1))
1083 continue;
1084
1085 if (range > 1) {
1086 if (range == 2) {
1087 len = snprintf(p, remaining, "%s %s ",
1088 val_to_name[start],
1089 val_to_name[i]);
1090 } else {
1091 len = snprintf(p, remaining, "(range %s %s) ",
1092 val_to_name[start],
1093 val_to_name[i]);
1094 }
1095 } else {
1096 len = snprintf(p, remaining, "%s ", val_to_name[start]);
1097 }
1098 if (len < 0 || len >= remaining) {
1099 goto exit;
1100 }
1101 p += len;
1102 remaining -= len;
1103
1104 range = 0;
1105 }
1106
1107 *(p-1) = ')'; /* Remove trailing ' ' */
1108 *p = '\0';
1109
1110 return catsbuf;
1111
1112 exit:
1113 free(catsbuf);
1114 return NULL;
1115 }
1116
write_sensitivitycategory_rules_to_cil(FILE *out, struct policydb *pdb)1117 static int write_sensitivitycategory_rules_to_cil(FILE *out, struct policydb *pdb)
1118 {
1119 level_datum_t *level;
1120 char *name, *cats;
1121 unsigned i;
1122 int rc = 0;
1123
1124 /* sensitivities */
1125 for (i=0; i < pdb->p_levels.nprim; i++) {
1126 name = pdb->p_sens_val_to_name[i];
1127 if (!name) continue;
1128 level = hashtab_search(pdb->p_levels.table, name);
1129 if (!level) {
1130 rc = -1;
1131 goto exit;
1132 }
1133 if (level->isalias) continue;
1134
1135 if (!ebitmap_is_empty(&level->level->cat)) {
1136 cats = cats_ebitmap_to_str(&level->level->cat, pdb->p_cat_val_to_name);
1137 sepol_printf(out, "(sensitivitycategory %s %s)\n", name, cats);
1138 free(cats);
1139 }
1140 }
1141
1142 exit:
1143 if (rc != 0) {
1144 sepol_log_err("Error writing sensitivitycategory rules to CIL\n");
1145 }
1146
1147 return rc;
1148 }
1149
write_mls_rules_to_cil(FILE *out, struct policydb *pdb)1150 static int write_mls_rules_to_cil(FILE *out, struct policydb *pdb)
1151 {
1152 int rc = 0;
1153
1154 if (!pdb->mls) {
1155 sepol_printf(out, "(mls false)\n");
1156 /* CIL requires MLS, even if the kernel binary won't have it */
1157 write_default_mls_level(out);
1158 return 0;
1159 }
1160
1161 sepol_printf(out, "(mls true)\n");
1162
1163 rc = write_sensitivity_rules_to_cil(out, pdb);
1164 if (rc != 0) {
1165 goto exit;
1166 }
1167
1168 rc = write_category_rules_to_cil(out, pdb);
1169 if (rc != 0) {
1170 goto exit;
1171 }
1172
1173 rc = write_sensitivitycategory_rules_to_cil(out, pdb);
1174 if (rc != 0) {
1175 goto exit;
1176 }
1177
1178 exit:
1179 if (rc != 0) {
1180 sepol_log_err("Error writing mls rules to CIL\n");
1181 }
1182
1183 return rc;
1184 }
1185
write_polcap_rules_to_cil(FILE *out, struct policydb *pdb)1186 static int write_polcap_rules_to_cil(FILE *out, struct policydb *pdb)
1187 {
1188 struct strs *strs;
1189 struct ebitmap_node *node;
1190 const char *name;
1191 uint32_t i;
1192 int rc = 0;
1193
1194 rc = strs_init(&strs, 32);
1195 if (rc != 0) {
1196 goto exit;
1197 }
1198
1199 ebitmap_for_each_positive_bit(&pdb->policycaps, node, i) {
1200 name = sepol_polcap_getname(i);
1201 if (name == NULL) {
1202 sepol_log_err("Unknown policy capability id: %i", i);
1203 rc = -1;
1204 goto exit;
1205 }
1206
1207 rc = strs_create_and_add(strs, "(policycap %s)", 1, name);
1208 if (rc != 0) {
1209 goto exit;
1210 }
1211 }
1212
1213 strs_sort(strs);
1214 strs_write_each(strs, out);
1215
1216 exit:
1217 strs_free_all(strs);
1218 strs_destroy(&strs);
1219
1220 if (rc != 0) {
1221 sepol_log_err("Error writing polcap rules to CIL\n");
1222 }
1223
1224 return rc;
1225 }
1226
write_type_attributes_to_cil(FILE *out, struct policydb *pdb)1227 static int write_type_attributes_to_cil(FILE *out, struct policydb *pdb)
1228 {
1229 type_datum_t *type;
1230 char *name;
1231 struct strs *strs;
1232 unsigned i, num;
1233 int rc = 0;
1234
1235 rc = strs_init(&strs, pdb->p_types.nprim);
1236 if (rc != 0) {
1237 goto exit;
1238 }
1239
1240 for (i=0; i < pdb->p_types.nprim; i++) {
1241 type = pdb->type_val_to_struct[i];
1242 if (type && type->flavor == TYPE_ATTRIB) {
1243 rc = strs_add(strs, pdb->p_type_val_to_name[i]);
1244 if (rc != 0) {
1245 goto exit;
1246 }
1247 }
1248 }
1249
1250 strs_sort(strs);
1251
1252 num = strs_num_items(strs);
1253 for (i = 0; i < num; i++) {
1254 name = strs_read_at_index(strs, i);
1255 if (!name) {
1256 rc = -1;
1257 goto exit;
1258 }
1259 sepol_printf(out, "(typeattribute %s)\n", name);
1260 }
1261
1262 exit:
1263 strs_destroy(&strs);
1264
1265 if (rc != 0) {
1266 sepol_log_err("Error writing typeattribute rules to CIL\n");
1267 }
1268
1269 return rc;
1270 }
1271
write_role_attributes_to_cil(FILE *out, struct policydb *pdb)1272 static int write_role_attributes_to_cil(FILE *out, struct policydb *pdb)
1273 {
1274 role_datum_t *role;
1275 char *name;
1276 struct strs *strs;
1277 unsigned i, num;
1278 int rc = 0;
1279
1280 rc = strs_init(&strs, pdb->p_roles.nprim);
1281 if (rc != 0) {
1282 goto exit;
1283 }
1284
1285 for (i=0; i < pdb->p_roles.nprim; i++) {
1286 role = pdb->role_val_to_struct[i];
1287 if (role && role->flavor == ROLE_ATTRIB) {
1288 rc = strs_add(strs, pdb->p_role_val_to_name[i]);
1289 if (rc != 0) {
1290 goto exit;
1291 }
1292 }
1293 }
1294
1295 strs_sort(strs);
1296
1297 num = strs_num_items(strs);
1298 for (i=0; i<num; i++) {
1299 name = strs_read_at_index(strs, i);
1300 if (!name) {
1301 rc = -1;
1302 goto exit;
1303 }
1304 sepol_printf(out, "(roleattribute %s)\n", name);
1305 }
1306
1307 exit:
1308 strs_destroy(&strs);
1309
1310 if (rc != 0) {
1311 sepol_log_err("Error writing roleattribute rules to CIL\n");
1312 }
1313
1314 return rc;
1315 }
1316
map_boolean_to_strs(char *key, void *data, void *args)1317 static int map_boolean_to_strs(char *key, void *data, void *args)
1318 {
1319 struct strs *strs = (struct strs *)args;
1320 struct cond_bool_datum *boolean = data;
1321 const char *value;
1322
1323 value = boolean->state ? "true" : "false";
1324
1325 return strs_create_and_add(strs, "(boolean %s %s)", 2, key, value);
1326 }
1327
write_boolean_decl_rules_to_cil(FILE *out, struct policydb *pdb)1328 static int write_boolean_decl_rules_to_cil(FILE *out, struct policydb *pdb)
1329 {
1330 struct strs *strs;
1331 int rc = 0;
1332
1333 rc = strs_init(&strs, 32);
1334 if (rc != 0) {
1335 goto exit;
1336 }
1337
1338 rc = hashtab_map(pdb->p_bools.table, map_boolean_to_strs, strs);
1339 if (rc != 0) {
1340 goto exit;
1341 }
1342
1343 strs_sort(strs);
1344 strs_write_each(strs, out);
1345
1346 exit:
1347 strs_free_all(strs);
1348 strs_destroy(&strs);
1349
1350 if (rc != 0) {
1351 sepol_log_err("Error writing boolean declarations to CIL\n");
1352 }
1353
1354 return rc;
1355 }
1356
write_type_decl_rules_to_cil(FILE *out, struct policydb *pdb)1357 static int write_type_decl_rules_to_cil(FILE *out, struct policydb *pdb)
1358 {
1359 type_datum_t *type;
1360 struct strs *strs;
1361 char *name;
1362 unsigned i, num;
1363 int rc = 0;
1364
1365 rc = strs_init(&strs, pdb->p_types.nprim);
1366 if (rc != 0) {
1367 goto exit;
1368 }
1369
1370 for (i=0; i < pdb->p_types.nprim; i++) {
1371 type = pdb->type_val_to_struct[i];
1372 if (type && type->flavor == TYPE_TYPE && type->primary) {
1373 rc = strs_add(strs, pdb->p_type_val_to_name[i]);
1374 if (rc != 0) {
1375 goto exit;
1376 }
1377 }
1378 }
1379
1380 strs_sort(strs);
1381
1382 num = strs_num_items(strs);
1383 for (i=0; i<num; i++) {
1384 name = strs_read_at_index(strs, i);
1385 if (!name) {
1386 rc = -1;
1387 goto exit;
1388 }
1389 sepol_printf(out, "(type %s)\n", name);
1390 }
1391
1392 exit:
1393 strs_destroy(&strs);
1394
1395 if (rc != 0) {
1396 sepol_log_err("Error writing type declarations to CIL\n");
1397 }
1398
1399 return rc;
1400 }
1401
map_count_type_aliases(__attribute__((unused)) char *key, void *data, void *args)1402 static int map_count_type_aliases(__attribute__((unused)) char *key, void *data, void *args)
1403 {
1404 type_datum_t *datum = data;
1405 unsigned *count = args;
1406
1407 if (datum->primary == 0 && datum->flavor == TYPE_TYPE)
1408 (*count)++;
1409
1410 return SEPOL_OK;
1411 }
1412
map_type_aliases_to_strs(char *key, void *data, void *args)1413 static int map_type_aliases_to_strs(char *key, void *data, void *args)
1414 {
1415 type_datum_t *datum = data;
1416 struct strs *strs = args;
1417 int rc = 0;
1418
1419 if (datum->primary == 0 && datum->flavor == TYPE_TYPE)
1420 rc = strs_add(strs, key);
1421
1422 return rc;
1423 }
1424
write_type_alias_rules_to_cil(FILE *out, struct policydb *pdb)1425 static int write_type_alias_rules_to_cil(FILE *out, struct policydb *pdb)
1426 {
1427 type_datum_t *alias;
1428 struct strs *strs;
1429 char *name;
1430 char *type;
1431 unsigned i, num = 0;
1432 int rc = 0;
1433
1434 rc = hashtab_map(pdb->p_types.table, map_count_type_aliases, &num);
1435 if (rc != 0) {
1436 goto exit;
1437 }
1438
1439 rc = strs_init(&strs, num);
1440 if (rc != 0) {
1441 goto exit;
1442 }
1443
1444 rc = hashtab_map(pdb->p_types.table, map_type_aliases_to_strs, strs);
1445 if (rc != 0) {
1446 goto exit;
1447 }
1448
1449 strs_sort(strs);
1450
1451 for (i=0; i<num; i++) {
1452 name = strs_read_at_index(strs, i);
1453 if (!name) {
1454 rc = -1;
1455 goto exit;
1456 }
1457 sepol_printf(out, "(typealias %s)\n", name);
1458 }
1459
1460 for (i=0; i<num; i++) {
1461 name = strs_read_at_index(strs, i);
1462 if (!name) {
1463 rc = -1;
1464 goto exit;
1465 }
1466 alias = hashtab_search(pdb->p_types.table, name);
1467 if (!alias) {
1468 rc = -1;
1469 goto exit;
1470 }
1471 type = pdb->p_type_val_to_name[alias->s.value - 1];
1472 sepol_printf(out, "(typealiasactual %s %s)\n", name, type);
1473 }
1474
1475 exit:
1476 strs_destroy(&strs);
1477
1478 if (rc != 0) {
1479 sepol_log_err("Error writing type alias rules to CIL\n");
1480 }
1481
1482 return rc;
1483 }
1484
write_type_bounds_rules_to_cil(FILE *out, struct policydb *pdb)1485 static int write_type_bounds_rules_to_cil(FILE *out, struct policydb *pdb)
1486 {
1487 type_datum_t *type;
1488 struct strs *strs;
1489 char *parent;
1490 char *child;
1491 unsigned i, num;
1492 int rc = 0;
1493
1494 rc = strs_init(&strs, pdb->p_types.nprim);
1495 if (rc != 0) {
1496 goto exit;
1497 }
1498
1499 for (i=0; i < pdb->p_types.nprim; i++) {
1500 type = pdb->type_val_to_struct[i];
1501 if (type && type->flavor == TYPE_TYPE) {
1502 if (type->bounds > 0) {
1503 rc = strs_add(strs, pdb->p_type_val_to_name[i]);
1504 if (rc != 0) {
1505 goto exit;
1506 }
1507 }
1508 }
1509 }
1510
1511 strs_sort(strs);
1512
1513 num = strs_num_items(strs);
1514 for (i=0; i<num; i++) {
1515 child = strs_read_at_index(strs, i);
1516 if (!child) {
1517 rc = -1;
1518 goto exit;
1519 }
1520 type = hashtab_search(pdb->p_types.table, child);
1521 if (!type) {
1522 rc = -1;
1523 goto exit;
1524 }
1525 parent = pdb->p_type_val_to_name[type->bounds - 1];
1526 sepol_printf(out, "(typebounds %s %s)\n", parent, child);
1527 }
1528
1529 exit:
1530 strs_destroy(&strs);
1531
1532 if (rc != 0) {
1533 sepol_log_err("Error writing type bounds rules to CIL\n");
1534 }
1535
1536 return rc;
1537 }
1538
write_type_attribute_sets_to_cil(FILE *out, struct policydb *pdb)1539 static int write_type_attribute_sets_to_cil(FILE *out, struct policydb *pdb)
1540 {
1541 type_datum_t *attr;
1542 struct strs *strs;
1543 ebitmap_t *typemap;
1544 char *name, *types;
1545 unsigned i;
1546 int rc;
1547
1548 rc = strs_init(&strs, pdb->p_types.nprim);
1549 if (rc != 0) {
1550 goto exit;
1551 }
1552
1553 for (i=0; i < pdb->p_types.nprim; i++) {
1554 attr = pdb->type_val_to_struct[i];
1555 if (!attr || attr->flavor != TYPE_ATTRIB) continue;
1556 name = pdb->p_type_val_to_name[i];
1557 typemap = &pdb->attr_type_map[i];
1558 if (ebitmap_is_empty(typemap)) continue;
1559 types = ebitmap_to_str(typemap, pdb->p_type_val_to_name, 1);
1560 if (!types) {
1561 rc = -1;
1562 goto exit;
1563 }
1564
1565 rc = strs_create_and_add(strs, "(typeattributeset %s (%s))",
1566 2, name, types);
1567 free(types);
1568 if (rc != 0) {
1569 goto exit;
1570 }
1571 }
1572
1573 strs_sort(strs);
1574 strs_write_each(strs, out);
1575
1576 exit:
1577 strs_free_all(strs);
1578 strs_destroy(&strs);
1579
1580 if (rc != 0) {
1581 sepol_log_err("Error writing typeattributeset rules to CIL\n");
1582 }
1583
1584 return rc;
1585 }
1586
write_type_permissive_rules_to_cil(FILE *out, struct policydb *pdb)1587 static int write_type_permissive_rules_to_cil(FILE *out, struct policydb *pdb)
1588 {
1589 struct strs *strs;
1590 char *name;
1591 struct ebitmap_node *node;
1592 unsigned i, num;
1593 int rc = 0;
1594
1595 rc = strs_init(&strs, pdb->p_types.nprim);
1596 if (rc != 0) {
1597 goto exit;
1598 }
1599
1600 ebitmap_for_each_positive_bit(&pdb->permissive_map, node, i) {
1601 rc = strs_add(strs, pdb->p_type_val_to_name[i-1]);
1602 if (rc != 0) {
1603 goto exit;
1604 }
1605 }
1606
1607 strs_sort(strs);
1608
1609 num = strs_num_items(strs);
1610 for (i=0; i<num; i++) {
1611 name = strs_read_at_index(strs, i);
1612 if (!name) {
1613 rc = -1;
1614 goto exit;
1615 }
1616 sepol_printf(out, "(typepermissive %s)\n", name);
1617 }
1618
1619 exit:
1620 strs_destroy(&strs);
1621
1622 if (rc != 0) {
1623 sepol_log_err("Error writing typepermissive rules to CIL\n");
1624 }
1625
1626 return rc;
1627 }
1628
1629 #define next_bit_in_range(i, p) (((i) + 1 < sizeof(p)*8) && xperm_test(((i) + 1), p))
1630
xperms_to_str(avtab_extended_perms_t *xperms)1631 static char *xperms_to_str(avtab_extended_perms_t *xperms)
1632 {
1633 uint16_t value;
1634 uint16_t low_bit;
1635 uint16_t low_value;
1636 unsigned int bit;
1637 unsigned int in_range = 0;
1638 static char xpermsbuf[2048];
1639 char *p;
1640 int len, remaining;
1641
1642 p = xpermsbuf;
1643 remaining = sizeof(xpermsbuf);
1644
1645 if ((xperms->specified != AVTAB_XPERMS_IOCTLFUNCTION)
1646 && (xperms->specified != AVTAB_XPERMS_IOCTLDRIVER)) {
1647 return NULL;
1648 }
1649
1650 for (bit = 0; bit < sizeof(xperms->perms)*8; bit++) {
1651 len = 0;
1652
1653 if (!xperm_test(bit, xperms->perms))
1654 continue;
1655
1656 if (in_range && next_bit_in_range(bit, xperms->perms)) {
1657 /* continue until high value found */
1658 continue;
1659 } else if (next_bit_in_range(bit, xperms->perms)) {
1660 /* low value */
1661 low_bit = bit;
1662 in_range = 1;
1663 continue;
1664 }
1665
1666 if (xperms->specified & AVTAB_XPERMS_IOCTLFUNCTION) {
1667 value = xperms->driver<<8 | bit;
1668 if (in_range) {
1669 low_value = xperms->driver<<8 | low_bit;
1670 len = snprintf(p, remaining, " (range 0x%hx 0x%hx)", low_value, value);
1671 in_range = 0;
1672 } else {
1673 len = snprintf(p, remaining, " 0x%hx", value);
1674 }
1675 } else if (xperms->specified & AVTAB_XPERMS_IOCTLDRIVER) {
1676 value = bit << 8;
1677 if (in_range) {
1678 low_value = low_bit << 8;
1679 len = snprintf(p, remaining, " (range 0x%hx 0x%hx)", low_value, (uint16_t) (value|0xff));
1680 in_range = 0;
1681 } else {
1682 len = snprintf(p, remaining, " (range 0x%hx 0x%hx)", value, (uint16_t) (value|0xff));
1683 }
1684
1685 }
1686 if (len < 0 || len >= remaining) {
1687 return NULL;
1688 }
1689 p += len;
1690 remaining -= len;
1691 }
1692
1693 if (remaining < 2) {
1694 return NULL;
1695 }
1696
1697 xpermsbuf[0] = '(';
1698 *p++ = ')';
1699 *p = '\0';
1700
1701 return xpermsbuf;
1702 }
1703
avtab_node_to_str(struct policydb *pdb, avtab_key_t *key, avtab_datum_t *datum)1704 static char *avtab_node_to_str(struct policydb *pdb, avtab_key_t *key, avtab_datum_t *datum)
1705 {
1706 uint32_t data = datum->data;
1707 type_datum_t *type;
1708 const char *flavor, *tgt;
1709 char *src, *class, *perms, *new;
1710 char *rule = NULL;
1711
1712 switch (0xFFF & key->specified) {
1713 case AVTAB_ALLOWED:
1714 flavor = "allow";
1715 break;
1716 case AVTAB_AUDITALLOW:
1717 flavor = "auditallow";
1718 break;
1719 case AVTAB_AUDITDENY:
1720 flavor = "dontaudit";
1721 data = ~data;
1722 break;
1723 case AVTAB_XPERMS_ALLOWED:
1724 flavor = "allowx";
1725 break;
1726 case AVTAB_XPERMS_AUDITALLOW:
1727 flavor = "auditallowx";
1728 break;
1729 case AVTAB_XPERMS_DONTAUDIT:
1730 flavor = "dontauditx";
1731 break;
1732 case AVTAB_TRANSITION:
1733 flavor = "typetransition";
1734 break;
1735 case AVTAB_MEMBER:
1736 flavor = "typemember";
1737 break;
1738 case AVTAB_CHANGE:
1739 flavor = "typechange";
1740 break;
1741 default:
1742 sepol_log_err("Unknown avtab type: %i", key->specified);
1743 goto exit;
1744 }
1745
1746 src = pdb->p_type_val_to_name[key->source_type - 1];
1747 tgt = pdb->p_type_val_to_name[key->target_type - 1];
1748 if (key->source_type == key->target_type && !(key->specified & AVTAB_TYPE)) {
1749 type = pdb->type_val_to_struct[key->source_type - 1];
1750 if (type->flavor != TYPE_ATTRIB) {
1751 tgt = "self";
1752 }
1753 }
1754 class = pdb->p_class_val_to_name[key->target_class - 1];
1755
1756 if (key->specified & AVTAB_AV) {
1757 perms = sepol_av_to_string(pdb, key->target_class, data);
1758 if (perms == NULL) {
1759 sepol_log_err("Failed to generate permission string");
1760 goto exit;
1761 }
1762 rule = create_str("(%s %s %s (%s (%s)))", 5,
1763 flavor, src, tgt, class, perms+1);
1764 } else if (key->specified & AVTAB_XPERMS) {
1765 perms = xperms_to_str(datum->xperms);
1766 if (perms == NULL) {
1767 sepol_log_err("Failed to generate extended permission string");
1768 goto exit;
1769 }
1770
1771 rule = create_str("(%s %s %s (%s %s (%s)))", 6,
1772 flavor, src, tgt, "ioctl", class, perms);
1773 } else {
1774 new = pdb->p_type_val_to_name[data - 1];
1775
1776 rule = create_str("(%s %s %s %s %s)", 5, flavor, src, tgt, class, new);
1777 }
1778
1779 if (!rule) {
1780 goto exit;
1781 }
1782
1783 return rule;
1784
1785 exit:
1786 return NULL;
1787 }
1788
1789 struct map_avtab_args {
1790 struct policydb *pdb;
1791 uint32_t flavor;
1792 struct strs *strs;
1793 };
1794
map_avtab_write_helper(avtab_key_t *key, avtab_datum_t *datum, void *args)1795 static int map_avtab_write_helper(avtab_key_t *key, avtab_datum_t *datum, void *args)
1796 {
1797 struct map_avtab_args *map_args = args;
1798 uint32_t flavor = map_args->flavor;
1799 struct policydb *pdb = map_args->pdb;
1800 struct strs *strs = map_args->strs;
1801 char *rule;
1802 int rc = 0;
1803
1804 if (key->specified & flavor) {
1805 rule = avtab_node_to_str(pdb, key, datum);
1806 if (!rule) {
1807 rc = -1;
1808 goto exit;
1809 }
1810 rc = strs_add(strs, rule);
1811 if (rc != 0) {
1812 free(rule);
1813 goto exit;
1814 }
1815 }
1816
1817 exit:
1818 return rc;
1819 }
1820
write_avtab_flavor_to_cil(FILE *out, struct policydb *pdb, uint32_t flavor, int indent)1821 static int write_avtab_flavor_to_cil(FILE *out, struct policydb *pdb, uint32_t flavor, int indent)
1822 {
1823 struct map_avtab_args args;
1824 struct strs *strs;
1825 int rc = 0;
1826
1827 rc = strs_init(&strs, 1000);
1828 if (rc != 0) {
1829 goto exit;
1830 }
1831
1832 args.pdb = pdb;
1833 args.flavor = flavor;
1834 args.strs = strs;
1835
1836 rc = avtab_map(&pdb->te_avtab, map_avtab_write_helper, &args);
1837 if (rc != 0) {
1838 goto exit;
1839 }
1840
1841 strs_sort(strs);
1842 strs_write_each_indented(strs, out, indent);
1843
1844 exit:
1845 strs_free_all(strs);
1846 strs_destroy(&strs);
1847
1848 return rc;
1849 }
1850
write_avtab_to_cil(FILE *out, struct policydb *pdb, int indent)1851 static int write_avtab_to_cil(FILE *out, struct policydb *pdb, int indent)
1852 {
1853 unsigned i;
1854 int rc = 0;
1855
1856 for (i = 0; i < AVTAB_FLAVORS_SZ; i++) {
1857 rc = write_avtab_flavor_to_cil(out, pdb, avtab_flavors[i], indent);
1858 if (rc != 0) {
1859 goto exit;
1860 }
1861 }
1862
1863 exit:
1864 if (rc != 0) {
1865 sepol_log_err("Error writing avtab rules to CIL\n");
1866 }
1867
1868 return rc;
1869 }
1870
1871 struct map_filename_trans_args {
1872 struct policydb *pdb;
1873 struct strs *strs;
1874 };
1875
map_filename_trans_to_str(hashtab_key_t key, void *data, void *arg)1876 static int map_filename_trans_to_str(hashtab_key_t key, void *data, void *arg)
1877 {
1878 filename_trans_key_t *ft = (filename_trans_key_t *)key;
1879 filename_trans_datum_t *datum = data;
1880 struct map_filename_trans_args *map_args = arg;
1881 struct policydb *pdb = map_args->pdb;
1882 struct strs *strs = map_args->strs;
1883 char *src, *tgt, *class, *filename, *new;
1884 struct ebitmap_node *node;
1885 uint32_t bit;
1886 int rc;
1887
1888 tgt = pdb->p_type_val_to_name[ft->ttype - 1];
1889 class = pdb->p_class_val_to_name[ft->tclass - 1];
1890 filename = ft->name;
1891 do {
1892 new = pdb->p_type_val_to_name[datum->otype - 1];
1893
1894 ebitmap_for_each_positive_bit(&datum->stypes, node, bit) {
1895 src = pdb->p_type_val_to_name[bit];
1896 rc = strs_create_and_add(strs,
1897 "(typetransition %s %s %s \"%s\" %s)",
1898 5, src, tgt, class, filename, new);
1899 if (rc)
1900 return rc;
1901 }
1902
1903 datum = datum->next;
1904 } while (datum);
1905
1906 return 0;
1907 }
1908
write_filename_trans_rules_to_cil(FILE *out, struct policydb *pdb)1909 static int write_filename_trans_rules_to_cil(FILE *out, struct policydb *pdb)
1910 {
1911 struct map_filename_trans_args args;
1912 struct strs *strs;
1913 int rc = 0;
1914
1915 rc = strs_init(&strs, 100);
1916 if (rc != 0) {
1917 goto exit;
1918 }
1919
1920 args.pdb = pdb;
1921 args.strs = strs;
1922
1923 rc = hashtab_map(pdb->filename_trans, map_filename_trans_to_str, &args);
1924 if (rc != 0) {
1925 goto exit;
1926 }
1927
1928 strs_sort(strs);
1929 strs_write_each(strs, out);
1930
1931 exit:
1932 strs_free_all(strs);
1933 strs_destroy(&strs);
1934
1935 if (rc != 0) {
1936 sepol_log_err("Error writing filename typetransition rules to CIL\n");
1937 }
1938
1939 return rc;
1940 }
1941
level_to_str(struct policydb *pdb, struct mls_level *level)1942 static char *level_to_str(struct policydb *pdb, struct mls_level *level)
1943 {
1944 ebitmap_t *cats = &level->cat;
1945 char *level_str = NULL;
1946 char *sens_str = pdb->p_sens_val_to_name[level->sens - 1];
1947 char *cats_str;
1948
1949 if (!ebitmap_is_empty(cats)) {
1950 cats_str = cats_ebitmap_to_str(cats, pdb->p_cat_val_to_name);
1951 level_str = create_str("(%s %s)", 2, sens_str, cats_str);
1952 free(cats_str);
1953 } else {
1954 level_str = create_str("(%s)", 1, sens_str);
1955 }
1956
1957 return level_str;
1958 }
1959
range_to_str(struct policydb *pdb, mls_range_t *range)1960 static char *range_to_str(struct policydb *pdb, mls_range_t *range)
1961 {
1962 char *low = NULL;
1963 char *high = NULL;
1964 char *range_str = NULL;
1965
1966 low = level_to_str(pdb, &range->level[0]);
1967 if (!low) {
1968 goto exit;
1969 }
1970
1971 high = level_to_str(pdb, &range->level[1]);
1972 if (!high) {
1973 goto exit;
1974 }
1975
1976 range_str = create_str("(%s %s)", 2, low, high);
1977
1978 exit:
1979 free(low);
1980 free(high);
1981
1982 return range_str;
1983 }
1984
1985 struct map_range_trans_args {
1986 struct policydb *pdb;
1987 struct strs *strs;
1988 };
1989
map_range_trans_to_str(hashtab_key_t key, void *data, void *arg)1990 static int map_range_trans_to_str(hashtab_key_t key, void *data, void *arg)
1991 {
1992 range_trans_t *rt = (range_trans_t *)key;
1993 mls_range_t *mls_range = data;
1994 struct map_range_trans_args *map_args = arg;
1995 struct policydb *pdb = map_args->pdb;
1996 struct strs *strs = map_args->strs;
1997 char *src, *tgt, *class, *range;
1998 int rc;
1999
2000 src = pdb->p_type_val_to_name[rt->source_type - 1];
2001 tgt = pdb->p_type_val_to_name[rt->target_type - 1];
2002 class = pdb->p_class_val_to_name[rt->target_class - 1];
2003 range = range_to_str(pdb, mls_range);
2004 if (!range) {
2005 rc = -1;
2006 goto exit;
2007 }
2008
2009 rc = strs_create_and_add(strs, "(rangetransition %s %s %s %s)", 4,
2010 src, tgt, class, range);
2011 free(range);
2012 if (rc != 0) {
2013 goto exit;
2014 }
2015
2016 exit:
2017 return rc;
2018 }
2019
write_range_trans_rules_to_cil(FILE *out, struct policydb *pdb)2020 static int write_range_trans_rules_to_cil(FILE *out, struct policydb *pdb)
2021 {
2022 struct map_range_trans_args args;
2023 struct strs *strs;
2024 int rc = 0;
2025
2026 rc = strs_init(&strs, 100);
2027 if (rc != 0) {
2028 goto exit;
2029 }
2030
2031 args.pdb = pdb;
2032 args.strs = strs;
2033
2034 rc = hashtab_map(pdb->range_tr, map_range_trans_to_str, &args);
2035 if (rc != 0) {
2036 goto exit;
2037 }
2038
2039 strs_sort(strs);
2040 strs_write_each(strs, out);
2041
2042 exit:
2043 strs_free_all(strs);
2044 strs_destroy(&strs);
2045
2046 if (rc != 0) {
2047 sepol_log_err("Error writing range transition rules to CIL\n");
2048 }
2049
2050 return rc;
2051 }
2052
write_cond_av_list_to_cil(FILE *out, struct policydb *pdb, cond_av_list_t *cond_list, int indent)2053 static int write_cond_av_list_to_cil(FILE *out, struct policydb *pdb, cond_av_list_t *cond_list, int indent)
2054 {
2055 cond_av_list_t *cond_av;
2056 avtab_ptr_t node;
2057 uint32_t flavor;
2058 avtab_key_t *key;
2059 avtab_datum_t *datum;
2060 struct strs *strs;
2061 char *rule;
2062 unsigned i;
2063 int rc;
2064
2065 for (i = 0; i < AVTAB_FLAVORS_SZ; i++) {
2066 flavor = avtab_flavors[i];
2067 rc = strs_init(&strs, 64);
2068 if (rc != 0) {
2069 goto exit;
2070 }
2071
2072 for (cond_av = cond_list; cond_av != NULL; cond_av = cond_av->next) {
2073 node = cond_av->node;
2074 key = &node->key;
2075 datum = &node->datum;
2076 if (key->specified & flavor) {
2077 rule = avtab_node_to_str(pdb, key, datum);
2078 if (!rule) {
2079 rc = -1;
2080 goto exit;
2081 }
2082 rc = strs_add(strs, rule);
2083 if (rc != 0) {
2084 free(rule);
2085 goto exit;
2086 }
2087 }
2088 }
2089
2090 strs_sort(strs);
2091 strs_write_each_indented(strs, out, indent);
2092 strs_free_all(strs);
2093 strs_destroy(&strs);
2094 }
2095
2096 return 0;
2097
2098 exit:
2099 strs_free_all(strs);
2100 strs_destroy(&strs);
2101 return rc;
2102 }
2103
2104 struct cond_data {
2105 char *expr;
2106 struct cond_node *cond;
2107 };
2108
cond_node_cmp(const void *a, const void *b)2109 static int cond_node_cmp(const void *a, const void *b)
2110 {
2111 const struct cond_data *aa = a;
2112 const struct cond_data *bb = b;
2113 return strcmp(aa->expr, bb->expr);
2114 }
2115
write_cond_nodes_to_cil(FILE *out, struct policydb *pdb)2116 static int write_cond_nodes_to_cil(FILE *out, struct policydb *pdb)
2117 {
2118 struct cond_data *cond_data;
2119 char *expr;
2120 struct cond_node *cond;
2121 unsigned i, num = 0;
2122 int rc = 0;
2123
2124 for (cond = pdb->cond_list; cond != NULL; cond = cond->next) {
2125 num++;
2126 }
2127
2128 cond_data = calloc(num, sizeof(struct cond_data));
2129 if (!cond_data) {
2130 rc = -1;
2131 goto exit;
2132 }
2133
2134 i = 0;
2135 for (cond = pdb->cond_list; cond != NULL; cond = cond->next) {
2136 cond_data[i].cond = cond;
2137 expr = cond_expr_to_str(pdb, cond->expr);
2138 if (!expr) {
2139 num = i;
2140 goto exit;
2141 }
2142 cond_data[i].expr = expr;
2143 i++;
2144 }
2145
2146 qsort(cond_data, num, sizeof(*cond_data), cond_node_cmp);
2147
2148 for (i=0; i<num; i++) {
2149 expr = cond_data[i].expr;
2150 cond = cond_data[i].cond;
2151
2152 sepol_printf(out, "(booleanif %s\n", expr);
2153
2154 if (cond->true_list != NULL) {
2155 sepol_indent(out, 1);
2156 sepol_printf(out, "(true\n");
2157 rc = write_cond_av_list_to_cil(out, pdb, cond->true_list, 2);
2158 if (rc != 0) {
2159 goto exit;
2160 }
2161 sepol_indent(out, 1);
2162 sepol_printf(out, ")\n");
2163 }
2164
2165 if (cond->false_list != NULL) {
2166 sepol_indent(out, 1);
2167 sepol_printf(out, "(false\n");
2168 rc = write_cond_av_list_to_cil(out, pdb, cond->false_list, 2);
2169 if (rc != 0) {
2170 goto exit;
2171 }
2172 sepol_indent(out, 1);
2173 sepol_printf(out, ")\n");
2174 }
2175 sepol_printf(out, ")\n");
2176 }
2177
2178 exit:
2179 if (cond_data) {
2180 for (i=0; i<num; i++) {
2181 free(cond_data[i].expr);
2182 }
2183 free(cond_data);
2184 }
2185
2186 if (rc != 0) {
2187 sepol_log_err("Error writing conditional rules to CIL\n");
2188 }
2189
2190 return rc;
2191 }
2192
write_role_decl_rules_to_cil(FILE *out, struct policydb *pdb)2193 static int write_role_decl_rules_to_cil(FILE *out, struct policydb *pdb)
2194 {
2195 struct role_datum *role;
2196 struct strs *strs, *type_strs;
2197 char *name, *parent, *child, *type;
2198 struct ebitmap *types;
2199 struct type_datum *type_datum;
2200 unsigned i, num, j, num_types;
2201 int rc = 0;
2202
2203 rc = strs_init(&strs, pdb->p_roles.nprim);
2204 if (rc != 0) {
2205 goto exit;
2206 }
2207
2208 for (i=0; i < pdb->p_roles.nprim; i++) {
2209 role = pdb->role_val_to_struct[i];
2210 if (role && role->flavor == ROLE_ROLE) {
2211 rc = strs_add(strs, pdb->p_role_val_to_name[i]);
2212 if (rc != 0) {
2213 goto exit;
2214 }
2215 }
2216 }
2217
2218 strs_sort(strs);
2219
2220 num = strs_num_items(strs);
2221
2222 for (i=0; i<num; i++) {
2223 name = strs_read_at_index(strs, i);
2224 if (!name) {
2225 continue;
2226 }
2227 sepol_printf(out, "(role %s)\n", name);
2228 }
2229
2230 for (i=0; i<num; i++) {
2231 child = strs_read_at_index(strs, i);
2232 if (!child) {
2233 continue;
2234 }
2235 role = hashtab_search(pdb->p_roles.table, child);
2236 if (!role) {
2237 rc = -1;
2238 goto exit;
2239 }
2240
2241 if (role->bounds > 0) {
2242 parent = pdb->p_role_val_to_name[role->bounds - 1];
2243 sepol_printf(out, "(rolebounds %s %s)\n", parent, child);
2244 }
2245 }
2246
2247 for (i=0; i<num; i++) {
2248 name = strs_read_at_index(strs, i);
2249 if (!name) {
2250 continue;
2251 }
2252 role = hashtab_search(pdb->p_roles.table, name);
2253 if (!role) {
2254 rc = -1;
2255 goto exit;
2256 }
2257 types = &role->types.types;
2258 if (types && !ebitmap_is_empty(types)) {
2259 rc = strs_init(&type_strs, pdb->p_types.nprim);
2260 if (rc != 0) {
2261 goto exit;
2262 }
2263 rc = ebitmap_to_strs(types, type_strs, pdb->p_type_val_to_name);
2264 if (rc != 0) {
2265 strs_destroy(&type_strs);
2266 goto exit;
2267 }
2268 strs_sort(type_strs);
2269
2270 num_types = strs_num_items(type_strs);
2271 for (j=0; j<num_types; j++) {
2272 type = strs_read_at_index(type_strs, j);
2273 sepol_printf(out, "(roletype %s %s)\n", name, type);
2274 }
2275 strs_destroy(&type_strs);
2276 }
2277 }
2278
2279 strs_destroy(&strs);
2280
2281 rc = strs_init(&strs, pdb->p_types.nprim);
2282 if (rc != 0) {
2283 goto exit;
2284 }
2285
2286 for (i=0; i < pdb->p_types.nprim; i++) {
2287 type_datum = pdb->type_val_to_struct[i];
2288 if (type_datum && type_datum->flavor == TYPE_TYPE && type_datum->primary) {
2289 rc = strs_add(strs, pdb->p_type_val_to_name[i]);
2290 if (rc != 0) {
2291 goto exit;
2292 }
2293 }
2294 }
2295
2296 strs_sort(strs);
2297
2298 num = strs_num_items(strs);
2299
2300 for (i=0; i<num; i++) {
2301 name = strs_read_at_index(strs, i);
2302 if (!name) {
2303 continue;
2304 }
2305 sepol_printf(out, "(roletype %s %s)\n", DEFAULT_OBJECT, name);
2306 }
2307
2308 exit:
2309 strs_destroy(&strs);
2310
2311 if (rc != 0) {
2312 sepol_log_err("Error writing role declarations to CIL\n");
2313 }
2314
2315 return rc;
2316 }
2317
write_role_transition_rules_to_cil(FILE *out, struct policydb *pdb)2318 static int write_role_transition_rules_to_cil(FILE *out, struct policydb *pdb)
2319 {
2320 role_trans_t *curr = pdb->role_tr;
2321 struct strs *strs;
2322 char *role, *type, *class, *new;
2323 int rc = 0;
2324
2325 rc = strs_init(&strs, 32);
2326 if (rc != 0) {
2327 goto exit;
2328 }
2329
2330 while (curr) {
2331 role = pdb->p_role_val_to_name[curr->role - 1];
2332 type = pdb->p_type_val_to_name[curr->type - 1];
2333 class = pdb->p_class_val_to_name[curr->tclass - 1];
2334 new = pdb->p_role_val_to_name[curr->new_role - 1];
2335
2336 rc = strs_create_and_add(strs, "(roletransition %s %s %s %s)", 4,
2337 role, type, class, new);
2338 if (rc != 0) {
2339 goto exit;
2340 }
2341
2342 curr = curr->next;
2343 }
2344
2345 strs_sort(strs);
2346 strs_write_each(strs, out);
2347
2348 exit:
2349 strs_free_all(strs);
2350 strs_destroy(&strs);
2351
2352 if (rc != 0) {
2353 sepol_log_err("Error writing role transition rules to CIL\n");
2354 }
2355
2356 return rc;
2357 }
2358
write_role_allow_rules_to_cil(FILE *out, struct policydb *pdb)2359 static int write_role_allow_rules_to_cil(FILE *out, struct policydb *pdb)
2360 {
2361 role_allow_t *curr = pdb->role_allow;
2362 struct strs *strs;
2363 char *role, *new;
2364 int rc = 0;
2365
2366 rc = strs_init(&strs, 32);
2367 if (rc != 0) {
2368 goto exit;
2369 }
2370
2371 while (curr) {
2372 role = pdb->p_role_val_to_name[curr->role - 1];
2373 new = pdb->p_role_val_to_name[curr->new_role - 1];
2374
2375 rc = strs_create_and_add(strs, "(roleallow %s %s)", 2, role, new);
2376 if (rc != 0) {
2377 goto exit;
2378 }
2379
2380 curr = curr->next;
2381 }
2382
2383 strs_sort(strs);
2384 strs_write_each(strs, out);
2385
2386 exit:
2387 strs_free_all(strs);
2388 strs_destroy(&strs);
2389
2390 if (rc != 0) {
2391 sepol_log_err("Error writing role allow rules to CIL\n");
2392 }
2393
2394 return rc;
2395 }
2396
write_user_decl_rules_to_cil(FILE *out, struct policydb *pdb)2397 static int write_user_decl_rules_to_cil(FILE *out, struct policydb *pdb)
2398 {
2399 struct user_datum *user;
2400 struct strs *strs, *role_strs;
2401 char *name, *role, *level, *range;
2402 struct ebitmap *roles;
2403 unsigned i, j, num, num_roles;
2404 int rc = 0;
2405
2406 rc = strs_init(&strs, pdb->p_users.nprim);
2407 if (rc != 0) {
2408 goto exit;
2409 }
2410
2411 for (i=0; i < pdb->p_users.nprim; i++) {
2412 if (!pdb->p_user_val_to_name[i]) continue;
2413 rc = strs_add(strs, pdb->p_user_val_to_name[i]);
2414 if (rc != 0) {
2415 goto exit;
2416 }
2417 }
2418
2419 strs_sort(strs);
2420
2421 num = strs_num_items(strs);
2422
2423 for (i=0; i<num; i++) {
2424 name = strs_read_at_index(strs, i);
2425 if (!name) {
2426 continue;
2427 }
2428 sepol_printf(out, "(user %s)\n", name);
2429 }
2430
2431 for (i=0; i<num; i++) {
2432 name = strs_read_at_index(strs, i);
2433 if (!name) {
2434 continue;
2435 }
2436
2437 user = hashtab_search(pdb->p_users.table, name);
2438 if (!user) {
2439 rc = -1;
2440 goto exit;
2441 }
2442
2443 roles = &user->roles.roles;
2444 if (roles && !ebitmap_is_empty(roles)) {
2445 rc = strs_init(&role_strs, pdb->p_roles.nprim);
2446 if (rc != 0) {
2447 goto exit;
2448 }
2449 rc = ebitmap_to_strs(roles, role_strs, pdb->p_role_val_to_name);
2450 if (rc != 0) {
2451 strs_destroy(&role_strs);
2452 goto exit;
2453 }
2454
2455 rc = strs_add(role_strs, (char *)DEFAULT_OBJECT);
2456 if (rc != 0) {
2457 strs_destroy(&role_strs);
2458 goto exit;
2459 }
2460
2461 strs_sort(role_strs);
2462
2463 num_roles = strs_num_items(role_strs);
2464 for (j=0; j<num_roles; j++) {
2465 role = strs_read_at_index(role_strs, j);
2466 sepol_printf(out, "(userrole %s %s)\n", name, role);
2467 }
2468 strs_destroy(&role_strs);
2469 }
2470 }
2471
2472 for (i=0; i<num; i++) {
2473 name = strs_read_at_index(strs, i);
2474 if (!name) {
2475 continue;
2476 }
2477
2478 user = hashtab_search(pdb->p_users.table, name);
2479 if (!user) {
2480 rc = -1;
2481 goto exit;
2482 }
2483
2484 sepol_printf(out, "(userlevel %s ", name);
2485
2486 if (pdb->mls) {
2487 level = level_to_str(pdb, &user->exp_dfltlevel);
2488 if (!level) {
2489 rc = -1;
2490 goto exit;
2491 }
2492 sepol_printf(out, "%s", level);
2493 free(level);
2494 } else {
2495 sepol_printf(out, "%s", DEFAULT_LEVEL);
2496 }
2497 sepol_printf(out, ")\n");
2498 }
2499
2500 for (i=0; i<num; i++) {
2501 name = strs_read_at_index(strs, i);
2502 if (!name) {
2503 continue;
2504 }
2505
2506 user = hashtab_search(pdb->p_users.table, name);
2507 if (!user) {
2508 rc = -1;
2509 goto exit;
2510 }
2511
2512 sepol_printf(out, "(userrange %s ", name);
2513 if (pdb->mls) {
2514 range = range_to_str(pdb, &user->exp_range);
2515 if (!range) {
2516 rc = -1;
2517 goto exit;
2518 }
2519 sepol_printf(out, "%s", range);
2520 free(range);
2521 } else {
2522 sepol_printf(out, "(%s %s)", DEFAULT_LEVEL, DEFAULT_LEVEL);
2523 }
2524 sepol_printf(out, ")\n");
2525 }
2526
2527 exit:
2528 if (strs)
2529 strs_destroy(&strs);
2530
2531 if (rc != 0) {
2532 sepol_log_err("Error writing user declarations to CIL\n");
2533 }
2534
2535 return rc;
2536 }
2537
context_to_str(struct policydb *pdb, struct context_struct *con)2538 static char *context_to_str(struct policydb *pdb, struct context_struct *con)
2539 {
2540 char *user, *role, *type, *range;
2541 char *ctx = NULL;
2542
2543 user = pdb->p_user_val_to_name[con->user - 1];
2544 role = pdb->p_role_val_to_name[con->role - 1];
2545 type = pdb->p_type_val_to_name[con->type - 1];
2546
2547 if (pdb->mls) {
2548 range = range_to_str(pdb, &con->range);
2549 } else {
2550 range = create_str("(%s %s)", 2, DEFAULT_LEVEL, DEFAULT_LEVEL);
2551 }
2552 if (!range) {
2553 goto exit;
2554 }
2555
2556 ctx = create_str("(%s %s %s %s)", 4, user, role, type, range);
2557 free(range);
2558
2559 exit:
2560 return ctx;
2561 }
2562
write_sid_context_rules_to_cil(FILE *out, struct policydb *pdb, const char *const *sid_to_str, unsigned num_sids)2563 static int write_sid_context_rules_to_cil(FILE *out, struct policydb *pdb, const char *const *sid_to_str, unsigned num_sids)
2564 {
2565 struct ocontext *isid;
2566 struct strs *strs;
2567 char *sid;
2568 char unknown[18];
2569 char *ctx, *rule;
2570 unsigned i;
2571 int rc = -1;
2572
2573 rc = strs_init(&strs, 32);
2574 if (rc != 0) {
2575 goto exit;
2576 }
2577
2578 for (isid = pdb->ocontexts[0]; isid != NULL; isid = isid->next) {
2579 i = isid->sid[0];
2580 if (i < num_sids) {
2581 sid = (char *)sid_to_str[i];
2582 } else {
2583 snprintf(unknown, 18, "%s%u", "UNKNOWN", i);
2584 sid = unknown;
2585 }
2586
2587 ctx = context_to_str(pdb, &isid->context[0]);
2588 if (!ctx) {
2589 rc = -1;
2590 goto exit;
2591 }
2592
2593 rule = create_str("(sidcontext %s %s)", 2, sid, ctx);
2594 free(ctx);
2595 if (!rule) {
2596 rc = -1;
2597 goto exit;
2598 }
2599
2600 rc = strs_add_at_index(strs, rule, i);
2601 if (rc != 0) {
2602 free(rule);
2603 goto exit;
2604 }
2605 }
2606
2607 strs_write_each(strs, out);
2608
2609 exit:
2610 strs_free_all(strs);
2611 strs_destroy(&strs);
2612
2613 if (rc != 0) {
2614 sepol_log_err("Error writing sidcontext rules to CIL\n");
2615 }
2616
2617 return rc;
2618 }
2619
write_selinux_isid_rules_to_cil(FILE *out, struct policydb *pdb)2620 static int write_selinux_isid_rules_to_cil(FILE *out, struct policydb *pdb)
2621 {
2622 return write_sid_context_rules_to_cil(out, pdb, selinux_sid_to_str,
2623 SELINUX_SID_SZ);
2624 }
2625
write_selinux_fsuse_rules_to_cil(FILE *out, struct policydb *pdb)2626 static int write_selinux_fsuse_rules_to_cil(FILE *out, struct policydb *pdb)
2627 {
2628 struct ocontext *fsuse;
2629 const char *behavior;
2630 char *name, *ctx;
2631 int rc = 0;
2632
2633 for (fsuse = pdb->ocontexts[5]; fsuse != NULL; fsuse = fsuse->next) {
2634 switch (fsuse->v.behavior) {
2635 case SECURITY_FS_USE_XATTR: behavior = "xattr"; break;
2636 case SECURITY_FS_USE_TRANS: behavior = "trans"; break;
2637 case SECURITY_FS_USE_TASK: behavior = "task"; break;
2638 default:
2639 sepol_log_err("Unknown fsuse behavior: %i", fsuse->v.behavior);
2640 rc = -1;
2641 goto exit;
2642 }
2643
2644 name = fsuse->u.name;
2645 ctx = context_to_str(pdb, &fsuse->context[0]);
2646 if (!ctx) {
2647 rc = -1;
2648 goto exit;
2649 }
2650
2651 sepol_printf(out, "(fsuse %s %s %s)\n", behavior, name, ctx);
2652
2653 free(ctx);
2654 }
2655
2656 exit:
2657 if (rc != 0) {
2658 sepol_log_err("Error writing fsuse rules to CIL\n");
2659 }
2660
2661 return rc;
2662 }
2663
write_genfscon_rules_to_cil(FILE *out, struct policydb *pdb)2664 static int write_genfscon_rules_to_cil(FILE *out, struct policydb *pdb)
2665 {
2666 struct genfs *genfs;
2667 struct ocontext *ocon;
2668 struct strs *strs;
2669 char *fstype, *name, *ctx;
2670 uint32_t sclass;
2671 const char *file_type;
2672 int rc;
2673
2674 rc = strs_init(&strs, 32);
2675 if (rc != 0) {
2676 goto exit;
2677 }
2678
2679 for (genfs = pdb->genfs; genfs != NULL; genfs = genfs->next) {
2680 for (ocon = genfs->head; ocon != NULL; ocon = ocon->next) {
2681 fstype = genfs->fstype;
2682 name = ocon->u.name;
2683
2684 sclass = ocon->v.sclass;
2685 file_type = NULL;
2686 if (sclass) {
2687 const char *class_name = pdb->p_class_val_to_name[sclass-1];
2688 if (strcmp(class_name, "file") == 0) {
2689 file_type = "file";
2690 } else if (strcmp(class_name, "dir") == 0) {
2691 file_type = "dir";
2692 } else if (strcmp(class_name, "chr_file") == 0) {
2693 file_type = "char";
2694 } else if (strcmp(class_name, "blk_file") == 0) {
2695 file_type = "block";
2696 } else if (strcmp(class_name, "sock_file") == 0) {
2697 file_type = "socket";
2698 } else if (strcmp(class_name, "fifo_file") == 0) {
2699 file_type = "pipe";
2700 } else if (strcmp(class_name, "lnk_file") == 0) {
2701 file_type = "symlink";
2702 } else {
2703 rc = -1;
2704 goto exit;
2705 }
2706 }
2707
2708 ctx = context_to_str(pdb, &ocon->context[0]);
2709 if (!ctx) {
2710 rc = -1;
2711 goto exit;
2712 }
2713
2714 if (file_type) {
2715 rc = strs_create_and_add(strs, "(genfscon %s \"%s\" %s %s)", 4,
2716 fstype, name, file_type, ctx);
2717 } else {
2718 rc = strs_create_and_add(strs, "(genfscon %s \"%s\" %s)", 3,
2719 fstype, name, ctx);
2720 }
2721 free(ctx);
2722 if (rc != 0) {
2723 goto exit;
2724 }
2725 }
2726 }
2727
2728 strs_sort(strs);
2729 strs_write_each(strs, out);
2730
2731 exit:
2732 strs_free_all(strs);
2733 strs_destroy(&strs);
2734
2735 if (rc != 0) {
2736 sepol_log_err("Error writing genfscon rules to CIL\n");
2737 }
2738
2739 return rc;
2740 }
2741
write_selinux_port_rules_to_cil(FILE *out, struct policydb *pdb)2742 static int write_selinux_port_rules_to_cil(FILE *out, struct policydb *pdb)
2743 {
2744 struct ocontext *portcon;
2745 const char *protocol;
2746 uint16_t low;
2747 uint16_t high;
2748 char low_high_str[44]; /* 2^64 <= 20 digits so "(low high)" <= 44 chars */
2749 char *ctx;
2750 int rc = 0;
2751
2752 for (portcon = pdb->ocontexts[2]; portcon != NULL; portcon = portcon->next) {
2753 switch (portcon->u.port.protocol) {
2754 case IPPROTO_TCP: protocol = "tcp"; break;
2755 case IPPROTO_UDP: protocol = "udp"; break;
2756 case IPPROTO_DCCP: protocol = "dccp"; break;
2757 case IPPROTO_SCTP: protocol = "sctp"; break;
2758 default:
2759 sepol_log_err("Unknown portcon protocol: %i", portcon->u.port.protocol);
2760 rc = -1;
2761 goto exit;
2762 }
2763
2764 low = portcon->u.port.low_port;
2765 high = portcon->u.port.high_port;
2766 if (low == high) {
2767 rc = snprintf(low_high_str, 44, "%u", low);
2768 } else {
2769 rc = snprintf(low_high_str, 44, "(%u %u)", low, high);
2770 }
2771 if (rc < 0 || rc >= 44) {
2772 rc = -1;
2773 goto exit;
2774 }
2775
2776 ctx = context_to_str(pdb, &portcon->context[0]);
2777 if (!ctx) {
2778 rc = -1;
2779 goto exit;
2780 }
2781
2782 sepol_printf(out, "(portcon %s %s %s)\n", protocol, low_high_str, ctx);
2783
2784 free(ctx);
2785 }
2786
2787 rc = 0;
2788
2789 exit:
2790 if (rc != 0) {
2791 sepol_log_err("Error writing portcon rules to CIL\n");
2792 }
2793
2794 return rc;
2795 }
2796
write_selinux_netif_rules_to_cil(FILE *out, struct policydb *pdb)2797 static int write_selinux_netif_rules_to_cil(FILE *out, struct policydb *pdb)
2798 {
2799 struct ocontext *netif;
2800 char *name, *ctx1, *ctx2;
2801 int rc = 0;
2802
2803 for (netif = pdb->ocontexts[3]; netif != NULL; netif = netif->next) {
2804 name = netif->u.name;
2805 ctx1 = context_to_str(pdb, &netif->context[0]);
2806 if (!ctx1) {
2807 rc = -1;
2808 goto exit;
2809 }
2810 ctx2 = context_to_str(pdb, &netif->context[1]);
2811 if (!ctx2) {
2812 free(ctx1);
2813 rc = -1;
2814 goto exit;
2815 }
2816
2817 sepol_printf(out, "(netifcon %s %s %s)\n", name, ctx1, ctx2);
2818
2819 free(ctx1);
2820 free(ctx2);
2821 }
2822
2823 exit:
2824 if (rc != 0) {
2825 sepol_log_err("Error writing netifcon rules to CIL\n");
2826 }
2827
2828 return rc;
2829 }
2830
write_selinux_node_rules_to_cil(FILE *out, struct policydb *pdb)2831 static int write_selinux_node_rules_to_cil(FILE *out, struct policydb *pdb)
2832 {
2833 struct ocontext *node;
2834 char addr[INET_ADDRSTRLEN];
2835 char mask[INET_ADDRSTRLEN];
2836 char *ctx;
2837 int rc = 0;
2838
2839 for (node = pdb->ocontexts[4]; node != NULL; node = node->next) {
2840 if (inet_ntop(AF_INET, &node->u.node.addr, addr, INET_ADDRSTRLEN) == NULL) {
2841 sepol_log_err("Nodecon address is invalid: %m");
2842 rc = -1;
2843 goto exit;
2844 }
2845
2846 if (inet_ntop(AF_INET, &node->u.node.mask, mask, INET_ADDRSTRLEN) == NULL) {
2847 sepol_log_err("Nodecon mask is invalid: %m");
2848 rc = -1;
2849 goto exit;
2850 }
2851
2852 ctx = context_to_str(pdb, &node->context[0]);
2853 if (!ctx) {
2854 rc = -1;
2855 goto exit;
2856 }
2857
2858 sepol_printf(out, "(nodecon (%s) (%s) %s)\n", addr, mask, ctx);
2859
2860 free(ctx);
2861 }
2862
2863 exit:
2864 if (rc != 0) {
2865 sepol_log_err("Error writing nodecon rules to CIL\n");
2866 }
2867
2868 return rc;
2869 }
2870
write_selinux_node6_rules_to_cil(FILE *out, struct policydb *pdb)2871 static int write_selinux_node6_rules_to_cil(FILE *out, struct policydb *pdb)
2872 {
2873 struct ocontext *node;
2874 char addr[INET6_ADDRSTRLEN];
2875 char mask[INET6_ADDRSTRLEN];
2876 char *ctx;
2877 int rc = 0;
2878
2879 for (node = pdb->ocontexts[6]; node != NULL; node = node->next) {
2880 if (inet_ntop(AF_INET6, &node->u.node6.addr, addr, INET6_ADDRSTRLEN) == NULL) {
2881 sepol_log_err("Nodecon address is invalid: %m");
2882 rc = -1;
2883 goto exit;
2884 }
2885
2886 if (inet_ntop(AF_INET6, &node->u.node6.mask, mask, INET6_ADDRSTRLEN) == NULL) {
2887 sepol_log_err("Nodecon mask is invalid: %m");
2888 rc = -1;
2889 goto exit;
2890 }
2891
2892 ctx = context_to_str(pdb, &node->context[0]);
2893 if (!ctx) {
2894 rc = -1;
2895 goto exit;
2896 }
2897
2898 sepol_printf(out, "(nodecon (%s) (%s) %s)\n", addr, mask, ctx);
2899
2900 free(ctx);
2901 }
2902
2903 exit:
2904 if (rc != 0) {
2905 sepol_log_err("Error writing nodecon rules to CIL\n");
2906 }
2907
2908 return rc;
2909 }
2910
write_selinux_ibpkey_rules_to_cil(FILE *out, struct policydb *pdb)2911 static int write_selinux_ibpkey_rules_to_cil(FILE *out, struct policydb *pdb)
2912 {
2913 struct ocontext *ibpkeycon;
2914 char subnet_prefix_str[INET6_ADDRSTRLEN];
2915 struct in6_addr subnet_prefix = IN6ADDR_ANY_INIT;
2916 uint16_t low;
2917 uint16_t high;
2918 char low_high_str[44]; /* 2^64 <= 20 digits so "(low high)" <= 44 chars */
2919 char *ctx;
2920 int rc = 0;
2921
2922 for (ibpkeycon = pdb->ocontexts[OCON_IBPKEY]; ibpkeycon != NULL;
2923 ibpkeycon = ibpkeycon->next) {
2924 memcpy(&subnet_prefix.s6_addr, &ibpkeycon->u.ibpkey.subnet_prefix,
2925 sizeof(ibpkeycon->u.ibpkey.subnet_prefix));
2926
2927 if (inet_ntop(AF_INET6, &subnet_prefix.s6_addr,
2928 subnet_prefix_str, INET6_ADDRSTRLEN) == NULL) {
2929 sepol_log_err("ibpkeycon subnet_prefix is invalid: %m");
2930 rc = -1;
2931 goto exit;
2932 }
2933
2934 low = ibpkeycon->u.ibpkey.low_pkey;
2935 high = ibpkeycon->u.ibpkey.high_pkey;
2936 if (low == high) {
2937 rc = snprintf(low_high_str, 44, "%u", low);
2938 } else {
2939 rc = snprintf(low_high_str, 44, "(%u %u)", low, high);
2940 }
2941 if (rc < 0 || rc >= 44) {
2942 rc = -1;
2943 goto exit;
2944 }
2945
2946 ctx = context_to_str(pdb, &ibpkeycon->context[0]);
2947 if (!ctx) {
2948 rc = -1;
2949 goto exit;
2950 }
2951
2952 sepol_printf(out, "(ibpkeycon %s %s %s)\n", subnet_prefix_str, low_high_str, ctx);
2953
2954 free(ctx);
2955 }
2956
2957 rc = 0;
2958
2959 exit:
2960 if (rc != 0) {
2961 sepol_log_err("Error writing ibpkeycon rules to CIL\n");
2962 }
2963
2964 return rc;
2965 }
2966
write_selinux_ibendport_rules_to_cil(FILE *out, struct policydb *pdb)2967 static int write_selinux_ibendport_rules_to_cil(FILE *out, struct policydb *pdb)
2968 {
2969 struct ocontext *ibendportcon;
2970 char port_str[4];
2971 char *ctx;
2972 int rc = 0;
2973
2974 for (ibendportcon = pdb->ocontexts[OCON_IBENDPORT];
2975 ibendportcon != NULL; ibendportcon = ibendportcon->next) {
2976 rc = snprintf(port_str, 4, "%u", ibendportcon->u.ibendport.port);
2977 if (rc < 0 || rc >= 4) {
2978 rc = -1;
2979 goto exit;
2980 }
2981
2982 ctx = context_to_str(pdb, &ibendportcon->context[0]);
2983 if (!ctx) {
2984 rc = -1;
2985 goto exit;
2986 }
2987
2988 sepol_printf(out, "(ibendportcon %s %s %s)\n",
2989 ibendportcon->u.ibendport.dev_name, port_str, ctx);
2990
2991 free(ctx);
2992 }
2993
2994 rc = 0;
2995
2996 exit:
2997 if (rc != 0) {
2998 sepol_log_err("Error writing ibendportcon rules to CIL\n");
2999 }
3000
3001 return rc;
3002 }
3003
write_xen_isid_rules_to_cil(FILE *out, struct policydb *pdb)3004 static int write_xen_isid_rules_to_cil(FILE *out, struct policydb *pdb)
3005 {
3006 return write_sid_context_rules_to_cil(out, pdb, xen_sid_to_str, XEN_SID_SZ);
3007 }
3008
write_xen_pirq_rules_to_cil(FILE *out, struct policydb *pdb)3009 static int write_xen_pirq_rules_to_cil(FILE *out, struct policydb *pdb)
3010 {
3011 struct ocontext *pirq;
3012 char pirq_str[21]; /* 2^64-1 <= 20 digits */
3013 char *ctx;
3014 int rc = 0;
3015
3016 for (pirq = pdb->ocontexts[1]; pirq != NULL; pirq = pirq->next) {
3017 rc = snprintf(pirq_str, 21, "%i", pirq->u.pirq);
3018 if (rc < 0 || rc >= 21) {
3019 rc = -1;
3020 goto exit;
3021 }
3022
3023 ctx = context_to_str(pdb, &pirq->context[0]);
3024 if (!ctx) {
3025 rc = -1;
3026 goto exit;
3027 }
3028
3029 sepol_printf(out, "(pirqcon %s %s)\n", pirq_str, ctx);
3030
3031 free(ctx);
3032 }
3033
3034 rc = 0;
3035
3036 exit:
3037 if (rc != 0) {
3038 sepol_log_err("Error writing pirqcon rules to CIL\n");
3039 }
3040
3041 return rc;
3042 }
3043
write_xen_ioport_rules_to_cil(FILE *out, struct policydb *pdb)3044 static int write_xen_ioport_rules_to_cil(FILE *out, struct policydb *pdb)
3045 {
3046 struct ocontext *ioport;
3047 uint32_t low;
3048 uint32_t high;
3049 char low_high_str[40]; /* 2^64-1 <= 16 digits (hex) so (low high) < 40 chars */
3050 char *ctx;
3051 int rc = 0;
3052
3053 for (ioport = pdb->ocontexts[2]; ioport != NULL; ioport = ioport->next) {
3054 low = ioport->u.ioport.low_ioport;
3055 high = ioport->u.ioport.high_ioport;
3056 if (low == high) {
3057 rc = snprintf(low_high_str, 40, "0x%x", low);
3058 } else {
3059 rc = snprintf(low_high_str, 40, "(0x%x 0x%x)", low, high);
3060 }
3061 if (rc < 0 || rc >= 40) {
3062 rc = -1;
3063 goto exit;
3064 }
3065
3066 ctx = context_to_str(pdb, &ioport->context[0]);
3067 if (!ctx) {
3068 rc = -1;
3069 goto exit;
3070 }
3071
3072 sepol_printf(out, "(ioportcon %s %s)\n", low_high_str, ctx);
3073
3074 free(ctx);
3075 }
3076
3077 rc = 0;
3078
3079 exit:
3080 if (rc != 0) {
3081 sepol_log_err("Error writing ioportcon rules to CIL\n");
3082 }
3083
3084 return rc;
3085 }
3086
write_xen_iomem_rules_to_cil(FILE *out, struct policydb *pdb)3087 static int write_xen_iomem_rules_to_cil(FILE *out, struct policydb *pdb)
3088 {
3089 struct ocontext *iomem;
3090 uint64_t low;
3091 uint64_t high;
3092 char low_high_str[40]; /* 2^64-1 <= 16 digits (hex) so (low high) < 40 chars */
3093 char *ctx;
3094 int rc = 0;
3095
3096 for (iomem = pdb->ocontexts[3]; iomem != NULL; iomem = iomem->next) {
3097 low = iomem->u.iomem.low_iomem;
3098 high = iomem->u.iomem.high_iomem;
3099 if (low == high) {
3100 rc = snprintf(low_high_str, 40, "0x%"PRIx64, low);
3101 } else {
3102 rc = snprintf(low_high_str, 40, "(0x%"PRIx64" 0x%"PRIx64")", low, high);
3103 }
3104 if (rc < 0 || rc >= 40) {
3105 rc = -1;
3106 goto exit;
3107 }
3108
3109 ctx = context_to_str(pdb, &iomem->context[0]);
3110 if (!ctx) {
3111 rc = -1;
3112 goto exit;
3113 }
3114
3115 sepol_printf(out, "(iomemcon %s %s)\n", low_high_str, ctx);
3116
3117 free(ctx);
3118 }
3119
3120 rc = 0;
3121
3122 exit:
3123 if (rc != 0) {
3124 sepol_log_err("Error writing iomemcon rules to CIL\n");
3125 }
3126
3127 return rc;
3128 }
3129
write_xen_pcidevice_rules_to_cil(FILE *out, struct policydb *pdb)3130 static int write_xen_pcidevice_rules_to_cil(FILE *out, struct policydb *pdb)
3131 {
3132 struct ocontext *pcid;
3133 char device_str[20]; /* 2^64-1 <= 16 digits (hex) so (low high) < 19 chars */
3134 char *ctx;
3135 int rc = 0;
3136
3137 for (pcid = pdb->ocontexts[4]; pcid != NULL; pcid = pcid->next) {
3138 rc = snprintf(device_str, 20, "0x%lx", (unsigned long)pcid->u.device);
3139 if (rc < 0 || rc >= 20) {
3140 rc = -1;
3141 goto exit;
3142 }
3143
3144 ctx = context_to_str(pdb, &pcid->context[0]);
3145 if (!ctx) {
3146 rc = -1;
3147 goto exit;
3148 }
3149
3150 sepol_printf(out, "(pcidevicecon %s %s)\n", device_str, ctx);
3151
3152 free(ctx);
3153 }
3154
3155 rc = 0;
3156
3157 exit:
3158 if (rc != 0) {
3159 sepol_log_err("Error writing pcidevicecon rules to CIL\n");
3160 }
3161
3162 return rc;
3163 }
3164
write_xen_devicetree_rules_to_cil(FILE *out, struct policydb *pdb)3165 static int write_xen_devicetree_rules_to_cil(FILE *out, struct policydb *pdb)
3166 {
3167 struct ocontext *dtree;
3168 char *name, *ctx;
3169 int rc = 0;
3170
3171 for (dtree = pdb->ocontexts[5]; dtree != NULL; dtree = dtree->next) {
3172 name = dtree->u.name;
3173 ctx = context_to_str(pdb, &dtree->context[0]);
3174 if (!ctx) {
3175 rc = -1;
3176 goto exit;
3177 }
3178
3179 sepol_printf(out, "(devicetreecon \"%s\" %s)\n", name, ctx);
3180
3181 free(ctx);
3182 }
3183
3184 exit:
3185 if (rc != 0) {
3186 sepol_log_err("Error writing devicetreecon rules to CIL\n");
3187 }
3188
3189 return rc;
3190 }
3191
sepol_kernel_policydb_to_cil(FILE *out, struct policydb *pdb)3192 int sepol_kernel_policydb_to_cil(FILE *out, struct policydb *pdb)
3193 {
3194 struct strs *mls_constraints = NULL;
3195 struct strs *non_mls_constraints = NULL;
3196 struct strs *mls_validatetrans = NULL;
3197 struct strs *non_mls_validatetrans = NULL;
3198 int rc = 0;
3199
3200 rc = strs_init(&mls_constraints, 32);
3201 if (rc != 0) {
3202 goto exit;
3203 }
3204
3205 rc = strs_init(&non_mls_constraints, 32);
3206 if (rc != 0) {
3207 goto exit;
3208 }
3209
3210 rc = strs_init(&mls_validatetrans, 32);
3211 if (rc != 0) {
3212 goto exit;
3213 }
3214
3215 rc = strs_init(&non_mls_validatetrans, 32);
3216 if (rc != 0) {
3217 goto exit;
3218 }
3219
3220 if (pdb == NULL) {
3221 sepol_log_err("No policy");
3222 rc = -1;
3223 goto exit;
3224 }
3225
3226 if (pdb->policy_type != SEPOL_POLICY_KERN) {
3227 sepol_log_err("Policy is not a kernel policy");
3228 rc = -1;
3229 goto exit;
3230 }
3231
3232 if (pdb->policyvers >= POLICYDB_VERSION_AVTAB && pdb->policyvers <= POLICYDB_VERSION_PERMISSIVE) {
3233 /*
3234 * For policy versions between 20 and 23, attributes exist in the policy,
3235 * but only in the type_attr_map. This means that there are gaps in both
3236 * the type_val_to_struct and p_type_val_to_name arrays and policy rules
3237 * can refer to those gaps.
3238 */
3239 sepol_log_err("Writing policy versions between 20 and 23 as CIL is not supported");
3240 rc = -1;
3241 goto exit;
3242 }
3243
3244 rc = constraint_rules_to_strs(pdb, mls_constraints, non_mls_constraints);
3245 if (rc != 0) {
3246 goto exit;
3247 }
3248
3249 rc = validatetrans_rules_to_strs(pdb, mls_validatetrans, non_mls_validatetrans);
3250 if (rc != 0) {
3251 goto exit;
3252 }
3253
3254 rc = write_handle_unknown_to_cil(out, pdb);
3255 if (rc != 0) {
3256 goto exit;
3257 }
3258
3259 rc = write_class_decl_rules_to_cil(out, pdb);
3260 if (rc != 0) {
3261 goto exit;
3262 }
3263
3264 rc = write_sid_decl_rules_to_cil(out, pdb);
3265 if (rc != 0) {
3266 goto exit;
3267 }
3268
3269 rc = write_default_rules_to_cil(out, pdb);
3270 if (rc != 0) {
3271 goto exit;
3272 }
3273
3274 rc = write_mls_rules_to_cil(out, pdb);
3275 if (rc != 0) {
3276 goto exit;
3277 }
3278
3279 strs_write_each(mls_constraints, out);
3280 strs_write_each(mls_validatetrans, out);
3281
3282 rc = write_polcap_rules_to_cil(out, pdb);
3283 if (rc != 0) {
3284 goto exit;
3285 }
3286
3287 rc = write_type_attributes_to_cil(out, pdb);
3288 if (rc != 0) {
3289 goto exit;
3290 }
3291
3292 rc = write_role_attributes_to_cil(out, pdb);
3293 if (rc != 0) {
3294 goto exit;
3295 }
3296
3297 rc = write_boolean_decl_rules_to_cil(out, pdb);
3298 if (rc != 0) {
3299 goto exit;
3300 }
3301
3302 rc = write_type_decl_rules_to_cil(out, pdb);
3303 if (rc != 0) {
3304 goto exit;
3305 }
3306
3307 rc = write_type_alias_rules_to_cil(out, pdb);
3308 if (rc != 0) {
3309 goto exit;
3310 }
3311
3312 rc = write_type_bounds_rules_to_cil(out, pdb);
3313 if (rc != 0) {
3314 goto exit;
3315 }
3316
3317 rc = write_type_attribute_sets_to_cil(out, pdb);
3318 if (rc != 0) {
3319 goto exit;
3320 }
3321
3322 rc = write_type_permissive_rules_to_cil(out, pdb);
3323 if (rc != 0) {
3324 goto exit;
3325 }
3326
3327 rc = write_avtab_to_cil(out, pdb, 0);
3328 if (rc != 0) {
3329 goto exit;
3330 }
3331
3332 rc = write_filename_trans_rules_to_cil(out, pdb);
3333 if (rc != 0) {
3334 goto exit;
3335 }
3336
3337 if (pdb->mls) {
3338 rc = write_range_trans_rules_to_cil(out, pdb);
3339 if (rc != 0) {
3340 goto exit;
3341 }
3342 }
3343
3344 rc = write_cond_nodes_to_cil(out, pdb);
3345 if (rc != 0) {
3346 goto exit;
3347 }
3348
3349 rc = write_role_decl_rules_to_cil(out, pdb);
3350 if (rc != 0) {
3351 goto exit;
3352 }
3353
3354 rc = write_role_transition_rules_to_cil(out, pdb);
3355 if (rc != 0) {
3356 goto exit;
3357 }
3358
3359 rc = write_role_allow_rules_to_cil(out, pdb);
3360 if (rc != 0) {
3361 goto exit;
3362 }
3363
3364 rc = write_user_decl_rules_to_cil(out, pdb);
3365 if (rc != 0) {
3366 goto exit;
3367 }
3368
3369 strs_write_each(non_mls_constraints, out);
3370 strs_write_each(non_mls_validatetrans, out);
3371
3372 rc = sort_ocontexts(pdb);
3373 if (rc != 0) {
3374 goto exit;
3375 }
3376
3377 if (pdb->target_platform == SEPOL_TARGET_SELINUX) {
3378 rc = write_selinux_isid_rules_to_cil(out, pdb);
3379 if (rc != 0) {
3380 goto exit;
3381 }
3382
3383 rc = write_selinux_fsuse_rules_to_cil(out, pdb);
3384 if (rc != 0) {
3385 goto exit;
3386 }
3387
3388 rc = write_genfscon_rules_to_cil(out, pdb);
3389 if (rc != 0) {
3390 goto exit;
3391 }
3392
3393 rc = write_selinux_port_rules_to_cil(out, pdb);
3394 if (rc != 0) {
3395 goto exit;
3396 }
3397
3398 rc = write_selinux_netif_rules_to_cil(out, pdb);
3399 if (rc != 0) {
3400 goto exit;
3401 }
3402
3403 rc = write_selinux_node_rules_to_cil(out, pdb);
3404 if (rc != 0) {
3405 goto exit;
3406 }
3407
3408 rc = write_selinux_node6_rules_to_cil(out, pdb);
3409 if (rc != 0) {
3410 goto exit;
3411 }
3412
3413 rc = write_selinux_ibpkey_rules_to_cil(out, pdb);
3414 if (rc != 0) {
3415 goto exit;
3416 }
3417
3418 rc = write_selinux_ibendport_rules_to_cil(out, pdb);
3419 if (rc != 0) {
3420 goto exit;
3421 }
3422 } else if (pdb->target_platform == SEPOL_TARGET_XEN) {
3423 rc = write_xen_isid_rules_to_cil(out, pdb);
3424 if (rc != 0) {
3425 goto exit;
3426 }
3427
3428 rc = write_xen_pirq_rules_to_cil(out, pdb);
3429 if (rc != 0) {
3430 goto exit;
3431 }
3432
3433 rc = write_xen_ioport_rules_to_cil(out, pdb);
3434 if (rc != 0) {
3435 goto exit;
3436 }
3437
3438 rc = write_xen_iomem_rules_to_cil(out, pdb);
3439 if (rc != 0) {
3440 goto exit;
3441 }
3442
3443 rc = write_xen_pcidevice_rules_to_cil(out, pdb);
3444 if (rc != 0) {
3445 goto exit;
3446 }
3447
3448 rc = write_xen_devicetree_rules_to_cil(out, pdb);
3449 if (rc != 0) {
3450 goto exit;
3451 }
3452 }
3453
3454 exit:
3455 strs_free_all(mls_constraints);
3456 strs_destroy(&mls_constraints);
3457 strs_free_all(non_mls_constraints);
3458 strs_destroy(&non_mls_constraints);
3459 strs_free_all(mls_validatetrans);
3460 strs_destroy(&mls_validatetrans);
3461 strs_free_all(non_mls_validatetrans);
3462 strs_destroy(&non_mls_validatetrans);
3463
3464 return rc;
3465 }
3466