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