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