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