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