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