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