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