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