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