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 = NULL;
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 && (xperms->specified != AVTAB_XPERMS_NLMSG)) {
1656 return NULL;
1657 }
1658
1659 retry:
1660 if (__builtin_mul_overflow(size, 2, &size))
1661 goto err;
1662 p = realloc(buffer, size);
1663 if (!p)
1664 goto err;
1665 buffer = p;
1666 remaining = size;
1667
1668 in_range = 0;
1669 for (bit = 0; bit < sizeof(xperms->perms)*8; bit++) {
1670 len = 0;
1671
1672 if (!xperm_test(bit, xperms->perms))
1673 continue;
1674
1675 if (in_range && next_bit_in_range(bit, xperms->perms)) {
1676 /* continue until high value found */
1677 continue;
1678 } else if (next_bit_in_range(bit, xperms->perms)) {
1679 /* low value */
1680 low_bit = bit;
1681 in_range = 1;
1682 continue;
1683 }
1684
1685 if ((xperms->specified == AVTAB_XPERMS_IOCTLFUNCTION)
1686 || (xperms->specified == AVTAB_XPERMS_NLMSG)) {
1687 value = xperms->driver<<8 | bit;
1688 if (in_range) {
1689 low_value = xperms->driver<<8 | low_bit;
1690 len = snprintf(p, remaining, " (range 0x%hx 0x%hx)", low_value, value);
1691 in_range = 0;
1692 } else {
1693 len = snprintf(p, remaining, " 0x%hx", value);
1694 }
1695 } else if (xperms->specified == AVTAB_XPERMS_IOCTLDRIVER) {
1696 value = bit << 8;
1697 if (in_range) {
1698 low_value = low_bit << 8;
1699 len = snprintf(p, remaining, " (range 0x%hx 0x%hx)", low_value, (uint16_t) (value|0xff));
1700 in_range = 0;
1701 } else {
1702 len = snprintf(p, remaining, " (range 0x%hx 0x%hx)", value, (uint16_t) (value|0xff));
1703 }
1704
1705 }
1706 if (len < 0)
1707 goto err;
1708 if ((size_t)len >= remaining)
1709 goto retry;
1710 p += len;
1711 remaining -= len;
1712 }
1713
1714 if (remaining < 2)
1715 goto retry;
1716
1717 buffer[0] = '(';
1718 *p++ = ')';
1719 *p = '\0';
1720
1721 return buffer;
1722
1723 err:
1724 free(buffer);
1725 return NULL;
1726 }
1727
avtab_node_to_str(struct policydb * pdb,avtab_key_t * key,avtab_datum_t * datum)1728 static char *avtab_node_to_str(struct policydb *pdb, avtab_key_t *key, avtab_datum_t *datum)
1729 {
1730 uint32_t data = datum->data;
1731 type_datum_t *type;
1732 const char *flavor, *tgt;
1733 char *src, *class, *perms, *new, *xperm;
1734 char *rule = NULL;
1735
1736 switch (0xFFF & key->specified) {
1737 case AVTAB_ALLOWED:
1738 flavor = "allow";
1739 break;
1740 case AVTAB_AUDITALLOW:
1741 flavor = "auditallow";
1742 break;
1743 case AVTAB_AUDITDENY:
1744 flavor = "dontaudit";
1745 data = ~data;
1746 break;
1747 case AVTAB_XPERMS_ALLOWED:
1748 flavor = "allowx";
1749 break;
1750 case AVTAB_XPERMS_AUDITALLOW:
1751 flavor = "auditallowx";
1752 break;
1753 case AVTAB_XPERMS_DONTAUDIT:
1754 flavor = "dontauditx";
1755 break;
1756 case AVTAB_TRANSITION:
1757 flavor = "typetransition";
1758 break;
1759 case AVTAB_MEMBER:
1760 flavor = "typemember";
1761 break;
1762 case AVTAB_CHANGE:
1763 flavor = "typechange";
1764 break;
1765 default:
1766 ERR(NULL, "Unknown avtab type: %i", key->specified);
1767 goto exit;
1768 }
1769
1770 src = pdb->p_type_val_to_name[key->source_type - 1];
1771 tgt = pdb->p_type_val_to_name[key->target_type - 1];
1772 if (key->source_type == key->target_type && !(key->specified & AVTAB_TYPE)) {
1773 type = pdb->type_val_to_struct[key->source_type - 1];
1774 if (type->flavor != TYPE_ATTRIB) {
1775 tgt = "self";
1776 }
1777 }
1778 class = pdb->p_class_val_to_name[key->target_class - 1];
1779
1780 if (key->specified & AVTAB_AV) {
1781 perms = sepol_av_to_string(pdb, key->target_class, data);
1782 if (perms == NULL) {
1783 ERR(NULL, "Failed to generate permission string");
1784 goto exit;
1785 }
1786 if (*perms == '\0') {
1787 ERR(NULL, "No permissions in permission string");
1788 free(perms);
1789 goto exit;
1790 }
1791 rule = create_str("(%s %s %s (%s (%s)))",
1792 flavor, src, tgt, class, perms+1);
1793 free(perms);
1794 } else if (key->specified & AVTAB_XPERMS) {
1795 perms = xperms_to_str(datum->xperms);
1796 if (perms == NULL) {
1797 ERR(NULL, "Failed to generate extended permission string");
1798 goto exit;
1799 }
1800 if (datum->xperms->specified == AVTAB_XPERMS_IOCTLFUNCTION || datum->xperms->specified == AVTAB_XPERMS_IOCTLDRIVER) {
1801 xperm = (char *) "ioctl";
1802 } else if (datum->xperms->specified == AVTAB_XPERMS_NLMSG) {
1803 xperm = (char *) "nlmsg";
1804 } else {
1805 ERR(NULL, "Unknown extended permssion");
1806 goto exit;
1807 }
1808 rule = create_str("(%s %s %s (%s %s (%s)))",
1809 flavor, src, tgt, xperm, class, perms);
1810 free(perms);
1811 } else {
1812 new = pdb->p_type_val_to_name[data - 1];
1813
1814 rule = create_str("(%s %s %s %s %s)", flavor, src, tgt, class, new);
1815 }
1816
1817 if (!rule) {
1818 goto exit;
1819 }
1820
1821 return rule;
1822
1823 exit:
1824 return NULL;
1825 }
1826
1827 struct map_avtab_args {
1828 struct policydb *pdb;
1829 uint32_t flavor;
1830 struct strs *strs;
1831 };
1832
map_avtab_write_helper(avtab_key_t * key,avtab_datum_t * datum,void * args)1833 static int map_avtab_write_helper(avtab_key_t *key, avtab_datum_t *datum, void *args)
1834 {
1835 struct map_avtab_args *map_args = args;
1836 uint32_t flavor = map_args->flavor;
1837 struct policydb *pdb = map_args->pdb;
1838 struct strs *strs = map_args->strs;
1839 char *rule;
1840 int rc = 0;
1841
1842 if (key->specified & flavor) {
1843 rule = avtab_node_to_str(pdb, key, datum);
1844 if (!rule) {
1845 rc = -1;
1846 goto exit;
1847 }
1848 rc = strs_add(strs, rule);
1849 if (rc != 0) {
1850 free(rule);
1851 goto exit;
1852 }
1853 }
1854
1855 exit:
1856 return rc;
1857 }
1858
write_avtab_flavor_to_cil(FILE * out,struct policydb * pdb,uint32_t flavor,int indent)1859 static int write_avtab_flavor_to_cil(FILE *out, struct policydb *pdb, uint32_t flavor, int indent)
1860 {
1861 struct map_avtab_args args;
1862 struct strs *strs;
1863 int rc = 0;
1864
1865 rc = strs_init(&strs, 1000);
1866 if (rc != 0) {
1867 goto exit;
1868 }
1869
1870 args.pdb = pdb;
1871 args.flavor = flavor;
1872 args.strs = strs;
1873
1874 rc = avtab_map(&pdb->te_avtab, map_avtab_write_helper, &args);
1875 if (rc != 0) {
1876 goto exit;
1877 }
1878
1879 strs_sort(strs);
1880 strs_write_each_indented(strs, out, indent);
1881
1882 exit:
1883 strs_free_all(strs);
1884 strs_destroy(&strs);
1885
1886 return rc;
1887 }
1888
write_avtab_to_cil(FILE * out,struct policydb * pdb,int indent)1889 static int write_avtab_to_cil(FILE *out, struct policydb *pdb, int indent)
1890 {
1891 unsigned i;
1892 int rc = 0;
1893
1894 for (i = 0; i < AVTAB_FLAVORS_SZ; i++) {
1895 rc = write_avtab_flavor_to_cil(out, pdb, avtab_flavors[i], indent);
1896 if (rc != 0) {
1897 goto exit;
1898 }
1899 }
1900
1901 exit:
1902 if (rc != 0) {
1903 ERR(NULL, "Error writing avtab rules to CIL");
1904 }
1905
1906 return rc;
1907 }
1908
1909 struct map_filename_trans_args {
1910 struct policydb *pdb;
1911 struct strs *strs;
1912 };
1913
map_filename_trans_to_str(hashtab_key_t key,void * data,void * arg)1914 static int map_filename_trans_to_str(hashtab_key_t key, void *data, void *arg)
1915 {
1916 filename_trans_key_t *ft = (filename_trans_key_t *)key;
1917 filename_trans_datum_t *datum = data;
1918 struct map_filename_trans_args *map_args = arg;
1919 struct policydb *pdb = map_args->pdb;
1920 struct strs *strs = map_args->strs;
1921 char *src, *tgt, *class, *filename, *new;
1922 struct ebitmap_node *node;
1923 uint32_t bit;
1924 int rc;
1925
1926 tgt = pdb->p_type_val_to_name[ft->ttype - 1];
1927 class = pdb->p_class_val_to_name[ft->tclass - 1];
1928 filename = ft->name;
1929 do {
1930 new = pdb->p_type_val_to_name[datum->otype - 1];
1931
1932 ebitmap_for_each_positive_bit(&datum->stypes, node, bit) {
1933 src = pdb->p_type_val_to_name[bit];
1934 rc = strs_create_and_add(strs,
1935 "(typetransition %s %s %s \"%s\" %s)",
1936 src, tgt, class, filename, new);
1937 if (rc)
1938 return rc;
1939 }
1940
1941 datum = datum->next;
1942 } while (datum);
1943
1944 return 0;
1945 }
1946
write_filename_trans_rules_to_cil(FILE * out,struct policydb * pdb)1947 static int write_filename_trans_rules_to_cil(FILE *out, struct policydb *pdb)
1948 {
1949 struct map_filename_trans_args args;
1950 struct strs *strs;
1951 int rc = 0;
1952
1953 rc = strs_init(&strs, 100);
1954 if (rc != 0) {
1955 goto exit;
1956 }
1957
1958 args.pdb = pdb;
1959 args.strs = strs;
1960
1961 rc = hashtab_map(pdb->filename_trans, map_filename_trans_to_str, &args);
1962 if (rc != 0) {
1963 goto exit;
1964 }
1965
1966 strs_sort(strs);
1967 strs_write_each(strs, out);
1968
1969 exit:
1970 strs_free_all(strs);
1971 strs_destroy(&strs);
1972
1973 if (rc != 0) {
1974 ERR(NULL, "Error writing filename typetransition rules to CIL");
1975 }
1976
1977 return rc;
1978 }
1979
level_to_str(struct policydb * pdb,struct mls_level * level)1980 static char *level_to_str(struct policydb *pdb, struct mls_level *level)
1981 {
1982 ebitmap_t *cats = &level->cat;
1983 char *level_str = NULL;
1984 char *sens_str = pdb->p_sens_val_to_name[level->sens - 1];
1985 char *cats_str;
1986
1987 if (!ebitmap_is_empty(cats)) {
1988 cats_str = cats_ebitmap_to_str(cats, pdb->p_cat_val_to_name);
1989 level_str = create_str("(%s %s)", sens_str, cats_str);
1990 free(cats_str);
1991 } else {
1992 level_str = create_str("(%s)", sens_str);
1993 }
1994
1995 return level_str;
1996 }
1997
range_to_str(struct policydb * pdb,mls_range_t * range)1998 static char *range_to_str(struct policydb *pdb, mls_range_t *range)
1999 {
2000 char *low = NULL;
2001 char *high = NULL;
2002 char *range_str = NULL;
2003
2004 low = level_to_str(pdb, &range->level[0]);
2005 if (!low) {
2006 goto exit;
2007 }
2008
2009 high = level_to_str(pdb, &range->level[1]);
2010 if (!high) {
2011 goto exit;
2012 }
2013
2014 range_str = create_str("(%s %s)", low, high);
2015
2016 exit:
2017 free(low);
2018 free(high);
2019
2020 return range_str;
2021 }
2022
2023 struct map_range_trans_args {
2024 struct policydb *pdb;
2025 struct strs *strs;
2026 };
2027
map_range_trans_to_str(hashtab_key_t key,void * data,void * arg)2028 static int map_range_trans_to_str(hashtab_key_t key, void *data, void *arg)
2029 {
2030 range_trans_t *rt = (range_trans_t *)key;
2031 mls_range_t *mls_range = data;
2032 struct map_range_trans_args *map_args = arg;
2033 struct policydb *pdb = map_args->pdb;
2034 struct strs *strs = map_args->strs;
2035 char *src, *tgt, *class, *range;
2036 int rc;
2037
2038 src = pdb->p_type_val_to_name[rt->source_type - 1];
2039 tgt = pdb->p_type_val_to_name[rt->target_type - 1];
2040 class = pdb->p_class_val_to_name[rt->target_class - 1];
2041 range = range_to_str(pdb, mls_range);
2042 if (!range) {
2043 rc = -1;
2044 goto exit;
2045 }
2046
2047 rc = strs_create_and_add(strs, "(rangetransition %s %s %s %s)",
2048 src, tgt, class, range);
2049 free(range);
2050 if (rc != 0) {
2051 goto exit;
2052 }
2053
2054 exit:
2055 return rc;
2056 }
2057
write_range_trans_rules_to_cil(FILE * out,struct policydb * pdb)2058 static int write_range_trans_rules_to_cil(FILE *out, struct policydb *pdb)
2059 {
2060 struct map_range_trans_args args;
2061 struct strs *strs;
2062 int rc = 0;
2063
2064 rc = strs_init(&strs, 100);
2065 if (rc != 0) {
2066 goto exit;
2067 }
2068
2069 args.pdb = pdb;
2070 args.strs = strs;
2071
2072 rc = hashtab_map(pdb->range_tr, map_range_trans_to_str, &args);
2073 if (rc != 0) {
2074 goto exit;
2075 }
2076
2077 strs_sort(strs);
2078 strs_write_each(strs, out);
2079
2080 exit:
2081 strs_free_all(strs);
2082 strs_destroy(&strs);
2083
2084 if (rc != 0) {
2085 ERR(NULL, "Error writing range transition rules to CIL");
2086 }
2087
2088 return rc;
2089 }
2090
write_cond_av_list_to_cil(FILE * out,struct policydb * pdb,cond_av_list_t * cond_list,int indent)2091 static int write_cond_av_list_to_cil(FILE *out, struct policydb *pdb, cond_av_list_t *cond_list, int indent)
2092 {
2093 cond_av_list_t *cond_av;
2094 avtab_ptr_t node;
2095 uint32_t flavor;
2096 avtab_key_t *key;
2097 avtab_datum_t *datum;
2098 struct strs *strs;
2099 char *rule;
2100 unsigned i;
2101 int rc;
2102
2103 for (i = 0; i < AVTAB_FLAVORS_SZ; i++) {
2104 flavor = avtab_flavors[i];
2105 rc = strs_init(&strs, 64);
2106 if (rc != 0) {
2107 goto exit;
2108 }
2109
2110 for (cond_av = cond_list; cond_av != NULL; cond_av = cond_av->next) {
2111 node = cond_av->node;
2112 key = &node->key;
2113 datum = &node->datum;
2114 if (key->specified & flavor) {
2115 rule = avtab_node_to_str(pdb, key, datum);
2116 if (!rule) {
2117 rc = -1;
2118 goto exit;
2119 }
2120 rc = strs_add(strs, rule);
2121 if (rc != 0) {
2122 free(rule);
2123 goto exit;
2124 }
2125 }
2126 }
2127
2128 strs_sort(strs);
2129 strs_write_each_indented(strs, out, indent);
2130 strs_free_all(strs);
2131 strs_destroy(&strs);
2132 }
2133
2134 return 0;
2135
2136 exit:
2137 strs_free_all(strs);
2138 strs_destroy(&strs);
2139 return rc;
2140 }
2141
2142 struct cond_data {
2143 char *expr;
2144 struct cond_node *cond;
2145 };
2146
cond_node_cmp(const void * a,const void * b)2147 static int cond_node_cmp(const void *a, const void *b)
2148 {
2149 const struct cond_data *aa = a;
2150 const struct cond_data *bb = b;
2151 return strcmp(aa->expr, bb->expr);
2152 }
2153
write_cond_nodes_to_cil(FILE * out,struct policydb * pdb)2154 static int write_cond_nodes_to_cil(FILE *out, struct policydb *pdb)
2155 {
2156 struct cond_data *cond_data;
2157 char *expr;
2158 struct cond_node *cond;
2159 unsigned i, num = 0;
2160 int rc = 0;
2161
2162 for (cond = pdb->cond_list; cond != NULL; cond = cond->next) {
2163 num++;
2164 }
2165
2166 cond_data = calloc(num, sizeof(struct cond_data));
2167 if (!cond_data) {
2168 rc = -1;
2169 goto exit;
2170 }
2171
2172 i = 0;
2173 for (cond = pdb->cond_list; cond != NULL; cond = cond->next) {
2174 cond_data[i].cond = cond;
2175 expr = cond_expr_to_str(pdb, cond->expr);
2176 if (!expr) {
2177 num = i;
2178 goto exit;
2179 }
2180 cond_data[i].expr = expr;
2181 i++;
2182 }
2183
2184 qsort(cond_data, num, sizeof(*cond_data), cond_node_cmp);
2185
2186 for (i=0; i<num; i++) {
2187 expr = cond_data[i].expr;
2188 cond = cond_data[i].cond;
2189
2190 sepol_printf(out, "(booleanif %s\n", expr);
2191
2192 if (cond->true_list != NULL) {
2193 sepol_indent(out, 1);
2194 sepol_printf(out, "(true\n");
2195 rc = write_cond_av_list_to_cil(out, pdb, cond->true_list, 2);
2196 if (rc != 0) {
2197 goto exit;
2198 }
2199 sepol_indent(out, 1);
2200 sepol_printf(out, ")\n");
2201 }
2202
2203 if (cond->false_list != NULL) {
2204 sepol_indent(out, 1);
2205 sepol_printf(out, "(false\n");
2206 rc = write_cond_av_list_to_cil(out, pdb, cond->false_list, 2);
2207 if (rc != 0) {
2208 goto exit;
2209 }
2210 sepol_indent(out, 1);
2211 sepol_printf(out, ")\n");
2212 }
2213 sepol_printf(out, ")\n");
2214 }
2215
2216 exit:
2217 if (cond_data) {
2218 for (i=0; i<num; i++) {
2219 free(cond_data[i].expr);
2220 }
2221 free(cond_data);
2222 }
2223
2224 if (rc != 0) {
2225 ERR(NULL, "Error writing conditional rules to CIL");
2226 }
2227
2228 return rc;
2229 }
2230
write_role_decl_rules_to_cil(FILE * out,struct policydb * pdb)2231 static int write_role_decl_rules_to_cil(FILE *out, struct policydb *pdb)
2232 {
2233 struct role_datum *role;
2234 struct strs *strs, *type_strs;
2235 char *name, *parent, *child, *type;
2236 struct ebitmap *types;
2237 struct type_datum *type_datum;
2238 unsigned i, num, j, num_types;
2239 int rc = 0;
2240
2241 rc = strs_init(&strs, pdb->p_roles.nprim);
2242 if (rc != 0) {
2243 goto exit;
2244 }
2245
2246 for (i=0; i < pdb->p_roles.nprim; i++) {
2247 role = pdb->role_val_to_struct[i];
2248 if (role && role->flavor == ROLE_ROLE) {
2249 rc = strs_add(strs, pdb->p_role_val_to_name[i]);
2250 if (rc != 0) {
2251 goto exit;
2252 }
2253 }
2254 }
2255
2256 strs_sort(strs);
2257
2258 num = strs_num_items(strs);
2259
2260 for (i=0; i<num; i++) {
2261 name = strs_read_at_index(strs, i);
2262 if (!name) {
2263 continue;
2264 }
2265 sepol_printf(out, "(role %s)\n", name);
2266 }
2267
2268 for (i=0; i<num; i++) {
2269 child = strs_read_at_index(strs, i);
2270 if (!child) {
2271 continue;
2272 }
2273 role = hashtab_search(pdb->p_roles.table, child);
2274 if (!role) {
2275 rc = -1;
2276 goto exit;
2277 }
2278
2279 if (role->bounds > 0) {
2280 parent = pdb->p_role_val_to_name[role->bounds - 1];
2281 sepol_printf(out, "(rolebounds %s %s)\n", parent, child);
2282 }
2283 }
2284
2285 for (i=0; i<num; i++) {
2286 name = strs_read_at_index(strs, i);
2287 if (!name) {
2288 continue;
2289 }
2290 role = hashtab_search(pdb->p_roles.table, name);
2291 if (!role) {
2292 rc = -1;
2293 goto exit;
2294 }
2295 types = &role->types.types;
2296 if (types && !ebitmap_is_empty(types)) {
2297 rc = strs_init(&type_strs, pdb->p_types.nprim);
2298 if (rc != 0) {
2299 goto exit;
2300 }
2301 rc = ebitmap_to_strs(types, type_strs, pdb->p_type_val_to_name);
2302 if (rc != 0) {
2303 strs_destroy(&type_strs);
2304 goto exit;
2305 }
2306 strs_sort(type_strs);
2307
2308 num_types = strs_num_items(type_strs);
2309 for (j=0; j<num_types; j++) {
2310 type = strs_read_at_index(type_strs, j);
2311 sepol_printf(out, "(roletype %s %s)\n", name, type);
2312 }
2313 strs_destroy(&type_strs);
2314 }
2315 }
2316
2317 strs_destroy(&strs);
2318
2319 rc = strs_init(&strs, pdb->p_types.nprim);
2320 if (rc != 0) {
2321 goto exit;
2322 }
2323
2324 for (i=0; i < pdb->p_types.nprim; i++) {
2325 type_datum = pdb->type_val_to_struct[i];
2326 if (type_datum && type_datum->flavor == TYPE_TYPE && type_datum->primary) {
2327 rc = strs_add(strs, pdb->p_type_val_to_name[i]);
2328 if (rc != 0) {
2329 goto exit;
2330 }
2331 }
2332 }
2333
2334 strs_sort(strs);
2335
2336 num = strs_num_items(strs);
2337
2338 for (i=0; i<num; i++) {
2339 name = strs_read_at_index(strs, i);
2340 if (!name) {
2341 continue;
2342 }
2343 sepol_printf(out, "(roletype %s %s)\n", DEFAULT_OBJECT, name);
2344 }
2345
2346 exit:
2347 strs_destroy(&strs);
2348
2349 if (rc != 0) {
2350 ERR(NULL, "Error writing role declarations to CIL");
2351 }
2352
2353 return rc;
2354 }
2355
write_role_transition_rules_to_cil(FILE * out,struct policydb * pdb)2356 static int write_role_transition_rules_to_cil(FILE *out, struct policydb *pdb)
2357 {
2358 role_trans_t *curr = pdb->role_tr;
2359 struct strs *strs;
2360 char *role, *type, *class, *new;
2361 int rc = 0;
2362
2363 rc = strs_init(&strs, 32);
2364 if (rc != 0) {
2365 goto exit;
2366 }
2367
2368 while (curr) {
2369 role = pdb->p_role_val_to_name[curr->role - 1];
2370 type = pdb->p_type_val_to_name[curr->type - 1];
2371 class = pdb->p_class_val_to_name[curr->tclass - 1];
2372 new = pdb->p_role_val_to_name[curr->new_role - 1];
2373
2374 rc = strs_create_and_add(strs, "(roletransition %s %s %s %s)",
2375 role, type, class, new);
2376 if (rc != 0) {
2377 goto exit;
2378 }
2379
2380 curr = curr->next;
2381 }
2382
2383 strs_sort(strs);
2384 strs_write_each(strs, out);
2385
2386 exit:
2387 strs_free_all(strs);
2388 strs_destroy(&strs);
2389
2390 if (rc != 0) {
2391 ERR(NULL, "Error writing role transition rules to CIL");
2392 }
2393
2394 return rc;
2395 }
2396
write_role_allow_rules_to_cil(FILE * out,struct policydb * pdb)2397 static int write_role_allow_rules_to_cil(FILE *out, struct policydb *pdb)
2398 {
2399 role_allow_t *curr = pdb->role_allow;
2400 struct strs *strs;
2401 char *role, *new;
2402 int rc = 0;
2403
2404 rc = strs_init(&strs, 32);
2405 if (rc != 0) {
2406 goto exit;
2407 }
2408
2409 while (curr) {
2410 role = pdb->p_role_val_to_name[curr->role - 1];
2411 new = pdb->p_role_val_to_name[curr->new_role - 1];
2412
2413 rc = strs_create_and_add(strs, "(roleallow %s %s)", role, new);
2414 if (rc != 0) {
2415 goto exit;
2416 }
2417
2418 curr = curr->next;
2419 }
2420
2421 strs_sort(strs);
2422 strs_write_each(strs, out);
2423
2424 exit:
2425 strs_free_all(strs);
2426 strs_destroy(&strs);
2427
2428 if (rc != 0) {
2429 ERR(NULL, "Error writing role allow rules to CIL");
2430 }
2431
2432 return rc;
2433 }
2434
write_user_decl_rules_to_cil(FILE * out,struct policydb * pdb)2435 static int write_user_decl_rules_to_cil(FILE *out, struct policydb *pdb)
2436 {
2437 struct user_datum *user;
2438 struct strs *strs, *role_strs;
2439 char *name, *role, *level, *range;
2440 struct ebitmap *roles;
2441 unsigned i, j, num, num_roles;
2442 int rc = 0;
2443
2444 rc = strs_init(&strs, pdb->p_users.nprim);
2445 if (rc != 0) {
2446 goto exit;
2447 }
2448
2449 for (i=0; i < pdb->p_users.nprim; i++) {
2450 if (!pdb->p_user_val_to_name[i]) continue;
2451 rc = strs_add(strs, pdb->p_user_val_to_name[i]);
2452 if (rc != 0) {
2453 goto exit;
2454 }
2455 }
2456
2457 strs_sort(strs);
2458
2459 num = strs_num_items(strs);
2460
2461 for (i=0; i<num; i++) {
2462 name = strs_read_at_index(strs, i);
2463 if (!name) {
2464 continue;
2465 }
2466 sepol_printf(out, "(user %s)\n", name);
2467 }
2468
2469 for (i=0; i<num; i++) {
2470 name = strs_read_at_index(strs, i);
2471 if (!name) {
2472 continue;
2473 }
2474
2475 user = hashtab_search(pdb->p_users.table, name);
2476 if (!user) {
2477 rc = -1;
2478 goto exit;
2479 }
2480
2481 roles = &user->roles.roles;
2482 if (roles && !ebitmap_is_empty(roles)) {
2483 rc = strs_init(&role_strs, pdb->p_roles.nprim);
2484 if (rc != 0) {
2485 goto exit;
2486 }
2487 rc = ebitmap_to_strs(roles, role_strs, pdb->p_role_val_to_name);
2488 if (rc != 0) {
2489 strs_destroy(&role_strs);
2490 goto exit;
2491 }
2492
2493 rc = strs_add(role_strs, (char *)DEFAULT_OBJECT);
2494 if (rc != 0) {
2495 strs_destroy(&role_strs);
2496 goto exit;
2497 }
2498
2499 strs_sort(role_strs);
2500
2501 num_roles = strs_num_items(role_strs);
2502 for (j=0; j<num_roles; j++) {
2503 role = strs_read_at_index(role_strs, j);
2504 sepol_printf(out, "(userrole %s %s)\n", name, role);
2505 }
2506 strs_destroy(&role_strs);
2507 }
2508 }
2509
2510 for (i=0; i<num; i++) {
2511 name = strs_read_at_index(strs, i);
2512 if (!name) {
2513 continue;
2514 }
2515
2516 user = hashtab_search(pdb->p_users.table, name);
2517 if (!user) {
2518 rc = -1;
2519 goto exit;
2520 }
2521
2522 sepol_printf(out, "(userlevel %s ", name);
2523
2524 if (pdb->mls) {
2525 level = level_to_str(pdb, &user->exp_dfltlevel);
2526 if (!level) {
2527 rc = -1;
2528 goto exit;
2529 }
2530 sepol_printf(out, "%s", level);
2531 free(level);
2532 } else {
2533 sepol_printf(out, "%s", DEFAULT_LEVEL);
2534 }
2535 sepol_printf(out, ")\n");
2536 }
2537
2538 for (i=0; i<num; i++) {
2539 name = strs_read_at_index(strs, i);
2540 if (!name) {
2541 continue;
2542 }
2543
2544 user = hashtab_search(pdb->p_users.table, name);
2545 if (!user) {
2546 rc = -1;
2547 goto exit;
2548 }
2549
2550 sepol_printf(out, "(userrange %s ", name);
2551 if (pdb->mls) {
2552 range = range_to_str(pdb, &user->exp_range);
2553 if (!range) {
2554 rc = -1;
2555 goto exit;
2556 }
2557 sepol_printf(out, "%s", range);
2558 free(range);
2559 } else {
2560 sepol_printf(out, "(%s %s)", DEFAULT_LEVEL, DEFAULT_LEVEL);
2561 }
2562 sepol_printf(out, ")\n");
2563 }
2564
2565 exit:
2566 if (strs)
2567 strs_destroy(&strs);
2568
2569 if (rc != 0) {
2570 ERR(NULL, "Error writing user declarations to CIL");
2571 }
2572
2573 return rc;
2574 }
2575
context_to_str(struct policydb * pdb,struct context_struct * con)2576 static char *context_to_str(struct policydb *pdb, struct context_struct *con)
2577 {
2578 char *user, *role, *type, *range;
2579 char *ctx = NULL;
2580
2581 user = pdb->p_user_val_to_name[con->user - 1];
2582 role = pdb->p_role_val_to_name[con->role - 1];
2583 type = pdb->p_type_val_to_name[con->type - 1];
2584
2585 if (pdb->mls) {
2586 range = range_to_str(pdb, &con->range);
2587 } else {
2588 range = create_str("(%s %s)", DEFAULT_LEVEL, DEFAULT_LEVEL);
2589 }
2590 if (!range) {
2591 goto exit;
2592 }
2593
2594 ctx = create_str("(%s %s %s %s)", user, role, type, range);
2595 free(range);
2596
2597 exit:
2598 return ctx;
2599 }
2600
write_sid_context_rules_to_cil(FILE * out,struct policydb * pdb,const char * const * sid_to_str,unsigned num_sids)2601 static int write_sid_context_rules_to_cil(FILE *out, struct policydb *pdb, const char *const *sid_to_str, unsigned num_sids)
2602 {
2603 struct ocontext *isid;
2604 struct strs *strs;
2605 char *sid;
2606 char unknown[18];
2607 char *ctx, *rule;
2608 unsigned i;
2609 int rc = -1;
2610
2611 rc = strs_init(&strs, 32);
2612 if (rc != 0) {
2613 goto exit;
2614 }
2615
2616 for (isid = pdb->ocontexts[0]; isid != NULL; isid = isid->next) {
2617 i = isid->sid[0];
2618 if (i < num_sids && sid_to_str[i]) {
2619 sid = (char *)sid_to_str[i];
2620 } else {
2621 snprintf(unknown, 18, "%s%u", "UNKNOWN", i);
2622 sid = unknown;
2623 }
2624
2625 ctx = context_to_str(pdb, &isid->context[0]);
2626 if (!ctx) {
2627 rc = -1;
2628 goto exit;
2629 }
2630
2631 rule = create_str("(sidcontext %s %s)", sid, ctx);
2632 free(ctx);
2633 if (!rule) {
2634 rc = -1;
2635 goto exit;
2636 }
2637
2638 rc = strs_add_at_index(strs, rule, i);
2639 if (rc != 0) {
2640 free(rule);
2641 goto exit;
2642 }
2643 }
2644
2645 strs_write_each(strs, out);
2646
2647 exit:
2648 strs_free_all(strs);
2649 strs_destroy(&strs);
2650
2651 if (rc != 0) {
2652 ERR(NULL, "Error writing sidcontext rules to CIL");
2653 }
2654
2655 return rc;
2656 }
2657
write_selinux_isid_rules_to_cil(FILE * out,struct policydb * pdb)2658 static int write_selinux_isid_rules_to_cil(FILE *out, struct policydb *pdb)
2659 {
2660 return write_sid_context_rules_to_cil(out, pdb, selinux_sid_to_str,
2661 SELINUX_SID_SZ);
2662 }
2663
write_selinux_fsuse_rules_to_cil(FILE * out,struct policydb * pdb)2664 static int write_selinux_fsuse_rules_to_cil(FILE *out, struct policydb *pdb)
2665 {
2666 struct ocontext *fsuse;
2667 const char *behavior;
2668 char *name, *ctx;
2669 int rc = 0;
2670
2671 for (fsuse = pdb->ocontexts[5]; fsuse != NULL; fsuse = fsuse->next) {
2672 switch (fsuse->v.behavior) {
2673 case SECURITY_FS_USE_XATTR: behavior = "xattr"; break;
2674 case SECURITY_FS_USE_TRANS: behavior = "trans"; break;
2675 case SECURITY_FS_USE_TASK: behavior = "task"; break;
2676 default:
2677 ERR(NULL, "Unknown fsuse behavior: %i", fsuse->v.behavior);
2678 rc = -1;
2679 goto exit;
2680 }
2681
2682 name = fsuse->u.name;
2683 ctx = context_to_str(pdb, &fsuse->context[0]);
2684 if (!ctx) {
2685 rc = -1;
2686 goto exit;
2687 }
2688
2689 sepol_printf(out, "(fsuse %s %s %s)\n", behavior, name, ctx);
2690
2691 free(ctx);
2692 }
2693
2694 exit:
2695 if (rc != 0) {
2696 ERR(NULL, "Error writing fsuse rules to CIL");
2697 }
2698
2699 return rc;
2700 }
2701
write_genfscon_rules_to_cil(FILE * out,struct policydb * pdb)2702 static int write_genfscon_rules_to_cil(FILE *out, struct policydb *pdb)
2703 {
2704 struct genfs *genfs;
2705 struct ocontext *ocon;
2706 struct strs *strs;
2707 char *fstype, *name, *ctx;
2708 uint32_t sclass;
2709 const char *file_type;
2710 int rc;
2711
2712 rc = strs_init(&strs, 32);
2713 if (rc != 0) {
2714 goto exit;
2715 }
2716
2717 for (genfs = pdb->genfs; genfs != NULL; genfs = genfs->next) {
2718 for (ocon = genfs->head; ocon != NULL; ocon = ocon->next) {
2719 fstype = genfs->fstype;
2720 name = ocon->u.name;
2721
2722 sclass = ocon->v.sclass;
2723 file_type = NULL;
2724 if (sclass) {
2725 const char *class_name = pdb->p_class_val_to_name[sclass-1];
2726 if (strcmp(class_name, "file") == 0) {
2727 file_type = "file";
2728 } else if (strcmp(class_name, "dir") == 0) {
2729 file_type = "dir";
2730 } else if (strcmp(class_name, "chr_file") == 0) {
2731 file_type = "char";
2732 } else if (strcmp(class_name, "blk_file") == 0) {
2733 file_type = "block";
2734 } else if (strcmp(class_name, "sock_file") == 0) {
2735 file_type = "socket";
2736 } else if (strcmp(class_name, "fifo_file") == 0) {
2737 file_type = "pipe";
2738 } else if (strcmp(class_name, "lnk_file") == 0) {
2739 file_type = "symlink";
2740 } else {
2741 rc = -1;
2742 goto exit;
2743 }
2744 }
2745
2746 ctx = context_to_str(pdb, &ocon->context[0]);
2747 if (!ctx) {
2748 rc = -1;
2749 goto exit;
2750 }
2751
2752 if (file_type) {
2753 rc = strs_create_and_add(strs, "(genfscon %s \"%s\" %s %s)",
2754 fstype, name, file_type, ctx);
2755 } else {
2756 rc = strs_create_and_add(strs, "(genfscon %s \"%s\" %s)",
2757 fstype, name, ctx);
2758 }
2759 free(ctx);
2760 if (rc != 0) {
2761 goto exit;
2762 }
2763 }
2764 }
2765
2766 strs_sort(strs);
2767 strs_write_each(strs, out);
2768
2769 exit:
2770 strs_free_all(strs);
2771 strs_destroy(&strs);
2772
2773 if (rc != 0) {
2774 ERR(NULL, "Error writing genfscon rules to CIL");
2775 }
2776
2777 return rc;
2778 }
2779
write_selinux_port_rules_to_cil(FILE * out,struct policydb * pdb)2780 static int write_selinux_port_rules_to_cil(FILE *out, struct policydb *pdb)
2781 {
2782 struct ocontext *portcon;
2783 const char *protocol;
2784 uint16_t low;
2785 uint16_t high;
2786 char low_high_str[44]; /* 2^64 <= 20 digits so "(low high)" <= 44 chars */
2787 char *ctx;
2788 int rc = 0;
2789
2790 for (portcon = pdb->ocontexts[2]; portcon != NULL; portcon = portcon->next) {
2791 switch (portcon->u.port.protocol) {
2792 case IPPROTO_TCP: protocol = "tcp"; break;
2793 case IPPROTO_UDP: protocol = "udp"; break;
2794 case IPPROTO_DCCP: protocol = "dccp"; break;
2795 case IPPROTO_SCTP: protocol = "sctp"; break;
2796 default:
2797 ERR(NULL, "Unknown portcon protocol: %i", portcon->u.port.protocol);
2798 rc = -1;
2799 goto exit;
2800 }
2801
2802 low = portcon->u.port.low_port;
2803 high = portcon->u.port.high_port;
2804 if (low == high) {
2805 rc = snprintf(low_high_str, 44, "%u", low);
2806 } else {
2807 rc = snprintf(low_high_str, 44, "(%u %u)", low, high);
2808 }
2809 if (rc < 0 || rc >= 44) {
2810 rc = -1;
2811 goto exit;
2812 }
2813
2814 ctx = context_to_str(pdb, &portcon->context[0]);
2815 if (!ctx) {
2816 rc = -1;
2817 goto exit;
2818 }
2819
2820 sepol_printf(out, "(portcon %s %s %s)\n", protocol, low_high_str, ctx);
2821
2822 free(ctx);
2823 }
2824
2825 rc = 0;
2826
2827 exit:
2828 if (rc != 0) {
2829 ERR(NULL, "Error writing portcon rules to CIL");
2830 }
2831
2832 return rc;
2833 }
2834
write_selinux_netif_rules_to_cil(FILE * out,struct policydb * pdb)2835 static int write_selinux_netif_rules_to_cil(FILE *out, struct policydb *pdb)
2836 {
2837 struct ocontext *netif;
2838 char *name, *ctx1, *ctx2;
2839 int rc = 0;
2840
2841 for (netif = pdb->ocontexts[3]; netif != NULL; netif = netif->next) {
2842 name = netif->u.name;
2843 ctx1 = context_to_str(pdb, &netif->context[0]);
2844 if (!ctx1) {
2845 rc = -1;
2846 goto exit;
2847 }
2848 ctx2 = context_to_str(pdb, &netif->context[1]);
2849 if (!ctx2) {
2850 free(ctx1);
2851 rc = -1;
2852 goto exit;
2853 }
2854
2855 sepol_printf(out, "(netifcon %s %s %s)\n", name, ctx1, ctx2);
2856
2857 free(ctx1);
2858 free(ctx2);
2859 }
2860
2861 exit:
2862 if (rc != 0) {
2863 ERR(NULL, "Error writing netifcon rules to CIL");
2864 }
2865
2866 return rc;
2867 }
2868
write_selinux_node_rules_to_cil(FILE * out,struct policydb * pdb)2869 static int write_selinux_node_rules_to_cil(FILE *out, struct policydb *pdb)
2870 {
2871 struct ocontext *node;
2872 char addr[INET_ADDRSTRLEN];
2873 char mask[INET_ADDRSTRLEN];
2874 char *ctx;
2875 int rc = 0;
2876
2877 for (node = pdb->ocontexts[4]; node != NULL; node = node->next) {
2878 if (inet_ntop(AF_INET, &node->u.node.addr, addr, INET_ADDRSTRLEN) == NULL) {
2879 ERR(NULL, "Nodecon address is invalid: %m");
2880 rc = -1;
2881 goto exit;
2882 }
2883
2884 if (inet_ntop(AF_INET, &node->u.node.mask, mask, INET_ADDRSTRLEN) == NULL) {
2885 ERR(NULL, "Nodecon mask is invalid: %m");
2886 rc = -1;
2887 goto exit;
2888 }
2889
2890 ctx = context_to_str(pdb, &node->context[0]);
2891 if (!ctx) {
2892 rc = -1;
2893 goto exit;
2894 }
2895
2896 sepol_printf(out, "(nodecon (%s) (%s) %s)\n", addr, mask, ctx);
2897
2898 free(ctx);
2899 }
2900
2901 exit:
2902 if (rc != 0) {
2903 ERR(NULL, "Error writing nodecon rules to CIL");
2904 }
2905
2906 return rc;
2907 }
2908
write_selinux_node6_rules_to_cil(FILE * out,struct policydb * pdb)2909 static int write_selinux_node6_rules_to_cil(FILE *out, struct policydb *pdb)
2910 {
2911 struct ocontext *node;
2912 char addr[INET6_ADDRSTRLEN];
2913 char mask[INET6_ADDRSTRLEN];
2914 char *ctx;
2915 int rc = 0;
2916
2917 for (node = pdb->ocontexts[6]; node != NULL; node = node->next) {
2918 if (inet_ntop(AF_INET6, &node->u.node6.addr, addr, INET6_ADDRSTRLEN) == NULL) {
2919 ERR(NULL, "Nodecon address is invalid: %m");
2920 rc = -1;
2921 goto exit;
2922 }
2923
2924 if (inet_ntop(AF_INET6, &node->u.node6.mask, mask, INET6_ADDRSTRLEN) == NULL) {
2925 ERR(NULL, "Nodecon mask is invalid: %m");
2926 rc = -1;
2927 goto exit;
2928 }
2929
2930 ctx = context_to_str(pdb, &node->context[0]);
2931 if (!ctx) {
2932 rc = -1;
2933 goto exit;
2934 }
2935
2936 sepol_printf(out, "(nodecon (%s) (%s) %s)\n", addr, mask, ctx);
2937
2938 free(ctx);
2939 }
2940
2941 exit:
2942 if (rc != 0) {
2943 ERR(NULL, "Error writing nodecon rules to CIL");
2944 }
2945
2946 return rc;
2947 }
2948
write_selinux_ibpkey_rules_to_cil(FILE * out,struct policydb * pdb)2949 static int write_selinux_ibpkey_rules_to_cil(FILE *out, struct policydb *pdb)
2950 {
2951 struct ocontext *ibpkeycon;
2952 char subnet_prefix_str[INET6_ADDRSTRLEN];
2953 struct in6_addr subnet_prefix = IN6ADDR_ANY_INIT;
2954 uint16_t low;
2955 uint16_t high;
2956 char low_high_str[44]; /* 2^64 <= 20 digits so "(low high)" <= 44 chars */
2957 char *ctx;
2958 int rc = 0;
2959
2960 for (ibpkeycon = pdb->ocontexts[OCON_IBPKEY]; ibpkeycon != NULL;
2961 ibpkeycon = ibpkeycon->next) {
2962 memcpy(&subnet_prefix.s6_addr, &ibpkeycon->u.ibpkey.subnet_prefix,
2963 sizeof(ibpkeycon->u.ibpkey.subnet_prefix));
2964
2965 if (inet_ntop(AF_INET6, &subnet_prefix.s6_addr,
2966 subnet_prefix_str, INET6_ADDRSTRLEN) == NULL) {
2967 ERR(NULL, "ibpkeycon subnet_prefix is invalid: %m");
2968 rc = -1;
2969 goto exit;
2970 }
2971
2972 low = ibpkeycon->u.ibpkey.low_pkey;
2973 high = ibpkeycon->u.ibpkey.high_pkey;
2974 if (low == high) {
2975 rc = snprintf(low_high_str, 44, "%u", low);
2976 } else {
2977 rc = snprintf(low_high_str, 44, "(%u %u)", low, high);
2978 }
2979 if (rc < 0 || rc >= 44) {
2980 rc = -1;
2981 goto exit;
2982 }
2983
2984 ctx = context_to_str(pdb, &ibpkeycon->context[0]);
2985 if (!ctx) {
2986 rc = -1;
2987 goto exit;
2988 }
2989
2990 sepol_printf(out, "(ibpkeycon %s %s %s)\n", subnet_prefix_str, low_high_str, ctx);
2991
2992 free(ctx);
2993 }
2994
2995 rc = 0;
2996
2997 exit:
2998 if (rc != 0) {
2999 ERR(NULL, "Error writing ibpkeycon rules to CIL");
3000 }
3001
3002 return rc;
3003 }
3004
write_selinux_ibendport_rules_to_cil(FILE * out,struct policydb * pdb)3005 static int write_selinux_ibendport_rules_to_cil(FILE *out, struct policydb *pdb)
3006 {
3007 struct ocontext *ibendportcon;
3008 char port_str[4];
3009 char *ctx;
3010 int rc = 0;
3011
3012 for (ibendportcon = pdb->ocontexts[OCON_IBENDPORT];
3013 ibendportcon != NULL; ibendportcon = ibendportcon->next) {
3014 rc = snprintf(port_str, 4, "%u", ibendportcon->u.ibendport.port);
3015 if (rc < 0 || rc >= 4) {
3016 rc = -1;
3017 goto exit;
3018 }
3019
3020 ctx = context_to_str(pdb, &ibendportcon->context[0]);
3021 if (!ctx) {
3022 rc = -1;
3023 goto exit;
3024 }
3025
3026 sepol_printf(out, "(ibendportcon %s %s %s)\n",
3027 ibendportcon->u.ibendport.dev_name, port_str, ctx);
3028
3029 free(ctx);
3030 }
3031
3032 rc = 0;
3033
3034 exit:
3035 if (rc != 0) {
3036 ERR(NULL, "Error writing ibendportcon rules to CIL");
3037 }
3038
3039 return rc;
3040 }
3041
write_xen_isid_rules_to_cil(FILE * out,struct policydb * pdb)3042 static int write_xen_isid_rules_to_cil(FILE *out, struct policydb *pdb)
3043 {
3044 return write_sid_context_rules_to_cil(out, pdb, xen_sid_to_str, XEN_SID_SZ);
3045 }
3046
write_xen_pirq_rules_to_cil(FILE * out,struct policydb * pdb)3047 static int write_xen_pirq_rules_to_cil(FILE *out, struct policydb *pdb)
3048 {
3049 struct ocontext *pirq;
3050 char pirq_str[21]; /* 2^64-1 <= 20 digits */
3051 char *ctx;
3052 int rc = 0;
3053
3054 for (pirq = pdb->ocontexts[1]; pirq != NULL; pirq = pirq->next) {
3055 rc = snprintf(pirq_str, 21, "%i", pirq->u.pirq);
3056 if (rc < 0 || rc >= 21) {
3057 rc = -1;
3058 goto exit;
3059 }
3060
3061 ctx = context_to_str(pdb, &pirq->context[0]);
3062 if (!ctx) {
3063 rc = -1;
3064 goto exit;
3065 }
3066
3067 sepol_printf(out, "(pirqcon %s %s)\n", pirq_str, ctx);
3068
3069 free(ctx);
3070 }
3071
3072 rc = 0;
3073
3074 exit:
3075 if (rc != 0) {
3076 ERR(NULL, "Error writing pirqcon rules to CIL");
3077 }
3078
3079 return rc;
3080 }
3081
write_xen_ioport_rules_to_cil(FILE * out,struct policydb * pdb)3082 static int write_xen_ioport_rules_to_cil(FILE *out, struct policydb *pdb)
3083 {
3084 struct ocontext *ioport;
3085 uint32_t low;
3086 uint32_t high;
3087 char low_high_str[40]; /* 2^64-1 <= 16 digits (hex) so (low high) < 40 chars */
3088 char *ctx;
3089 int rc = 0;
3090
3091 for (ioport = pdb->ocontexts[2]; ioport != NULL; ioport = ioport->next) {
3092 low = ioport->u.ioport.low_ioport;
3093 high = ioport->u.ioport.high_ioport;
3094 if (low == high) {
3095 rc = snprintf(low_high_str, 40, "0x%x", low);
3096 } else {
3097 rc = snprintf(low_high_str, 40, "(0x%x 0x%x)", low, high);
3098 }
3099 if (rc < 0 || rc >= 40) {
3100 rc = -1;
3101 goto exit;
3102 }
3103
3104 ctx = context_to_str(pdb, &ioport->context[0]);
3105 if (!ctx) {
3106 rc = -1;
3107 goto exit;
3108 }
3109
3110 sepol_printf(out, "(ioportcon %s %s)\n", low_high_str, ctx);
3111
3112 free(ctx);
3113 }
3114
3115 rc = 0;
3116
3117 exit:
3118 if (rc != 0) {
3119 ERR(NULL, "Error writing ioportcon rules to CIL");
3120 }
3121
3122 return rc;
3123 }
3124
write_xen_iomem_rules_to_cil(FILE * out,struct policydb * pdb)3125 static int write_xen_iomem_rules_to_cil(FILE *out, struct policydb *pdb)
3126 {
3127 struct ocontext *iomem;
3128 uint64_t low;
3129 uint64_t high;
3130 char low_high_str[40]; /* 2^64-1 <= 16 digits (hex) so (low high) < 40 chars */
3131 char *ctx;
3132 int rc = 0;
3133
3134 for (iomem = pdb->ocontexts[3]; iomem != NULL; iomem = iomem->next) {
3135 low = iomem->u.iomem.low_iomem;
3136 high = iomem->u.iomem.high_iomem;
3137 if (low == high) {
3138 rc = snprintf(low_high_str, 40, "0x%"PRIx64, low);
3139 } else {
3140 rc = snprintf(low_high_str, 40, "(0x%"PRIx64" 0x%"PRIx64")", low, high);
3141 }
3142 if (rc < 0 || rc >= 40) {
3143 rc = -1;
3144 goto exit;
3145 }
3146
3147 ctx = context_to_str(pdb, &iomem->context[0]);
3148 if (!ctx) {
3149 rc = -1;
3150 goto exit;
3151 }
3152
3153 sepol_printf(out, "(iomemcon %s %s)\n", low_high_str, ctx);
3154
3155 free(ctx);
3156 }
3157
3158 rc = 0;
3159
3160 exit:
3161 if (rc != 0) {
3162 ERR(NULL, "Error writing iomemcon rules to CIL");
3163 }
3164
3165 return rc;
3166 }
3167
write_xen_pcidevice_rules_to_cil(FILE * out,struct policydb * pdb)3168 static int write_xen_pcidevice_rules_to_cil(FILE *out, struct policydb *pdb)
3169 {
3170 struct ocontext *pcid;
3171 char device_str[20]; /* 2^64-1 <= 16 digits (hex) so (low high) < 19 chars */
3172 char *ctx;
3173 int rc = 0;
3174
3175 for (pcid = pdb->ocontexts[4]; pcid != NULL; pcid = pcid->next) {
3176 rc = snprintf(device_str, 20, "0x%lx", (unsigned long)pcid->u.device);
3177 if (rc < 0 || rc >= 20) {
3178 rc = -1;
3179 goto exit;
3180 }
3181
3182 ctx = context_to_str(pdb, &pcid->context[0]);
3183 if (!ctx) {
3184 rc = -1;
3185 goto exit;
3186 }
3187
3188 sepol_printf(out, "(pcidevicecon %s %s)\n", device_str, ctx);
3189
3190 free(ctx);
3191 }
3192
3193 rc = 0;
3194
3195 exit:
3196 if (rc != 0) {
3197 ERR(NULL, "Error writing pcidevicecon rules to CIL");
3198 }
3199
3200 return rc;
3201 }
3202
write_xen_devicetree_rules_to_cil(FILE * out,struct policydb * pdb)3203 static int write_xen_devicetree_rules_to_cil(FILE *out, struct policydb *pdb)
3204 {
3205 struct ocontext *dtree;
3206 char *name, *ctx;
3207 int rc = 0;
3208
3209 for (dtree = pdb->ocontexts[5]; dtree != NULL; dtree = dtree->next) {
3210 name = dtree->u.name;
3211 ctx = context_to_str(pdb, &dtree->context[0]);
3212 if (!ctx) {
3213 rc = -1;
3214 goto exit;
3215 }
3216
3217 sepol_printf(out, "(devicetreecon \"%s\" %s)\n", name, ctx);
3218
3219 free(ctx);
3220 }
3221
3222 exit:
3223 if (rc != 0) {
3224 ERR(NULL, "Error writing devicetreecon rules to CIL");
3225 }
3226
3227 return rc;
3228 }
3229
sepol_kernel_policydb_to_cil(FILE * out,struct policydb * pdb)3230 int sepol_kernel_policydb_to_cil(FILE *out, struct policydb *pdb)
3231 {
3232 struct strs *mls_constraints = NULL;
3233 struct strs *non_mls_constraints = NULL;
3234 struct strs *mls_validatetrans = NULL;
3235 struct strs *non_mls_validatetrans = NULL;
3236 int rc = 0;
3237
3238 rc = strs_init(&mls_constraints, 32);
3239 if (rc != 0) {
3240 goto exit;
3241 }
3242
3243 rc = strs_init(&non_mls_constraints, 32);
3244 if (rc != 0) {
3245 goto exit;
3246 }
3247
3248 rc = strs_init(&mls_validatetrans, 32);
3249 if (rc != 0) {
3250 goto exit;
3251 }
3252
3253 rc = strs_init(&non_mls_validatetrans, 32);
3254 if (rc != 0) {
3255 goto exit;
3256 }
3257
3258 if (pdb == NULL) {
3259 ERR(NULL, "No policy");
3260 rc = -1;
3261 goto exit;
3262 }
3263
3264 if (pdb->policy_type != SEPOL_POLICY_KERN) {
3265 ERR(NULL, "Policy is not a kernel policy");
3266 rc = -1;
3267 goto exit;
3268 }
3269
3270 if (pdb->policyvers >= POLICYDB_VERSION_AVTAB && pdb->policyvers <= POLICYDB_VERSION_PERMISSIVE) {
3271 /*
3272 * For policy versions between 20 and 23, attributes exist in the policy,
3273 * but only in the type_attr_map. This means that there are gaps in both
3274 * the type_val_to_struct and p_type_val_to_name arrays and policy rules
3275 * can refer to those gaps.
3276 */
3277 ERR(NULL, "Writing policy versions between 20 and 23 as CIL is not supported");
3278 rc = -1;
3279 goto exit;
3280 }
3281
3282 rc = constraint_rules_to_strs(pdb, mls_constraints, non_mls_constraints);
3283 if (rc != 0) {
3284 goto exit;
3285 }
3286
3287 rc = validatetrans_rules_to_strs(pdb, mls_validatetrans, non_mls_validatetrans);
3288 if (rc != 0) {
3289 goto exit;
3290 }
3291
3292 rc = write_handle_unknown_to_cil(out, pdb);
3293 if (rc != 0) {
3294 goto exit;
3295 }
3296
3297 rc = write_class_decl_rules_to_cil(out, pdb);
3298 if (rc != 0) {
3299 goto exit;
3300 }
3301
3302 rc = write_sid_decl_rules_to_cil(out, pdb);
3303 if (rc != 0) {
3304 goto exit;
3305 }
3306
3307 rc = write_default_rules_to_cil(out, pdb);
3308 if (rc != 0) {
3309 goto exit;
3310 }
3311
3312 rc = write_mls_rules_to_cil(out, pdb);
3313 if (rc != 0) {
3314 goto exit;
3315 }
3316
3317 strs_write_each(mls_constraints, out);
3318 strs_write_each(mls_validatetrans, out);
3319
3320 rc = write_polcap_rules_to_cil(out, pdb);
3321 if (rc != 0) {
3322 goto exit;
3323 }
3324
3325 rc = write_type_attributes_to_cil(out, pdb);
3326 if (rc != 0) {
3327 goto exit;
3328 }
3329
3330 rc = write_role_attributes_to_cil(out, pdb);
3331 if (rc != 0) {
3332 goto exit;
3333 }
3334
3335 rc = write_boolean_decl_rules_to_cil(out, pdb);
3336 if (rc != 0) {
3337 goto exit;
3338 }
3339
3340 rc = write_type_decl_rules_to_cil(out, pdb);
3341 if (rc != 0) {
3342 goto exit;
3343 }
3344
3345 rc = write_type_alias_rules_to_cil(out, pdb);
3346 if (rc != 0) {
3347 goto exit;
3348 }
3349
3350 rc = write_type_bounds_rules_to_cil(out, pdb);
3351 if (rc != 0) {
3352 goto exit;
3353 }
3354
3355 rc = write_type_attribute_sets_to_cil(out, pdb);
3356 if (rc != 0) {
3357 goto exit;
3358 }
3359
3360 rc = write_type_permissive_rules_to_cil(out, pdb);
3361 if (rc != 0) {
3362 goto exit;
3363 }
3364
3365 rc = write_avtab_to_cil(out, pdb, 0);
3366 if (rc != 0) {
3367 goto exit;
3368 }
3369
3370 rc = write_filename_trans_rules_to_cil(out, pdb);
3371 if (rc != 0) {
3372 goto exit;
3373 }
3374
3375 if (pdb->mls) {
3376 rc = write_range_trans_rules_to_cil(out, pdb);
3377 if (rc != 0) {
3378 goto exit;
3379 }
3380 }
3381
3382 rc = write_cond_nodes_to_cil(out, pdb);
3383 if (rc != 0) {
3384 goto exit;
3385 }
3386
3387 rc = write_role_decl_rules_to_cil(out, pdb);
3388 if (rc != 0) {
3389 goto exit;
3390 }
3391
3392 rc = write_role_transition_rules_to_cil(out, pdb);
3393 if (rc != 0) {
3394 goto exit;
3395 }
3396
3397 rc = write_role_allow_rules_to_cil(out, pdb);
3398 if (rc != 0) {
3399 goto exit;
3400 }
3401
3402 rc = write_user_decl_rules_to_cil(out, pdb);
3403 if (rc != 0) {
3404 goto exit;
3405 }
3406
3407 strs_write_each(non_mls_constraints, out);
3408 strs_write_each(non_mls_validatetrans, out);
3409
3410 rc = sort_ocontexts(pdb);
3411 if (rc != 0) {
3412 goto exit;
3413 }
3414
3415 if (pdb->target_platform == SEPOL_TARGET_SELINUX) {
3416 rc = write_selinux_isid_rules_to_cil(out, pdb);
3417 if (rc != 0) {
3418 goto exit;
3419 }
3420
3421 rc = write_selinux_fsuse_rules_to_cil(out, pdb);
3422 if (rc != 0) {
3423 goto exit;
3424 }
3425
3426 rc = write_genfscon_rules_to_cil(out, pdb);
3427 if (rc != 0) {
3428 goto exit;
3429 }
3430
3431 rc = write_selinux_port_rules_to_cil(out, pdb);
3432 if (rc != 0) {
3433 goto exit;
3434 }
3435
3436 rc = write_selinux_netif_rules_to_cil(out, pdb);
3437 if (rc != 0) {
3438 goto exit;
3439 }
3440
3441 rc = write_selinux_node_rules_to_cil(out, pdb);
3442 if (rc != 0) {
3443 goto exit;
3444 }
3445
3446 rc = write_selinux_node6_rules_to_cil(out, pdb);
3447 if (rc != 0) {
3448 goto exit;
3449 }
3450
3451 rc = write_selinux_ibpkey_rules_to_cil(out, pdb);
3452 if (rc != 0) {
3453 goto exit;
3454 }
3455
3456 rc = write_selinux_ibendport_rules_to_cil(out, pdb);
3457 if (rc != 0) {
3458 goto exit;
3459 }
3460 } else if (pdb->target_platform == SEPOL_TARGET_XEN) {
3461 rc = write_xen_isid_rules_to_cil(out, pdb);
3462 if (rc != 0) {
3463 goto exit;
3464 }
3465
3466 rc = write_xen_pirq_rules_to_cil(out, pdb);
3467 if (rc != 0) {
3468 goto exit;
3469 }
3470
3471 rc = write_xen_ioport_rules_to_cil(out, pdb);
3472 if (rc != 0) {
3473 goto exit;
3474 }
3475
3476 rc = write_xen_iomem_rules_to_cil(out, pdb);
3477 if (rc != 0) {
3478 goto exit;
3479 }
3480
3481 rc = write_xen_pcidevice_rules_to_cil(out, pdb);
3482 if (rc != 0) {
3483 goto exit;
3484 }
3485
3486 rc = write_xen_devicetree_rules_to_cil(out, pdb);
3487 if (rc != 0) {
3488 goto exit;
3489 }
3490 }
3491
3492 exit:
3493 strs_free_all(mls_constraints);
3494 strs_destroy(&mls_constraints);
3495 strs_free_all(non_mls_constraints);
3496 strs_destroy(&non_mls_constraints);
3497 strs_free_all(mls_validatetrans);
3498 strs_destroy(&mls_validatetrans);
3499 strs_free_all(non_mls_validatetrans);
3500 strs_destroy(&non_mls_validatetrans);
3501
3502 return rc;
3503 }
3504