xref: /OK3568_Linux_fs/kernel/security/selinux/ss/policydb.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * Implementation of the policy database.
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * Author : Stephen Smalley, <sds@tycho.nsa.gov>
6*4882a593Smuzhiyun  */
7*4882a593Smuzhiyun 
8*4882a593Smuzhiyun /*
9*4882a593Smuzhiyun  * Updated: Trusted Computer Solutions, Inc. <dgoeddel@trustedcs.com>
10*4882a593Smuzhiyun  *
11*4882a593Smuzhiyun  *	Support for enhanced MLS infrastructure.
12*4882a593Smuzhiyun  *
13*4882a593Smuzhiyun  * Updated: Frank Mayer <mayerf@tresys.com> and Karl MacMillan <kmacmillan@tresys.com>
14*4882a593Smuzhiyun  *
15*4882a593Smuzhiyun  *	Added conditional policy language extensions
16*4882a593Smuzhiyun  *
17*4882a593Smuzhiyun  * Updated: Hewlett-Packard <paul@paul-moore.com>
18*4882a593Smuzhiyun  *
19*4882a593Smuzhiyun  *      Added support for the policy capability bitmap
20*4882a593Smuzhiyun  *
21*4882a593Smuzhiyun  * Update: Mellanox Techonologies
22*4882a593Smuzhiyun  *
23*4882a593Smuzhiyun  *	Added Infiniband support
24*4882a593Smuzhiyun  *
25*4882a593Smuzhiyun  * Copyright (C) 2016 Mellanox Techonologies
26*4882a593Smuzhiyun  * Copyright (C) 2007 Hewlett-Packard Development Company, L.P.
27*4882a593Smuzhiyun  * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc.
28*4882a593Smuzhiyun  * Copyright (C) 2003 - 2004 Tresys Technology, LLC
29*4882a593Smuzhiyun  */
30*4882a593Smuzhiyun 
31*4882a593Smuzhiyun #include <linux/kernel.h>
32*4882a593Smuzhiyun #include <linux/sched.h>
33*4882a593Smuzhiyun #include <linux/slab.h>
34*4882a593Smuzhiyun #include <linux/string.h>
35*4882a593Smuzhiyun #include <linux/errno.h>
36*4882a593Smuzhiyun #include <linux/audit.h>
37*4882a593Smuzhiyun #include "security.h"
38*4882a593Smuzhiyun 
39*4882a593Smuzhiyun #include "policydb.h"
40*4882a593Smuzhiyun #include "conditional.h"
41*4882a593Smuzhiyun #include "mls.h"
42*4882a593Smuzhiyun #include "services.h"
43*4882a593Smuzhiyun 
44*4882a593Smuzhiyun #define _DEBUG_HASHES
45*4882a593Smuzhiyun 
46*4882a593Smuzhiyun #ifdef DEBUG_HASHES
47*4882a593Smuzhiyun static const char *symtab_name[SYM_NUM] = {
48*4882a593Smuzhiyun 	"common prefixes",
49*4882a593Smuzhiyun 	"classes",
50*4882a593Smuzhiyun 	"roles",
51*4882a593Smuzhiyun 	"types",
52*4882a593Smuzhiyun 	"users",
53*4882a593Smuzhiyun 	"bools",
54*4882a593Smuzhiyun 	"levels",
55*4882a593Smuzhiyun 	"categories",
56*4882a593Smuzhiyun };
57*4882a593Smuzhiyun #endif
58*4882a593Smuzhiyun 
59*4882a593Smuzhiyun struct policydb_compat_info {
60*4882a593Smuzhiyun 	int version;
61*4882a593Smuzhiyun 	int sym_num;
62*4882a593Smuzhiyun 	int ocon_num;
63*4882a593Smuzhiyun };
64*4882a593Smuzhiyun 
65*4882a593Smuzhiyun /* These need to be updated if SYM_NUM or OCON_NUM changes */
66*4882a593Smuzhiyun static struct policydb_compat_info policydb_compat[] = {
67*4882a593Smuzhiyun 	{
68*4882a593Smuzhiyun 		.version	= POLICYDB_VERSION_BASE,
69*4882a593Smuzhiyun 		.sym_num	= SYM_NUM - 3,
70*4882a593Smuzhiyun 		.ocon_num	= OCON_NUM - 3,
71*4882a593Smuzhiyun 	},
72*4882a593Smuzhiyun 	{
73*4882a593Smuzhiyun 		.version	= POLICYDB_VERSION_BOOL,
74*4882a593Smuzhiyun 		.sym_num	= SYM_NUM - 2,
75*4882a593Smuzhiyun 		.ocon_num	= OCON_NUM - 3,
76*4882a593Smuzhiyun 	},
77*4882a593Smuzhiyun 	{
78*4882a593Smuzhiyun 		.version	= POLICYDB_VERSION_IPV6,
79*4882a593Smuzhiyun 		.sym_num	= SYM_NUM - 2,
80*4882a593Smuzhiyun 		.ocon_num	= OCON_NUM - 2,
81*4882a593Smuzhiyun 	},
82*4882a593Smuzhiyun 	{
83*4882a593Smuzhiyun 		.version	= POLICYDB_VERSION_NLCLASS,
84*4882a593Smuzhiyun 		.sym_num	= SYM_NUM - 2,
85*4882a593Smuzhiyun 		.ocon_num	= OCON_NUM - 2,
86*4882a593Smuzhiyun 	},
87*4882a593Smuzhiyun 	{
88*4882a593Smuzhiyun 		.version	= POLICYDB_VERSION_MLS,
89*4882a593Smuzhiyun 		.sym_num	= SYM_NUM,
90*4882a593Smuzhiyun 		.ocon_num	= OCON_NUM - 2,
91*4882a593Smuzhiyun 	},
92*4882a593Smuzhiyun 	{
93*4882a593Smuzhiyun 		.version	= POLICYDB_VERSION_AVTAB,
94*4882a593Smuzhiyun 		.sym_num	= SYM_NUM,
95*4882a593Smuzhiyun 		.ocon_num	= OCON_NUM - 2,
96*4882a593Smuzhiyun 	},
97*4882a593Smuzhiyun 	{
98*4882a593Smuzhiyun 		.version	= POLICYDB_VERSION_RANGETRANS,
99*4882a593Smuzhiyun 		.sym_num	= SYM_NUM,
100*4882a593Smuzhiyun 		.ocon_num	= OCON_NUM - 2,
101*4882a593Smuzhiyun 	},
102*4882a593Smuzhiyun 	{
103*4882a593Smuzhiyun 		.version	= POLICYDB_VERSION_POLCAP,
104*4882a593Smuzhiyun 		.sym_num	= SYM_NUM,
105*4882a593Smuzhiyun 		.ocon_num	= OCON_NUM - 2,
106*4882a593Smuzhiyun 	},
107*4882a593Smuzhiyun 	{
108*4882a593Smuzhiyun 		.version	= POLICYDB_VERSION_PERMISSIVE,
109*4882a593Smuzhiyun 		.sym_num	= SYM_NUM,
110*4882a593Smuzhiyun 		.ocon_num	= OCON_NUM - 2,
111*4882a593Smuzhiyun 	},
112*4882a593Smuzhiyun 	{
113*4882a593Smuzhiyun 		.version	= POLICYDB_VERSION_BOUNDARY,
114*4882a593Smuzhiyun 		.sym_num	= SYM_NUM,
115*4882a593Smuzhiyun 		.ocon_num	= OCON_NUM - 2,
116*4882a593Smuzhiyun 	},
117*4882a593Smuzhiyun 	{
118*4882a593Smuzhiyun 		.version	= POLICYDB_VERSION_FILENAME_TRANS,
119*4882a593Smuzhiyun 		.sym_num	= SYM_NUM,
120*4882a593Smuzhiyun 		.ocon_num	= OCON_NUM - 2,
121*4882a593Smuzhiyun 	},
122*4882a593Smuzhiyun 	{
123*4882a593Smuzhiyun 		.version	= POLICYDB_VERSION_ROLETRANS,
124*4882a593Smuzhiyun 		.sym_num	= SYM_NUM,
125*4882a593Smuzhiyun 		.ocon_num	= OCON_NUM - 2,
126*4882a593Smuzhiyun 	},
127*4882a593Smuzhiyun 	{
128*4882a593Smuzhiyun 		.version	= POLICYDB_VERSION_NEW_OBJECT_DEFAULTS,
129*4882a593Smuzhiyun 		.sym_num	= SYM_NUM,
130*4882a593Smuzhiyun 		.ocon_num	= OCON_NUM - 2,
131*4882a593Smuzhiyun 	},
132*4882a593Smuzhiyun 	{
133*4882a593Smuzhiyun 		.version	= POLICYDB_VERSION_DEFAULT_TYPE,
134*4882a593Smuzhiyun 		.sym_num	= SYM_NUM,
135*4882a593Smuzhiyun 		.ocon_num	= OCON_NUM - 2,
136*4882a593Smuzhiyun 	},
137*4882a593Smuzhiyun 	{
138*4882a593Smuzhiyun 		.version	= POLICYDB_VERSION_CONSTRAINT_NAMES,
139*4882a593Smuzhiyun 		.sym_num	= SYM_NUM,
140*4882a593Smuzhiyun 		.ocon_num	= OCON_NUM - 2,
141*4882a593Smuzhiyun 	},
142*4882a593Smuzhiyun 	{
143*4882a593Smuzhiyun 		.version	= POLICYDB_VERSION_XPERMS_IOCTL,
144*4882a593Smuzhiyun 		.sym_num	= SYM_NUM,
145*4882a593Smuzhiyun 		.ocon_num	= OCON_NUM - 2,
146*4882a593Smuzhiyun 	},
147*4882a593Smuzhiyun 	{
148*4882a593Smuzhiyun 		.version	= POLICYDB_VERSION_INFINIBAND,
149*4882a593Smuzhiyun 		.sym_num	= SYM_NUM,
150*4882a593Smuzhiyun 		.ocon_num	= OCON_NUM,
151*4882a593Smuzhiyun 	},
152*4882a593Smuzhiyun 	{
153*4882a593Smuzhiyun 		.version	= POLICYDB_VERSION_GLBLUB,
154*4882a593Smuzhiyun 		.sym_num	= SYM_NUM,
155*4882a593Smuzhiyun 		.ocon_num	= OCON_NUM,
156*4882a593Smuzhiyun 	},
157*4882a593Smuzhiyun 	{
158*4882a593Smuzhiyun 		.version	= POLICYDB_VERSION_COMP_FTRANS,
159*4882a593Smuzhiyun 		.sym_num	= SYM_NUM,
160*4882a593Smuzhiyun 		.ocon_num	= OCON_NUM,
161*4882a593Smuzhiyun 	},
162*4882a593Smuzhiyun };
163*4882a593Smuzhiyun 
policydb_lookup_compat(int version)164*4882a593Smuzhiyun static struct policydb_compat_info *policydb_lookup_compat(int version)
165*4882a593Smuzhiyun {
166*4882a593Smuzhiyun 	int i;
167*4882a593Smuzhiyun 	struct policydb_compat_info *info = NULL;
168*4882a593Smuzhiyun 
169*4882a593Smuzhiyun 	for (i = 0; i < ARRAY_SIZE(policydb_compat); i++) {
170*4882a593Smuzhiyun 		if (policydb_compat[i].version == version) {
171*4882a593Smuzhiyun 			info = &policydb_compat[i];
172*4882a593Smuzhiyun 			break;
173*4882a593Smuzhiyun 		}
174*4882a593Smuzhiyun 	}
175*4882a593Smuzhiyun 	return info;
176*4882a593Smuzhiyun }
177*4882a593Smuzhiyun 
178*4882a593Smuzhiyun /*
179*4882a593Smuzhiyun  * The following *_destroy functions are used to
180*4882a593Smuzhiyun  * free any memory allocated for each kind of
181*4882a593Smuzhiyun  * symbol data in the policy database.
182*4882a593Smuzhiyun  */
183*4882a593Smuzhiyun 
perm_destroy(void * key,void * datum,void * p)184*4882a593Smuzhiyun static int perm_destroy(void *key, void *datum, void *p)
185*4882a593Smuzhiyun {
186*4882a593Smuzhiyun 	kfree(key);
187*4882a593Smuzhiyun 	kfree(datum);
188*4882a593Smuzhiyun 	return 0;
189*4882a593Smuzhiyun }
190*4882a593Smuzhiyun 
common_destroy(void * key,void * datum,void * p)191*4882a593Smuzhiyun static int common_destroy(void *key, void *datum, void *p)
192*4882a593Smuzhiyun {
193*4882a593Smuzhiyun 	struct common_datum *comdatum;
194*4882a593Smuzhiyun 
195*4882a593Smuzhiyun 	kfree(key);
196*4882a593Smuzhiyun 	if (datum) {
197*4882a593Smuzhiyun 		comdatum = datum;
198*4882a593Smuzhiyun 		hashtab_map(&comdatum->permissions.table, perm_destroy, NULL);
199*4882a593Smuzhiyun 		hashtab_destroy(&comdatum->permissions.table);
200*4882a593Smuzhiyun 	}
201*4882a593Smuzhiyun 	kfree(datum);
202*4882a593Smuzhiyun 	return 0;
203*4882a593Smuzhiyun }
204*4882a593Smuzhiyun 
constraint_expr_destroy(struct constraint_expr * expr)205*4882a593Smuzhiyun static void constraint_expr_destroy(struct constraint_expr *expr)
206*4882a593Smuzhiyun {
207*4882a593Smuzhiyun 	if (expr) {
208*4882a593Smuzhiyun 		ebitmap_destroy(&expr->names);
209*4882a593Smuzhiyun 		if (expr->type_names) {
210*4882a593Smuzhiyun 			ebitmap_destroy(&expr->type_names->types);
211*4882a593Smuzhiyun 			ebitmap_destroy(&expr->type_names->negset);
212*4882a593Smuzhiyun 			kfree(expr->type_names);
213*4882a593Smuzhiyun 		}
214*4882a593Smuzhiyun 		kfree(expr);
215*4882a593Smuzhiyun 	}
216*4882a593Smuzhiyun }
217*4882a593Smuzhiyun 
cls_destroy(void * key,void * datum,void * p)218*4882a593Smuzhiyun static int cls_destroy(void *key, void *datum, void *p)
219*4882a593Smuzhiyun {
220*4882a593Smuzhiyun 	struct class_datum *cladatum;
221*4882a593Smuzhiyun 	struct constraint_node *constraint, *ctemp;
222*4882a593Smuzhiyun 	struct constraint_expr *e, *etmp;
223*4882a593Smuzhiyun 
224*4882a593Smuzhiyun 	kfree(key);
225*4882a593Smuzhiyun 	if (datum) {
226*4882a593Smuzhiyun 		cladatum = datum;
227*4882a593Smuzhiyun 		hashtab_map(&cladatum->permissions.table, perm_destroy, NULL);
228*4882a593Smuzhiyun 		hashtab_destroy(&cladatum->permissions.table);
229*4882a593Smuzhiyun 		constraint = cladatum->constraints;
230*4882a593Smuzhiyun 		while (constraint) {
231*4882a593Smuzhiyun 			e = constraint->expr;
232*4882a593Smuzhiyun 			while (e) {
233*4882a593Smuzhiyun 				etmp = e;
234*4882a593Smuzhiyun 				e = e->next;
235*4882a593Smuzhiyun 				constraint_expr_destroy(etmp);
236*4882a593Smuzhiyun 			}
237*4882a593Smuzhiyun 			ctemp = constraint;
238*4882a593Smuzhiyun 			constraint = constraint->next;
239*4882a593Smuzhiyun 			kfree(ctemp);
240*4882a593Smuzhiyun 		}
241*4882a593Smuzhiyun 
242*4882a593Smuzhiyun 		constraint = cladatum->validatetrans;
243*4882a593Smuzhiyun 		while (constraint) {
244*4882a593Smuzhiyun 			e = constraint->expr;
245*4882a593Smuzhiyun 			while (e) {
246*4882a593Smuzhiyun 				etmp = e;
247*4882a593Smuzhiyun 				e = e->next;
248*4882a593Smuzhiyun 				constraint_expr_destroy(etmp);
249*4882a593Smuzhiyun 			}
250*4882a593Smuzhiyun 			ctemp = constraint;
251*4882a593Smuzhiyun 			constraint = constraint->next;
252*4882a593Smuzhiyun 			kfree(ctemp);
253*4882a593Smuzhiyun 		}
254*4882a593Smuzhiyun 		kfree(cladatum->comkey);
255*4882a593Smuzhiyun 	}
256*4882a593Smuzhiyun 	kfree(datum);
257*4882a593Smuzhiyun 	return 0;
258*4882a593Smuzhiyun }
259*4882a593Smuzhiyun 
role_destroy(void * key,void * datum,void * p)260*4882a593Smuzhiyun static int role_destroy(void *key, void *datum, void *p)
261*4882a593Smuzhiyun {
262*4882a593Smuzhiyun 	struct role_datum *role;
263*4882a593Smuzhiyun 
264*4882a593Smuzhiyun 	kfree(key);
265*4882a593Smuzhiyun 	if (datum) {
266*4882a593Smuzhiyun 		role = datum;
267*4882a593Smuzhiyun 		ebitmap_destroy(&role->dominates);
268*4882a593Smuzhiyun 		ebitmap_destroy(&role->types);
269*4882a593Smuzhiyun 	}
270*4882a593Smuzhiyun 	kfree(datum);
271*4882a593Smuzhiyun 	return 0;
272*4882a593Smuzhiyun }
273*4882a593Smuzhiyun 
type_destroy(void * key,void * datum,void * p)274*4882a593Smuzhiyun static int type_destroy(void *key, void *datum, void *p)
275*4882a593Smuzhiyun {
276*4882a593Smuzhiyun 	kfree(key);
277*4882a593Smuzhiyun 	kfree(datum);
278*4882a593Smuzhiyun 	return 0;
279*4882a593Smuzhiyun }
280*4882a593Smuzhiyun 
user_destroy(void * key,void * datum,void * p)281*4882a593Smuzhiyun static int user_destroy(void *key, void *datum, void *p)
282*4882a593Smuzhiyun {
283*4882a593Smuzhiyun 	struct user_datum *usrdatum;
284*4882a593Smuzhiyun 
285*4882a593Smuzhiyun 	kfree(key);
286*4882a593Smuzhiyun 	if (datum) {
287*4882a593Smuzhiyun 		usrdatum = datum;
288*4882a593Smuzhiyun 		ebitmap_destroy(&usrdatum->roles);
289*4882a593Smuzhiyun 		ebitmap_destroy(&usrdatum->range.level[0].cat);
290*4882a593Smuzhiyun 		ebitmap_destroy(&usrdatum->range.level[1].cat);
291*4882a593Smuzhiyun 		ebitmap_destroy(&usrdatum->dfltlevel.cat);
292*4882a593Smuzhiyun 	}
293*4882a593Smuzhiyun 	kfree(datum);
294*4882a593Smuzhiyun 	return 0;
295*4882a593Smuzhiyun }
296*4882a593Smuzhiyun 
sens_destroy(void * key,void * datum,void * p)297*4882a593Smuzhiyun static int sens_destroy(void *key, void *datum, void *p)
298*4882a593Smuzhiyun {
299*4882a593Smuzhiyun 	struct level_datum *levdatum;
300*4882a593Smuzhiyun 
301*4882a593Smuzhiyun 	kfree(key);
302*4882a593Smuzhiyun 	if (datum) {
303*4882a593Smuzhiyun 		levdatum = datum;
304*4882a593Smuzhiyun 		if (levdatum->level)
305*4882a593Smuzhiyun 			ebitmap_destroy(&levdatum->level->cat);
306*4882a593Smuzhiyun 		kfree(levdatum->level);
307*4882a593Smuzhiyun 	}
308*4882a593Smuzhiyun 	kfree(datum);
309*4882a593Smuzhiyun 	return 0;
310*4882a593Smuzhiyun }
311*4882a593Smuzhiyun 
cat_destroy(void * key,void * datum,void * p)312*4882a593Smuzhiyun static int cat_destroy(void *key, void *datum, void *p)
313*4882a593Smuzhiyun {
314*4882a593Smuzhiyun 	kfree(key);
315*4882a593Smuzhiyun 	kfree(datum);
316*4882a593Smuzhiyun 	return 0;
317*4882a593Smuzhiyun }
318*4882a593Smuzhiyun 
319*4882a593Smuzhiyun static int (*destroy_f[SYM_NUM]) (void *key, void *datum, void *datap) =
320*4882a593Smuzhiyun {
321*4882a593Smuzhiyun 	common_destroy,
322*4882a593Smuzhiyun 	cls_destroy,
323*4882a593Smuzhiyun 	role_destroy,
324*4882a593Smuzhiyun 	type_destroy,
325*4882a593Smuzhiyun 	user_destroy,
326*4882a593Smuzhiyun 	cond_destroy_bool,
327*4882a593Smuzhiyun 	sens_destroy,
328*4882a593Smuzhiyun 	cat_destroy,
329*4882a593Smuzhiyun };
330*4882a593Smuzhiyun 
filenametr_destroy(void * key,void * datum,void * p)331*4882a593Smuzhiyun static int filenametr_destroy(void *key, void *datum, void *p)
332*4882a593Smuzhiyun {
333*4882a593Smuzhiyun 	struct filename_trans_key *ft = key;
334*4882a593Smuzhiyun 	struct filename_trans_datum *next, *d = datum;
335*4882a593Smuzhiyun 
336*4882a593Smuzhiyun 	kfree(ft->name);
337*4882a593Smuzhiyun 	kfree(key);
338*4882a593Smuzhiyun 	do {
339*4882a593Smuzhiyun 		ebitmap_destroy(&d->stypes);
340*4882a593Smuzhiyun 		next = d->next;
341*4882a593Smuzhiyun 		kfree(d);
342*4882a593Smuzhiyun 		d = next;
343*4882a593Smuzhiyun 	} while (unlikely(d));
344*4882a593Smuzhiyun 	cond_resched();
345*4882a593Smuzhiyun 	return 0;
346*4882a593Smuzhiyun }
347*4882a593Smuzhiyun 
range_tr_destroy(void * key,void * datum,void * p)348*4882a593Smuzhiyun static int range_tr_destroy(void *key, void *datum, void *p)
349*4882a593Smuzhiyun {
350*4882a593Smuzhiyun 	struct mls_range *rt = datum;
351*4882a593Smuzhiyun 
352*4882a593Smuzhiyun 	kfree(key);
353*4882a593Smuzhiyun 	ebitmap_destroy(&rt->level[0].cat);
354*4882a593Smuzhiyun 	ebitmap_destroy(&rt->level[1].cat);
355*4882a593Smuzhiyun 	kfree(datum);
356*4882a593Smuzhiyun 	cond_resched();
357*4882a593Smuzhiyun 	return 0;
358*4882a593Smuzhiyun }
359*4882a593Smuzhiyun 
role_tr_destroy(void * key,void * datum,void * p)360*4882a593Smuzhiyun static int role_tr_destroy(void *key, void *datum, void *p)
361*4882a593Smuzhiyun {
362*4882a593Smuzhiyun 	kfree(key);
363*4882a593Smuzhiyun 	kfree(datum);
364*4882a593Smuzhiyun 	return 0;
365*4882a593Smuzhiyun }
366*4882a593Smuzhiyun 
ocontext_destroy(struct ocontext * c,int i)367*4882a593Smuzhiyun static void ocontext_destroy(struct ocontext *c, int i)
368*4882a593Smuzhiyun {
369*4882a593Smuzhiyun 	if (!c)
370*4882a593Smuzhiyun 		return;
371*4882a593Smuzhiyun 
372*4882a593Smuzhiyun 	context_destroy(&c->context[0]);
373*4882a593Smuzhiyun 	context_destroy(&c->context[1]);
374*4882a593Smuzhiyun 	if (i == OCON_ISID || i == OCON_FS ||
375*4882a593Smuzhiyun 	    i == OCON_NETIF || i == OCON_FSUSE)
376*4882a593Smuzhiyun 		kfree(c->u.name);
377*4882a593Smuzhiyun 	kfree(c);
378*4882a593Smuzhiyun }
379*4882a593Smuzhiyun 
380*4882a593Smuzhiyun /*
381*4882a593Smuzhiyun  * Initialize the role table.
382*4882a593Smuzhiyun  */
roles_init(struct policydb * p)383*4882a593Smuzhiyun static int roles_init(struct policydb *p)
384*4882a593Smuzhiyun {
385*4882a593Smuzhiyun 	char *key = NULL;
386*4882a593Smuzhiyun 	int rc;
387*4882a593Smuzhiyun 	struct role_datum *role;
388*4882a593Smuzhiyun 
389*4882a593Smuzhiyun 	role = kzalloc(sizeof(*role), GFP_KERNEL);
390*4882a593Smuzhiyun 	if (!role)
391*4882a593Smuzhiyun 		return -ENOMEM;
392*4882a593Smuzhiyun 
393*4882a593Smuzhiyun 	rc = -EINVAL;
394*4882a593Smuzhiyun 	role->value = ++p->p_roles.nprim;
395*4882a593Smuzhiyun 	if (role->value != OBJECT_R_VAL)
396*4882a593Smuzhiyun 		goto out;
397*4882a593Smuzhiyun 
398*4882a593Smuzhiyun 	rc = -ENOMEM;
399*4882a593Smuzhiyun 	key = kstrdup(OBJECT_R, GFP_KERNEL);
400*4882a593Smuzhiyun 	if (!key)
401*4882a593Smuzhiyun 		goto out;
402*4882a593Smuzhiyun 
403*4882a593Smuzhiyun 	rc = symtab_insert(&p->p_roles, key, role);
404*4882a593Smuzhiyun 	if (rc)
405*4882a593Smuzhiyun 		goto out;
406*4882a593Smuzhiyun 
407*4882a593Smuzhiyun 	return 0;
408*4882a593Smuzhiyun out:
409*4882a593Smuzhiyun 	kfree(key);
410*4882a593Smuzhiyun 	kfree(role);
411*4882a593Smuzhiyun 	return rc;
412*4882a593Smuzhiyun }
413*4882a593Smuzhiyun 
filenametr_hash(const void * k)414*4882a593Smuzhiyun static u32 filenametr_hash(const void *k)
415*4882a593Smuzhiyun {
416*4882a593Smuzhiyun 	const struct filename_trans_key *ft = k;
417*4882a593Smuzhiyun 	unsigned long hash;
418*4882a593Smuzhiyun 	unsigned int byte_num;
419*4882a593Smuzhiyun 	unsigned char focus;
420*4882a593Smuzhiyun 
421*4882a593Smuzhiyun 	hash = ft->ttype ^ ft->tclass;
422*4882a593Smuzhiyun 
423*4882a593Smuzhiyun 	byte_num = 0;
424*4882a593Smuzhiyun 	while ((focus = ft->name[byte_num++]))
425*4882a593Smuzhiyun 		hash = partial_name_hash(focus, hash);
426*4882a593Smuzhiyun 	return hash;
427*4882a593Smuzhiyun }
428*4882a593Smuzhiyun 
filenametr_cmp(const void * k1,const void * k2)429*4882a593Smuzhiyun static int filenametr_cmp(const void *k1, const void *k2)
430*4882a593Smuzhiyun {
431*4882a593Smuzhiyun 	const struct filename_trans_key *ft1 = k1;
432*4882a593Smuzhiyun 	const struct filename_trans_key *ft2 = k2;
433*4882a593Smuzhiyun 	int v;
434*4882a593Smuzhiyun 
435*4882a593Smuzhiyun 	v = ft1->ttype - ft2->ttype;
436*4882a593Smuzhiyun 	if (v)
437*4882a593Smuzhiyun 		return v;
438*4882a593Smuzhiyun 
439*4882a593Smuzhiyun 	v = ft1->tclass - ft2->tclass;
440*4882a593Smuzhiyun 	if (v)
441*4882a593Smuzhiyun 		return v;
442*4882a593Smuzhiyun 
443*4882a593Smuzhiyun 	return strcmp(ft1->name, ft2->name);
444*4882a593Smuzhiyun 
445*4882a593Smuzhiyun }
446*4882a593Smuzhiyun 
447*4882a593Smuzhiyun static const struct hashtab_key_params filenametr_key_params = {
448*4882a593Smuzhiyun 	.hash = filenametr_hash,
449*4882a593Smuzhiyun 	.cmp = filenametr_cmp,
450*4882a593Smuzhiyun };
451*4882a593Smuzhiyun 
policydb_filenametr_search(struct policydb * p,struct filename_trans_key * key)452*4882a593Smuzhiyun struct filename_trans_datum *policydb_filenametr_search(
453*4882a593Smuzhiyun 	struct policydb *p, struct filename_trans_key *key)
454*4882a593Smuzhiyun {
455*4882a593Smuzhiyun 	return hashtab_search(&p->filename_trans, key, filenametr_key_params);
456*4882a593Smuzhiyun }
457*4882a593Smuzhiyun 
rangetr_hash(const void * k)458*4882a593Smuzhiyun static u32 rangetr_hash(const void *k)
459*4882a593Smuzhiyun {
460*4882a593Smuzhiyun 	const struct range_trans *key = k;
461*4882a593Smuzhiyun 
462*4882a593Smuzhiyun 	return key->source_type + (key->target_type << 3) +
463*4882a593Smuzhiyun 		(key->target_class << 5);
464*4882a593Smuzhiyun }
465*4882a593Smuzhiyun 
rangetr_cmp(const void * k1,const void * k2)466*4882a593Smuzhiyun static int rangetr_cmp(const void *k1, const void *k2)
467*4882a593Smuzhiyun {
468*4882a593Smuzhiyun 	const struct range_trans *key1 = k1, *key2 = k2;
469*4882a593Smuzhiyun 	int v;
470*4882a593Smuzhiyun 
471*4882a593Smuzhiyun 	v = key1->source_type - key2->source_type;
472*4882a593Smuzhiyun 	if (v)
473*4882a593Smuzhiyun 		return v;
474*4882a593Smuzhiyun 
475*4882a593Smuzhiyun 	v = key1->target_type - key2->target_type;
476*4882a593Smuzhiyun 	if (v)
477*4882a593Smuzhiyun 		return v;
478*4882a593Smuzhiyun 
479*4882a593Smuzhiyun 	v = key1->target_class - key2->target_class;
480*4882a593Smuzhiyun 
481*4882a593Smuzhiyun 	return v;
482*4882a593Smuzhiyun }
483*4882a593Smuzhiyun 
484*4882a593Smuzhiyun static const struct hashtab_key_params rangetr_key_params = {
485*4882a593Smuzhiyun 	.hash = rangetr_hash,
486*4882a593Smuzhiyun 	.cmp = rangetr_cmp,
487*4882a593Smuzhiyun };
488*4882a593Smuzhiyun 
policydb_rangetr_search(struct policydb * p,struct range_trans * key)489*4882a593Smuzhiyun struct mls_range *policydb_rangetr_search(struct policydb *p,
490*4882a593Smuzhiyun 					  struct range_trans *key)
491*4882a593Smuzhiyun {
492*4882a593Smuzhiyun 	return hashtab_search(&p->range_tr, key, rangetr_key_params);
493*4882a593Smuzhiyun }
494*4882a593Smuzhiyun 
role_trans_hash(const void * k)495*4882a593Smuzhiyun static u32 role_trans_hash(const void *k)
496*4882a593Smuzhiyun {
497*4882a593Smuzhiyun 	const struct role_trans_key *key = k;
498*4882a593Smuzhiyun 
499*4882a593Smuzhiyun 	return key->role + (key->type << 3) + (key->tclass << 5);
500*4882a593Smuzhiyun }
501*4882a593Smuzhiyun 
role_trans_cmp(const void * k1,const void * k2)502*4882a593Smuzhiyun static int role_trans_cmp(const void *k1, const void *k2)
503*4882a593Smuzhiyun {
504*4882a593Smuzhiyun 	const struct role_trans_key *key1 = k1, *key2 = k2;
505*4882a593Smuzhiyun 	int v;
506*4882a593Smuzhiyun 
507*4882a593Smuzhiyun 	v = key1->role - key2->role;
508*4882a593Smuzhiyun 	if (v)
509*4882a593Smuzhiyun 		return v;
510*4882a593Smuzhiyun 
511*4882a593Smuzhiyun 	v = key1->type - key2->type;
512*4882a593Smuzhiyun 	if (v)
513*4882a593Smuzhiyun 		return v;
514*4882a593Smuzhiyun 
515*4882a593Smuzhiyun 	return key1->tclass - key2->tclass;
516*4882a593Smuzhiyun }
517*4882a593Smuzhiyun 
518*4882a593Smuzhiyun static const struct hashtab_key_params roletr_key_params = {
519*4882a593Smuzhiyun 	.hash = role_trans_hash,
520*4882a593Smuzhiyun 	.cmp = role_trans_cmp,
521*4882a593Smuzhiyun };
522*4882a593Smuzhiyun 
policydb_roletr_search(struct policydb * p,struct role_trans_key * key)523*4882a593Smuzhiyun struct role_trans_datum *policydb_roletr_search(struct policydb *p,
524*4882a593Smuzhiyun 						struct role_trans_key *key)
525*4882a593Smuzhiyun {
526*4882a593Smuzhiyun 	return hashtab_search(&p->role_tr, key, roletr_key_params);
527*4882a593Smuzhiyun }
528*4882a593Smuzhiyun 
529*4882a593Smuzhiyun /*
530*4882a593Smuzhiyun  * Initialize a policy database structure.
531*4882a593Smuzhiyun  */
policydb_init(struct policydb * p)532*4882a593Smuzhiyun static void policydb_init(struct policydb *p)
533*4882a593Smuzhiyun {
534*4882a593Smuzhiyun 	memset(p, 0, sizeof(*p));
535*4882a593Smuzhiyun 
536*4882a593Smuzhiyun 	avtab_init(&p->te_avtab);
537*4882a593Smuzhiyun 	cond_policydb_init(p);
538*4882a593Smuzhiyun 
539*4882a593Smuzhiyun 	ebitmap_init(&p->filename_trans_ttypes);
540*4882a593Smuzhiyun 	ebitmap_init(&p->policycaps);
541*4882a593Smuzhiyun 	ebitmap_init(&p->permissive_map);
542*4882a593Smuzhiyun }
543*4882a593Smuzhiyun 
544*4882a593Smuzhiyun /*
545*4882a593Smuzhiyun  * The following *_index functions are used to
546*4882a593Smuzhiyun  * define the val_to_name and val_to_struct arrays
547*4882a593Smuzhiyun  * in a policy database structure.  The val_to_name
548*4882a593Smuzhiyun  * arrays are used when converting security context
549*4882a593Smuzhiyun  * structures into string representations.  The
550*4882a593Smuzhiyun  * val_to_struct arrays are used when the attributes
551*4882a593Smuzhiyun  * of a class, role, or user are needed.
552*4882a593Smuzhiyun  */
553*4882a593Smuzhiyun 
common_index(void * key,void * datum,void * datap)554*4882a593Smuzhiyun static int common_index(void *key, void *datum, void *datap)
555*4882a593Smuzhiyun {
556*4882a593Smuzhiyun 	struct policydb *p;
557*4882a593Smuzhiyun 	struct common_datum *comdatum;
558*4882a593Smuzhiyun 
559*4882a593Smuzhiyun 	comdatum = datum;
560*4882a593Smuzhiyun 	p = datap;
561*4882a593Smuzhiyun 	if (!comdatum->value || comdatum->value > p->p_commons.nprim)
562*4882a593Smuzhiyun 		return -EINVAL;
563*4882a593Smuzhiyun 
564*4882a593Smuzhiyun 	p->sym_val_to_name[SYM_COMMONS][comdatum->value - 1] = key;
565*4882a593Smuzhiyun 
566*4882a593Smuzhiyun 	return 0;
567*4882a593Smuzhiyun }
568*4882a593Smuzhiyun 
class_index(void * key,void * datum,void * datap)569*4882a593Smuzhiyun static int class_index(void *key, void *datum, void *datap)
570*4882a593Smuzhiyun {
571*4882a593Smuzhiyun 	struct policydb *p;
572*4882a593Smuzhiyun 	struct class_datum *cladatum;
573*4882a593Smuzhiyun 
574*4882a593Smuzhiyun 	cladatum = datum;
575*4882a593Smuzhiyun 	p = datap;
576*4882a593Smuzhiyun 	if (!cladatum->value || cladatum->value > p->p_classes.nprim)
577*4882a593Smuzhiyun 		return -EINVAL;
578*4882a593Smuzhiyun 
579*4882a593Smuzhiyun 	p->sym_val_to_name[SYM_CLASSES][cladatum->value - 1] = key;
580*4882a593Smuzhiyun 	p->class_val_to_struct[cladatum->value - 1] = cladatum;
581*4882a593Smuzhiyun 	return 0;
582*4882a593Smuzhiyun }
583*4882a593Smuzhiyun 
role_index(void * key,void * datum,void * datap)584*4882a593Smuzhiyun static int role_index(void *key, void *datum, void *datap)
585*4882a593Smuzhiyun {
586*4882a593Smuzhiyun 	struct policydb *p;
587*4882a593Smuzhiyun 	struct role_datum *role;
588*4882a593Smuzhiyun 
589*4882a593Smuzhiyun 	role = datum;
590*4882a593Smuzhiyun 	p = datap;
591*4882a593Smuzhiyun 	if (!role->value
592*4882a593Smuzhiyun 	    || role->value > p->p_roles.nprim
593*4882a593Smuzhiyun 	    || role->bounds > p->p_roles.nprim)
594*4882a593Smuzhiyun 		return -EINVAL;
595*4882a593Smuzhiyun 
596*4882a593Smuzhiyun 	p->sym_val_to_name[SYM_ROLES][role->value - 1] = key;
597*4882a593Smuzhiyun 	p->role_val_to_struct[role->value - 1] = role;
598*4882a593Smuzhiyun 	return 0;
599*4882a593Smuzhiyun }
600*4882a593Smuzhiyun 
type_index(void * key,void * datum,void * datap)601*4882a593Smuzhiyun static int type_index(void *key, void *datum, void *datap)
602*4882a593Smuzhiyun {
603*4882a593Smuzhiyun 	struct policydb *p;
604*4882a593Smuzhiyun 	struct type_datum *typdatum;
605*4882a593Smuzhiyun 
606*4882a593Smuzhiyun 	typdatum = datum;
607*4882a593Smuzhiyun 	p = datap;
608*4882a593Smuzhiyun 
609*4882a593Smuzhiyun 	if (typdatum->primary) {
610*4882a593Smuzhiyun 		if (!typdatum->value
611*4882a593Smuzhiyun 		    || typdatum->value > p->p_types.nprim
612*4882a593Smuzhiyun 		    || typdatum->bounds > p->p_types.nprim)
613*4882a593Smuzhiyun 			return -EINVAL;
614*4882a593Smuzhiyun 		p->sym_val_to_name[SYM_TYPES][typdatum->value - 1] = key;
615*4882a593Smuzhiyun 		p->type_val_to_struct[typdatum->value - 1] = typdatum;
616*4882a593Smuzhiyun 	}
617*4882a593Smuzhiyun 
618*4882a593Smuzhiyun 	return 0;
619*4882a593Smuzhiyun }
620*4882a593Smuzhiyun 
user_index(void * key,void * datum,void * datap)621*4882a593Smuzhiyun static int user_index(void *key, void *datum, void *datap)
622*4882a593Smuzhiyun {
623*4882a593Smuzhiyun 	struct policydb *p;
624*4882a593Smuzhiyun 	struct user_datum *usrdatum;
625*4882a593Smuzhiyun 
626*4882a593Smuzhiyun 	usrdatum = datum;
627*4882a593Smuzhiyun 	p = datap;
628*4882a593Smuzhiyun 	if (!usrdatum->value
629*4882a593Smuzhiyun 	    || usrdatum->value > p->p_users.nprim
630*4882a593Smuzhiyun 	    || usrdatum->bounds > p->p_users.nprim)
631*4882a593Smuzhiyun 		return -EINVAL;
632*4882a593Smuzhiyun 
633*4882a593Smuzhiyun 	p->sym_val_to_name[SYM_USERS][usrdatum->value - 1] = key;
634*4882a593Smuzhiyun 	p->user_val_to_struct[usrdatum->value - 1] = usrdatum;
635*4882a593Smuzhiyun 	return 0;
636*4882a593Smuzhiyun }
637*4882a593Smuzhiyun 
sens_index(void * key,void * datum,void * datap)638*4882a593Smuzhiyun static int sens_index(void *key, void *datum, void *datap)
639*4882a593Smuzhiyun {
640*4882a593Smuzhiyun 	struct policydb *p;
641*4882a593Smuzhiyun 	struct level_datum *levdatum;
642*4882a593Smuzhiyun 
643*4882a593Smuzhiyun 	levdatum = datum;
644*4882a593Smuzhiyun 	p = datap;
645*4882a593Smuzhiyun 
646*4882a593Smuzhiyun 	if (!levdatum->isalias) {
647*4882a593Smuzhiyun 		if (!levdatum->level->sens ||
648*4882a593Smuzhiyun 		    levdatum->level->sens > p->p_levels.nprim)
649*4882a593Smuzhiyun 			return -EINVAL;
650*4882a593Smuzhiyun 
651*4882a593Smuzhiyun 		p->sym_val_to_name[SYM_LEVELS][levdatum->level->sens - 1] = key;
652*4882a593Smuzhiyun 	}
653*4882a593Smuzhiyun 
654*4882a593Smuzhiyun 	return 0;
655*4882a593Smuzhiyun }
656*4882a593Smuzhiyun 
cat_index(void * key,void * datum,void * datap)657*4882a593Smuzhiyun static int cat_index(void *key, void *datum, void *datap)
658*4882a593Smuzhiyun {
659*4882a593Smuzhiyun 	struct policydb *p;
660*4882a593Smuzhiyun 	struct cat_datum *catdatum;
661*4882a593Smuzhiyun 
662*4882a593Smuzhiyun 	catdatum = datum;
663*4882a593Smuzhiyun 	p = datap;
664*4882a593Smuzhiyun 
665*4882a593Smuzhiyun 	if (!catdatum->isalias) {
666*4882a593Smuzhiyun 		if (!catdatum->value || catdatum->value > p->p_cats.nprim)
667*4882a593Smuzhiyun 			return -EINVAL;
668*4882a593Smuzhiyun 
669*4882a593Smuzhiyun 		p->sym_val_to_name[SYM_CATS][catdatum->value - 1] = key;
670*4882a593Smuzhiyun 	}
671*4882a593Smuzhiyun 
672*4882a593Smuzhiyun 	return 0;
673*4882a593Smuzhiyun }
674*4882a593Smuzhiyun 
675*4882a593Smuzhiyun static int (*index_f[SYM_NUM]) (void *key, void *datum, void *datap) =
676*4882a593Smuzhiyun {
677*4882a593Smuzhiyun 	common_index,
678*4882a593Smuzhiyun 	class_index,
679*4882a593Smuzhiyun 	role_index,
680*4882a593Smuzhiyun 	type_index,
681*4882a593Smuzhiyun 	user_index,
682*4882a593Smuzhiyun 	cond_index_bool,
683*4882a593Smuzhiyun 	sens_index,
684*4882a593Smuzhiyun 	cat_index,
685*4882a593Smuzhiyun };
686*4882a593Smuzhiyun 
687*4882a593Smuzhiyun #ifdef DEBUG_HASHES
hash_eval(struct hashtab * h,const char * hash_name)688*4882a593Smuzhiyun static void hash_eval(struct hashtab *h, const char *hash_name)
689*4882a593Smuzhiyun {
690*4882a593Smuzhiyun 	struct hashtab_info info;
691*4882a593Smuzhiyun 
692*4882a593Smuzhiyun 	hashtab_stat(h, &info);
693*4882a593Smuzhiyun 	pr_debug("SELinux: %s:  %d entries and %d/%d buckets used, longest chain length %d\n",
694*4882a593Smuzhiyun 		 hash_name, h->nel, info.slots_used, h->size,
695*4882a593Smuzhiyun 		 info.max_chain_len);
696*4882a593Smuzhiyun }
697*4882a593Smuzhiyun 
symtab_hash_eval(struct symtab * s)698*4882a593Smuzhiyun static void symtab_hash_eval(struct symtab *s)
699*4882a593Smuzhiyun {
700*4882a593Smuzhiyun 	int i;
701*4882a593Smuzhiyun 
702*4882a593Smuzhiyun 	for (i = 0; i < SYM_NUM; i++)
703*4882a593Smuzhiyun 		hash_eval(&s[i].table, symtab_name[i]);
704*4882a593Smuzhiyun }
705*4882a593Smuzhiyun 
706*4882a593Smuzhiyun #else
hash_eval(struct hashtab * h,char * hash_name)707*4882a593Smuzhiyun static inline void hash_eval(struct hashtab *h, char *hash_name)
708*4882a593Smuzhiyun {
709*4882a593Smuzhiyun }
710*4882a593Smuzhiyun #endif
711*4882a593Smuzhiyun 
712*4882a593Smuzhiyun /*
713*4882a593Smuzhiyun  * Define the other val_to_name and val_to_struct arrays
714*4882a593Smuzhiyun  * in a policy database structure.
715*4882a593Smuzhiyun  *
716*4882a593Smuzhiyun  * Caller must clean up on failure.
717*4882a593Smuzhiyun  */
policydb_index(struct policydb * p)718*4882a593Smuzhiyun static int policydb_index(struct policydb *p)
719*4882a593Smuzhiyun {
720*4882a593Smuzhiyun 	int i, rc;
721*4882a593Smuzhiyun 
722*4882a593Smuzhiyun 	if (p->mls_enabled)
723*4882a593Smuzhiyun 		pr_debug("SELinux:  %d users, %d roles, %d types, %d bools, %d sens, %d cats\n",
724*4882a593Smuzhiyun 			 p->p_users.nprim, p->p_roles.nprim, p->p_types.nprim,
725*4882a593Smuzhiyun 			 p->p_bools.nprim, p->p_levels.nprim, p->p_cats.nprim);
726*4882a593Smuzhiyun 	else
727*4882a593Smuzhiyun 		pr_debug("SELinux:  %d users, %d roles, %d types, %d bools\n",
728*4882a593Smuzhiyun 			 p->p_users.nprim, p->p_roles.nprim, p->p_types.nprim,
729*4882a593Smuzhiyun 			 p->p_bools.nprim);
730*4882a593Smuzhiyun 
731*4882a593Smuzhiyun 	pr_debug("SELinux:  %d classes, %d rules\n",
732*4882a593Smuzhiyun 		 p->p_classes.nprim, p->te_avtab.nel);
733*4882a593Smuzhiyun 
734*4882a593Smuzhiyun #ifdef DEBUG_HASHES
735*4882a593Smuzhiyun 	avtab_hash_eval(&p->te_avtab, "rules");
736*4882a593Smuzhiyun 	symtab_hash_eval(p->symtab);
737*4882a593Smuzhiyun #endif
738*4882a593Smuzhiyun 
739*4882a593Smuzhiyun 	p->class_val_to_struct = kcalloc(p->p_classes.nprim,
740*4882a593Smuzhiyun 					 sizeof(*p->class_val_to_struct),
741*4882a593Smuzhiyun 					 GFP_KERNEL);
742*4882a593Smuzhiyun 	if (!p->class_val_to_struct)
743*4882a593Smuzhiyun 		return -ENOMEM;
744*4882a593Smuzhiyun 
745*4882a593Smuzhiyun 	p->role_val_to_struct = kcalloc(p->p_roles.nprim,
746*4882a593Smuzhiyun 					sizeof(*p->role_val_to_struct),
747*4882a593Smuzhiyun 					GFP_KERNEL);
748*4882a593Smuzhiyun 	if (!p->role_val_to_struct)
749*4882a593Smuzhiyun 		return -ENOMEM;
750*4882a593Smuzhiyun 
751*4882a593Smuzhiyun 	p->user_val_to_struct = kcalloc(p->p_users.nprim,
752*4882a593Smuzhiyun 					sizeof(*p->user_val_to_struct),
753*4882a593Smuzhiyun 					GFP_KERNEL);
754*4882a593Smuzhiyun 	if (!p->user_val_to_struct)
755*4882a593Smuzhiyun 		return -ENOMEM;
756*4882a593Smuzhiyun 
757*4882a593Smuzhiyun 	p->type_val_to_struct = kvcalloc(p->p_types.nprim,
758*4882a593Smuzhiyun 					 sizeof(*p->type_val_to_struct),
759*4882a593Smuzhiyun 					 GFP_KERNEL);
760*4882a593Smuzhiyun 	if (!p->type_val_to_struct)
761*4882a593Smuzhiyun 		return -ENOMEM;
762*4882a593Smuzhiyun 
763*4882a593Smuzhiyun 	rc = cond_init_bool_indexes(p);
764*4882a593Smuzhiyun 	if (rc)
765*4882a593Smuzhiyun 		goto out;
766*4882a593Smuzhiyun 
767*4882a593Smuzhiyun 	for (i = 0; i < SYM_NUM; i++) {
768*4882a593Smuzhiyun 		p->sym_val_to_name[i] = kvcalloc(p->symtab[i].nprim,
769*4882a593Smuzhiyun 						 sizeof(char *),
770*4882a593Smuzhiyun 						 GFP_KERNEL);
771*4882a593Smuzhiyun 		if (!p->sym_val_to_name[i])
772*4882a593Smuzhiyun 			return -ENOMEM;
773*4882a593Smuzhiyun 
774*4882a593Smuzhiyun 		rc = hashtab_map(&p->symtab[i].table, index_f[i], p);
775*4882a593Smuzhiyun 		if (rc)
776*4882a593Smuzhiyun 			goto out;
777*4882a593Smuzhiyun 	}
778*4882a593Smuzhiyun 	rc = 0;
779*4882a593Smuzhiyun out:
780*4882a593Smuzhiyun 	return rc;
781*4882a593Smuzhiyun }
782*4882a593Smuzhiyun 
783*4882a593Smuzhiyun /*
784*4882a593Smuzhiyun  * Free any memory allocated by a policy database structure.
785*4882a593Smuzhiyun  */
policydb_destroy(struct policydb * p)786*4882a593Smuzhiyun void policydb_destroy(struct policydb *p)
787*4882a593Smuzhiyun {
788*4882a593Smuzhiyun 	struct ocontext *c, *ctmp;
789*4882a593Smuzhiyun 	struct genfs *g, *gtmp;
790*4882a593Smuzhiyun 	int i;
791*4882a593Smuzhiyun 	struct role_allow *ra, *lra = NULL;
792*4882a593Smuzhiyun 
793*4882a593Smuzhiyun 	for (i = 0; i < SYM_NUM; i++) {
794*4882a593Smuzhiyun 		cond_resched();
795*4882a593Smuzhiyun 		hashtab_map(&p->symtab[i].table, destroy_f[i], NULL);
796*4882a593Smuzhiyun 		hashtab_destroy(&p->symtab[i].table);
797*4882a593Smuzhiyun 	}
798*4882a593Smuzhiyun 
799*4882a593Smuzhiyun 	for (i = 0; i < SYM_NUM; i++)
800*4882a593Smuzhiyun 		kvfree(p->sym_val_to_name[i]);
801*4882a593Smuzhiyun 
802*4882a593Smuzhiyun 	kfree(p->class_val_to_struct);
803*4882a593Smuzhiyun 	kfree(p->role_val_to_struct);
804*4882a593Smuzhiyun 	kfree(p->user_val_to_struct);
805*4882a593Smuzhiyun 	kvfree(p->type_val_to_struct);
806*4882a593Smuzhiyun 
807*4882a593Smuzhiyun 	avtab_destroy(&p->te_avtab);
808*4882a593Smuzhiyun 
809*4882a593Smuzhiyun 	for (i = 0; i < OCON_NUM; i++) {
810*4882a593Smuzhiyun 		cond_resched();
811*4882a593Smuzhiyun 		c = p->ocontexts[i];
812*4882a593Smuzhiyun 		while (c) {
813*4882a593Smuzhiyun 			ctmp = c;
814*4882a593Smuzhiyun 			c = c->next;
815*4882a593Smuzhiyun 			ocontext_destroy(ctmp, i);
816*4882a593Smuzhiyun 		}
817*4882a593Smuzhiyun 		p->ocontexts[i] = NULL;
818*4882a593Smuzhiyun 	}
819*4882a593Smuzhiyun 
820*4882a593Smuzhiyun 	g = p->genfs;
821*4882a593Smuzhiyun 	while (g) {
822*4882a593Smuzhiyun 		cond_resched();
823*4882a593Smuzhiyun 		kfree(g->fstype);
824*4882a593Smuzhiyun 		c = g->head;
825*4882a593Smuzhiyun 		while (c) {
826*4882a593Smuzhiyun 			ctmp = c;
827*4882a593Smuzhiyun 			c = c->next;
828*4882a593Smuzhiyun 			ocontext_destroy(ctmp, OCON_FSUSE);
829*4882a593Smuzhiyun 		}
830*4882a593Smuzhiyun 		gtmp = g;
831*4882a593Smuzhiyun 		g = g->next;
832*4882a593Smuzhiyun 		kfree(gtmp);
833*4882a593Smuzhiyun 	}
834*4882a593Smuzhiyun 	p->genfs = NULL;
835*4882a593Smuzhiyun 
836*4882a593Smuzhiyun 	cond_policydb_destroy(p);
837*4882a593Smuzhiyun 
838*4882a593Smuzhiyun 	hashtab_map(&p->role_tr, role_tr_destroy, NULL);
839*4882a593Smuzhiyun 	hashtab_destroy(&p->role_tr);
840*4882a593Smuzhiyun 
841*4882a593Smuzhiyun 	for (ra = p->role_allow; ra; ra = ra->next) {
842*4882a593Smuzhiyun 		cond_resched();
843*4882a593Smuzhiyun 		kfree(lra);
844*4882a593Smuzhiyun 		lra = ra;
845*4882a593Smuzhiyun 	}
846*4882a593Smuzhiyun 	kfree(lra);
847*4882a593Smuzhiyun 
848*4882a593Smuzhiyun 	hashtab_map(&p->filename_trans, filenametr_destroy, NULL);
849*4882a593Smuzhiyun 	hashtab_destroy(&p->filename_trans);
850*4882a593Smuzhiyun 
851*4882a593Smuzhiyun 	hashtab_map(&p->range_tr, range_tr_destroy, NULL);
852*4882a593Smuzhiyun 	hashtab_destroy(&p->range_tr);
853*4882a593Smuzhiyun 
854*4882a593Smuzhiyun 	if (p->type_attr_map_array) {
855*4882a593Smuzhiyun 		for (i = 0; i < p->p_types.nprim; i++)
856*4882a593Smuzhiyun 			ebitmap_destroy(&p->type_attr_map_array[i]);
857*4882a593Smuzhiyun 		kvfree(p->type_attr_map_array);
858*4882a593Smuzhiyun 	}
859*4882a593Smuzhiyun 
860*4882a593Smuzhiyun 	ebitmap_destroy(&p->filename_trans_ttypes);
861*4882a593Smuzhiyun 	ebitmap_destroy(&p->policycaps);
862*4882a593Smuzhiyun 	ebitmap_destroy(&p->permissive_map);
863*4882a593Smuzhiyun }
864*4882a593Smuzhiyun 
865*4882a593Smuzhiyun /*
866*4882a593Smuzhiyun  * Load the initial SIDs specified in a policy database
867*4882a593Smuzhiyun  * structure into a SID table.
868*4882a593Smuzhiyun  */
policydb_load_isids(struct policydb * p,struct sidtab * s)869*4882a593Smuzhiyun int policydb_load_isids(struct policydb *p, struct sidtab *s)
870*4882a593Smuzhiyun {
871*4882a593Smuzhiyun 	struct ocontext *head, *c;
872*4882a593Smuzhiyun 	int rc;
873*4882a593Smuzhiyun 
874*4882a593Smuzhiyun 	rc = sidtab_init(s);
875*4882a593Smuzhiyun 	if (rc) {
876*4882a593Smuzhiyun 		pr_err("SELinux:  out of memory on SID table init\n");
877*4882a593Smuzhiyun 		return rc;
878*4882a593Smuzhiyun 	}
879*4882a593Smuzhiyun 
880*4882a593Smuzhiyun 	head = p->ocontexts[OCON_ISID];
881*4882a593Smuzhiyun 	for (c = head; c; c = c->next) {
882*4882a593Smuzhiyun 		u32 sid = c->sid[0];
883*4882a593Smuzhiyun 		const char *name = security_get_initial_sid_context(sid);
884*4882a593Smuzhiyun 
885*4882a593Smuzhiyun 		if (sid == SECSID_NULL) {
886*4882a593Smuzhiyun 			pr_err("SELinux:  SID 0 was assigned a context.\n");
887*4882a593Smuzhiyun 			sidtab_destroy(s);
888*4882a593Smuzhiyun 			return -EINVAL;
889*4882a593Smuzhiyun 		}
890*4882a593Smuzhiyun 
891*4882a593Smuzhiyun 		/* Ignore initial SIDs unused by this kernel. */
892*4882a593Smuzhiyun 		if (!name)
893*4882a593Smuzhiyun 			continue;
894*4882a593Smuzhiyun 
895*4882a593Smuzhiyun 		rc = sidtab_set_initial(s, sid, &c->context[0]);
896*4882a593Smuzhiyun 		if (rc) {
897*4882a593Smuzhiyun 			pr_err("SELinux:  unable to load initial SID %s.\n",
898*4882a593Smuzhiyun 			       name);
899*4882a593Smuzhiyun 			sidtab_destroy(s);
900*4882a593Smuzhiyun 			return rc;
901*4882a593Smuzhiyun 		}
902*4882a593Smuzhiyun 	}
903*4882a593Smuzhiyun 	return 0;
904*4882a593Smuzhiyun }
905*4882a593Smuzhiyun 
policydb_class_isvalid(struct policydb * p,unsigned int class)906*4882a593Smuzhiyun int policydb_class_isvalid(struct policydb *p, unsigned int class)
907*4882a593Smuzhiyun {
908*4882a593Smuzhiyun 	if (!class || class > p->p_classes.nprim)
909*4882a593Smuzhiyun 		return 0;
910*4882a593Smuzhiyun 	return 1;
911*4882a593Smuzhiyun }
912*4882a593Smuzhiyun 
policydb_role_isvalid(struct policydb * p,unsigned int role)913*4882a593Smuzhiyun int policydb_role_isvalid(struct policydb *p, unsigned int role)
914*4882a593Smuzhiyun {
915*4882a593Smuzhiyun 	if (!role || role > p->p_roles.nprim)
916*4882a593Smuzhiyun 		return 0;
917*4882a593Smuzhiyun 	return 1;
918*4882a593Smuzhiyun }
919*4882a593Smuzhiyun 
policydb_type_isvalid(struct policydb * p,unsigned int type)920*4882a593Smuzhiyun int policydb_type_isvalid(struct policydb *p, unsigned int type)
921*4882a593Smuzhiyun {
922*4882a593Smuzhiyun 	if (!type || type > p->p_types.nprim)
923*4882a593Smuzhiyun 		return 0;
924*4882a593Smuzhiyun 	return 1;
925*4882a593Smuzhiyun }
926*4882a593Smuzhiyun 
927*4882a593Smuzhiyun /*
928*4882a593Smuzhiyun  * Return 1 if the fields in the security context
929*4882a593Smuzhiyun  * structure `c' are valid.  Return 0 otherwise.
930*4882a593Smuzhiyun  */
policydb_context_isvalid(struct policydb * p,struct context * c)931*4882a593Smuzhiyun int policydb_context_isvalid(struct policydb *p, struct context *c)
932*4882a593Smuzhiyun {
933*4882a593Smuzhiyun 	struct role_datum *role;
934*4882a593Smuzhiyun 	struct user_datum *usrdatum;
935*4882a593Smuzhiyun 
936*4882a593Smuzhiyun 	if (!c->role || c->role > p->p_roles.nprim)
937*4882a593Smuzhiyun 		return 0;
938*4882a593Smuzhiyun 
939*4882a593Smuzhiyun 	if (!c->user || c->user > p->p_users.nprim)
940*4882a593Smuzhiyun 		return 0;
941*4882a593Smuzhiyun 
942*4882a593Smuzhiyun 	if (!c->type || c->type > p->p_types.nprim)
943*4882a593Smuzhiyun 		return 0;
944*4882a593Smuzhiyun 
945*4882a593Smuzhiyun 	if (c->role != OBJECT_R_VAL) {
946*4882a593Smuzhiyun 		/*
947*4882a593Smuzhiyun 		 * Role must be authorized for the type.
948*4882a593Smuzhiyun 		 */
949*4882a593Smuzhiyun 		role = p->role_val_to_struct[c->role - 1];
950*4882a593Smuzhiyun 		if (!role || !ebitmap_get_bit(&role->types, c->type - 1))
951*4882a593Smuzhiyun 			/* role may not be associated with type */
952*4882a593Smuzhiyun 			return 0;
953*4882a593Smuzhiyun 
954*4882a593Smuzhiyun 		/*
955*4882a593Smuzhiyun 		 * User must be authorized for the role.
956*4882a593Smuzhiyun 		 */
957*4882a593Smuzhiyun 		usrdatum = p->user_val_to_struct[c->user - 1];
958*4882a593Smuzhiyun 		if (!usrdatum)
959*4882a593Smuzhiyun 			return 0;
960*4882a593Smuzhiyun 
961*4882a593Smuzhiyun 		if (!ebitmap_get_bit(&usrdatum->roles, c->role - 1))
962*4882a593Smuzhiyun 			/* user may not be associated with role */
963*4882a593Smuzhiyun 			return 0;
964*4882a593Smuzhiyun 	}
965*4882a593Smuzhiyun 
966*4882a593Smuzhiyun 	if (!mls_context_isvalid(p, c))
967*4882a593Smuzhiyun 		return 0;
968*4882a593Smuzhiyun 
969*4882a593Smuzhiyun 	return 1;
970*4882a593Smuzhiyun }
971*4882a593Smuzhiyun 
972*4882a593Smuzhiyun /*
973*4882a593Smuzhiyun  * Read a MLS range structure from a policydb binary
974*4882a593Smuzhiyun  * representation file.
975*4882a593Smuzhiyun  */
mls_read_range_helper(struct mls_range * r,void * fp)976*4882a593Smuzhiyun static int mls_read_range_helper(struct mls_range *r, void *fp)
977*4882a593Smuzhiyun {
978*4882a593Smuzhiyun 	__le32 buf[2];
979*4882a593Smuzhiyun 	u32 items;
980*4882a593Smuzhiyun 	int rc;
981*4882a593Smuzhiyun 
982*4882a593Smuzhiyun 	rc = next_entry(buf, fp, sizeof(u32));
983*4882a593Smuzhiyun 	if (rc)
984*4882a593Smuzhiyun 		goto out;
985*4882a593Smuzhiyun 
986*4882a593Smuzhiyun 	rc = -EINVAL;
987*4882a593Smuzhiyun 	items = le32_to_cpu(buf[0]);
988*4882a593Smuzhiyun 	if (items > ARRAY_SIZE(buf)) {
989*4882a593Smuzhiyun 		pr_err("SELinux: mls:  range overflow\n");
990*4882a593Smuzhiyun 		goto out;
991*4882a593Smuzhiyun 	}
992*4882a593Smuzhiyun 
993*4882a593Smuzhiyun 	rc = next_entry(buf, fp, sizeof(u32) * items);
994*4882a593Smuzhiyun 	if (rc) {
995*4882a593Smuzhiyun 		pr_err("SELinux: mls:  truncated range\n");
996*4882a593Smuzhiyun 		goto out;
997*4882a593Smuzhiyun 	}
998*4882a593Smuzhiyun 
999*4882a593Smuzhiyun 	r->level[0].sens = le32_to_cpu(buf[0]);
1000*4882a593Smuzhiyun 	if (items > 1)
1001*4882a593Smuzhiyun 		r->level[1].sens = le32_to_cpu(buf[1]);
1002*4882a593Smuzhiyun 	else
1003*4882a593Smuzhiyun 		r->level[1].sens = r->level[0].sens;
1004*4882a593Smuzhiyun 
1005*4882a593Smuzhiyun 	rc = ebitmap_read(&r->level[0].cat, fp);
1006*4882a593Smuzhiyun 	if (rc) {
1007*4882a593Smuzhiyun 		pr_err("SELinux: mls:  error reading low categories\n");
1008*4882a593Smuzhiyun 		goto out;
1009*4882a593Smuzhiyun 	}
1010*4882a593Smuzhiyun 	if (items > 1) {
1011*4882a593Smuzhiyun 		rc = ebitmap_read(&r->level[1].cat, fp);
1012*4882a593Smuzhiyun 		if (rc) {
1013*4882a593Smuzhiyun 			pr_err("SELinux: mls:  error reading high categories\n");
1014*4882a593Smuzhiyun 			goto bad_high;
1015*4882a593Smuzhiyun 		}
1016*4882a593Smuzhiyun 	} else {
1017*4882a593Smuzhiyun 		rc = ebitmap_cpy(&r->level[1].cat, &r->level[0].cat);
1018*4882a593Smuzhiyun 		if (rc) {
1019*4882a593Smuzhiyun 			pr_err("SELinux: mls:  out of memory\n");
1020*4882a593Smuzhiyun 			goto bad_high;
1021*4882a593Smuzhiyun 		}
1022*4882a593Smuzhiyun 	}
1023*4882a593Smuzhiyun 
1024*4882a593Smuzhiyun 	return 0;
1025*4882a593Smuzhiyun bad_high:
1026*4882a593Smuzhiyun 	ebitmap_destroy(&r->level[0].cat);
1027*4882a593Smuzhiyun out:
1028*4882a593Smuzhiyun 	return rc;
1029*4882a593Smuzhiyun }
1030*4882a593Smuzhiyun 
1031*4882a593Smuzhiyun /*
1032*4882a593Smuzhiyun  * Read and validate a security context structure
1033*4882a593Smuzhiyun  * from a policydb binary representation file.
1034*4882a593Smuzhiyun  */
context_read_and_validate(struct context * c,struct policydb * p,void * fp)1035*4882a593Smuzhiyun static int context_read_and_validate(struct context *c,
1036*4882a593Smuzhiyun 				     struct policydb *p,
1037*4882a593Smuzhiyun 				     void *fp)
1038*4882a593Smuzhiyun {
1039*4882a593Smuzhiyun 	__le32 buf[3];
1040*4882a593Smuzhiyun 	int rc;
1041*4882a593Smuzhiyun 
1042*4882a593Smuzhiyun 	rc = next_entry(buf, fp, sizeof buf);
1043*4882a593Smuzhiyun 	if (rc) {
1044*4882a593Smuzhiyun 		pr_err("SELinux: context truncated\n");
1045*4882a593Smuzhiyun 		goto out;
1046*4882a593Smuzhiyun 	}
1047*4882a593Smuzhiyun 	c->user = le32_to_cpu(buf[0]);
1048*4882a593Smuzhiyun 	c->role = le32_to_cpu(buf[1]);
1049*4882a593Smuzhiyun 	c->type = le32_to_cpu(buf[2]);
1050*4882a593Smuzhiyun 	if (p->policyvers >= POLICYDB_VERSION_MLS) {
1051*4882a593Smuzhiyun 		rc = mls_read_range_helper(&c->range, fp);
1052*4882a593Smuzhiyun 		if (rc) {
1053*4882a593Smuzhiyun 			pr_err("SELinux: error reading MLS range of context\n");
1054*4882a593Smuzhiyun 			goto out;
1055*4882a593Smuzhiyun 		}
1056*4882a593Smuzhiyun 	}
1057*4882a593Smuzhiyun 
1058*4882a593Smuzhiyun 	rc = -EINVAL;
1059*4882a593Smuzhiyun 	if (!policydb_context_isvalid(p, c)) {
1060*4882a593Smuzhiyun 		pr_err("SELinux:  invalid security context\n");
1061*4882a593Smuzhiyun 		context_destroy(c);
1062*4882a593Smuzhiyun 		goto out;
1063*4882a593Smuzhiyun 	}
1064*4882a593Smuzhiyun 	rc = 0;
1065*4882a593Smuzhiyun out:
1066*4882a593Smuzhiyun 	return rc;
1067*4882a593Smuzhiyun }
1068*4882a593Smuzhiyun 
1069*4882a593Smuzhiyun /*
1070*4882a593Smuzhiyun  * The following *_read functions are used to
1071*4882a593Smuzhiyun  * read the symbol data from a policy database
1072*4882a593Smuzhiyun  * binary representation file.
1073*4882a593Smuzhiyun  */
1074*4882a593Smuzhiyun 
str_read(char ** strp,gfp_t flags,void * fp,u32 len)1075*4882a593Smuzhiyun static int str_read(char **strp, gfp_t flags, void *fp, u32 len)
1076*4882a593Smuzhiyun {
1077*4882a593Smuzhiyun 	int rc;
1078*4882a593Smuzhiyun 	char *str;
1079*4882a593Smuzhiyun 
1080*4882a593Smuzhiyun 	if ((len == 0) || (len == (u32)-1))
1081*4882a593Smuzhiyun 		return -EINVAL;
1082*4882a593Smuzhiyun 
1083*4882a593Smuzhiyun 	str = kmalloc(len + 1, flags | __GFP_NOWARN);
1084*4882a593Smuzhiyun 	if (!str)
1085*4882a593Smuzhiyun 		return -ENOMEM;
1086*4882a593Smuzhiyun 
1087*4882a593Smuzhiyun 	rc = next_entry(str, fp, len);
1088*4882a593Smuzhiyun 	if (rc) {
1089*4882a593Smuzhiyun 		kfree(str);
1090*4882a593Smuzhiyun 		return rc;
1091*4882a593Smuzhiyun 	}
1092*4882a593Smuzhiyun 
1093*4882a593Smuzhiyun 	str[len] = '\0';
1094*4882a593Smuzhiyun 	*strp = str;
1095*4882a593Smuzhiyun 	return 0;
1096*4882a593Smuzhiyun }
1097*4882a593Smuzhiyun 
perm_read(struct policydb * p,struct symtab * s,void * fp)1098*4882a593Smuzhiyun static int perm_read(struct policydb *p, struct symtab *s, void *fp)
1099*4882a593Smuzhiyun {
1100*4882a593Smuzhiyun 	char *key = NULL;
1101*4882a593Smuzhiyun 	struct perm_datum *perdatum;
1102*4882a593Smuzhiyun 	int rc;
1103*4882a593Smuzhiyun 	__le32 buf[2];
1104*4882a593Smuzhiyun 	u32 len;
1105*4882a593Smuzhiyun 
1106*4882a593Smuzhiyun 	perdatum = kzalloc(sizeof(*perdatum), GFP_KERNEL);
1107*4882a593Smuzhiyun 	if (!perdatum)
1108*4882a593Smuzhiyun 		return -ENOMEM;
1109*4882a593Smuzhiyun 
1110*4882a593Smuzhiyun 	rc = next_entry(buf, fp, sizeof buf);
1111*4882a593Smuzhiyun 	if (rc)
1112*4882a593Smuzhiyun 		goto bad;
1113*4882a593Smuzhiyun 
1114*4882a593Smuzhiyun 	len = le32_to_cpu(buf[0]);
1115*4882a593Smuzhiyun 	perdatum->value = le32_to_cpu(buf[1]);
1116*4882a593Smuzhiyun 
1117*4882a593Smuzhiyun 	rc = str_read(&key, GFP_KERNEL, fp, len);
1118*4882a593Smuzhiyun 	if (rc)
1119*4882a593Smuzhiyun 		goto bad;
1120*4882a593Smuzhiyun 
1121*4882a593Smuzhiyun 	rc = symtab_insert(s, key, perdatum);
1122*4882a593Smuzhiyun 	if (rc)
1123*4882a593Smuzhiyun 		goto bad;
1124*4882a593Smuzhiyun 
1125*4882a593Smuzhiyun 	return 0;
1126*4882a593Smuzhiyun bad:
1127*4882a593Smuzhiyun 	perm_destroy(key, perdatum, NULL);
1128*4882a593Smuzhiyun 	return rc;
1129*4882a593Smuzhiyun }
1130*4882a593Smuzhiyun 
common_read(struct policydb * p,struct symtab * s,void * fp)1131*4882a593Smuzhiyun static int common_read(struct policydb *p, struct symtab *s, void *fp)
1132*4882a593Smuzhiyun {
1133*4882a593Smuzhiyun 	char *key = NULL;
1134*4882a593Smuzhiyun 	struct common_datum *comdatum;
1135*4882a593Smuzhiyun 	__le32 buf[4];
1136*4882a593Smuzhiyun 	u32 len, nel;
1137*4882a593Smuzhiyun 	int i, rc;
1138*4882a593Smuzhiyun 
1139*4882a593Smuzhiyun 	comdatum = kzalloc(sizeof(*comdatum), GFP_KERNEL);
1140*4882a593Smuzhiyun 	if (!comdatum)
1141*4882a593Smuzhiyun 		return -ENOMEM;
1142*4882a593Smuzhiyun 
1143*4882a593Smuzhiyun 	rc = next_entry(buf, fp, sizeof buf);
1144*4882a593Smuzhiyun 	if (rc)
1145*4882a593Smuzhiyun 		goto bad;
1146*4882a593Smuzhiyun 
1147*4882a593Smuzhiyun 	len = le32_to_cpu(buf[0]);
1148*4882a593Smuzhiyun 	comdatum->value = le32_to_cpu(buf[1]);
1149*4882a593Smuzhiyun 	nel = le32_to_cpu(buf[3]);
1150*4882a593Smuzhiyun 
1151*4882a593Smuzhiyun 	rc = symtab_init(&comdatum->permissions, nel);
1152*4882a593Smuzhiyun 	if (rc)
1153*4882a593Smuzhiyun 		goto bad;
1154*4882a593Smuzhiyun 	comdatum->permissions.nprim = le32_to_cpu(buf[2]);
1155*4882a593Smuzhiyun 
1156*4882a593Smuzhiyun 	rc = str_read(&key, GFP_KERNEL, fp, len);
1157*4882a593Smuzhiyun 	if (rc)
1158*4882a593Smuzhiyun 		goto bad;
1159*4882a593Smuzhiyun 
1160*4882a593Smuzhiyun 	for (i = 0; i < nel; i++) {
1161*4882a593Smuzhiyun 		rc = perm_read(p, &comdatum->permissions, fp);
1162*4882a593Smuzhiyun 		if (rc)
1163*4882a593Smuzhiyun 			goto bad;
1164*4882a593Smuzhiyun 	}
1165*4882a593Smuzhiyun 
1166*4882a593Smuzhiyun 	rc = symtab_insert(s, key, comdatum);
1167*4882a593Smuzhiyun 	if (rc)
1168*4882a593Smuzhiyun 		goto bad;
1169*4882a593Smuzhiyun 	return 0;
1170*4882a593Smuzhiyun bad:
1171*4882a593Smuzhiyun 	common_destroy(key, comdatum, NULL);
1172*4882a593Smuzhiyun 	return rc;
1173*4882a593Smuzhiyun }
1174*4882a593Smuzhiyun 
type_set_init(struct type_set * t)1175*4882a593Smuzhiyun static void type_set_init(struct type_set *t)
1176*4882a593Smuzhiyun {
1177*4882a593Smuzhiyun 	ebitmap_init(&t->types);
1178*4882a593Smuzhiyun 	ebitmap_init(&t->negset);
1179*4882a593Smuzhiyun }
1180*4882a593Smuzhiyun 
type_set_read(struct type_set * t,void * fp)1181*4882a593Smuzhiyun static int type_set_read(struct type_set *t, void *fp)
1182*4882a593Smuzhiyun {
1183*4882a593Smuzhiyun 	__le32 buf[1];
1184*4882a593Smuzhiyun 	int rc;
1185*4882a593Smuzhiyun 
1186*4882a593Smuzhiyun 	if (ebitmap_read(&t->types, fp))
1187*4882a593Smuzhiyun 		return -EINVAL;
1188*4882a593Smuzhiyun 	if (ebitmap_read(&t->negset, fp))
1189*4882a593Smuzhiyun 		return -EINVAL;
1190*4882a593Smuzhiyun 
1191*4882a593Smuzhiyun 	rc = next_entry(buf, fp, sizeof(u32));
1192*4882a593Smuzhiyun 	if (rc < 0)
1193*4882a593Smuzhiyun 		return -EINVAL;
1194*4882a593Smuzhiyun 	t->flags = le32_to_cpu(buf[0]);
1195*4882a593Smuzhiyun 
1196*4882a593Smuzhiyun 	return 0;
1197*4882a593Smuzhiyun }
1198*4882a593Smuzhiyun 
1199*4882a593Smuzhiyun 
read_cons_helper(struct policydb * p,struct constraint_node ** nodep,int ncons,int allowxtarget,void * fp)1200*4882a593Smuzhiyun static int read_cons_helper(struct policydb *p,
1201*4882a593Smuzhiyun 				struct constraint_node **nodep,
1202*4882a593Smuzhiyun 				int ncons, int allowxtarget, void *fp)
1203*4882a593Smuzhiyun {
1204*4882a593Smuzhiyun 	struct constraint_node *c, *lc;
1205*4882a593Smuzhiyun 	struct constraint_expr *e, *le;
1206*4882a593Smuzhiyun 	__le32 buf[3];
1207*4882a593Smuzhiyun 	u32 nexpr;
1208*4882a593Smuzhiyun 	int rc, i, j, depth;
1209*4882a593Smuzhiyun 
1210*4882a593Smuzhiyun 	lc = NULL;
1211*4882a593Smuzhiyun 	for (i = 0; i < ncons; i++) {
1212*4882a593Smuzhiyun 		c = kzalloc(sizeof(*c), GFP_KERNEL);
1213*4882a593Smuzhiyun 		if (!c)
1214*4882a593Smuzhiyun 			return -ENOMEM;
1215*4882a593Smuzhiyun 
1216*4882a593Smuzhiyun 		if (lc)
1217*4882a593Smuzhiyun 			lc->next = c;
1218*4882a593Smuzhiyun 		else
1219*4882a593Smuzhiyun 			*nodep = c;
1220*4882a593Smuzhiyun 
1221*4882a593Smuzhiyun 		rc = next_entry(buf, fp, (sizeof(u32) * 2));
1222*4882a593Smuzhiyun 		if (rc)
1223*4882a593Smuzhiyun 			return rc;
1224*4882a593Smuzhiyun 		c->permissions = le32_to_cpu(buf[0]);
1225*4882a593Smuzhiyun 		nexpr = le32_to_cpu(buf[1]);
1226*4882a593Smuzhiyun 		le = NULL;
1227*4882a593Smuzhiyun 		depth = -1;
1228*4882a593Smuzhiyun 		for (j = 0; j < nexpr; j++) {
1229*4882a593Smuzhiyun 			e = kzalloc(sizeof(*e), GFP_KERNEL);
1230*4882a593Smuzhiyun 			if (!e)
1231*4882a593Smuzhiyun 				return -ENOMEM;
1232*4882a593Smuzhiyun 
1233*4882a593Smuzhiyun 			if (le)
1234*4882a593Smuzhiyun 				le->next = e;
1235*4882a593Smuzhiyun 			else
1236*4882a593Smuzhiyun 				c->expr = e;
1237*4882a593Smuzhiyun 
1238*4882a593Smuzhiyun 			rc = next_entry(buf, fp, (sizeof(u32) * 3));
1239*4882a593Smuzhiyun 			if (rc)
1240*4882a593Smuzhiyun 				return rc;
1241*4882a593Smuzhiyun 			e->expr_type = le32_to_cpu(buf[0]);
1242*4882a593Smuzhiyun 			e->attr = le32_to_cpu(buf[1]);
1243*4882a593Smuzhiyun 			e->op = le32_to_cpu(buf[2]);
1244*4882a593Smuzhiyun 
1245*4882a593Smuzhiyun 			switch (e->expr_type) {
1246*4882a593Smuzhiyun 			case CEXPR_NOT:
1247*4882a593Smuzhiyun 				if (depth < 0)
1248*4882a593Smuzhiyun 					return -EINVAL;
1249*4882a593Smuzhiyun 				break;
1250*4882a593Smuzhiyun 			case CEXPR_AND:
1251*4882a593Smuzhiyun 			case CEXPR_OR:
1252*4882a593Smuzhiyun 				if (depth < 1)
1253*4882a593Smuzhiyun 					return -EINVAL;
1254*4882a593Smuzhiyun 				depth--;
1255*4882a593Smuzhiyun 				break;
1256*4882a593Smuzhiyun 			case CEXPR_ATTR:
1257*4882a593Smuzhiyun 				if (depth == (CEXPR_MAXDEPTH - 1))
1258*4882a593Smuzhiyun 					return -EINVAL;
1259*4882a593Smuzhiyun 				depth++;
1260*4882a593Smuzhiyun 				break;
1261*4882a593Smuzhiyun 			case CEXPR_NAMES:
1262*4882a593Smuzhiyun 				if (!allowxtarget && (e->attr & CEXPR_XTARGET))
1263*4882a593Smuzhiyun 					return -EINVAL;
1264*4882a593Smuzhiyun 				if (depth == (CEXPR_MAXDEPTH - 1))
1265*4882a593Smuzhiyun 					return -EINVAL;
1266*4882a593Smuzhiyun 				depth++;
1267*4882a593Smuzhiyun 				rc = ebitmap_read(&e->names, fp);
1268*4882a593Smuzhiyun 				if (rc)
1269*4882a593Smuzhiyun 					return rc;
1270*4882a593Smuzhiyun 				if (p->policyvers >=
1271*4882a593Smuzhiyun 				    POLICYDB_VERSION_CONSTRAINT_NAMES) {
1272*4882a593Smuzhiyun 					e->type_names = kzalloc(sizeof
1273*4882a593Smuzhiyun 						(*e->type_names), GFP_KERNEL);
1274*4882a593Smuzhiyun 					if (!e->type_names)
1275*4882a593Smuzhiyun 						return -ENOMEM;
1276*4882a593Smuzhiyun 					type_set_init(e->type_names);
1277*4882a593Smuzhiyun 					rc = type_set_read(e->type_names, fp);
1278*4882a593Smuzhiyun 					if (rc)
1279*4882a593Smuzhiyun 						return rc;
1280*4882a593Smuzhiyun 				}
1281*4882a593Smuzhiyun 				break;
1282*4882a593Smuzhiyun 			default:
1283*4882a593Smuzhiyun 				return -EINVAL;
1284*4882a593Smuzhiyun 			}
1285*4882a593Smuzhiyun 			le = e;
1286*4882a593Smuzhiyun 		}
1287*4882a593Smuzhiyun 		if (depth != 0)
1288*4882a593Smuzhiyun 			return -EINVAL;
1289*4882a593Smuzhiyun 		lc = c;
1290*4882a593Smuzhiyun 	}
1291*4882a593Smuzhiyun 
1292*4882a593Smuzhiyun 	return 0;
1293*4882a593Smuzhiyun }
1294*4882a593Smuzhiyun 
class_read(struct policydb * p,struct symtab * s,void * fp)1295*4882a593Smuzhiyun static int class_read(struct policydb *p, struct symtab *s, void *fp)
1296*4882a593Smuzhiyun {
1297*4882a593Smuzhiyun 	char *key = NULL;
1298*4882a593Smuzhiyun 	struct class_datum *cladatum;
1299*4882a593Smuzhiyun 	__le32 buf[6];
1300*4882a593Smuzhiyun 	u32 len, len2, ncons, nel;
1301*4882a593Smuzhiyun 	int i, rc;
1302*4882a593Smuzhiyun 
1303*4882a593Smuzhiyun 	cladatum = kzalloc(sizeof(*cladatum), GFP_KERNEL);
1304*4882a593Smuzhiyun 	if (!cladatum)
1305*4882a593Smuzhiyun 		return -ENOMEM;
1306*4882a593Smuzhiyun 
1307*4882a593Smuzhiyun 	rc = next_entry(buf, fp, sizeof(u32)*6);
1308*4882a593Smuzhiyun 	if (rc)
1309*4882a593Smuzhiyun 		goto bad;
1310*4882a593Smuzhiyun 
1311*4882a593Smuzhiyun 	len = le32_to_cpu(buf[0]);
1312*4882a593Smuzhiyun 	len2 = le32_to_cpu(buf[1]);
1313*4882a593Smuzhiyun 	cladatum->value = le32_to_cpu(buf[2]);
1314*4882a593Smuzhiyun 	nel = le32_to_cpu(buf[4]);
1315*4882a593Smuzhiyun 
1316*4882a593Smuzhiyun 	rc = symtab_init(&cladatum->permissions, nel);
1317*4882a593Smuzhiyun 	if (rc)
1318*4882a593Smuzhiyun 		goto bad;
1319*4882a593Smuzhiyun 	cladatum->permissions.nprim = le32_to_cpu(buf[3]);
1320*4882a593Smuzhiyun 
1321*4882a593Smuzhiyun 	ncons = le32_to_cpu(buf[5]);
1322*4882a593Smuzhiyun 
1323*4882a593Smuzhiyun 	rc = str_read(&key, GFP_KERNEL, fp, len);
1324*4882a593Smuzhiyun 	if (rc)
1325*4882a593Smuzhiyun 		goto bad;
1326*4882a593Smuzhiyun 
1327*4882a593Smuzhiyun 	if (len2) {
1328*4882a593Smuzhiyun 		rc = str_read(&cladatum->comkey, GFP_KERNEL, fp, len2);
1329*4882a593Smuzhiyun 		if (rc)
1330*4882a593Smuzhiyun 			goto bad;
1331*4882a593Smuzhiyun 
1332*4882a593Smuzhiyun 		rc = -EINVAL;
1333*4882a593Smuzhiyun 		cladatum->comdatum = symtab_search(&p->p_commons,
1334*4882a593Smuzhiyun 						   cladatum->comkey);
1335*4882a593Smuzhiyun 		if (!cladatum->comdatum) {
1336*4882a593Smuzhiyun 			pr_err("SELinux:  unknown common %s\n",
1337*4882a593Smuzhiyun 			       cladatum->comkey);
1338*4882a593Smuzhiyun 			goto bad;
1339*4882a593Smuzhiyun 		}
1340*4882a593Smuzhiyun 	}
1341*4882a593Smuzhiyun 	for (i = 0; i < nel; i++) {
1342*4882a593Smuzhiyun 		rc = perm_read(p, &cladatum->permissions, fp);
1343*4882a593Smuzhiyun 		if (rc)
1344*4882a593Smuzhiyun 			goto bad;
1345*4882a593Smuzhiyun 	}
1346*4882a593Smuzhiyun 
1347*4882a593Smuzhiyun 	rc = read_cons_helper(p, &cladatum->constraints, ncons, 0, fp);
1348*4882a593Smuzhiyun 	if (rc)
1349*4882a593Smuzhiyun 		goto bad;
1350*4882a593Smuzhiyun 
1351*4882a593Smuzhiyun 	if (p->policyvers >= POLICYDB_VERSION_VALIDATETRANS) {
1352*4882a593Smuzhiyun 		/* grab the validatetrans rules */
1353*4882a593Smuzhiyun 		rc = next_entry(buf, fp, sizeof(u32));
1354*4882a593Smuzhiyun 		if (rc)
1355*4882a593Smuzhiyun 			goto bad;
1356*4882a593Smuzhiyun 		ncons = le32_to_cpu(buf[0]);
1357*4882a593Smuzhiyun 		rc = read_cons_helper(p, &cladatum->validatetrans,
1358*4882a593Smuzhiyun 				ncons, 1, fp);
1359*4882a593Smuzhiyun 		if (rc)
1360*4882a593Smuzhiyun 			goto bad;
1361*4882a593Smuzhiyun 	}
1362*4882a593Smuzhiyun 
1363*4882a593Smuzhiyun 	if (p->policyvers >= POLICYDB_VERSION_NEW_OBJECT_DEFAULTS) {
1364*4882a593Smuzhiyun 		rc = next_entry(buf, fp, sizeof(u32) * 3);
1365*4882a593Smuzhiyun 		if (rc)
1366*4882a593Smuzhiyun 			goto bad;
1367*4882a593Smuzhiyun 
1368*4882a593Smuzhiyun 		cladatum->default_user = le32_to_cpu(buf[0]);
1369*4882a593Smuzhiyun 		cladatum->default_role = le32_to_cpu(buf[1]);
1370*4882a593Smuzhiyun 		cladatum->default_range = le32_to_cpu(buf[2]);
1371*4882a593Smuzhiyun 	}
1372*4882a593Smuzhiyun 
1373*4882a593Smuzhiyun 	if (p->policyvers >= POLICYDB_VERSION_DEFAULT_TYPE) {
1374*4882a593Smuzhiyun 		rc = next_entry(buf, fp, sizeof(u32) * 1);
1375*4882a593Smuzhiyun 		if (rc)
1376*4882a593Smuzhiyun 			goto bad;
1377*4882a593Smuzhiyun 		cladatum->default_type = le32_to_cpu(buf[0]);
1378*4882a593Smuzhiyun 	}
1379*4882a593Smuzhiyun 
1380*4882a593Smuzhiyun 	rc = symtab_insert(s, key, cladatum);
1381*4882a593Smuzhiyun 	if (rc)
1382*4882a593Smuzhiyun 		goto bad;
1383*4882a593Smuzhiyun 
1384*4882a593Smuzhiyun 	return 0;
1385*4882a593Smuzhiyun bad:
1386*4882a593Smuzhiyun 	cls_destroy(key, cladatum, NULL);
1387*4882a593Smuzhiyun 	return rc;
1388*4882a593Smuzhiyun }
1389*4882a593Smuzhiyun 
role_read(struct policydb * p,struct symtab * s,void * fp)1390*4882a593Smuzhiyun static int role_read(struct policydb *p, struct symtab *s, void *fp)
1391*4882a593Smuzhiyun {
1392*4882a593Smuzhiyun 	char *key = NULL;
1393*4882a593Smuzhiyun 	struct role_datum *role;
1394*4882a593Smuzhiyun 	int rc, to_read = 2;
1395*4882a593Smuzhiyun 	__le32 buf[3];
1396*4882a593Smuzhiyun 	u32 len;
1397*4882a593Smuzhiyun 
1398*4882a593Smuzhiyun 	role = kzalloc(sizeof(*role), GFP_KERNEL);
1399*4882a593Smuzhiyun 	if (!role)
1400*4882a593Smuzhiyun 		return -ENOMEM;
1401*4882a593Smuzhiyun 
1402*4882a593Smuzhiyun 	if (p->policyvers >= POLICYDB_VERSION_BOUNDARY)
1403*4882a593Smuzhiyun 		to_read = 3;
1404*4882a593Smuzhiyun 
1405*4882a593Smuzhiyun 	rc = next_entry(buf, fp, sizeof(buf[0]) * to_read);
1406*4882a593Smuzhiyun 	if (rc)
1407*4882a593Smuzhiyun 		goto bad;
1408*4882a593Smuzhiyun 
1409*4882a593Smuzhiyun 	len = le32_to_cpu(buf[0]);
1410*4882a593Smuzhiyun 	role->value = le32_to_cpu(buf[1]);
1411*4882a593Smuzhiyun 	if (p->policyvers >= POLICYDB_VERSION_BOUNDARY)
1412*4882a593Smuzhiyun 		role->bounds = le32_to_cpu(buf[2]);
1413*4882a593Smuzhiyun 
1414*4882a593Smuzhiyun 	rc = str_read(&key, GFP_KERNEL, fp, len);
1415*4882a593Smuzhiyun 	if (rc)
1416*4882a593Smuzhiyun 		goto bad;
1417*4882a593Smuzhiyun 
1418*4882a593Smuzhiyun 	rc = ebitmap_read(&role->dominates, fp);
1419*4882a593Smuzhiyun 	if (rc)
1420*4882a593Smuzhiyun 		goto bad;
1421*4882a593Smuzhiyun 
1422*4882a593Smuzhiyun 	rc = ebitmap_read(&role->types, fp);
1423*4882a593Smuzhiyun 	if (rc)
1424*4882a593Smuzhiyun 		goto bad;
1425*4882a593Smuzhiyun 
1426*4882a593Smuzhiyun 	if (strcmp(key, OBJECT_R) == 0) {
1427*4882a593Smuzhiyun 		rc = -EINVAL;
1428*4882a593Smuzhiyun 		if (role->value != OBJECT_R_VAL) {
1429*4882a593Smuzhiyun 			pr_err("SELinux: Role %s has wrong value %d\n",
1430*4882a593Smuzhiyun 			       OBJECT_R, role->value);
1431*4882a593Smuzhiyun 			goto bad;
1432*4882a593Smuzhiyun 		}
1433*4882a593Smuzhiyun 		rc = 0;
1434*4882a593Smuzhiyun 		goto bad;
1435*4882a593Smuzhiyun 	}
1436*4882a593Smuzhiyun 
1437*4882a593Smuzhiyun 	rc = symtab_insert(s, key, role);
1438*4882a593Smuzhiyun 	if (rc)
1439*4882a593Smuzhiyun 		goto bad;
1440*4882a593Smuzhiyun 	return 0;
1441*4882a593Smuzhiyun bad:
1442*4882a593Smuzhiyun 	role_destroy(key, role, NULL);
1443*4882a593Smuzhiyun 	return rc;
1444*4882a593Smuzhiyun }
1445*4882a593Smuzhiyun 
type_read(struct policydb * p,struct symtab * s,void * fp)1446*4882a593Smuzhiyun static int type_read(struct policydb *p, struct symtab *s, void *fp)
1447*4882a593Smuzhiyun {
1448*4882a593Smuzhiyun 	char *key = NULL;
1449*4882a593Smuzhiyun 	struct type_datum *typdatum;
1450*4882a593Smuzhiyun 	int rc, to_read = 3;
1451*4882a593Smuzhiyun 	__le32 buf[4];
1452*4882a593Smuzhiyun 	u32 len;
1453*4882a593Smuzhiyun 
1454*4882a593Smuzhiyun 	typdatum = kzalloc(sizeof(*typdatum), GFP_KERNEL);
1455*4882a593Smuzhiyun 	if (!typdatum)
1456*4882a593Smuzhiyun 		return -ENOMEM;
1457*4882a593Smuzhiyun 
1458*4882a593Smuzhiyun 	if (p->policyvers >= POLICYDB_VERSION_BOUNDARY)
1459*4882a593Smuzhiyun 		to_read = 4;
1460*4882a593Smuzhiyun 
1461*4882a593Smuzhiyun 	rc = next_entry(buf, fp, sizeof(buf[0]) * to_read);
1462*4882a593Smuzhiyun 	if (rc)
1463*4882a593Smuzhiyun 		goto bad;
1464*4882a593Smuzhiyun 
1465*4882a593Smuzhiyun 	len = le32_to_cpu(buf[0]);
1466*4882a593Smuzhiyun 	typdatum->value = le32_to_cpu(buf[1]);
1467*4882a593Smuzhiyun 	if (p->policyvers >= POLICYDB_VERSION_BOUNDARY) {
1468*4882a593Smuzhiyun 		u32 prop = le32_to_cpu(buf[2]);
1469*4882a593Smuzhiyun 
1470*4882a593Smuzhiyun 		if (prop & TYPEDATUM_PROPERTY_PRIMARY)
1471*4882a593Smuzhiyun 			typdatum->primary = 1;
1472*4882a593Smuzhiyun 		if (prop & TYPEDATUM_PROPERTY_ATTRIBUTE)
1473*4882a593Smuzhiyun 			typdatum->attribute = 1;
1474*4882a593Smuzhiyun 
1475*4882a593Smuzhiyun 		typdatum->bounds = le32_to_cpu(buf[3]);
1476*4882a593Smuzhiyun 	} else {
1477*4882a593Smuzhiyun 		typdatum->primary = le32_to_cpu(buf[2]);
1478*4882a593Smuzhiyun 	}
1479*4882a593Smuzhiyun 
1480*4882a593Smuzhiyun 	rc = str_read(&key, GFP_KERNEL, fp, len);
1481*4882a593Smuzhiyun 	if (rc)
1482*4882a593Smuzhiyun 		goto bad;
1483*4882a593Smuzhiyun 
1484*4882a593Smuzhiyun 	rc = symtab_insert(s, key, typdatum);
1485*4882a593Smuzhiyun 	if (rc)
1486*4882a593Smuzhiyun 		goto bad;
1487*4882a593Smuzhiyun 	return 0;
1488*4882a593Smuzhiyun bad:
1489*4882a593Smuzhiyun 	type_destroy(key, typdatum, NULL);
1490*4882a593Smuzhiyun 	return rc;
1491*4882a593Smuzhiyun }
1492*4882a593Smuzhiyun 
1493*4882a593Smuzhiyun 
1494*4882a593Smuzhiyun /*
1495*4882a593Smuzhiyun  * Read a MLS level structure from a policydb binary
1496*4882a593Smuzhiyun  * representation file.
1497*4882a593Smuzhiyun  */
mls_read_level(struct mls_level * lp,void * fp)1498*4882a593Smuzhiyun static int mls_read_level(struct mls_level *lp, void *fp)
1499*4882a593Smuzhiyun {
1500*4882a593Smuzhiyun 	__le32 buf[1];
1501*4882a593Smuzhiyun 	int rc;
1502*4882a593Smuzhiyun 
1503*4882a593Smuzhiyun 	memset(lp, 0, sizeof(*lp));
1504*4882a593Smuzhiyun 
1505*4882a593Smuzhiyun 	rc = next_entry(buf, fp, sizeof buf);
1506*4882a593Smuzhiyun 	if (rc) {
1507*4882a593Smuzhiyun 		pr_err("SELinux: mls: truncated level\n");
1508*4882a593Smuzhiyun 		return rc;
1509*4882a593Smuzhiyun 	}
1510*4882a593Smuzhiyun 	lp->sens = le32_to_cpu(buf[0]);
1511*4882a593Smuzhiyun 
1512*4882a593Smuzhiyun 	rc = ebitmap_read(&lp->cat, fp);
1513*4882a593Smuzhiyun 	if (rc) {
1514*4882a593Smuzhiyun 		pr_err("SELinux: mls:  error reading level categories\n");
1515*4882a593Smuzhiyun 		return rc;
1516*4882a593Smuzhiyun 	}
1517*4882a593Smuzhiyun 	return 0;
1518*4882a593Smuzhiyun }
1519*4882a593Smuzhiyun 
user_read(struct policydb * p,struct symtab * s,void * fp)1520*4882a593Smuzhiyun static int user_read(struct policydb *p, struct symtab *s, void *fp)
1521*4882a593Smuzhiyun {
1522*4882a593Smuzhiyun 	char *key = NULL;
1523*4882a593Smuzhiyun 	struct user_datum *usrdatum;
1524*4882a593Smuzhiyun 	int rc, to_read = 2;
1525*4882a593Smuzhiyun 	__le32 buf[3];
1526*4882a593Smuzhiyun 	u32 len;
1527*4882a593Smuzhiyun 
1528*4882a593Smuzhiyun 	usrdatum = kzalloc(sizeof(*usrdatum), GFP_KERNEL);
1529*4882a593Smuzhiyun 	if (!usrdatum)
1530*4882a593Smuzhiyun 		return -ENOMEM;
1531*4882a593Smuzhiyun 
1532*4882a593Smuzhiyun 	if (p->policyvers >= POLICYDB_VERSION_BOUNDARY)
1533*4882a593Smuzhiyun 		to_read = 3;
1534*4882a593Smuzhiyun 
1535*4882a593Smuzhiyun 	rc = next_entry(buf, fp, sizeof(buf[0]) * to_read);
1536*4882a593Smuzhiyun 	if (rc)
1537*4882a593Smuzhiyun 		goto bad;
1538*4882a593Smuzhiyun 
1539*4882a593Smuzhiyun 	len = le32_to_cpu(buf[0]);
1540*4882a593Smuzhiyun 	usrdatum->value = le32_to_cpu(buf[1]);
1541*4882a593Smuzhiyun 	if (p->policyvers >= POLICYDB_VERSION_BOUNDARY)
1542*4882a593Smuzhiyun 		usrdatum->bounds = le32_to_cpu(buf[2]);
1543*4882a593Smuzhiyun 
1544*4882a593Smuzhiyun 	rc = str_read(&key, GFP_KERNEL, fp, len);
1545*4882a593Smuzhiyun 	if (rc)
1546*4882a593Smuzhiyun 		goto bad;
1547*4882a593Smuzhiyun 
1548*4882a593Smuzhiyun 	rc = ebitmap_read(&usrdatum->roles, fp);
1549*4882a593Smuzhiyun 	if (rc)
1550*4882a593Smuzhiyun 		goto bad;
1551*4882a593Smuzhiyun 
1552*4882a593Smuzhiyun 	if (p->policyvers >= POLICYDB_VERSION_MLS) {
1553*4882a593Smuzhiyun 		rc = mls_read_range_helper(&usrdatum->range, fp);
1554*4882a593Smuzhiyun 		if (rc)
1555*4882a593Smuzhiyun 			goto bad;
1556*4882a593Smuzhiyun 		rc = mls_read_level(&usrdatum->dfltlevel, fp);
1557*4882a593Smuzhiyun 		if (rc)
1558*4882a593Smuzhiyun 			goto bad;
1559*4882a593Smuzhiyun 	}
1560*4882a593Smuzhiyun 
1561*4882a593Smuzhiyun 	rc = symtab_insert(s, key, usrdatum);
1562*4882a593Smuzhiyun 	if (rc)
1563*4882a593Smuzhiyun 		goto bad;
1564*4882a593Smuzhiyun 	return 0;
1565*4882a593Smuzhiyun bad:
1566*4882a593Smuzhiyun 	user_destroy(key, usrdatum, NULL);
1567*4882a593Smuzhiyun 	return rc;
1568*4882a593Smuzhiyun }
1569*4882a593Smuzhiyun 
sens_read(struct policydb * p,struct symtab * s,void * fp)1570*4882a593Smuzhiyun static int sens_read(struct policydb *p, struct symtab *s, void *fp)
1571*4882a593Smuzhiyun {
1572*4882a593Smuzhiyun 	char *key = NULL;
1573*4882a593Smuzhiyun 	struct level_datum *levdatum;
1574*4882a593Smuzhiyun 	int rc;
1575*4882a593Smuzhiyun 	__le32 buf[2];
1576*4882a593Smuzhiyun 	u32 len;
1577*4882a593Smuzhiyun 
1578*4882a593Smuzhiyun 	levdatum = kzalloc(sizeof(*levdatum), GFP_ATOMIC);
1579*4882a593Smuzhiyun 	if (!levdatum)
1580*4882a593Smuzhiyun 		return -ENOMEM;
1581*4882a593Smuzhiyun 
1582*4882a593Smuzhiyun 	rc = next_entry(buf, fp, sizeof buf);
1583*4882a593Smuzhiyun 	if (rc)
1584*4882a593Smuzhiyun 		goto bad;
1585*4882a593Smuzhiyun 
1586*4882a593Smuzhiyun 	len = le32_to_cpu(buf[0]);
1587*4882a593Smuzhiyun 	levdatum->isalias = le32_to_cpu(buf[1]);
1588*4882a593Smuzhiyun 
1589*4882a593Smuzhiyun 	rc = str_read(&key, GFP_ATOMIC, fp, len);
1590*4882a593Smuzhiyun 	if (rc)
1591*4882a593Smuzhiyun 		goto bad;
1592*4882a593Smuzhiyun 
1593*4882a593Smuzhiyun 	rc = -ENOMEM;
1594*4882a593Smuzhiyun 	levdatum->level = kmalloc(sizeof(*levdatum->level), GFP_ATOMIC);
1595*4882a593Smuzhiyun 	if (!levdatum->level)
1596*4882a593Smuzhiyun 		goto bad;
1597*4882a593Smuzhiyun 
1598*4882a593Smuzhiyun 	rc = mls_read_level(levdatum->level, fp);
1599*4882a593Smuzhiyun 	if (rc)
1600*4882a593Smuzhiyun 		goto bad;
1601*4882a593Smuzhiyun 
1602*4882a593Smuzhiyun 	rc = symtab_insert(s, key, levdatum);
1603*4882a593Smuzhiyun 	if (rc)
1604*4882a593Smuzhiyun 		goto bad;
1605*4882a593Smuzhiyun 	return 0;
1606*4882a593Smuzhiyun bad:
1607*4882a593Smuzhiyun 	sens_destroy(key, levdatum, NULL);
1608*4882a593Smuzhiyun 	return rc;
1609*4882a593Smuzhiyun }
1610*4882a593Smuzhiyun 
cat_read(struct policydb * p,struct symtab * s,void * fp)1611*4882a593Smuzhiyun static int cat_read(struct policydb *p, struct symtab *s, void *fp)
1612*4882a593Smuzhiyun {
1613*4882a593Smuzhiyun 	char *key = NULL;
1614*4882a593Smuzhiyun 	struct cat_datum *catdatum;
1615*4882a593Smuzhiyun 	int rc;
1616*4882a593Smuzhiyun 	__le32 buf[3];
1617*4882a593Smuzhiyun 	u32 len;
1618*4882a593Smuzhiyun 
1619*4882a593Smuzhiyun 	catdatum = kzalloc(sizeof(*catdatum), GFP_ATOMIC);
1620*4882a593Smuzhiyun 	if (!catdatum)
1621*4882a593Smuzhiyun 		return -ENOMEM;
1622*4882a593Smuzhiyun 
1623*4882a593Smuzhiyun 	rc = next_entry(buf, fp, sizeof buf);
1624*4882a593Smuzhiyun 	if (rc)
1625*4882a593Smuzhiyun 		goto bad;
1626*4882a593Smuzhiyun 
1627*4882a593Smuzhiyun 	len = le32_to_cpu(buf[0]);
1628*4882a593Smuzhiyun 	catdatum->value = le32_to_cpu(buf[1]);
1629*4882a593Smuzhiyun 	catdatum->isalias = le32_to_cpu(buf[2]);
1630*4882a593Smuzhiyun 
1631*4882a593Smuzhiyun 	rc = str_read(&key, GFP_ATOMIC, fp, len);
1632*4882a593Smuzhiyun 	if (rc)
1633*4882a593Smuzhiyun 		goto bad;
1634*4882a593Smuzhiyun 
1635*4882a593Smuzhiyun 	rc = symtab_insert(s, key, catdatum);
1636*4882a593Smuzhiyun 	if (rc)
1637*4882a593Smuzhiyun 		goto bad;
1638*4882a593Smuzhiyun 	return 0;
1639*4882a593Smuzhiyun bad:
1640*4882a593Smuzhiyun 	cat_destroy(key, catdatum, NULL);
1641*4882a593Smuzhiyun 	return rc;
1642*4882a593Smuzhiyun }
1643*4882a593Smuzhiyun 
1644*4882a593Smuzhiyun static int (*read_f[SYM_NUM]) (struct policydb *p, struct symtab *s, void *fp) =
1645*4882a593Smuzhiyun {
1646*4882a593Smuzhiyun 	common_read,
1647*4882a593Smuzhiyun 	class_read,
1648*4882a593Smuzhiyun 	role_read,
1649*4882a593Smuzhiyun 	type_read,
1650*4882a593Smuzhiyun 	user_read,
1651*4882a593Smuzhiyun 	cond_read_bool,
1652*4882a593Smuzhiyun 	sens_read,
1653*4882a593Smuzhiyun 	cat_read,
1654*4882a593Smuzhiyun };
1655*4882a593Smuzhiyun 
user_bounds_sanity_check(void * key,void * datum,void * datap)1656*4882a593Smuzhiyun static int user_bounds_sanity_check(void *key, void *datum, void *datap)
1657*4882a593Smuzhiyun {
1658*4882a593Smuzhiyun 	struct user_datum *upper, *user;
1659*4882a593Smuzhiyun 	struct policydb *p = datap;
1660*4882a593Smuzhiyun 	int depth = 0;
1661*4882a593Smuzhiyun 
1662*4882a593Smuzhiyun 	upper = user = datum;
1663*4882a593Smuzhiyun 	while (upper->bounds) {
1664*4882a593Smuzhiyun 		struct ebitmap_node *node;
1665*4882a593Smuzhiyun 		unsigned long bit;
1666*4882a593Smuzhiyun 
1667*4882a593Smuzhiyun 		if (++depth == POLICYDB_BOUNDS_MAXDEPTH) {
1668*4882a593Smuzhiyun 			pr_err("SELinux: user %s: "
1669*4882a593Smuzhiyun 			       "too deep or looped boundary",
1670*4882a593Smuzhiyun 			       (char *) key);
1671*4882a593Smuzhiyun 			return -EINVAL;
1672*4882a593Smuzhiyun 		}
1673*4882a593Smuzhiyun 
1674*4882a593Smuzhiyun 		upper = p->user_val_to_struct[upper->bounds - 1];
1675*4882a593Smuzhiyun 		ebitmap_for_each_positive_bit(&user->roles, node, bit) {
1676*4882a593Smuzhiyun 			if (ebitmap_get_bit(&upper->roles, bit))
1677*4882a593Smuzhiyun 				continue;
1678*4882a593Smuzhiyun 
1679*4882a593Smuzhiyun 			pr_err("SELinux: boundary violated policy: "
1680*4882a593Smuzhiyun 			       "user=%s role=%s bounds=%s\n",
1681*4882a593Smuzhiyun 			       sym_name(p, SYM_USERS, user->value - 1),
1682*4882a593Smuzhiyun 			       sym_name(p, SYM_ROLES, bit),
1683*4882a593Smuzhiyun 			       sym_name(p, SYM_USERS, upper->value - 1));
1684*4882a593Smuzhiyun 
1685*4882a593Smuzhiyun 			return -EINVAL;
1686*4882a593Smuzhiyun 		}
1687*4882a593Smuzhiyun 	}
1688*4882a593Smuzhiyun 
1689*4882a593Smuzhiyun 	return 0;
1690*4882a593Smuzhiyun }
1691*4882a593Smuzhiyun 
role_bounds_sanity_check(void * key,void * datum,void * datap)1692*4882a593Smuzhiyun static int role_bounds_sanity_check(void *key, void *datum, void *datap)
1693*4882a593Smuzhiyun {
1694*4882a593Smuzhiyun 	struct role_datum *upper, *role;
1695*4882a593Smuzhiyun 	struct policydb *p = datap;
1696*4882a593Smuzhiyun 	int depth = 0;
1697*4882a593Smuzhiyun 
1698*4882a593Smuzhiyun 	upper = role = datum;
1699*4882a593Smuzhiyun 	while (upper->bounds) {
1700*4882a593Smuzhiyun 		struct ebitmap_node *node;
1701*4882a593Smuzhiyun 		unsigned long bit;
1702*4882a593Smuzhiyun 
1703*4882a593Smuzhiyun 		if (++depth == POLICYDB_BOUNDS_MAXDEPTH) {
1704*4882a593Smuzhiyun 			pr_err("SELinux: role %s: "
1705*4882a593Smuzhiyun 			       "too deep or looped bounds\n",
1706*4882a593Smuzhiyun 			       (char *) key);
1707*4882a593Smuzhiyun 			return -EINVAL;
1708*4882a593Smuzhiyun 		}
1709*4882a593Smuzhiyun 
1710*4882a593Smuzhiyun 		upper = p->role_val_to_struct[upper->bounds - 1];
1711*4882a593Smuzhiyun 		ebitmap_for_each_positive_bit(&role->types, node, bit) {
1712*4882a593Smuzhiyun 			if (ebitmap_get_bit(&upper->types, bit))
1713*4882a593Smuzhiyun 				continue;
1714*4882a593Smuzhiyun 
1715*4882a593Smuzhiyun 			pr_err("SELinux: boundary violated policy: "
1716*4882a593Smuzhiyun 			       "role=%s type=%s bounds=%s\n",
1717*4882a593Smuzhiyun 			       sym_name(p, SYM_ROLES, role->value - 1),
1718*4882a593Smuzhiyun 			       sym_name(p, SYM_TYPES, bit),
1719*4882a593Smuzhiyun 			       sym_name(p, SYM_ROLES, upper->value - 1));
1720*4882a593Smuzhiyun 
1721*4882a593Smuzhiyun 			return -EINVAL;
1722*4882a593Smuzhiyun 		}
1723*4882a593Smuzhiyun 	}
1724*4882a593Smuzhiyun 
1725*4882a593Smuzhiyun 	return 0;
1726*4882a593Smuzhiyun }
1727*4882a593Smuzhiyun 
type_bounds_sanity_check(void * key,void * datum,void * datap)1728*4882a593Smuzhiyun static int type_bounds_sanity_check(void *key, void *datum, void *datap)
1729*4882a593Smuzhiyun {
1730*4882a593Smuzhiyun 	struct type_datum *upper;
1731*4882a593Smuzhiyun 	struct policydb *p = datap;
1732*4882a593Smuzhiyun 	int depth = 0;
1733*4882a593Smuzhiyun 
1734*4882a593Smuzhiyun 	upper = datum;
1735*4882a593Smuzhiyun 	while (upper->bounds) {
1736*4882a593Smuzhiyun 		if (++depth == POLICYDB_BOUNDS_MAXDEPTH) {
1737*4882a593Smuzhiyun 			pr_err("SELinux: type %s: "
1738*4882a593Smuzhiyun 			       "too deep or looped boundary\n",
1739*4882a593Smuzhiyun 			       (char *) key);
1740*4882a593Smuzhiyun 			return -EINVAL;
1741*4882a593Smuzhiyun 		}
1742*4882a593Smuzhiyun 
1743*4882a593Smuzhiyun 		upper = p->type_val_to_struct[upper->bounds - 1];
1744*4882a593Smuzhiyun 		BUG_ON(!upper);
1745*4882a593Smuzhiyun 
1746*4882a593Smuzhiyun 		if (upper->attribute) {
1747*4882a593Smuzhiyun 			pr_err("SELinux: type %s: "
1748*4882a593Smuzhiyun 			       "bounded by attribute %s",
1749*4882a593Smuzhiyun 			       (char *) key,
1750*4882a593Smuzhiyun 			       sym_name(p, SYM_TYPES, upper->value - 1));
1751*4882a593Smuzhiyun 			return -EINVAL;
1752*4882a593Smuzhiyun 		}
1753*4882a593Smuzhiyun 	}
1754*4882a593Smuzhiyun 
1755*4882a593Smuzhiyun 	return 0;
1756*4882a593Smuzhiyun }
1757*4882a593Smuzhiyun 
policydb_bounds_sanity_check(struct policydb * p)1758*4882a593Smuzhiyun static int policydb_bounds_sanity_check(struct policydb *p)
1759*4882a593Smuzhiyun {
1760*4882a593Smuzhiyun 	int rc;
1761*4882a593Smuzhiyun 
1762*4882a593Smuzhiyun 	if (p->policyvers < POLICYDB_VERSION_BOUNDARY)
1763*4882a593Smuzhiyun 		return 0;
1764*4882a593Smuzhiyun 
1765*4882a593Smuzhiyun 	rc = hashtab_map(&p->p_users.table, user_bounds_sanity_check, p);
1766*4882a593Smuzhiyun 	if (rc)
1767*4882a593Smuzhiyun 		return rc;
1768*4882a593Smuzhiyun 
1769*4882a593Smuzhiyun 	rc = hashtab_map(&p->p_roles.table, role_bounds_sanity_check, p);
1770*4882a593Smuzhiyun 	if (rc)
1771*4882a593Smuzhiyun 		return rc;
1772*4882a593Smuzhiyun 
1773*4882a593Smuzhiyun 	rc = hashtab_map(&p->p_types.table, type_bounds_sanity_check, p);
1774*4882a593Smuzhiyun 	if (rc)
1775*4882a593Smuzhiyun 		return rc;
1776*4882a593Smuzhiyun 
1777*4882a593Smuzhiyun 	return 0;
1778*4882a593Smuzhiyun }
1779*4882a593Smuzhiyun 
string_to_security_class(struct policydb * p,const char * name)1780*4882a593Smuzhiyun u16 string_to_security_class(struct policydb *p, const char *name)
1781*4882a593Smuzhiyun {
1782*4882a593Smuzhiyun 	struct class_datum *cladatum;
1783*4882a593Smuzhiyun 
1784*4882a593Smuzhiyun 	cladatum = symtab_search(&p->p_classes, name);
1785*4882a593Smuzhiyun 	if (!cladatum)
1786*4882a593Smuzhiyun 		return 0;
1787*4882a593Smuzhiyun 
1788*4882a593Smuzhiyun 	return cladatum->value;
1789*4882a593Smuzhiyun }
1790*4882a593Smuzhiyun 
string_to_av_perm(struct policydb * p,u16 tclass,const char * name)1791*4882a593Smuzhiyun u32 string_to_av_perm(struct policydb *p, u16 tclass, const char *name)
1792*4882a593Smuzhiyun {
1793*4882a593Smuzhiyun 	struct class_datum *cladatum;
1794*4882a593Smuzhiyun 	struct perm_datum *perdatum = NULL;
1795*4882a593Smuzhiyun 	struct common_datum *comdatum;
1796*4882a593Smuzhiyun 
1797*4882a593Smuzhiyun 	if (!tclass || tclass > p->p_classes.nprim)
1798*4882a593Smuzhiyun 		return 0;
1799*4882a593Smuzhiyun 
1800*4882a593Smuzhiyun 	cladatum = p->class_val_to_struct[tclass-1];
1801*4882a593Smuzhiyun 	comdatum = cladatum->comdatum;
1802*4882a593Smuzhiyun 	if (comdatum)
1803*4882a593Smuzhiyun 		perdatum = symtab_search(&comdatum->permissions, name);
1804*4882a593Smuzhiyun 	if (!perdatum)
1805*4882a593Smuzhiyun 		perdatum = symtab_search(&cladatum->permissions, name);
1806*4882a593Smuzhiyun 	if (!perdatum)
1807*4882a593Smuzhiyun 		return 0;
1808*4882a593Smuzhiyun 
1809*4882a593Smuzhiyun 	return 1U << (perdatum->value-1);
1810*4882a593Smuzhiyun }
1811*4882a593Smuzhiyun 
range_read(struct policydb * p,void * fp)1812*4882a593Smuzhiyun static int range_read(struct policydb *p, void *fp)
1813*4882a593Smuzhiyun {
1814*4882a593Smuzhiyun 	struct range_trans *rt = NULL;
1815*4882a593Smuzhiyun 	struct mls_range *r = NULL;
1816*4882a593Smuzhiyun 	int i, rc;
1817*4882a593Smuzhiyun 	__le32 buf[2];
1818*4882a593Smuzhiyun 	u32 nel;
1819*4882a593Smuzhiyun 
1820*4882a593Smuzhiyun 	if (p->policyvers < POLICYDB_VERSION_MLS)
1821*4882a593Smuzhiyun 		return 0;
1822*4882a593Smuzhiyun 
1823*4882a593Smuzhiyun 	rc = next_entry(buf, fp, sizeof(u32));
1824*4882a593Smuzhiyun 	if (rc)
1825*4882a593Smuzhiyun 		return rc;
1826*4882a593Smuzhiyun 
1827*4882a593Smuzhiyun 	nel = le32_to_cpu(buf[0]);
1828*4882a593Smuzhiyun 
1829*4882a593Smuzhiyun 	rc = hashtab_init(&p->range_tr, nel);
1830*4882a593Smuzhiyun 	if (rc)
1831*4882a593Smuzhiyun 		return rc;
1832*4882a593Smuzhiyun 
1833*4882a593Smuzhiyun 	for (i = 0; i < nel; i++) {
1834*4882a593Smuzhiyun 		rc = -ENOMEM;
1835*4882a593Smuzhiyun 		rt = kzalloc(sizeof(*rt), GFP_KERNEL);
1836*4882a593Smuzhiyun 		if (!rt)
1837*4882a593Smuzhiyun 			goto out;
1838*4882a593Smuzhiyun 
1839*4882a593Smuzhiyun 		rc = next_entry(buf, fp, (sizeof(u32) * 2));
1840*4882a593Smuzhiyun 		if (rc)
1841*4882a593Smuzhiyun 			goto out;
1842*4882a593Smuzhiyun 
1843*4882a593Smuzhiyun 		rt->source_type = le32_to_cpu(buf[0]);
1844*4882a593Smuzhiyun 		rt->target_type = le32_to_cpu(buf[1]);
1845*4882a593Smuzhiyun 		if (p->policyvers >= POLICYDB_VERSION_RANGETRANS) {
1846*4882a593Smuzhiyun 			rc = next_entry(buf, fp, sizeof(u32));
1847*4882a593Smuzhiyun 			if (rc)
1848*4882a593Smuzhiyun 				goto out;
1849*4882a593Smuzhiyun 			rt->target_class = le32_to_cpu(buf[0]);
1850*4882a593Smuzhiyun 		} else
1851*4882a593Smuzhiyun 			rt->target_class = p->process_class;
1852*4882a593Smuzhiyun 
1853*4882a593Smuzhiyun 		rc = -EINVAL;
1854*4882a593Smuzhiyun 		if (!policydb_type_isvalid(p, rt->source_type) ||
1855*4882a593Smuzhiyun 		    !policydb_type_isvalid(p, rt->target_type) ||
1856*4882a593Smuzhiyun 		    !policydb_class_isvalid(p, rt->target_class))
1857*4882a593Smuzhiyun 			goto out;
1858*4882a593Smuzhiyun 
1859*4882a593Smuzhiyun 		rc = -ENOMEM;
1860*4882a593Smuzhiyun 		r = kzalloc(sizeof(*r), GFP_KERNEL);
1861*4882a593Smuzhiyun 		if (!r)
1862*4882a593Smuzhiyun 			goto out;
1863*4882a593Smuzhiyun 
1864*4882a593Smuzhiyun 		rc = mls_read_range_helper(r, fp);
1865*4882a593Smuzhiyun 		if (rc)
1866*4882a593Smuzhiyun 			goto out;
1867*4882a593Smuzhiyun 
1868*4882a593Smuzhiyun 		rc = -EINVAL;
1869*4882a593Smuzhiyun 		if (!mls_range_isvalid(p, r)) {
1870*4882a593Smuzhiyun 			pr_warn("SELinux:  rangetrans:  invalid range\n");
1871*4882a593Smuzhiyun 			goto out;
1872*4882a593Smuzhiyun 		}
1873*4882a593Smuzhiyun 
1874*4882a593Smuzhiyun 		rc = hashtab_insert(&p->range_tr, rt, r, rangetr_key_params);
1875*4882a593Smuzhiyun 		if (rc)
1876*4882a593Smuzhiyun 			goto out;
1877*4882a593Smuzhiyun 
1878*4882a593Smuzhiyun 		rt = NULL;
1879*4882a593Smuzhiyun 		r = NULL;
1880*4882a593Smuzhiyun 	}
1881*4882a593Smuzhiyun 	hash_eval(&p->range_tr, "rangetr");
1882*4882a593Smuzhiyun 	rc = 0;
1883*4882a593Smuzhiyun out:
1884*4882a593Smuzhiyun 	kfree(rt);
1885*4882a593Smuzhiyun 	kfree(r);
1886*4882a593Smuzhiyun 	return rc;
1887*4882a593Smuzhiyun }
1888*4882a593Smuzhiyun 
filename_trans_read_helper_compat(struct policydb * p,void * fp)1889*4882a593Smuzhiyun static int filename_trans_read_helper_compat(struct policydb *p, void *fp)
1890*4882a593Smuzhiyun {
1891*4882a593Smuzhiyun 	struct filename_trans_key key, *ft = NULL;
1892*4882a593Smuzhiyun 	struct filename_trans_datum *last, *datum = NULL;
1893*4882a593Smuzhiyun 	char *name = NULL;
1894*4882a593Smuzhiyun 	u32 len, stype, otype;
1895*4882a593Smuzhiyun 	__le32 buf[4];
1896*4882a593Smuzhiyun 	int rc;
1897*4882a593Smuzhiyun 
1898*4882a593Smuzhiyun 	/* length of the path component string */
1899*4882a593Smuzhiyun 	rc = next_entry(buf, fp, sizeof(u32));
1900*4882a593Smuzhiyun 	if (rc)
1901*4882a593Smuzhiyun 		return rc;
1902*4882a593Smuzhiyun 	len = le32_to_cpu(buf[0]);
1903*4882a593Smuzhiyun 
1904*4882a593Smuzhiyun 	/* path component string */
1905*4882a593Smuzhiyun 	rc = str_read(&name, GFP_KERNEL, fp, len);
1906*4882a593Smuzhiyun 	if (rc)
1907*4882a593Smuzhiyun 		return rc;
1908*4882a593Smuzhiyun 
1909*4882a593Smuzhiyun 	rc = next_entry(buf, fp, sizeof(u32) * 4);
1910*4882a593Smuzhiyun 	if (rc)
1911*4882a593Smuzhiyun 		goto out;
1912*4882a593Smuzhiyun 
1913*4882a593Smuzhiyun 	stype = le32_to_cpu(buf[0]);
1914*4882a593Smuzhiyun 	key.ttype = le32_to_cpu(buf[1]);
1915*4882a593Smuzhiyun 	key.tclass = le32_to_cpu(buf[2]);
1916*4882a593Smuzhiyun 	key.name = name;
1917*4882a593Smuzhiyun 
1918*4882a593Smuzhiyun 	otype = le32_to_cpu(buf[3]);
1919*4882a593Smuzhiyun 
1920*4882a593Smuzhiyun 	last = NULL;
1921*4882a593Smuzhiyun 	datum = policydb_filenametr_search(p, &key);
1922*4882a593Smuzhiyun 	while (datum) {
1923*4882a593Smuzhiyun 		if (unlikely(ebitmap_get_bit(&datum->stypes, stype - 1))) {
1924*4882a593Smuzhiyun 			/* conflicting/duplicate rules are ignored */
1925*4882a593Smuzhiyun 			datum = NULL;
1926*4882a593Smuzhiyun 			goto out;
1927*4882a593Smuzhiyun 		}
1928*4882a593Smuzhiyun 		if (likely(datum->otype == otype))
1929*4882a593Smuzhiyun 			break;
1930*4882a593Smuzhiyun 		last = datum;
1931*4882a593Smuzhiyun 		datum = datum->next;
1932*4882a593Smuzhiyun 	}
1933*4882a593Smuzhiyun 	if (!datum) {
1934*4882a593Smuzhiyun 		rc = -ENOMEM;
1935*4882a593Smuzhiyun 		datum = kmalloc(sizeof(*datum), GFP_KERNEL);
1936*4882a593Smuzhiyun 		if (!datum)
1937*4882a593Smuzhiyun 			goto out;
1938*4882a593Smuzhiyun 
1939*4882a593Smuzhiyun 		ebitmap_init(&datum->stypes);
1940*4882a593Smuzhiyun 		datum->otype = otype;
1941*4882a593Smuzhiyun 		datum->next = NULL;
1942*4882a593Smuzhiyun 
1943*4882a593Smuzhiyun 		if (unlikely(last)) {
1944*4882a593Smuzhiyun 			last->next = datum;
1945*4882a593Smuzhiyun 		} else {
1946*4882a593Smuzhiyun 			rc = -ENOMEM;
1947*4882a593Smuzhiyun 			ft = kmemdup(&key, sizeof(key), GFP_KERNEL);
1948*4882a593Smuzhiyun 			if (!ft)
1949*4882a593Smuzhiyun 				goto out;
1950*4882a593Smuzhiyun 
1951*4882a593Smuzhiyun 			rc = hashtab_insert(&p->filename_trans, ft, datum,
1952*4882a593Smuzhiyun 					    filenametr_key_params);
1953*4882a593Smuzhiyun 			if (rc)
1954*4882a593Smuzhiyun 				goto out;
1955*4882a593Smuzhiyun 			name = NULL;
1956*4882a593Smuzhiyun 
1957*4882a593Smuzhiyun 			rc = ebitmap_set_bit(&p->filename_trans_ttypes,
1958*4882a593Smuzhiyun 					     key.ttype, 1);
1959*4882a593Smuzhiyun 			if (rc)
1960*4882a593Smuzhiyun 				return rc;
1961*4882a593Smuzhiyun 		}
1962*4882a593Smuzhiyun 	}
1963*4882a593Smuzhiyun 	kfree(name);
1964*4882a593Smuzhiyun 	return ebitmap_set_bit(&datum->stypes, stype - 1, 1);
1965*4882a593Smuzhiyun 
1966*4882a593Smuzhiyun out:
1967*4882a593Smuzhiyun 	kfree(ft);
1968*4882a593Smuzhiyun 	kfree(name);
1969*4882a593Smuzhiyun 	kfree(datum);
1970*4882a593Smuzhiyun 	return rc;
1971*4882a593Smuzhiyun }
1972*4882a593Smuzhiyun 
filename_trans_read_helper(struct policydb * p,void * fp)1973*4882a593Smuzhiyun static int filename_trans_read_helper(struct policydb *p, void *fp)
1974*4882a593Smuzhiyun {
1975*4882a593Smuzhiyun 	struct filename_trans_key *ft = NULL;
1976*4882a593Smuzhiyun 	struct filename_trans_datum **dst, *datum, *first = NULL;
1977*4882a593Smuzhiyun 	char *name = NULL;
1978*4882a593Smuzhiyun 	u32 len, ttype, tclass, ndatum, i;
1979*4882a593Smuzhiyun 	__le32 buf[3];
1980*4882a593Smuzhiyun 	int rc;
1981*4882a593Smuzhiyun 
1982*4882a593Smuzhiyun 	/* length of the path component string */
1983*4882a593Smuzhiyun 	rc = next_entry(buf, fp, sizeof(u32));
1984*4882a593Smuzhiyun 	if (rc)
1985*4882a593Smuzhiyun 		return rc;
1986*4882a593Smuzhiyun 	len = le32_to_cpu(buf[0]);
1987*4882a593Smuzhiyun 
1988*4882a593Smuzhiyun 	/* path component string */
1989*4882a593Smuzhiyun 	rc = str_read(&name, GFP_KERNEL, fp, len);
1990*4882a593Smuzhiyun 	if (rc)
1991*4882a593Smuzhiyun 		return rc;
1992*4882a593Smuzhiyun 
1993*4882a593Smuzhiyun 	rc = next_entry(buf, fp, sizeof(u32) * 3);
1994*4882a593Smuzhiyun 	if (rc)
1995*4882a593Smuzhiyun 		goto out;
1996*4882a593Smuzhiyun 
1997*4882a593Smuzhiyun 	ttype = le32_to_cpu(buf[0]);
1998*4882a593Smuzhiyun 	tclass = le32_to_cpu(buf[1]);
1999*4882a593Smuzhiyun 
2000*4882a593Smuzhiyun 	ndatum = le32_to_cpu(buf[2]);
2001*4882a593Smuzhiyun 	if (ndatum == 0) {
2002*4882a593Smuzhiyun 		pr_err("SELinux:  Filename transition key with no datum\n");
2003*4882a593Smuzhiyun 		rc = -ENOENT;
2004*4882a593Smuzhiyun 		goto out;
2005*4882a593Smuzhiyun 	}
2006*4882a593Smuzhiyun 
2007*4882a593Smuzhiyun 	dst = &first;
2008*4882a593Smuzhiyun 	for (i = 0; i < ndatum; i++) {
2009*4882a593Smuzhiyun 		rc = -ENOMEM;
2010*4882a593Smuzhiyun 		datum = kmalloc(sizeof(*datum), GFP_KERNEL);
2011*4882a593Smuzhiyun 		if (!datum)
2012*4882a593Smuzhiyun 			goto out;
2013*4882a593Smuzhiyun 
2014*4882a593Smuzhiyun 		*dst = datum;
2015*4882a593Smuzhiyun 
2016*4882a593Smuzhiyun 		/* ebitmap_read() will at least init the bitmap */
2017*4882a593Smuzhiyun 		rc = ebitmap_read(&datum->stypes, fp);
2018*4882a593Smuzhiyun 		if (rc)
2019*4882a593Smuzhiyun 			goto out;
2020*4882a593Smuzhiyun 
2021*4882a593Smuzhiyun 		rc = next_entry(buf, fp, sizeof(u32));
2022*4882a593Smuzhiyun 		if (rc)
2023*4882a593Smuzhiyun 			goto out;
2024*4882a593Smuzhiyun 
2025*4882a593Smuzhiyun 		datum->otype = le32_to_cpu(buf[0]);
2026*4882a593Smuzhiyun 		datum->next = NULL;
2027*4882a593Smuzhiyun 
2028*4882a593Smuzhiyun 		dst = &datum->next;
2029*4882a593Smuzhiyun 	}
2030*4882a593Smuzhiyun 
2031*4882a593Smuzhiyun 	rc = -ENOMEM;
2032*4882a593Smuzhiyun 	ft = kmalloc(sizeof(*ft), GFP_KERNEL);
2033*4882a593Smuzhiyun 	if (!ft)
2034*4882a593Smuzhiyun 		goto out;
2035*4882a593Smuzhiyun 
2036*4882a593Smuzhiyun 	ft->ttype = ttype;
2037*4882a593Smuzhiyun 	ft->tclass = tclass;
2038*4882a593Smuzhiyun 	ft->name = name;
2039*4882a593Smuzhiyun 
2040*4882a593Smuzhiyun 	rc = hashtab_insert(&p->filename_trans, ft, first,
2041*4882a593Smuzhiyun 			    filenametr_key_params);
2042*4882a593Smuzhiyun 	if (rc == -EEXIST)
2043*4882a593Smuzhiyun 		pr_err("SELinux:  Duplicate filename transition key\n");
2044*4882a593Smuzhiyun 	if (rc)
2045*4882a593Smuzhiyun 		goto out;
2046*4882a593Smuzhiyun 
2047*4882a593Smuzhiyun 	return ebitmap_set_bit(&p->filename_trans_ttypes, ttype, 1);
2048*4882a593Smuzhiyun 
2049*4882a593Smuzhiyun out:
2050*4882a593Smuzhiyun 	kfree(ft);
2051*4882a593Smuzhiyun 	kfree(name);
2052*4882a593Smuzhiyun 	while (first) {
2053*4882a593Smuzhiyun 		datum = first;
2054*4882a593Smuzhiyun 		first = first->next;
2055*4882a593Smuzhiyun 
2056*4882a593Smuzhiyun 		ebitmap_destroy(&datum->stypes);
2057*4882a593Smuzhiyun 		kfree(datum);
2058*4882a593Smuzhiyun 	}
2059*4882a593Smuzhiyun 	return rc;
2060*4882a593Smuzhiyun }
2061*4882a593Smuzhiyun 
filename_trans_read(struct policydb * p,void * fp)2062*4882a593Smuzhiyun static int filename_trans_read(struct policydb *p, void *fp)
2063*4882a593Smuzhiyun {
2064*4882a593Smuzhiyun 	u32 nel;
2065*4882a593Smuzhiyun 	__le32 buf[1];
2066*4882a593Smuzhiyun 	int rc, i;
2067*4882a593Smuzhiyun 
2068*4882a593Smuzhiyun 	if (p->policyvers < POLICYDB_VERSION_FILENAME_TRANS)
2069*4882a593Smuzhiyun 		return 0;
2070*4882a593Smuzhiyun 
2071*4882a593Smuzhiyun 	rc = next_entry(buf, fp, sizeof(u32));
2072*4882a593Smuzhiyun 	if (rc)
2073*4882a593Smuzhiyun 		return rc;
2074*4882a593Smuzhiyun 	nel = le32_to_cpu(buf[0]);
2075*4882a593Smuzhiyun 
2076*4882a593Smuzhiyun 	if (p->policyvers < POLICYDB_VERSION_COMP_FTRANS) {
2077*4882a593Smuzhiyun 		p->compat_filename_trans_count = nel;
2078*4882a593Smuzhiyun 
2079*4882a593Smuzhiyun 		rc = hashtab_init(&p->filename_trans, (1 << 11));
2080*4882a593Smuzhiyun 		if (rc)
2081*4882a593Smuzhiyun 			return rc;
2082*4882a593Smuzhiyun 
2083*4882a593Smuzhiyun 		for (i = 0; i < nel; i++) {
2084*4882a593Smuzhiyun 			rc = filename_trans_read_helper_compat(p, fp);
2085*4882a593Smuzhiyun 			if (rc)
2086*4882a593Smuzhiyun 				return rc;
2087*4882a593Smuzhiyun 		}
2088*4882a593Smuzhiyun 	} else {
2089*4882a593Smuzhiyun 		rc = hashtab_init(&p->filename_trans, nel);
2090*4882a593Smuzhiyun 		if (rc)
2091*4882a593Smuzhiyun 			return rc;
2092*4882a593Smuzhiyun 
2093*4882a593Smuzhiyun 		for (i = 0; i < nel; i++) {
2094*4882a593Smuzhiyun 			rc = filename_trans_read_helper(p, fp);
2095*4882a593Smuzhiyun 			if (rc)
2096*4882a593Smuzhiyun 				return rc;
2097*4882a593Smuzhiyun 		}
2098*4882a593Smuzhiyun 	}
2099*4882a593Smuzhiyun 	hash_eval(&p->filename_trans, "filenametr");
2100*4882a593Smuzhiyun 	return 0;
2101*4882a593Smuzhiyun }
2102*4882a593Smuzhiyun 
genfs_read(struct policydb * p,void * fp)2103*4882a593Smuzhiyun static int genfs_read(struct policydb *p, void *fp)
2104*4882a593Smuzhiyun {
2105*4882a593Smuzhiyun 	int i, j, rc;
2106*4882a593Smuzhiyun 	u32 nel, nel2, len, len2;
2107*4882a593Smuzhiyun 	__le32 buf[1];
2108*4882a593Smuzhiyun 	struct ocontext *l, *c;
2109*4882a593Smuzhiyun 	struct ocontext *newc = NULL;
2110*4882a593Smuzhiyun 	struct genfs *genfs_p, *genfs;
2111*4882a593Smuzhiyun 	struct genfs *newgenfs = NULL;
2112*4882a593Smuzhiyun 
2113*4882a593Smuzhiyun 	rc = next_entry(buf, fp, sizeof(u32));
2114*4882a593Smuzhiyun 	if (rc)
2115*4882a593Smuzhiyun 		return rc;
2116*4882a593Smuzhiyun 	nel = le32_to_cpu(buf[0]);
2117*4882a593Smuzhiyun 
2118*4882a593Smuzhiyun 	for (i = 0; i < nel; i++) {
2119*4882a593Smuzhiyun 		rc = next_entry(buf, fp, sizeof(u32));
2120*4882a593Smuzhiyun 		if (rc)
2121*4882a593Smuzhiyun 			goto out;
2122*4882a593Smuzhiyun 		len = le32_to_cpu(buf[0]);
2123*4882a593Smuzhiyun 
2124*4882a593Smuzhiyun 		rc = -ENOMEM;
2125*4882a593Smuzhiyun 		newgenfs = kzalloc(sizeof(*newgenfs), GFP_KERNEL);
2126*4882a593Smuzhiyun 		if (!newgenfs)
2127*4882a593Smuzhiyun 			goto out;
2128*4882a593Smuzhiyun 
2129*4882a593Smuzhiyun 		rc = str_read(&newgenfs->fstype, GFP_KERNEL, fp, len);
2130*4882a593Smuzhiyun 		if (rc)
2131*4882a593Smuzhiyun 			goto out;
2132*4882a593Smuzhiyun 
2133*4882a593Smuzhiyun 		for (genfs_p = NULL, genfs = p->genfs; genfs;
2134*4882a593Smuzhiyun 		     genfs_p = genfs, genfs = genfs->next) {
2135*4882a593Smuzhiyun 			rc = -EINVAL;
2136*4882a593Smuzhiyun 			if (strcmp(newgenfs->fstype, genfs->fstype) == 0) {
2137*4882a593Smuzhiyun 				pr_err("SELinux:  dup genfs fstype %s\n",
2138*4882a593Smuzhiyun 				       newgenfs->fstype);
2139*4882a593Smuzhiyun 				goto out;
2140*4882a593Smuzhiyun 			}
2141*4882a593Smuzhiyun 			if (strcmp(newgenfs->fstype, genfs->fstype) < 0)
2142*4882a593Smuzhiyun 				break;
2143*4882a593Smuzhiyun 		}
2144*4882a593Smuzhiyun 		newgenfs->next = genfs;
2145*4882a593Smuzhiyun 		if (genfs_p)
2146*4882a593Smuzhiyun 			genfs_p->next = newgenfs;
2147*4882a593Smuzhiyun 		else
2148*4882a593Smuzhiyun 			p->genfs = newgenfs;
2149*4882a593Smuzhiyun 		genfs = newgenfs;
2150*4882a593Smuzhiyun 		newgenfs = NULL;
2151*4882a593Smuzhiyun 
2152*4882a593Smuzhiyun 		rc = next_entry(buf, fp, sizeof(u32));
2153*4882a593Smuzhiyun 		if (rc)
2154*4882a593Smuzhiyun 			goto out;
2155*4882a593Smuzhiyun 
2156*4882a593Smuzhiyun 		nel2 = le32_to_cpu(buf[0]);
2157*4882a593Smuzhiyun 		for (j = 0; j < nel2; j++) {
2158*4882a593Smuzhiyun 			rc = next_entry(buf, fp, sizeof(u32));
2159*4882a593Smuzhiyun 			if (rc)
2160*4882a593Smuzhiyun 				goto out;
2161*4882a593Smuzhiyun 			len = le32_to_cpu(buf[0]);
2162*4882a593Smuzhiyun 
2163*4882a593Smuzhiyun 			rc = -ENOMEM;
2164*4882a593Smuzhiyun 			newc = kzalloc(sizeof(*newc), GFP_KERNEL);
2165*4882a593Smuzhiyun 			if (!newc)
2166*4882a593Smuzhiyun 				goto out;
2167*4882a593Smuzhiyun 
2168*4882a593Smuzhiyun 			rc = str_read(&newc->u.name, GFP_KERNEL, fp, len);
2169*4882a593Smuzhiyun 			if (rc)
2170*4882a593Smuzhiyun 				goto out;
2171*4882a593Smuzhiyun 
2172*4882a593Smuzhiyun 			rc = next_entry(buf, fp, sizeof(u32));
2173*4882a593Smuzhiyun 			if (rc)
2174*4882a593Smuzhiyun 				goto out;
2175*4882a593Smuzhiyun 
2176*4882a593Smuzhiyun 			newc->v.sclass = le32_to_cpu(buf[0]);
2177*4882a593Smuzhiyun 			rc = context_read_and_validate(&newc->context[0], p, fp);
2178*4882a593Smuzhiyun 			if (rc)
2179*4882a593Smuzhiyun 				goto out;
2180*4882a593Smuzhiyun 
2181*4882a593Smuzhiyun 			for (l = NULL, c = genfs->head; c;
2182*4882a593Smuzhiyun 			     l = c, c = c->next) {
2183*4882a593Smuzhiyun 				rc = -EINVAL;
2184*4882a593Smuzhiyun 				if (!strcmp(newc->u.name, c->u.name) &&
2185*4882a593Smuzhiyun 				    (!c->v.sclass || !newc->v.sclass ||
2186*4882a593Smuzhiyun 				     newc->v.sclass == c->v.sclass)) {
2187*4882a593Smuzhiyun 					pr_err("SELinux:  dup genfs entry (%s,%s)\n",
2188*4882a593Smuzhiyun 					       genfs->fstype, c->u.name);
2189*4882a593Smuzhiyun 					goto out;
2190*4882a593Smuzhiyun 				}
2191*4882a593Smuzhiyun 				len = strlen(newc->u.name);
2192*4882a593Smuzhiyun 				len2 = strlen(c->u.name);
2193*4882a593Smuzhiyun 				if (len > len2)
2194*4882a593Smuzhiyun 					break;
2195*4882a593Smuzhiyun 			}
2196*4882a593Smuzhiyun 
2197*4882a593Smuzhiyun 			newc->next = c;
2198*4882a593Smuzhiyun 			if (l)
2199*4882a593Smuzhiyun 				l->next = newc;
2200*4882a593Smuzhiyun 			else
2201*4882a593Smuzhiyun 				genfs->head = newc;
2202*4882a593Smuzhiyun 			newc = NULL;
2203*4882a593Smuzhiyun 		}
2204*4882a593Smuzhiyun 	}
2205*4882a593Smuzhiyun 	rc = 0;
2206*4882a593Smuzhiyun out:
2207*4882a593Smuzhiyun 	if (newgenfs) {
2208*4882a593Smuzhiyun 		kfree(newgenfs->fstype);
2209*4882a593Smuzhiyun 		kfree(newgenfs);
2210*4882a593Smuzhiyun 	}
2211*4882a593Smuzhiyun 	ocontext_destroy(newc, OCON_FSUSE);
2212*4882a593Smuzhiyun 
2213*4882a593Smuzhiyun 	return rc;
2214*4882a593Smuzhiyun }
2215*4882a593Smuzhiyun 
ocontext_read(struct policydb * p,struct policydb_compat_info * info,void * fp)2216*4882a593Smuzhiyun static int ocontext_read(struct policydb *p, struct policydb_compat_info *info,
2217*4882a593Smuzhiyun 			 void *fp)
2218*4882a593Smuzhiyun {
2219*4882a593Smuzhiyun 	int i, j, rc;
2220*4882a593Smuzhiyun 	u32 nel, len;
2221*4882a593Smuzhiyun 	__be64 prefixbuf[1];
2222*4882a593Smuzhiyun 	__le32 buf[3];
2223*4882a593Smuzhiyun 	struct ocontext *l, *c;
2224*4882a593Smuzhiyun 	u32 nodebuf[8];
2225*4882a593Smuzhiyun 
2226*4882a593Smuzhiyun 	for (i = 0; i < info->ocon_num; i++) {
2227*4882a593Smuzhiyun 		rc = next_entry(buf, fp, sizeof(u32));
2228*4882a593Smuzhiyun 		if (rc)
2229*4882a593Smuzhiyun 			goto out;
2230*4882a593Smuzhiyun 		nel = le32_to_cpu(buf[0]);
2231*4882a593Smuzhiyun 
2232*4882a593Smuzhiyun 		l = NULL;
2233*4882a593Smuzhiyun 		for (j = 0; j < nel; j++) {
2234*4882a593Smuzhiyun 			rc = -ENOMEM;
2235*4882a593Smuzhiyun 			c = kzalloc(sizeof(*c), GFP_KERNEL);
2236*4882a593Smuzhiyun 			if (!c)
2237*4882a593Smuzhiyun 				goto out;
2238*4882a593Smuzhiyun 			if (l)
2239*4882a593Smuzhiyun 				l->next = c;
2240*4882a593Smuzhiyun 			else
2241*4882a593Smuzhiyun 				p->ocontexts[i] = c;
2242*4882a593Smuzhiyun 			l = c;
2243*4882a593Smuzhiyun 
2244*4882a593Smuzhiyun 			switch (i) {
2245*4882a593Smuzhiyun 			case OCON_ISID:
2246*4882a593Smuzhiyun 				rc = next_entry(buf, fp, sizeof(u32));
2247*4882a593Smuzhiyun 				if (rc)
2248*4882a593Smuzhiyun 					goto out;
2249*4882a593Smuzhiyun 
2250*4882a593Smuzhiyun 				c->sid[0] = le32_to_cpu(buf[0]);
2251*4882a593Smuzhiyun 				rc = context_read_and_validate(&c->context[0], p, fp);
2252*4882a593Smuzhiyun 				if (rc)
2253*4882a593Smuzhiyun 					goto out;
2254*4882a593Smuzhiyun 				break;
2255*4882a593Smuzhiyun 			case OCON_FS:
2256*4882a593Smuzhiyun 			case OCON_NETIF:
2257*4882a593Smuzhiyun 				rc = next_entry(buf, fp, sizeof(u32));
2258*4882a593Smuzhiyun 				if (rc)
2259*4882a593Smuzhiyun 					goto out;
2260*4882a593Smuzhiyun 				len = le32_to_cpu(buf[0]);
2261*4882a593Smuzhiyun 
2262*4882a593Smuzhiyun 				rc = str_read(&c->u.name, GFP_KERNEL, fp, len);
2263*4882a593Smuzhiyun 				if (rc)
2264*4882a593Smuzhiyun 					goto out;
2265*4882a593Smuzhiyun 
2266*4882a593Smuzhiyun 				rc = context_read_and_validate(&c->context[0], p, fp);
2267*4882a593Smuzhiyun 				if (rc)
2268*4882a593Smuzhiyun 					goto out;
2269*4882a593Smuzhiyun 				rc = context_read_and_validate(&c->context[1], p, fp);
2270*4882a593Smuzhiyun 				if (rc)
2271*4882a593Smuzhiyun 					goto out;
2272*4882a593Smuzhiyun 				break;
2273*4882a593Smuzhiyun 			case OCON_PORT:
2274*4882a593Smuzhiyun 				rc = next_entry(buf, fp, sizeof(u32)*3);
2275*4882a593Smuzhiyun 				if (rc)
2276*4882a593Smuzhiyun 					goto out;
2277*4882a593Smuzhiyun 				c->u.port.protocol = le32_to_cpu(buf[0]);
2278*4882a593Smuzhiyun 				c->u.port.low_port = le32_to_cpu(buf[1]);
2279*4882a593Smuzhiyun 				c->u.port.high_port = le32_to_cpu(buf[2]);
2280*4882a593Smuzhiyun 				rc = context_read_and_validate(&c->context[0], p, fp);
2281*4882a593Smuzhiyun 				if (rc)
2282*4882a593Smuzhiyun 					goto out;
2283*4882a593Smuzhiyun 				break;
2284*4882a593Smuzhiyun 			case OCON_NODE:
2285*4882a593Smuzhiyun 				rc = next_entry(nodebuf, fp, sizeof(u32) * 2);
2286*4882a593Smuzhiyun 				if (rc)
2287*4882a593Smuzhiyun 					goto out;
2288*4882a593Smuzhiyun 				c->u.node.addr = nodebuf[0]; /* network order */
2289*4882a593Smuzhiyun 				c->u.node.mask = nodebuf[1]; /* network order */
2290*4882a593Smuzhiyun 				rc = context_read_and_validate(&c->context[0], p, fp);
2291*4882a593Smuzhiyun 				if (rc)
2292*4882a593Smuzhiyun 					goto out;
2293*4882a593Smuzhiyun 				break;
2294*4882a593Smuzhiyun 			case OCON_FSUSE:
2295*4882a593Smuzhiyun 				rc = next_entry(buf, fp, sizeof(u32)*2);
2296*4882a593Smuzhiyun 				if (rc)
2297*4882a593Smuzhiyun 					goto out;
2298*4882a593Smuzhiyun 
2299*4882a593Smuzhiyun 				rc = -EINVAL;
2300*4882a593Smuzhiyun 				c->v.behavior = le32_to_cpu(buf[0]);
2301*4882a593Smuzhiyun 				/* Determined at runtime, not in policy DB. */
2302*4882a593Smuzhiyun 				if (c->v.behavior == SECURITY_FS_USE_MNTPOINT)
2303*4882a593Smuzhiyun 					goto out;
2304*4882a593Smuzhiyun 				if (c->v.behavior > SECURITY_FS_USE_MAX)
2305*4882a593Smuzhiyun 					goto out;
2306*4882a593Smuzhiyun 
2307*4882a593Smuzhiyun 				len = le32_to_cpu(buf[1]);
2308*4882a593Smuzhiyun 				rc = str_read(&c->u.name, GFP_KERNEL, fp, len);
2309*4882a593Smuzhiyun 				if (rc)
2310*4882a593Smuzhiyun 					goto out;
2311*4882a593Smuzhiyun 
2312*4882a593Smuzhiyun 				rc = context_read_and_validate(&c->context[0], p, fp);
2313*4882a593Smuzhiyun 				if (rc)
2314*4882a593Smuzhiyun 					goto out;
2315*4882a593Smuzhiyun 				break;
2316*4882a593Smuzhiyun 			case OCON_NODE6: {
2317*4882a593Smuzhiyun 				int k;
2318*4882a593Smuzhiyun 
2319*4882a593Smuzhiyun 				rc = next_entry(nodebuf, fp, sizeof(u32) * 8);
2320*4882a593Smuzhiyun 				if (rc)
2321*4882a593Smuzhiyun 					goto out;
2322*4882a593Smuzhiyun 				for (k = 0; k < 4; k++)
2323*4882a593Smuzhiyun 					c->u.node6.addr[k] = nodebuf[k];
2324*4882a593Smuzhiyun 				for (k = 0; k < 4; k++)
2325*4882a593Smuzhiyun 					c->u.node6.mask[k] = nodebuf[k+4];
2326*4882a593Smuzhiyun 				rc = context_read_and_validate(&c->context[0], p, fp);
2327*4882a593Smuzhiyun 				if (rc)
2328*4882a593Smuzhiyun 					goto out;
2329*4882a593Smuzhiyun 				break;
2330*4882a593Smuzhiyun 			}
2331*4882a593Smuzhiyun 			case OCON_IBPKEY: {
2332*4882a593Smuzhiyun 				u32 pkey_lo, pkey_hi;
2333*4882a593Smuzhiyun 
2334*4882a593Smuzhiyun 				rc = next_entry(prefixbuf, fp, sizeof(u64));
2335*4882a593Smuzhiyun 				if (rc)
2336*4882a593Smuzhiyun 					goto out;
2337*4882a593Smuzhiyun 
2338*4882a593Smuzhiyun 				/* we need to have subnet_prefix in CPU order */
2339*4882a593Smuzhiyun 				c->u.ibpkey.subnet_prefix = be64_to_cpu(prefixbuf[0]);
2340*4882a593Smuzhiyun 
2341*4882a593Smuzhiyun 				rc = next_entry(buf, fp, sizeof(u32) * 2);
2342*4882a593Smuzhiyun 				if (rc)
2343*4882a593Smuzhiyun 					goto out;
2344*4882a593Smuzhiyun 
2345*4882a593Smuzhiyun 				pkey_lo = le32_to_cpu(buf[0]);
2346*4882a593Smuzhiyun 				pkey_hi = le32_to_cpu(buf[1]);
2347*4882a593Smuzhiyun 
2348*4882a593Smuzhiyun 				if (pkey_lo > U16_MAX || pkey_hi > U16_MAX) {
2349*4882a593Smuzhiyun 					rc = -EINVAL;
2350*4882a593Smuzhiyun 					goto out;
2351*4882a593Smuzhiyun 				}
2352*4882a593Smuzhiyun 
2353*4882a593Smuzhiyun 				c->u.ibpkey.low_pkey  = pkey_lo;
2354*4882a593Smuzhiyun 				c->u.ibpkey.high_pkey = pkey_hi;
2355*4882a593Smuzhiyun 
2356*4882a593Smuzhiyun 				rc = context_read_and_validate(&c->context[0],
2357*4882a593Smuzhiyun 							       p,
2358*4882a593Smuzhiyun 							       fp);
2359*4882a593Smuzhiyun 				if (rc)
2360*4882a593Smuzhiyun 					goto out;
2361*4882a593Smuzhiyun 				break;
2362*4882a593Smuzhiyun 			}
2363*4882a593Smuzhiyun 			case OCON_IBENDPORT: {
2364*4882a593Smuzhiyun 				u32 port;
2365*4882a593Smuzhiyun 
2366*4882a593Smuzhiyun 				rc = next_entry(buf, fp, sizeof(u32) * 2);
2367*4882a593Smuzhiyun 				if (rc)
2368*4882a593Smuzhiyun 					goto out;
2369*4882a593Smuzhiyun 				len = le32_to_cpu(buf[0]);
2370*4882a593Smuzhiyun 
2371*4882a593Smuzhiyun 				rc = str_read(&c->u.ibendport.dev_name, GFP_KERNEL, fp, len);
2372*4882a593Smuzhiyun 				if (rc)
2373*4882a593Smuzhiyun 					goto out;
2374*4882a593Smuzhiyun 
2375*4882a593Smuzhiyun 				port = le32_to_cpu(buf[1]);
2376*4882a593Smuzhiyun 				if (port > U8_MAX || port == 0) {
2377*4882a593Smuzhiyun 					rc = -EINVAL;
2378*4882a593Smuzhiyun 					goto out;
2379*4882a593Smuzhiyun 				}
2380*4882a593Smuzhiyun 
2381*4882a593Smuzhiyun 				c->u.ibendport.port = port;
2382*4882a593Smuzhiyun 
2383*4882a593Smuzhiyun 				rc = context_read_and_validate(&c->context[0],
2384*4882a593Smuzhiyun 							       p,
2385*4882a593Smuzhiyun 							       fp);
2386*4882a593Smuzhiyun 				if (rc)
2387*4882a593Smuzhiyun 					goto out;
2388*4882a593Smuzhiyun 				break;
2389*4882a593Smuzhiyun 			} /* end case */
2390*4882a593Smuzhiyun 			} /* end switch */
2391*4882a593Smuzhiyun 		}
2392*4882a593Smuzhiyun 	}
2393*4882a593Smuzhiyun 	rc = 0;
2394*4882a593Smuzhiyun out:
2395*4882a593Smuzhiyun 	return rc;
2396*4882a593Smuzhiyun }
2397*4882a593Smuzhiyun 
2398*4882a593Smuzhiyun /*
2399*4882a593Smuzhiyun  * Read the configuration data from a policy database binary
2400*4882a593Smuzhiyun  * representation file into a policy database structure.
2401*4882a593Smuzhiyun  */
policydb_read(struct policydb * p,void * fp)2402*4882a593Smuzhiyun int policydb_read(struct policydb *p, void *fp)
2403*4882a593Smuzhiyun {
2404*4882a593Smuzhiyun 	struct role_allow *ra, *lra;
2405*4882a593Smuzhiyun 	struct role_trans_key *rtk = NULL;
2406*4882a593Smuzhiyun 	struct role_trans_datum *rtd = NULL;
2407*4882a593Smuzhiyun 	int i, j, rc;
2408*4882a593Smuzhiyun 	__le32 buf[4];
2409*4882a593Smuzhiyun 	u32 len, nprim, nel, perm;
2410*4882a593Smuzhiyun 
2411*4882a593Smuzhiyun 	char *policydb_str;
2412*4882a593Smuzhiyun 	struct policydb_compat_info *info;
2413*4882a593Smuzhiyun 
2414*4882a593Smuzhiyun 	policydb_init(p);
2415*4882a593Smuzhiyun 
2416*4882a593Smuzhiyun 	/* Read the magic number and string length. */
2417*4882a593Smuzhiyun 	rc = next_entry(buf, fp, sizeof(u32) * 2);
2418*4882a593Smuzhiyun 	if (rc)
2419*4882a593Smuzhiyun 		goto bad;
2420*4882a593Smuzhiyun 
2421*4882a593Smuzhiyun 	rc = -EINVAL;
2422*4882a593Smuzhiyun 	if (le32_to_cpu(buf[0]) != POLICYDB_MAGIC) {
2423*4882a593Smuzhiyun 		pr_err("SELinux:  policydb magic number 0x%x does "
2424*4882a593Smuzhiyun 		       "not match expected magic number 0x%x\n",
2425*4882a593Smuzhiyun 		       le32_to_cpu(buf[0]), POLICYDB_MAGIC);
2426*4882a593Smuzhiyun 		goto bad;
2427*4882a593Smuzhiyun 	}
2428*4882a593Smuzhiyun 
2429*4882a593Smuzhiyun 	rc = -EINVAL;
2430*4882a593Smuzhiyun 	len = le32_to_cpu(buf[1]);
2431*4882a593Smuzhiyun 	if (len != strlen(POLICYDB_STRING)) {
2432*4882a593Smuzhiyun 		pr_err("SELinux:  policydb string length %d does not "
2433*4882a593Smuzhiyun 		       "match expected length %zu\n",
2434*4882a593Smuzhiyun 		       len, strlen(POLICYDB_STRING));
2435*4882a593Smuzhiyun 		goto bad;
2436*4882a593Smuzhiyun 	}
2437*4882a593Smuzhiyun 
2438*4882a593Smuzhiyun 	rc = -ENOMEM;
2439*4882a593Smuzhiyun 	policydb_str = kmalloc(len + 1, GFP_KERNEL);
2440*4882a593Smuzhiyun 	if (!policydb_str) {
2441*4882a593Smuzhiyun 		pr_err("SELinux:  unable to allocate memory for policydb "
2442*4882a593Smuzhiyun 		       "string of length %d\n", len);
2443*4882a593Smuzhiyun 		goto bad;
2444*4882a593Smuzhiyun 	}
2445*4882a593Smuzhiyun 
2446*4882a593Smuzhiyun 	rc = next_entry(policydb_str, fp, len);
2447*4882a593Smuzhiyun 	if (rc) {
2448*4882a593Smuzhiyun 		pr_err("SELinux:  truncated policydb string identifier\n");
2449*4882a593Smuzhiyun 		kfree(policydb_str);
2450*4882a593Smuzhiyun 		goto bad;
2451*4882a593Smuzhiyun 	}
2452*4882a593Smuzhiyun 
2453*4882a593Smuzhiyun 	rc = -EINVAL;
2454*4882a593Smuzhiyun 	policydb_str[len] = '\0';
2455*4882a593Smuzhiyun 	if (strcmp(policydb_str, POLICYDB_STRING)) {
2456*4882a593Smuzhiyun 		pr_err("SELinux:  policydb string %s does not match "
2457*4882a593Smuzhiyun 		       "my string %s\n", policydb_str, POLICYDB_STRING);
2458*4882a593Smuzhiyun 		kfree(policydb_str);
2459*4882a593Smuzhiyun 		goto bad;
2460*4882a593Smuzhiyun 	}
2461*4882a593Smuzhiyun 	/* Done with policydb_str. */
2462*4882a593Smuzhiyun 	kfree(policydb_str);
2463*4882a593Smuzhiyun 	policydb_str = NULL;
2464*4882a593Smuzhiyun 
2465*4882a593Smuzhiyun 	/* Read the version and table sizes. */
2466*4882a593Smuzhiyun 	rc = next_entry(buf, fp, sizeof(u32)*4);
2467*4882a593Smuzhiyun 	if (rc)
2468*4882a593Smuzhiyun 		goto bad;
2469*4882a593Smuzhiyun 
2470*4882a593Smuzhiyun 	rc = -EINVAL;
2471*4882a593Smuzhiyun 	p->policyvers = le32_to_cpu(buf[0]);
2472*4882a593Smuzhiyun 	if (p->policyvers < POLICYDB_VERSION_MIN ||
2473*4882a593Smuzhiyun 	    p->policyvers > POLICYDB_VERSION_MAX) {
2474*4882a593Smuzhiyun 		pr_err("SELinux:  policydb version %d does not match "
2475*4882a593Smuzhiyun 		       "my version range %d-%d\n",
2476*4882a593Smuzhiyun 		       le32_to_cpu(buf[0]), POLICYDB_VERSION_MIN, POLICYDB_VERSION_MAX);
2477*4882a593Smuzhiyun 		goto bad;
2478*4882a593Smuzhiyun 	}
2479*4882a593Smuzhiyun 
2480*4882a593Smuzhiyun 	if ((le32_to_cpu(buf[1]) & POLICYDB_CONFIG_MLS)) {
2481*4882a593Smuzhiyun 		p->mls_enabled = 1;
2482*4882a593Smuzhiyun 
2483*4882a593Smuzhiyun 		rc = -EINVAL;
2484*4882a593Smuzhiyun 		if (p->policyvers < POLICYDB_VERSION_MLS) {
2485*4882a593Smuzhiyun 			pr_err("SELinux: security policydb version %d "
2486*4882a593Smuzhiyun 				"(MLS) not backwards compatible\n",
2487*4882a593Smuzhiyun 				p->policyvers);
2488*4882a593Smuzhiyun 			goto bad;
2489*4882a593Smuzhiyun 		}
2490*4882a593Smuzhiyun 	}
2491*4882a593Smuzhiyun 	p->reject_unknown = !!(le32_to_cpu(buf[1]) & REJECT_UNKNOWN);
2492*4882a593Smuzhiyun 	p->allow_unknown = !!(le32_to_cpu(buf[1]) & ALLOW_UNKNOWN);
2493*4882a593Smuzhiyun 
2494*4882a593Smuzhiyun 	if ((le32_to_cpu(buf[1]) & POLICYDB_CONFIG_ANDROID_NETLINK_ROUTE)) {
2495*4882a593Smuzhiyun 		p->android_netlink_route = 1;
2496*4882a593Smuzhiyun 	}
2497*4882a593Smuzhiyun 
2498*4882a593Smuzhiyun 	if ((le32_to_cpu(buf[1]) & POLICYDB_CONFIG_ANDROID_NETLINK_GETNEIGH)) {
2499*4882a593Smuzhiyun 		p->android_netlink_getneigh = 1;
2500*4882a593Smuzhiyun 	}
2501*4882a593Smuzhiyun 
2502*4882a593Smuzhiyun 	if (p->policyvers >= POLICYDB_VERSION_POLCAP) {
2503*4882a593Smuzhiyun 		rc = ebitmap_read(&p->policycaps, fp);
2504*4882a593Smuzhiyun 		if (rc)
2505*4882a593Smuzhiyun 			goto bad;
2506*4882a593Smuzhiyun 	}
2507*4882a593Smuzhiyun 
2508*4882a593Smuzhiyun 	if (p->policyvers >= POLICYDB_VERSION_PERMISSIVE) {
2509*4882a593Smuzhiyun 		rc = ebitmap_read(&p->permissive_map, fp);
2510*4882a593Smuzhiyun 		if (rc)
2511*4882a593Smuzhiyun 			goto bad;
2512*4882a593Smuzhiyun 	}
2513*4882a593Smuzhiyun 
2514*4882a593Smuzhiyun 	rc = -EINVAL;
2515*4882a593Smuzhiyun 	info = policydb_lookup_compat(p->policyvers);
2516*4882a593Smuzhiyun 	if (!info) {
2517*4882a593Smuzhiyun 		pr_err("SELinux:  unable to find policy compat info "
2518*4882a593Smuzhiyun 		       "for version %d\n", p->policyvers);
2519*4882a593Smuzhiyun 		goto bad;
2520*4882a593Smuzhiyun 	}
2521*4882a593Smuzhiyun 
2522*4882a593Smuzhiyun 	rc = -EINVAL;
2523*4882a593Smuzhiyun 	if (le32_to_cpu(buf[2]) != info->sym_num ||
2524*4882a593Smuzhiyun 		le32_to_cpu(buf[3]) != info->ocon_num) {
2525*4882a593Smuzhiyun 		pr_err("SELinux:  policydb table sizes (%d,%d) do "
2526*4882a593Smuzhiyun 		       "not match mine (%d,%d)\n", le32_to_cpu(buf[2]),
2527*4882a593Smuzhiyun 			le32_to_cpu(buf[3]),
2528*4882a593Smuzhiyun 		       info->sym_num, info->ocon_num);
2529*4882a593Smuzhiyun 		goto bad;
2530*4882a593Smuzhiyun 	}
2531*4882a593Smuzhiyun 
2532*4882a593Smuzhiyun 	for (i = 0; i < info->sym_num; i++) {
2533*4882a593Smuzhiyun 		rc = next_entry(buf, fp, sizeof(u32)*2);
2534*4882a593Smuzhiyun 		if (rc)
2535*4882a593Smuzhiyun 			goto bad;
2536*4882a593Smuzhiyun 		nprim = le32_to_cpu(buf[0]);
2537*4882a593Smuzhiyun 		nel = le32_to_cpu(buf[1]);
2538*4882a593Smuzhiyun 
2539*4882a593Smuzhiyun 		rc = symtab_init(&p->symtab[i], nel);
2540*4882a593Smuzhiyun 		if (rc)
2541*4882a593Smuzhiyun 			goto out;
2542*4882a593Smuzhiyun 
2543*4882a593Smuzhiyun 		if (i == SYM_ROLES) {
2544*4882a593Smuzhiyun 			rc = roles_init(p);
2545*4882a593Smuzhiyun 			if (rc)
2546*4882a593Smuzhiyun 				goto out;
2547*4882a593Smuzhiyun 		}
2548*4882a593Smuzhiyun 
2549*4882a593Smuzhiyun 		for (j = 0; j < nel; j++) {
2550*4882a593Smuzhiyun 			rc = read_f[i](p, &p->symtab[i], fp);
2551*4882a593Smuzhiyun 			if (rc)
2552*4882a593Smuzhiyun 				goto bad;
2553*4882a593Smuzhiyun 		}
2554*4882a593Smuzhiyun 
2555*4882a593Smuzhiyun 		p->symtab[i].nprim = nprim;
2556*4882a593Smuzhiyun 	}
2557*4882a593Smuzhiyun 
2558*4882a593Smuzhiyun 	rc = -EINVAL;
2559*4882a593Smuzhiyun 	p->process_class = string_to_security_class(p, "process");
2560*4882a593Smuzhiyun 	if (!p->process_class) {
2561*4882a593Smuzhiyun 		pr_err("SELinux: process class is required, not defined in policy\n");
2562*4882a593Smuzhiyun 		goto bad;
2563*4882a593Smuzhiyun 	}
2564*4882a593Smuzhiyun 
2565*4882a593Smuzhiyun 	rc = avtab_read(&p->te_avtab, fp, p);
2566*4882a593Smuzhiyun 	if (rc)
2567*4882a593Smuzhiyun 		goto bad;
2568*4882a593Smuzhiyun 
2569*4882a593Smuzhiyun 	if (p->policyvers >= POLICYDB_VERSION_BOOL) {
2570*4882a593Smuzhiyun 		rc = cond_read_list(p, fp);
2571*4882a593Smuzhiyun 		if (rc)
2572*4882a593Smuzhiyun 			goto bad;
2573*4882a593Smuzhiyun 	}
2574*4882a593Smuzhiyun 
2575*4882a593Smuzhiyun 	rc = next_entry(buf, fp, sizeof(u32));
2576*4882a593Smuzhiyun 	if (rc)
2577*4882a593Smuzhiyun 		goto bad;
2578*4882a593Smuzhiyun 	nel = le32_to_cpu(buf[0]);
2579*4882a593Smuzhiyun 
2580*4882a593Smuzhiyun 	rc = hashtab_init(&p->role_tr, nel);
2581*4882a593Smuzhiyun 	if (rc)
2582*4882a593Smuzhiyun 		goto bad;
2583*4882a593Smuzhiyun 	for (i = 0; i < nel; i++) {
2584*4882a593Smuzhiyun 		rc = -ENOMEM;
2585*4882a593Smuzhiyun 		rtk = kmalloc(sizeof(*rtk), GFP_KERNEL);
2586*4882a593Smuzhiyun 		if (!rtk)
2587*4882a593Smuzhiyun 			goto bad;
2588*4882a593Smuzhiyun 
2589*4882a593Smuzhiyun 		rc = -ENOMEM;
2590*4882a593Smuzhiyun 		rtd = kmalloc(sizeof(*rtd), GFP_KERNEL);
2591*4882a593Smuzhiyun 		if (!rtd)
2592*4882a593Smuzhiyun 			goto bad;
2593*4882a593Smuzhiyun 
2594*4882a593Smuzhiyun 		rc = next_entry(buf, fp, sizeof(u32)*3);
2595*4882a593Smuzhiyun 		if (rc)
2596*4882a593Smuzhiyun 			goto bad;
2597*4882a593Smuzhiyun 
2598*4882a593Smuzhiyun 		rc = -EINVAL;
2599*4882a593Smuzhiyun 		rtk->role = le32_to_cpu(buf[0]);
2600*4882a593Smuzhiyun 		rtk->type = le32_to_cpu(buf[1]);
2601*4882a593Smuzhiyun 		rtd->new_role = le32_to_cpu(buf[2]);
2602*4882a593Smuzhiyun 		if (p->policyvers >= POLICYDB_VERSION_ROLETRANS) {
2603*4882a593Smuzhiyun 			rc = next_entry(buf, fp, sizeof(u32));
2604*4882a593Smuzhiyun 			if (rc)
2605*4882a593Smuzhiyun 				goto bad;
2606*4882a593Smuzhiyun 			rtk->tclass = le32_to_cpu(buf[0]);
2607*4882a593Smuzhiyun 		} else
2608*4882a593Smuzhiyun 			rtk->tclass = p->process_class;
2609*4882a593Smuzhiyun 
2610*4882a593Smuzhiyun 		rc = -EINVAL;
2611*4882a593Smuzhiyun 		if (!policydb_role_isvalid(p, rtk->role) ||
2612*4882a593Smuzhiyun 		    !policydb_type_isvalid(p, rtk->type) ||
2613*4882a593Smuzhiyun 		    !policydb_class_isvalid(p, rtk->tclass) ||
2614*4882a593Smuzhiyun 		    !policydb_role_isvalid(p, rtd->new_role))
2615*4882a593Smuzhiyun 			goto bad;
2616*4882a593Smuzhiyun 
2617*4882a593Smuzhiyun 		rc = hashtab_insert(&p->role_tr, rtk, rtd, roletr_key_params);
2618*4882a593Smuzhiyun 		if (rc)
2619*4882a593Smuzhiyun 			goto bad;
2620*4882a593Smuzhiyun 
2621*4882a593Smuzhiyun 		rtk = NULL;
2622*4882a593Smuzhiyun 		rtd = NULL;
2623*4882a593Smuzhiyun 	}
2624*4882a593Smuzhiyun 
2625*4882a593Smuzhiyun 	rc = next_entry(buf, fp, sizeof(u32));
2626*4882a593Smuzhiyun 	if (rc)
2627*4882a593Smuzhiyun 		goto bad;
2628*4882a593Smuzhiyun 	nel = le32_to_cpu(buf[0]);
2629*4882a593Smuzhiyun 	lra = NULL;
2630*4882a593Smuzhiyun 	for (i = 0; i < nel; i++) {
2631*4882a593Smuzhiyun 		rc = -ENOMEM;
2632*4882a593Smuzhiyun 		ra = kzalloc(sizeof(*ra), GFP_KERNEL);
2633*4882a593Smuzhiyun 		if (!ra)
2634*4882a593Smuzhiyun 			goto bad;
2635*4882a593Smuzhiyun 		if (lra)
2636*4882a593Smuzhiyun 			lra->next = ra;
2637*4882a593Smuzhiyun 		else
2638*4882a593Smuzhiyun 			p->role_allow = ra;
2639*4882a593Smuzhiyun 		rc = next_entry(buf, fp, sizeof(u32)*2);
2640*4882a593Smuzhiyun 		if (rc)
2641*4882a593Smuzhiyun 			goto bad;
2642*4882a593Smuzhiyun 
2643*4882a593Smuzhiyun 		rc = -EINVAL;
2644*4882a593Smuzhiyun 		ra->role = le32_to_cpu(buf[0]);
2645*4882a593Smuzhiyun 		ra->new_role = le32_to_cpu(buf[1]);
2646*4882a593Smuzhiyun 		if (!policydb_role_isvalid(p, ra->role) ||
2647*4882a593Smuzhiyun 		    !policydb_role_isvalid(p, ra->new_role))
2648*4882a593Smuzhiyun 			goto bad;
2649*4882a593Smuzhiyun 		lra = ra;
2650*4882a593Smuzhiyun 	}
2651*4882a593Smuzhiyun 
2652*4882a593Smuzhiyun 	rc = filename_trans_read(p, fp);
2653*4882a593Smuzhiyun 	if (rc)
2654*4882a593Smuzhiyun 		goto bad;
2655*4882a593Smuzhiyun 
2656*4882a593Smuzhiyun 	rc = policydb_index(p);
2657*4882a593Smuzhiyun 	if (rc)
2658*4882a593Smuzhiyun 		goto bad;
2659*4882a593Smuzhiyun 
2660*4882a593Smuzhiyun 	rc = -EINVAL;
2661*4882a593Smuzhiyun 	perm = string_to_av_perm(p, p->process_class, "transition");
2662*4882a593Smuzhiyun 	if (!perm) {
2663*4882a593Smuzhiyun 		pr_err("SELinux: process transition permission is required, not defined in policy\n");
2664*4882a593Smuzhiyun 		goto bad;
2665*4882a593Smuzhiyun 	}
2666*4882a593Smuzhiyun 	p->process_trans_perms = perm;
2667*4882a593Smuzhiyun 	perm = string_to_av_perm(p, p->process_class, "dyntransition");
2668*4882a593Smuzhiyun 	if (!perm) {
2669*4882a593Smuzhiyun 		pr_err("SELinux: process dyntransition permission is required, not defined in policy\n");
2670*4882a593Smuzhiyun 		goto bad;
2671*4882a593Smuzhiyun 	}
2672*4882a593Smuzhiyun 	p->process_trans_perms |= perm;
2673*4882a593Smuzhiyun 
2674*4882a593Smuzhiyun 	rc = ocontext_read(p, info, fp);
2675*4882a593Smuzhiyun 	if (rc)
2676*4882a593Smuzhiyun 		goto bad;
2677*4882a593Smuzhiyun 
2678*4882a593Smuzhiyun 	rc = genfs_read(p, fp);
2679*4882a593Smuzhiyun 	if (rc)
2680*4882a593Smuzhiyun 		goto bad;
2681*4882a593Smuzhiyun 
2682*4882a593Smuzhiyun 	rc = range_read(p, fp);
2683*4882a593Smuzhiyun 	if (rc)
2684*4882a593Smuzhiyun 		goto bad;
2685*4882a593Smuzhiyun 
2686*4882a593Smuzhiyun 	rc = -ENOMEM;
2687*4882a593Smuzhiyun 	p->type_attr_map_array = kvcalloc(p->p_types.nprim,
2688*4882a593Smuzhiyun 					  sizeof(*p->type_attr_map_array),
2689*4882a593Smuzhiyun 					  GFP_KERNEL);
2690*4882a593Smuzhiyun 	if (!p->type_attr_map_array)
2691*4882a593Smuzhiyun 		goto bad;
2692*4882a593Smuzhiyun 
2693*4882a593Smuzhiyun 	/* just in case ebitmap_init() becomes more than just a memset(0): */
2694*4882a593Smuzhiyun 	for (i = 0; i < p->p_types.nprim; i++)
2695*4882a593Smuzhiyun 		ebitmap_init(&p->type_attr_map_array[i]);
2696*4882a593Smuzhiyun 
2697*4882a593Smuzhiyun 	for (i = 0; i < p->p_types.nprim; i++) {
2698*4882a593Smuzhiyun 		struct ebitmap *e = &p->type_attr_map_array[i];
2699*4882a593Smuzhiyun 
2700*4882a593Smuzhiyun 		if (p->policyvers >= POLICYDB_VERSION_AVTAB) {
2701*4882a593Smuzhiyun 			rc = ebitmap_read(e, fp);
2702*4882a593Smuzhiyun 			if (rc)
2703*4882a593Smuzhiyun 				goto bad;
2704*4882a593Smuzhiyun 		}
2705*4882a593Smuzhiyun 		/* add the type itself as the degenerate case */
2706*4882a593Smuzhiyun 		rc = ebitmap_set_bit(e, i, 1);
2707*4882a593Smuzhiyun 		if (rc)
2708*4882a593Smuzhiyun 			goto bad;
2709*4882a593Smuzhiyun 	}
2710*4882a593Smuzhiyun 
2711*4882a593Smuzhiyun 	rc = policydb_bounds_sanity_check(p);
2712*4882a593Smuzhiyun 	if (rc)
2713*4882a593Smuzhiyun 		goto bad;
2714*4882a593Smuzhiyun 
2715*4882a593Smuzhiyun 	rc = 0;
2716*4882a593Smuzhiyun out:
2717*4882a593Smuzhiyun 	return rc;
2718*4882a593Smuzhiyun bad:
2719*4882a593Smuzhiyun 	kfree(rtk);
2720*4882a593Smuzhiyun 	kfree(rtd);
2721*4882a593Smuzhiyun 	policydb_destroy(p);
2722*4882a593Smuzhiyun 	goto out;
2723*4882a593Smuzhiyun }
2724*4882a593Smuzhiyun 
2725*4882a593Smuzhiyun /*
2726*4882a593Smuzhiyun  * Write a MLS level structure to a policydb binary
2727*4882a593Smuzhiyun  * representation file.
2728*4882a593Smuzhiyun  */
mls_write_level(struct mls_level * l,void * fp)2729*4882a593Smuzhiyun static int mls_write_level(struct mls_level *l, void *fp)
2730*4882a593Smuzhiyun {
2731*4882a593Smuzhiyun 	__le32 buf[1];
2732*4882a593Smuzhiyun 	int rc;
2733*4882a593Smuzhiyun 
2734*4882a593Smuzhiyun 	buf[0] = cpu_to_le32(l->sens);
2735*4882a593Smuzhiyun 	rc = put_entry(buf, sizeof(u32), 1, fp);
2736*4882a593Smuzhiyun 	if (rc)
2737*4882a593Smuzhiyun 		return rc;
2738*4882a593Smuzhiyun 
2739*4882a593Smuzhiyun 	rc = ebitmap_write(&l->cat, fp);
2740*4882a593Smuzhiyun 	if (rc)
2741*4882a593Smuzhiyun 		return rc;
2742*4882a593Smuzhiyun 
2743*4882a593Smuzhiyun 	return 0;
2744*4882a593Smuzhiyun }
2745*4882a593Smuzhiyun 
2746*4882a593Smuzhiyun /*
2747*4882a593Smuzhiyun  * Write a MLS range structure to a policydb binary
2748*4882a593Smuzhiyun  * representation file.
2749*4882a593Smuzhiyun  */
mls_write_range_helper(struct mls_range * r,void * fp)2750*4882a593Smuzhiyun static int mls_write_range_helper(struct mls_range *r, void *fp)
2751*4882a593Smuzhiyun {
2752*4882a593Smuzhiyun 	__le32 buf[3];
2753*4882a593Smuzhiyun 	size_t items;
2754*4882a593Smuzhiyun 	int rc, eq;
2755*4882a593Smuzhiyun 
2756*4882a593Smuzhiyun 	eq = mls_level_eq(&r->level[1], &r->level[0]);
2757*4882a593Smuzhiyun 
2758*4882a593Smuzhiyun 	if (eq)
2759*4882a593Smuzhiyun 		items = 2;
2760*4882a593Smuzhiyun 	else
2761*4882a593Smuzhiyun 		items = 3;
2762*4882a593Smuzhiyun 	buf[0] = cpu_to_le32(items-1);
2763*4882a593Smuzhiyun 	buf[1] = cpu_to_le32(r->level[0].sens);
2764*4882a593Smuzhiyun 	if (!eq)
2765*4882a593Smuzhiyun 		buf[2] = cpu_to_le32(r->level[1].sens);
2766*4882a593Smuzhiyun 
2767*4882a593Smuzhiyun 	BUG_ON(items > ARRAY_SIZE(buf));
2768*4882a593Smuzhiyun 
2769*4882a593Smuzhiyun 	rc = put_entry(buf, sizeof(u32), items, fp);
2770*4882a593Smuzhiyun 	if (rc)
2771*4882a593Smuzhiyun 		return rc;
2772*4882a593Smuzhiyun 
2773*4882a593Smuzhiyun 	rc = ebitmap_write(&r->level[0].cat, fp);
2774*4882a593Smuzhiyun 	if (rc)
2775*4882a593Smuzhiyun 		return rc;
2776*4882a593Smuzhiyun 	if (!eq) {
2777*4882a593Smuzhiyun 		rc = ebitmap_write(&r->level[1].cat, fp);
2778*4882a593Smuzhiyun 		if (rc)
2779*4882a593Smuzhiyun 			return rc;
2780*4882a593Smuzhiyun 	}
2781*4882a593Smuzhiyun 
2782*4882a593Smuzhiyun 	return 0;
2783*4882a593Smuzhiyun }
2784*4882a593Smuzhiyun 
sens_write(void * vkey,void * datum,void * ptr)2785*4882a593Smuzhiyun static int sens_write(void *vkey, void *datum, void *ptr)
2786*4882a593Smuzhiyun {
2787*4882a593Smuzhiyun 	char *key = vkey;
2788*4882a593Smuzhiyun 	struct level_datum *levdatum = datum;
2789*4882a593Smuzhiyun 	struct policy_data *pd = ptr;
2790*4882a593Smuzhiyun 	void *fp = pd->fp;
2791*4882a593Smuzhiyun 	__le32 buf[2];
2792*4882a593Smuzhiyun 	size_t len;
2793*4882a593Smuzhiyun 	int rc;
2794*4882a593Smuzhiyun 
2795*4882a593Smuzhiyun 	len = strlen(key);
2796*4882a593Smuzhiyun 	buf[0] = cpu_to_le32(len);
2797*4882a593Smuzhiyun 	buf[1] = cpu_to_le32(levdatum->isalias);
2798*4882a593Smuzhiyun 	rc = put_entry(buf, sizeof(u32), 2, fp);
2799*4882a593Smuzhiyun 	if (rc)
2800*4882a593Smuzhiyun 		return rc;
2801*4882a593Smuzhiyun 
2802*4882a593Smuzhiyun 	rc = put_entry(key, 1, len, fp);
2803*4882a593Smuzhiyun 	if (rc)
2804*4882a593Smuzhiyun 		return rc;
2805*4882a593Smuzhiyun 
2806*4882a593Smuzhiyun 	rc = mls_write_level(levdatum->level, fp);
2807*4882a593Smuzhiyun 	if (rc)
2808*4882a593Smuzhiyun 		return rc;
2809*4882a593Smuzhiyun 
2810*4882a593Smuzhiyun 	return 0;
2811*4882a593Smuzhiyun }
2812*4882a593Smuzhiyun 
cat_write(void * vkey,void * datum,void * ptr)2813*4882a593Smuzhiyun static int cat_write(void *vkey, void *datum, void *ptr)
2814*4882a593Smuzhiyun {
2815*4882a593Smuzhiyun 	char *key = vkey;
2816*4882a593Smuzhiyun 	struct cat_datum *catdatum = datum;
2817*4882a593Smuzhiyun 	struct policy_data *pd = ptr;
2818*4882a593Smuzhiyun 	void *fp = pd->fp;
2819*4882a593Smuzhiyun 	__le32 buf[3];
2820*4882a593Smuzhiyun 	size_t len;
2821*4882a593Smuzhiyun 	int rc;
2822*4882a593Smuzhiyun 
2823*4882a593Smuzhiyun 	len = strlen(key);
2824*4882a593Smuzhiyun 	buf[0] = cpu_to_le32(len);
2825*4882a593Smuzhiyun 	buf[1] = cpu_to_le32(catdatum->value);
2826*4882a593Smuzhiyun 	buf[2] = cpu_to_le32(catdatum->isalias);
2827*4882a593Smuzhiyun 	rc = put_entry(buf, sizeof(u32), 3, fp);
2828*4882a593Smuzhiyun 	if (rc)
2829*4882a593Smuzhiyun 		return rc;
2830*4882a593Smuzhiyun 
2831*4882a593Smuzhiyun 	rc = put_entry(key, 1, len, fp);
2832*4882a593Smuzhiyun 	if (rc)
2833*4882a593Smuzhiyun 		return rc;
2834*4882a593Smuzhiyun 
2835*4882a593Smuzhiyun 	return 0;
2836*4882a593Smuzhiyun }
2837*4882a593Smuzhiyun 
role_trans_write_one(void * key,void * datum,void * ptr)2838*4882a593Smuzhiyun static int role_trans_write_one(void *key, void *datum, void *ptr)
2839*4882a593Smuzhiyun {
2840*4882a593Smuzhiyun 	struct role_trans_key *rtk = key;
2841*4882a593Smuzhiyun 	struct role_trans_datum *rtd = datum;
2842*4882a593Smuzhiyun 	struct policy_data *pd = ptr;
2843*4882a593Smuzhiyun 	void *fp = pd->fp;
2844*4882a593Smuzhiyun 	struct policydb *p = pd->p;
2845*4882a593Smuzhiyun 	__le32 buf[3];
2846*4882a593Smuzhiyun 	int rc;
2847*4882a593Smuzhiyun 
2848*4882a593Smuzhiyun 	buf[0] = cpu_to_le32(rtk->role);
2849*4882a593Smuzhiyun 	buf[1] = cpu_to_le32(rtk->type);
2850*4882a593Smuzhiyun 	buf[2] = cpu_to_le32(rtd->new_role);
2851*4882a593Smuzhiyun 	rc = put_entry(buf, sizeof(u32), 3, fp);
2852*4882a593Smuzhiyun 	if (rc)
2853*4882a593Smuzhiyun 		return rc;
2854*4882a593Smuzhiyun 	if (p->policyvers >= POLICYDB_VERSION_ROLETRANS) {
2855*4882a593Smuzhiyun 		buf[0] = cpu_to_le32(rtk->tclass);
2856*4882a593Smuzhiyun 		rc = put_entry(buf, sizeof(u32), 1, fp);
2857*4882a593Smuzhiyun 		if (rc)
2858*4882a593Smuzhiyun 			return rc;
2859*4882a593Smuzhiyun 	}
2860*4882a593Smuzhiyun 	return 0;
2861*4882a593Smuzhiyun }
2862*4882a593Smuzhiyun 
role_trans_write(struct policydb * p,void * fp)2863*4882a593Smuzhiyun static int role_trans_write(struct policydb *p, void *fp)
2864*4882a593Smuzhiyun {
2865*4882a593Smuzhiyun 	struct policy_data pd = { .p = p, .fp = fp };
2866*4882a593Smuzhiyun 	__le32 buf[1];
2867*4882a593Smuzhiyun 	int rc;
2868*4882a593Smuzhiyun 
2869*4882a593Smuzhiyun 	buf[0] = cpu_to_le32(p->role_tr.nel);
2870*4882a593Smuzhiyun 	rc = put_entry(buf, sizeof(u32), 1, fp);
2871*4882a593Smuzhiyun 	if (rc)
2872*4882a593Smuzhiyun 		return rc;
2873*4882a593Smuzhiyun 
2874*4882a593Smuzhiyun 	return hashtab_map(&p->role_tr, role_trans_write_one, &pd);
2875*4882a593Smuzhiyun }
2876*4882a593Smuzhiyun 
role_allow_write(struct role_allow * r,void * fp)2877*4882a593Smuzhiyun static int role_allow_write(struct role_allow *r, void *fp)
2878*4882a593Smuzhiyun {
2879*4882a593Smuzhiyun 	struct role_allow *ra;
2880*4882a593Smuzhiyun 	__le32 buf[2];
2881*4882a593Smuzhiyun 	size_t nel;
2882*4882a593Smuzhiyun 	int rc;
2883*4882a593Smuzhiyun 
2884*4882a593Smuzhiyun 	nel = 0;
2885*4882a593Smuzhiyun 	for (ra = r; ra; ra = ra->next)
2886*4882a593Smuzhiyun 		nel++;
2887*4882a593Smuzhiyun 	buf[0] = cpu_to_le32(nel);
2888*4882a593Smuzhiyun 	rc = put_entry(buf, sizeof(u32), 1, fp);
2889*4882a593Smuzhiyun 	if (rc)
2890*4882a593Smuzhiyun 		return rc;
2891*4882a593Smuzhiyun 	for (ra = r; ra; ra = ra->next) {
2892*4882a593Smuzhiyun 		buf[0] = cpu_to_le32(ra->role);
2893*4882a593Smuzhiyun 		buf[1] = cpu_to_le32(ra->new_role);
2894*4882a593Smuzhiyun 		rc = put_entry(buf, sizeof(u32), 2, fp);
2895*4882a593Smuzhiyun 		if (rc)
2896*4882a593Smuzhiyun 			return rc;
2897*4882a593Smuzhiyun 	}
2898*4882a593Smuzhiyun 	return 0;
2899*4882a593Smuzhiyun }
2900*4882a593Smuzhiyun 
2901*4882a593Smuzhiyun /*
2902*4882a593Smuzhiyun  * Write a security context structure
2903*4882a593Smuzhiyun  * to a policydb binary representation file.
2904*4882a593Smuzhiyun  */
context_write(struct policydb * p,struct context * c,void * fp)2905*4882a593Smuzhiyun static int context_write(struct policydb *p, struct context *c,
2906*4882a593Smuzhiyun 			 void *fp)
2907*4882a593Smuzhiyun {
2908*4882a593Smuzhiyun 	int rc;
2909*4882a593Smuzhiyun 	__le32 buf[3];
2910*4882a593Smuzhiyun 
2911*4882a593Smuzhiyun 	buf[0] = cpu_to_le32(c->user);
2912*4882a593Smuzhiyun 	buf[1] = cpu_to_le32(c->role);
2913*4882a593Smuzhiyun 	buf[2] = cpu_to_le32(c->type);
2914*4882a593Smuzhiyun 
2915*4882a593Smuzhiyun 	rc = put_entry(buf, sizeof(u32), 3, fp);
2916*4882a593Smuzhiyun 	if (rc)
2917*4882a593Smuzhiyun 		return rc;
2918*4882a593Smuzhiyun 
2919*4882a593Smuzhiyun 	rc = mls_write_range_helper(&c->range, fp);
2920*4882a593Smuzhiyun 	if (rc)
2921*4882a593Smuzhiyun 		return rc;
2922*4882a593Smuzhiyun 
2923*4882a593Smuzhiyun 	return 0;
2924*4882a593Smuzhiyun }
2925*4882a593Smuzhiyun 
2926*4882a593Smuzhiyun /*
2927*4882a593Smuzhiyun  * The following *_write functions are used to
2928*4882a593Smuzhiyun  * write the symbol data to a policy database
2929*4882a593Smuzhiyun  * binary representation file.
2930*4882a593Smuzhiyun  */
2931*4882a593Smuzhiyun 
perm_write(void * vkey,void * datum,void * fp)2932*4882a593Smuzhiyun static int perm_write(void *vkey, void *datum, void *fp)
2933*4882a593Smuzhiyun {
2934*4882a593Smuzhiyun 	char *key = vkey;
2935*4882a593Smuzhiyun 	struct perm_datum *perdatum = datum;
2936*4882a593Smuzhiyun 	__le32 buf[2];
2937*4882a593Smuzhiyun 	size_t len;
2938*4882a593Smuzhiyun 	int rc;
2939*4882a593Smuzhiyun 
2940*4882a593Smuzhiyun 	len = strlen(key);
2941*4882a593Smuzhiyun 	buf[0] = cpu_to_le32(len);
2942*4882a593Smuzhiyun 	buf[1] = cpu_to_le32(perdatum->value);
2943*4882a593Smuzhiyun 	rc = put_entry(buf, sizeof(u32), 2, fp);
2944*4882a593Smuzhiyun 	if (rc)
2945*4882a593Smuzhiyun 		return rc;
2946*4882a593Smuzhiyun 
2947*4882a593Smuzhiyun 	rc = put_entry(key, 1, len, fp);
2948*4882a593Smuzhiyun 	if (rc)
2949*4882a593Smuzhiyun 		return rc;
2950*4882a593Smuzhiyun 
2951*4882a593Smuzhiyun 	return 0;
2952*4882a593Smuzhiyun }
2953*4882a593Smuzhiyun 
common_write(void * vkey,void * datum,void * ptr)2954*4882a593Smuzhiyun static int common_write(void *vkey, void *datum, void *ptr)
2955*4882a593Smuzhiyun {
2956*4882a593Smuzhiyun 	char *key = vkey;
2957*4882a593Smuzhiyun 	struct common_datum *comdatum = datum;
2958*4882a593Smuzhiyun 	struct policy_data *pd = ptr;
2959*4882a593Smuzhiyun 	void *fp = pd->fp;
2960*4882a593Smuzhiyun 	__le32 buf[4];
2961*4882a593Smuzhiyun 	size_t len;
2962*4882a593Smuzhiyun 	int rc;
2963*4882a593Smuzhiyun 
2964*4882a593Smuzhiyun 	len = strlen(key);
2965*4882a593Smuzhiyun 	buf[0] = cpu_to_le32(len);
2966*4882a593Smuzhiyun 	buf[1] = cpu_to_le32(comdatum->value);
2967*4882a593Smuzhiyun 	buf[2] = cpu_to_le32(comdatum->permissions.nprim);
2968*4882a593Smuzhiyun 	buf[3] = cpu_to_le32(comdatum->permissions.table.nel);
2969*4882a593Smuzhiyun 	rc = put_entry(buf, sizeof(u32), 4, fp);
2970*4882a593Smuzhiyun 	if (rc)
2971*4882a593Smuzhiyun 		return rc;
2972*4882a593Smuzhiyun 
2973*4882a593Smuzhiyun 	rc = put_entry(key, 1, len, fp);
2974*4882a593Smuzhiyun 	if (rc)
2975*4882a593Smuzhiyun 		return rc;
2976*4882a593Smuzhiyun 
2977*4882a593Smuzhiyun 	rc = hashtab_map(&comdatum->permissions.table, perm_write, fp);
2978*4882a593Smuzhiyun 	if (rc)
2979*4882a593Smuzhiyun 		return rc;
2980*4882a593Smuzhiyun 
2981*4882a593Smuzhiyun 	return 0;
2982*4882a593Smuzhiyun }
2983*4882a593Smuzhiyun 
type_set_write(struct type_set * t,void * fp)2984*4882a593Smuzhiyun static int type_set_write(struct type_set *t, void *fp)
2985*4882a593Smuzhiyun {
2986*4882a593Smuzhiyun 	int rc;
2987*4882a593Smuzhiyun 	__le32 buf[1];
2988*4882a593Smuzhiyun 
2989*4882a593Smuzhiyun 	if (ebitmap_write(&t->types, fp))
2990*4882a593Smuzhiyun 		return -EINVAL;
2991*4882a593Smuzhiyun 	if (ebitmap_write(&t->negset, fp))
2992*4882a593Smuzhiyun 		return -EINVAL;
2993*4882a593Smuzhiyun 
2994*4882a593Smuzhiyun 	buf[0] = cpu_to_le32(t->flags);
2995*4882a593Smuzhiyun 	rc = put_entry(buf, sizeof(u32), 1, fp);
2996*4882a593Smuzhiyun 	if (rc)
2997*4882a593Smuzhiyun 		return -EINVAL;
2998*4882a593Smuzhiyun 
2999*4882a593Smuzhiyun 	return 0;
3000*4882a593Smuzhiyun }
3001*4882a593Smuzhiyun 
write_cons_helper(struct policydb * p,struct constraint_node * node,void * fp)3002*4882a593Smuzhiyun static int write_cons_helper(struct policydb *p, struct constraint_node *node,
3003*4882a593Smuzhiyun 			     void *fp)
3004*4882a593Smuzhiyun {
3005*4882a593Smuzhiyun 	struct constraint_node *c;
3006*4882a593Smuzhiyun 	struct constraint_expr *e;
3007*4882a593Smuzhiyun 	__le32 buf[3];
3008*4882a593Smuzhiyun 	u32 nel;
3009*4882a593Smuzhiyun 	int rc;
3010*4882a593Smuzhiyun 
3011*4882a593Smuzhiyun 	for (c = node; c; c = c->next) {
3012*4882a593Smuzhiyun 		nel = 0;
3013*4882a593Smuzhiyun 		for (e = c->expr; e; e = e->next)
3014*4882a593Smuzhiyun 			nel++;
3015*4882a593Smuzhiyun 		buf[0] = cpu_to_le32(c->permissions);
3016*4882a593Smuzhiyun 		buf[1] = cpu_to_le32(nel);
3017*4882a593Smuzhiyun 		rc = put_entry(buf, sizeof(u32), 2, fp);
3018*4882a593Smuzhiyun 		if (rc)
3019*4882a593Smuzhiyun 			return rc;
3020*4882a593Smuzhiyun 		for (e = c->expr; e; e = e->next) {
3021*4882a593Smuzhiyun 			buf[0] = cpu_to_le32(e->expr_type);
3022*4882a593Smuzhiyun 			buf[1] = cpu_to_le32(e->attr);
3023*4882a593Smuzhiyun 			buf[2] = cpu_to_le32(e->op);
3024*4882a593Smuzhiyun 			rc = put_entry(buf, sizeof(u32), 3, fp);
3025*4882a593Smuzhiyun 			if (rc)
3026*4882a593Smuzhiyun 				return rc;
3027*4882a593Smuzhiyun 
3028*4882a593Smuzhiyun 			switch (e->expr_type) {
3029*4882a593Smuzhiyun 			case CEXPR_NAMES:
3030*4882a593Smuzhiyun 				rc = ebitmap_write(&e->names, fp);
3031*4882a593Smuzhiyun 				if (rc)
3032*4882a593Smuzhiyun 					return rc;
3033*4882a593Smuzhiyun 				if (p->policyvers >=
3034*4882a593Smuzhiyun 					POLICYDB_VERSION_CONSTRAINT_NAMES) {
3035*4882a593Smuzhiyun 					rc = type_set_write(e->type_names, fp);
3036*4882a593Smuzhiyun 					if (rc)
3037*4882a593Smuzhiyun 						return rc;
3038*4882a593Smuzhiyun 				}
3039*4882a593Smuzhiyun 				break;
3040*4882a593Smuzhiyun 			default:
3041*4882a593Smuzhiyun 				break;
3042*4882a593Smuzhiyun 			}
3043*4882a593Smuzhiyun 		}
3044*4882a593Smuzhiyun 	}
3045*4882a593Smuzhiyun 
3046*4882a593Smuzhiyun 	return 0;
3047*4882a593Smuzhiyun }
3048*4882a593Smuzhiyun 
class_write(void * vkey,void * datum,void * ptr)3049*4882a593Smuzhiyun static int class_write(void *vkey, void *datum, void *ptr)
3050*4882a593Smuzhiyun {
3051*4882a593Smuzhiyun 	char *key = vkey;
3052*4882a593Smuzhiyun 	struct class_datum *cladatum = datum;
3053*4882a593Smuzhiyun 	struct policy_data *pd = ptr;
3054*4882a593Smuzhiyun 	void *fp = pd->fp;
3055*4882a593Smuzhiyun 	struct policydb *p = pd->p;
3056*4882a593Smuzhiyun 	struct constraint_node *c;
3057*4882a593Smuzhiyun 	__le32 buf[6];
3058*4882a593Smuzhiyun 	u32 ncons;
3059*4882a593Smuzhiyun 	size_t len, len2;
3060*4882a593Smuzhiyun 	int rc;
3061*4882a593Smuzhiyun 
3062*4882a593Smuzhiyun 	len = strlen(key);
3063*4882a593Smuzhiyun 	if (cladatum->comkey)
3064*4882a593Smuzhiyun 		len2 = strlen(cladatum->comkey);
3065*4882a593Smuzhiyun 	else
3066*4882a593Smuzhiyun 		len2 = 0;
3067*4882a593Smuzhiyun 
3068*4882a593Smuzhiyun 	ncons = 0;
3069*4882a593Smuzhiyun 	for (c = cladatum->constraints; c; c = c->next)
3070*4882a593Smuzhiyun 		ncons++;
3071*4882a593Smuzhiyun 
3072*4882a593Smuzhiyun 	buf[0] = cpu_to_le32(len);
3073*4882a593Smuzhiyun 	buf[1] = cpu_to_le32(len2);
3074*4882a593Smuzhiyun 	buf[2] = cpu_to_le32(cladatum->value);
3075*4882a593Smuzhiyun 	buf[3] = cpu_to_le32(cladatum->permissions.nprim);
3076*4882a593Smuzhiyun 	buf[4] = cpu_to_le32(cladatum->permissions.table.nel);
3077*4882a593Smuzhiyun 	buf[5] = cpu_to_le32(ncons);
3078*4882a593Smuzhiyun 	rc = put_entry(buf, sizeof(u32), 6, fp);
3079*4882a593Smuzhiyun 	if (rc)
3080*4882a593Smuzhiyun 		return rc;
3081*4882a593Smuzhiyun 
3082*4882a593Smuzhiyun 	rc = put_entry(key, 1, len, fp);
3083*4882a593Smuzhiyun 	if (rc)
3084*4882a593Smuzhiyun 		return rc;
3085*4882a593Smuzhiyun 
3086*4882a593Smuzhiyun 	if (cladatum->comkey) {
3087*4882a593Smuzhiyun 		rc = put_entry(cladatum->comkey, 1, len2, fp);
3088*4882a593Smuzhiyun 		if (rc)
3089*4882a593Smuzhiyun 			return rc;
3090*4882a593Smuzhiyun 	}
3091*4882a593Smuzhiyun 
3092*4882a593Smuzhiyun 	rc = hashtab_map(&cladatum->permissions.table, perm_write, fp);
3093*4882a593Smuzhiyun 	if (rc)
3094*4882a593Smuzhiyun 		return rc;
3095*4882a593Smuzhiyun 
3096*4882a593Smuzhiyun 	rc = write_cons_helper(p, cladatum->constraints, fp);
3097*4882a593Smuzhiyun 	if (rc)
3098*4882a593Smuzhiyun 		return rc;
3099*4882a593Smuzhiyun 
3100*4882a593Smuzhiyun 	/* write out the validatetrans rule */
3101*4882a593Smuzhiyun 	ncons = 0;
3102*4882a593Smuzhiyun 	for (c = cladatum->validatetrans; c; c = c->next)
3103*4882a593Smuzhiyun 		ncons++;
3104*4882a593Smuzhiyun 
3105*4882a593Smuzhiyun 	buf[0] = cpu_to_le32(ncons);
3106*4882a593Smuzhiyun 	rc = put_entry(buf, sizeof(u32), 1, fp);
3107*4882a593Smuzhiyun 	if (rc)
3108*4882a593Smuzhiyun 		return rc;
3109*4882a593Smuzhiyun 
3110*4882a593Smuzhiyun 	rc = write_cons_helper(p, cladatum->validatetrans, fp);
3111*4882a593Smuzhiyun 	if (rc)
3112*4882a593Smuzhiyun 		return rc;
3113*4882a593Smuzhiyun 
3114*4882a593Smuzhiyun 	if (p->policyvers >= POLICYDB_VERSION_NEW_OBJECT_DEFAULTS) {
3115*4882a593Smuzhiyun 		buf[0] = cpu_to_le32(cladatum->default_user);
3116*4882a593Smuzhiyun 		buf[1] = cpu_to_le32(cladatum->default_role);
3117*4882a593Smuzhiyun 		buf[2] = cpu_to_le32(cladatum->default_range);
3118*4882a593Smuzhiyun 
3119*4882a593Smuzhiyun 		rc = put_entry(buf, sizeof(uint32_t), 3, fp);
3120*4882a593Smuzhiyun 		if (rc)
3121*4882a593Smuzhiyun 			return rc;
3122*4882a593Smuzhiyun 	}
3123*4882a593Smuzhiyun 
3124*4882a593Smuzhiyun 	if (p->policyvers >= POLICYDB_VERSION_DEFAULT_TYPE) {
3125*4882a593Smuzhiyun 		buf[0] = cpu_to_le32(cladatum->default_type);
3126*4882a593Smuzhiyun 		rc = put_entry(buf, sizeof(uint32_t), 1, fp);
3127*4882a593Smuzhiyun 		if (rc)
3128*4882a593Smuzhiyun 			return rc;
3129*4882a593Smuzhiyun 	}
3130*4882a593Smuzhiyun 
3131*4882a593Smuzhiyun 	return 0;
3132*4882a593Smuzhiyun }
3133*4882a593Smuzhiyun 
role_write(void * vkey,void * datum,void * ptr)3134*4882a593Smuzhiyun static int role_write(void *vkey, void *datum, void *ptr)
3135*4882a593Smuzhiyun {
3136*4882a593Smuzhiyun 	char *key = vkey;
3137*4882a593Smuzhiyun 	struct role_datum *role = datum;
3138*4882a593Smuzhiyun 	struct policy_data *pd = ptr;
3139*4882a593Smuzhiyun 	void *fp = pd->fp;
3140*4882a593Smuzhiyun 	struct policydb *p = pd->p;
3141*4882a593Smuzhiyun 	__le32 buf[3];
3142*4882a593Smuzhiyun 	size_t items, len;
3143*4882a593Smuzhiyun 	int rc;
3144*4882a593Smuzhiyun 
3145*4882a593Smuzhiyun 	len = strlen(key);
3146*4882a593Smuzhiyun 	items = 0;
3147*4882a593Smuzhiyun 	buf[items++] = cpu_to_le32(len);
3148*4882a593Smuzhiyun 	buf[items++] = cpu_to_le32(role->value);
3149*4882a593Smuzhiyun 	if (p->policyvers >= POLICYDB_VERSION_BOUNDARY)
3150*4882a593Smuzhiyun 		buf[items++] = cpu_to_le32(role->bounds);
3151*4882a593Smuzhiyun 
3152*4882a593Smuzhiyun 	BUG_ON(items > ARRAY_SIZE(buf));
3153*4882a593Smuzhiyun 
3154*4882a593Smuzhiyun 	rc = put_entry(buf, sizeof(u32), items, fp);
3155*4882a593Smuzhiyun 	if (rc)
3156*4882a593Smuzhiyun 		return rc;
3157*4882a593Smuzhiyun 
3158*4882a593Smuzhiyun 	rc = put_entry(key, 1, len, fp);
3159*4882a593Smuzhiyun 	if (rc)
3160*4882a593Smuzhiyun 		return rc;
3161*4882a593Smuzhiyun 
3162*4882a593Smuzhiyun 	rc = ebitmap_write(&role->dominates, fp);
3163*4882a593Smuzhiyun 	if (rc)
3164*4882a593Smuzhiyun 		return rc;
3165*4882a593Smuzhiyun 
3166*4882a593Smuzhiyun 	rc = ebitmap_write(&role->types, fp);
3167*4882a593Smuzhiyun 	if (rc)
3168*4882a593Smuzhiyun 		return rc;
3169*4882a593Smuzhiyun 
3170*4882a593Smuzhiyun 	return 0;
3171*4882a593Smuzhiyun }
3172*4882a593Smuzhiyun 
type_write(void * vkey,void * datum,void * ptr)3173*4882a593Smuzhiyun static int type_write(void *vkey, void *datum, void *ptr)
3174*4882a593Smuzhiyun {
3175*4882a593Smuzhiyun 	char *key = vkey;
3176*4882a593Smuzhiyun 	struct type_datum *typdatum = datum;
3177*4882a593Smuzhiyun 	struct policy_data *pd = ptr;
3178*4882a593Smuzhiyun 	struct policydb *p = pd->p;
3179*4882a593Smuzhiyun 	void *fp = pd->fp;
3180*4882a593Smuzhiyun 	__le32 buf[4];
3181*4882a593Smuzhiyun 	int rc;
3182*4882a593Smuzhiyun 	size_t items, len;
3183*4882a593Smuzhiyun 
3184*4882a593Smuzhiyun 	len = strlen(key);
3185*4882a593Smuzhiyun 	items = 0;
3186*4882a593Smuzhiyun 	buf[items++] = cpu_to_le32(len);
3187*4882a593Smuzhiyun 	buf[items++] = cpu_to_le32(typdatum->value);
3188*4882a593Smuzhiyun 	if (p->policyvers >= POLICYDB_VERSION_BOUNDARY) {
3189*4882a593Smuzhiyun 		u32 properties = 0;
3190*4882a593Smuzhiyun 
3191*4882a593Smuzhiyun 		if (typdatum->primary)
3192*4882a593Smuzhiyun 			properties |= TYPEDATUM_PROPERTY_PRIMARY;
3193*4882a593Smuzhiyun 
3194*4882a593Smuzhiyun 		if (typdatum->attribute)
3195*4882a593Smuzhiyun 			properties |= TYPEDATUM_PROPERTY_ATTRIBUTE;
3196*4882a593Smuzhiyun 
3197*4882a593Smuzhiyun 		buf[items++] = cpu_to_le32(properties);
3198*4882a593Smuzhiyun 		buf[items++] = cpu_to_le32(typdatum->bounds);
3199*4882a593Smuzhiyun 	} else {
3200*4882a593Smuzhiyun 		buf[items++] = cpu_to_le32(typdatum->primary);
3201*4882a593Smuzhiyun 	}
3202*4882a593Smuzhiyun 	BUG_ON(items > ARRAY_SIZE(buf));
3203*4882a593Smuzhiyun 	rc = put_entry(buf, sizeof(u32), items, fp);
3204*4882a593Smuzhiyun 	if (rc)
3205*4882a593Smuzhiyun 		return rc;
3206*4882a593Smuzhiyun 
3207*4882a593Smuzhiyun 	rc = put_entry(key, 1, len, fp);
3208*4882a593Smuzhiyun 	if (rc)
3209*4882a593Smuzhiyun 		return rc;
3210*4882a593Smuzhiyun 
3211*4882a593Smuzhiyun 	return 0;
3212*4882a593Smuzhiyun }
3213*4882a593Smuzhiyun 
user_write(void * vkey,void * datum,void * ptr)3214*4882a593Smuzhiyun static int user_write(void *vkey, void *datum, void *ptr)
3215*4882a593Smuzhiyun {
3216*4882a593Smuzhiyun 	char *key = vkey;
3217*4882a593Smuzhiyun 	struct user_datum *usrdatum = datum;
3218*4882a593Smuzhiyun 	struct policy_data *pd = ptr;
3219*4882a593Smuzhiyun 	struct policydb *p = pd->p;
3220*4882a593Smuzhiyun 	void *fp = pd->fp;
3221*4882a593Smuzhiyun 	__le32 buf[3];
3222*4882a593Smuzhiyun 	size_t items, len;
3223*4882a593Smuzhiyun 	int rc;
3224*4882a593Smuzhiyun 
3225*4882a593Smuzhiyun 	len = strlen(key);
3226*4882a593Smuzhiyun 	items = 0;
3227*4882a593Smuzhiyun 	buf[items++] = cpu_to_le32(len);
3228*4882a593Smuzhiyun 	buf[items++] = cpu_to_le32(usrdatum->value);
3229*4882a593Smuzhiyun 	if (p->policyvers >= POLICYDB_VERSION_BOUNDARY)
3230*4882a593Smuzhiyun 		buf[items++] = cpu_to_le32(usrdatum->bounds);
3231*4882a593Smuzhiyun 	BUG_ON(items > ARRAY_SIZE(buf));
3232*4882a593Smuzhiyun 	rc = put_entry(buf, sizeof(u32), items, fp);
3233*4882a593Smuzhiyun 	if (rc)
3234*4882a593Smuzhiyun 		return rc;
3235*4882a593Smuzhiyun 
3236*4882a593Smuzhiyun 	rc = put_entry(key, 1, len, fp);
3237*4882a593Smuzhiyun 	if (rc)
3238*4882a593Smuzhiyun 		return rc;
3239*4882a593Smuzhiyun 
3240*4882a593Smuzhiyun 	rc = ebitmap_write(&usrdatum->roles, fp);
3241*4882a593Smuzhiyun 	if (rc)
3242*4882a593Smuzhiyun 		return rc;
3243*4882a593Smuzhiyun 
3244*4882a593Smuzhiyun 	rc = mls_write_range_helper(&usrdatum->range, fp);
3245*4882a593Smuzhiyun 	if (rc)
3246*4882a593Smuzhiyun 		return rc;
3247*4882a593Smuzhiyun 
3248*4882a593Smuzhiyun 	rc = mls_write_level(&usrdatum->dfltlevel, fp);
3249*4882a593Smuzhiyun 	if (rc)
3250*4882a593Smuzhiyun 		return rc;
3251*4882a593Smuzhiyun 
3252*4882a593Smuzhiyun 	return 0;
3253*4882a593Smuzhiyun }
3254*4882a593Smuzhiyun 
3255*4882a593Smuzhiyun static int (*write_f[SYM_NUM]) (void *key, void *datum,
3256*4882a593Smuzhiyun 				void *datap) =
3257*4882a593Smuzhiyun {
3258*4882a593Smuzhiyun 	common_write,
3259*4882a593Smuzhiyun 	class_write,
3260*4882a593Smuzhiyun 	role_write,
3261*4882a593Smuzhiyun 	type_write,
3262*4882a593Smuzhiyun 	user_write,
3263*4882a593Smuzhiyun 	cond_write_bool,
3264*4882a593Smuzhiyun 	sens_write,
3265*4882a593Smuzhiyun 	cat_write,
3266*4882a593Smuzhiyun };
3267*4882a593Smuzhiyun 
ocontext_write(struct policydb * p,struct policydb_compat_info * info,void * fp)3268*4882a593Smuzhiyun static int ocontext_write(struct policydb *p, struct policydb_compat_info *info,
3269*4882a593Smuzhiyun 			  void *fp)
3270*4882a593Smuzhiyun {
3271*4882a593Smuzhiyun 	unsigned int i, j, rc;
3272*4882a593Smuzhiyun 	size_t nel, len;
3273*4882a593Smuzhiyun 	__be64 prefixbuf[1];
3274*4882a593Smuzhiyun 	__le32 buf[3];
3275*4882a593Smuzhiyun 	u32 nodebuf[8];
3276*4882a593Smuzhiyun 	struct ocontext *c;
3277*4882a593Smuzhiyun 	for (i = 0; i < info->ocon_num; i++) {
3278*4882a593Smuzhiyun 		nel = 0;
3279*4882a593Smuzhiyun 		for (c = p->ocontexts[i]; c; c = c->next)
3280*4882a593Smuzhiyun 			nel++;
3281*4882a593Smuzhiyun 		buf[0] = cpu_to_le32(nel);
3282*4882a593Smuzhiyun 		rc = put_entry(buf, sizeof(u32), 1, fp);
3283*4882a593Smuzhiyun 		if (rc)
3284*4882a593Smuzhiyun 			return rc;
3285*4882a593Smuzhiyun 		for (c = p->ocontexts[i]; c; c = c->next) {
3286*4882a593Smuzhiyun 			switch (i) {
3287*4882a593Smuzhiyun 			case OCON_ISID:
3288*4882a593Smuzhiyun 				buf[0] = cpu_to_le32(c->sid[0]);
3289*4882a593Smuzhiyun 				rc = put_entry(buf, sizeof(u32), 1, fp);
3290*4882a593Smuzhiyun 				if (rc)
3291*4882a593Smuzhiyun 					return rc;
3292*4882a593Smuzhiyun 				rc = context_write(p, &c->context[0], fp);
3293*4882a593Smuzhiyun 				if (rc)
3294*4882a593Smuzhiyun 					return rc;
3295*4882a593Smuzhiyun 				break;
3296*4882a593Smuzhiyun 			case OCON_FS:
3297*4882a593Smuzhiyun 			case OCON_NETIF:
3298*4882a593Smuzhiyun 				len = strlen(c->u.name);
3299*4882a593Smuzhiyun 				buf[0] = cpu_to_le32(len);
3300*4882a593Smuzhiyun 				rc = put_entry(buf, sizeof(u32), 1, fp);
3301*4882a593Smuzhiyun 				if (rc)
3302*4882a593Smuzhiyun 					return rc;
3303*4882a593Smuzhiyun 				rc = put_entry(c->u.name, 1, len, fp);
3304*4882a593Smuzhiyun 				if (rc)
3305*4882a593Smuzhiyun 					return rc;
3306*4882a593Smuzhiyun 				rc = context_write(p, &c->context[0], fp);
3307*4882a593Smuzhiyun 				if (rc)
3308*4882a593Smuzhiyun 					return rc;
3309*4882a593Smuzhiyun 				rc = context_write(p, &c->context[1], fp);
3310*4882a593Smuzhiyun 				if (rc)
3311*4882a593Smuzhiyun 					return rc;
3312*4882a593Smuzhiyun 				break;
3313*4882a593Smuzhiyun 			case OCON_PORT:
3314*4882a593Smuzhiyun 				buf[0] = cpu_to_le32(c->u.port.protocol);
3315*4882a593Smuzhiyun 				buf[1] = cpu_to_le32(c->u.port.low_port);
3316*4882a593Smuzhiyun 				buf[2] = cpu_to_le32(c->u.port.high_port);
3317*4882a593Smuzhiyun 				rc = put_entry(buf, sizeof(u32), 3, fp);
3318*4882a593Smuzhiyun 				if (rc)
3319*4882a593Smuzhiyun 					return rc;
3320*4882a593Smuzhiyun 				rc = context_write(p, &c->context[0], fp);
3321*4882a593Smuzhiyun 				if (rc)
3322*4882a593Smuzhiyun 					return rc;
3323*4882a593Smuzhiyun 				break;
3324*4882a593Smuzhiyun 			case OCON_NODE:
3325*4882a593Smuzhiyun 				nodebuf[0] = c->u.node.addr; /* network order */
3326*4882a593Smuzhiyun 				nodebuf[1] = c->u.node.mask; /* network order */
3327*4882a593Smuzhiyun 				rc = put_entry(nodebuf, sizeof(u32), 2, fp);
3328*4882a593Smuzhiyun 				if (rc)
3329*4882a593Smuzhiyun 					return rc;
3330*4882a593Smuzhiyun 				rc = context_write(p, &c->context[0], fp);
3331*4882a593Smuzhiyun 				if (rc)
3332*4882a593Smuzhiyun 					return rc;
3333*4882a593Smuzhiyun 				break;
3334*4882a593Smuzhiyun 			case OCON_FSUSE:
3335*4882a593Smuzhiyun 				buf[0] = cpu_to_le32(c->v.behavior);
3336*4882a593Smuzhiyun 				len = strlen(c->u.name);
3337*4882a593Smuzhiyun 				buf[1] = cpu_to_le32(len);
3338*4882a593Smuzhiyun 				rc = put_entry(buf, sizeof(u32), 2, fp);
3339*4882a593Smuzhiyun 				if (rc)
3340*4882a593Smuzhiyun 					return rc;
3341*4882a593Smuzhiyun 				rc = put_entry(c->u.name, 1, len, fp);
3342*4882a593Smuzhiyun 				if (rc)
3343*4882a593Smuzhiyun 					return rc;
3344*4882a593Smuzhiyun 				rc = context_write(p, &c->context[0], fp);
3345*4882a593Smuzhiyun 				if (rc)
3346*4882a593Smuzhiyun 					return rc;
3347*4882a593Smuzhiyun 				break;
3348*4882a593Smuzhiyun 			case OCON_NODE6:
3349*4882a593Smuzhiyun 				for (j = 0; j < 4; j++)
3350*4882a593Smuzhiyun 					nodebuf[j] = c->u.node6.addr[j]; /* network order */
3351*4882a593Smuzhiyun 				for (j = 0; j < 4; j++)
3352*4882a593Smuzhiyun 					nodebuf[j + 4] = c->u.node6.mask[j]; /* network order */
3353*4882a593Smuzhiyun 				rc = put_entry(nodebuf, sizeof(u32), 8, fp);
3354*4882a593Smuzhiyun 				if (rc)
3355*4882a593Smuzhiyun 					return rc;
3356*4882a593Smuzhiyun 				rc = context_write(p, &c->context[0], fp);
3357*4882a593Smuzhiyun 				if (rc)
3358*4882a593Smuzhiyun 					return rc;
3359*4882a593Smuzhiyun 				break;
3360*4882a593Smuzhiyun 			case OCON_IBPKEY:
3361*4882a593Smuzhiyun 				/* subnet_prefix is in CPU order */
3362*4882a593Smuzhiyun 				prefixbuf[0] = cpu_to_be64(c->u.ibpkey.subnet_prefix);
3363*4882a593Smuzhiyun 
3364*4882a593Smuzhiyun 				rc = put_entry(prefixbuf, sizeof(u64), 1, fp);
3365*4882a593Smuzhiyun 				if (rc)
3366*4882a593Smuzhiyun 					return rc;
3367*4882a593Smuzhiyun 
3368*4882a593Smuzhiyun 				buf[0] = cpu_to_le32(c->u.ibpkey.low_pkey);
3369*4882a593Smuzhiyun 				buf[1] = cpu_to_le32(c->u.ibpkey.high_pkey);
3370*4882a593Smuzhiyun 
3371*4882a593Smuzhiyun 				rc = put_entry(buf, sizeof(u32), 2, fp);
3372*4882a593Smuzhiyun 				if (rc)
3373*4882a593Smuzhiyun 					return rc;
3374*4882a593Smuzhiyun 				rc = context_write(p, &c->context[0], fp);
3375*4882a593Smuzhiyun 				if (rc)
3376*4882a593Smuzhiyun 					return rc;
3377*4882a593Smuzhiyun 				break;
3378*4882a593Smuzhiyun 			case OCON_IBENDPORT:
3379*4882a593Smuzhiyun 				len = strlen(c->u.ibendport.dev_name);
3380*4882a593Smuzhiyun 				buf[0] = cpu_to_le32(len);
3381*4882a593Smuzhiyun 				buf[1] = cpu_to_le32(c->u.ibendport.port);
3382*4882a593Smuzhiyun 				rc = put_entry(buf, sizeof(u32), 2, fp);
3383*4882a593Smuzhiyun 				if (rc)
3384*4882a593Smuzhiyun 					return rc;
3385*4882a593Smuzhiyun 				rc = put_entry(c->u.ibendport.dev_name, 1, len, fp);
3386*4882a593Smuzhiyun 				if (rc)
3387*4882a593Smuzhiyun 					return rc;
3388*4882a593Smuzhiyun 				rc = context_write(p, &c->context[0], fp);
3389*4882a593Smuzhiyun 				if (rc)
3390*4882a593Smuzhiyun 					return rc;
3391*4882a593Smuzhiyun 				break;
3392*4882a593Smuzhiyun 			}
3393*4882a593Smuzhiyun 		}
3394*4882a593Smuzhiyun 	}
3395*4882a593Smuzhiyun 	return 0;
3396*4882a593Smuzhiyun }
3397*4882a593Smuzhiyun 
genfs_write(struct policydb * p,void * fp)3398*4882a593Smuzhiyun static int genfs_write(struct policydb *p, void *fp)
3399*4882a593Smuzhiyun {
3400*4882a593Smuzhiyun 	struct genfs *genfs;
3401*4882a593Smuzhiyun 	struct ocontext *c;
3402*4882a593Smuzhiyun 	size_t len;
3403*4882a593Smuzhiyun 	__le32 buf[1];
3404*4882a593Smuzhiyun 	int rc;
3405*4882a593Smuzhiyun 
3406*4882a593Smuzhiyun 	len = 0;
3407*4882a593Smuzhiyun 	for (genfs = p->genfs; genfs; genfs = genfs->next)
3408*4882a593Smuzhiyun 		len++;
3409*4882a593Smuzhiyun 	buf[0] = cpu_to_le32(len);
3410*4882a593Smuzhiyun 	rc = put_entry(buf, sizeof(u32), 1, fp);
3411*4882a593Smuzhiyun 	if (rc)
3412*4882a593Smuzhiyun 		return rc;
3413*4882a593Smuzhiyun 	for (genfs = p->genfs; genfs; genfs = genfs->next) {
3414*4882a593Smuzhiyun 		len = strlen(genfs->fstype);
3415*4882a593Smuzhiyun 		buf[0] = cpu_to_le32(len);
3416*4882a593Smuzhiyun 		rc = put_entry(buf, sizeof(u32), 1, fp);
3417*4882a593Smuzhiyun 		if (rc)
3418*4882a593Smuzhiyun 			return rc;
3419*4882a593Smuzhiyun 		rc = put_entry(genfs->fstype, 1, len, fp);
3420*4882a593Smuzhiyun 		if (rc)
3421*4882a593Smuzhiyun 			return rc;
3422*4882a593Smuzhiyun 		len = 0;
3423*4882a593Smuzhiyun 		for (c = genfs->head; c; c = c->next)
3424*4882a593Smuzhiyun 			len++;
3425*4882a593Smuzhiyun 		buf[0] = cpu_to_le32(len);
3426*4882a593Smuzhiyun 		rc = put_entry(buf, sizeof(u32), 1, fp);
3427*4882a593Smuzhiyun 		if (rc)
3428*4882a593Smuzhiyun 			return rc;
3429*4882a593Smuzhiyun 		for (c = genfs->head; c; c = c->next) {
3430*4882a593Smuzhiyun 			len = strlen(c->u.name);
3431*4882a593Smuzhiyun 			buf[0] = cpu_to_le32(len);
3432*4882a593Smuzhiyun 			rc = put_entry(buf, sizeof(u32), 1, fp);
3433*4882a593Smuzhiyun 			if (rc)
3434*4882a593Smuzhiyun 				return rc;
3435*4882a593Smuzhiyun 			rc = put_entry(c->u.name, 1, len, fp);
3436*4882a593Smuzhiyun 			if (rc)
3437*4882a593Smuzhiyun 				return rc;
3438*4882a593Smuzhiyun 			buf[0] = cpu_to_le32(c->v.sclass);
3439*4882a593Smuzhiyun 			rc = put_entry(buf, sizeof(u32), 1, fp);
3440*4882a593Smuzhiyun 			if (rc)
3441*4882a593Smuzhiyun 				return rc;
3442*4882a593Smuzhiyun 			rc = context_write(p, &c->context[0], fp);
3443*4882a593Smuzhiyun 			if (rc)
3444*4882a593Smuzhiyun 				return rc;
3445*4882a593Smuzhiyun 		}
3446*4882a593Smuzhiyun 	}
3447*4882a593Smuzhiyun 	return 0;
3448*4882a593Smuzhiyun }
3449*4882a593Smuzhiyun 
range_write_helper(void * key,void * data,void * ptr)3450*4882a593Smuzhiyun static int range_write_helper(void *key, void *data, void *ptr)
3451*4882a593Smuzhiyun {
3452*4882a593Smuzhiyun 	__le32 buf[2];
3453*4882a593Smuzhiyun 	struct range_trans *rt = key;
3454*4882a593Smuzhiyun 	struct mls_range *r = data;
3455*4882a593Smuzhiyun 	struct policy_data *pd = ptr;
3456*4882a593Smuzhiyun 	void *fp = pd->fp;
3457*4882a593Smuzhiyun 	struct policydb *p = pd->p;
3458*4882a593Smuzhiyun 	int rc;
3459*4882a593Smuzhiyun 
3460*4882a593Smuzhiyun 	buf[0] = cpu_to_le32(rt->source_type);
3461*4882a593Smuzhiyun 	buf[1] = cpu_to_le32(rt->target_type);
3462*4882a593Smuzhiyun 	rc = put_entry(buf, sizeof(u32), 2, fp);
3463*4882a593Smuzhiyun 	if (rc)
3464*4882a593Smuzhiyun 		return rc;
3465*4882a593Smuzhiyun 	if (p->policyvers >= POLICYDB_VERSION_RANGETRANS) {
3466*4882a593Smuzhiyun 		buf[0] = cpu_to_le32(rt->target_class);
3467*4882a593Smuzhiyun 		rc = put_entry(buf, sizeof(u32), 1, fp);
3468*4882a593Smuzhiyun 		if (rc)
3469*4882a593Smuzhiyun 			return rc;
3470*4882a593Smuzhiyun 	}
3471*4882a593Smuzhiyun 	rc = mls_write_range_helper(r, fp);
3472*4882a593Smuzhiyun 	if (rc)
3473*4882a593Smuzhiyun 		return rc;
3474*4882a593Smuzhiyun 
3475*4882a593Smuzhiyun 	return 0;
3476*4882a593Smuzhiyun }
3477*4882a593Smuzhiyun 
range_write(struct policydb * p,void * fp)3478*4882a593Smuzhiyun static int range_write(struct policydb *p, void *fp)
3479*4882a593Smuzhiyun {
3480*4882a593Smuzhiyun 	__le32 buf[1];
3481*4882a593Smuzhiyun 	int rc;
3482*4882a593Smuzhiyun 	struct policy_data pd;
3483*4882a593Smuzhiyun 
3484*4882a593Smuzhiyun 	pd.p = p;
3485*4882a593Smuzhiyun 	pd.fp = fp;
3486*4882a593Smuzhiyun 
3487*4882a593Smuzhiyun 	buf[0] = cpu_to_le32(p->range_tr.nel);
3488*4882a593Smuzhiyun 	rc = put_entry(buf, sizeof(u32), 1, fp);
3489*4882a593Smuzhiyun 	if (rc)
3490*4882a593Smuzhiyun 		return rc;
3491*4882a593Smuzhiyun 
3492*4882a593Smuzhiyun 	/* actually write all of the entries */
3493*4882a593Smuzhiyun 	rc = hashtab_map(&p->range_tr, range_write_helper, &pd);
3494*4882a593Smuzhiyun 	if (rc)
3495*4882a593Smuzhiyun 		return rc;
3496*4882a593Smuzhiyun 
3497*4882a593Smuzhiyun 	return 0;
3498*4882a593Smuzhiyun }
3499*4882a593Smuzhiyun 
filename_write_helper_compat(void * key,void * data,void * ptr)3500*4882a593Smuzhiyun static int filename_write_helper_compat(void *key, void *data, void *ptr)
3501*4882a593Smuzhiyun {
3502*4882a593Smuzhiyun 	struct filename_trans_key *ft = key;
3503*4882a593Smuzhiyun 	struct filename_trans_datum *datum = data;
3504*4882a593Smuzhiyun 	struct ebitmap_node *node;
3505*4882a593Smuzhiyun 	void *fp = ptr;
3506*4882a593Smuzhiyun 	__le32 buf[4];
3507*4882a593Smuzhiyun 	int rc;
3508*4882a593Smuzhiyun 	u32 bit, len = strlen(ft->name);
3509*4882a593Smuzhiyun 
3510*4882a593Smuzhiyun 	do {
3511*4882a593Smuzhiyun 		ebitmap_for_each_positive_bit(&datum->stypes, node, bit) {
3512*4882a593Smuzhiyun 			buf[0] = cpu_to_le32(len);
3513*4882a593Smuzhiyun 			rc = put_entry(buf, sizeof(u32), 1, fp);
3514*4882a593Smuzhiyun 			if (rc)
3515*4882a593Smuzhiyun 				return rc;
3516*4882a593Smuzhiyun 
3517*4882a593Smuzhiyun 			rc = put_entry(ft->name, sizeof(char), len, fp);
3518*4882a593Smuzhiyun 			if (rc)
3519*4882a593Smuzhiyun 				return rc;
3520*4882a593Smuzhiyun 
3521*4882a593Smuzhiyun 			buf[0] = cpu_to_le32(bit + 1);
3522*4882a593Smuzhiyun 			buf[1] = cpu_to_le32(ft->ttype);
3523*4882a593Smuzhiyun 			buf[2] = cpu_to_le32(ft->tclass);
3524*4882a593Smuzhiyun 			buf[3] = cpu_to_le32(datum->otype);
3525*4882a593Smuzhiyun 
3526*4882a593Smuzhiyun 			rc = put_entry(buf, sizeof(u32), 4, fp);
3527*4882a593Smuzhiyun 			if (rc)
3528*4882a593Smuzhiyun 				return rc;
3529*4882a593Smuzhiyun 		}
3530*4882a593Smuzhiyun 
3531*4882a593Smuzhiyun 		datum = datum->next;
3532*4882a593Smuzhiyun 	} while (unlikely(datum));
3533*4882a593Smuzhiyun 
3534*4882a593Smuzhiyun 	return 0;
3535*4882a593Smuzhiyun }
3536*4882a593Smuzhiyun 
filename_write_helper(void * key,void * data,void * ptr)3537*4882a593Smuzhiyun static int filename_write_helper(void *key, void *data, void *ptr)
3538*4882a593Smuzhiyun {
3539*4882a593Smuzhiyun 	struct filename_trans_key *ft = key;
3540*4882a593Smuzhiyun 	struct filename_trans_datum *datum;
3541*4882a593Smuzhiyun 	void *fp = ptr;
3542*4882a593Smuzhiyun 	__le32 buf[3];
3543*4882a593Smuzhiyun 	int rc;
3544*4882a593Smuzhiyun 	u32 ndatum, len = strlen(ft->name);
3545*4882a593Smuzhiyun 
3546*4882a593Smuzhiyun 	buf[0] = cpu_to_le32(len);
3547*4882a593Smuzhiyun 	rc = put_entry(buf, sizeof(u32), 1, fp);
3548*4882a593Smuzhiyun 	if (rc)
3549*4882a593Smuzhiyun 		return rc;
3550*4882a593Smuzhiyun 
3551*4882a593Smuzhiyun 	rc = put_entry(ft->name, sizeof(char), len, fp);
3552*4882a593Smuzhiyun 	if (rc)
3553*4882a593Smuzhiyun 		return rc;
3554*4882a593Smuzhiyun 
3555*4882a593Smuzhiyun 	ndatum = 0;
3556*4882a593Smuzhiyun 	datum = data;
3557*4882a593Smuzhiyun 	do {
3558*4882a593Smuzhiyun 		ndatum++;
3559*4882a593Smuzhiyun 		datum = datum->next;
3560*4882a593Smuzhiyun 	} while (unlikely(datum));
3561*4882a593Smuzhiyun 
3562*4882a593Smuzhiyun 	buf[0] = cpu_to_le32(ft->ttype);
3563*4882a593Smuzhiyun 	buf[1] = cpu_to_le32(ft->tclass);
3564*4882a593Smuzhiyun 	buf[2] = cpu_to_le32(ndatum);
3565*4882a593Smuzhiyun 	rc = put_entry(buf, sizeof(u32), 3, fp);
3566*4882a593Smuzhiyun 	if (rc)
3567*4882a593Smuzhiyun 		return rc;
3568*4882a593Smuzhiyun 
3569*4882a593Smuzhiyun 	datum = data;
3570*4882a593Smuzhiyun 	do {
3571*4882a593Smuzhiyun 		rc = ebitmap_write(&datum->stypes, fp);
3572*4882a593Smuzhiyun 		if (rc)
3573*4882a593Smuzhiyun 			return rc;
3574*4882a593Smuzhiyun 
3575*4882a593Smuzhiyun 		buf[0] = cpu_to_le32(datum->otype);
3576*4882a593Smuzhiyun 		rc = put_entry(buf, sizeof(u32), 1, fp);
3577*4882a593Smuzhiyun 		if (rc)
3578*4882a593Smuzhiyun 			return rc;
3579*4882a593Smuzhiyun 
3580*4882a593Smuzhiyun 		datum = datum->next;
3581*4882a593Smuzhiyun 	} while (unlikely(datum));
3582*4882a593Smuzhiyun 
3583*4882a593Smuzhiyun 	return 0;
3584*4882a593Smuzhiyun }
3585*4882a593Smuzhiyun 
filename_trans_write(struct policydb * p,void * fp)3586*4882a593Smuzhiyun static int filename_trans_write(struct policydb *p, void *fp)
3587*4882a593Smuzhiyun {
3588*4882a593Smuzhiyun 	__le32 buf[1];
3589*4882a593Smuzhiyun 	int rc;
3590*4882a593Smuzhiyun 
3591*4882a593Smuzhiyun 	if (p->policyvers < POLICYDB_VERSION_FILENAME_TRANS)
3592*4882a593Smuzhiyun 		return 0;
3593*4882a593Smuzhiyun 
3594*4882a593Smuzhiyun 	if (p->policyvers < POLICYDB_VERSION_COMP_FTRANS) {
3595*4882a593Smuzhiyun 		buf[0] = cpu_to_le32(p->compat_filename_trans_count);
3596*4882a593Smuzhiyun 		rc = put_entry(buf, sizeof(u32), 1, fp);
3597*4882a593Smuzhiyun 		if (rc)
3598*4882a593Smuzhiyun 			return rc;
3599*4882a593Smuzhiyun 
3600*4882a593Smuzhiyun 		rc = hashtab_map(&p->filename_trans,
3601*4882a593Smuzhiyun 				 filename_write_helper_compat, fp);
3602*4882a593Smuzhiyun 	} else {
3603*4882a593Smuzhiyun 		buf[0] = cpu_to_le32(p->filename_trans.nel);
3604*4882a593Smuzhiyun 		rc = put_entry(buf, sizeof(u32), 1, fp);
3605*4882a593Smuzhiyun 		if (rc)
3606*4882a593Smuzhiyun 			return rc;
3607*4882a593Smuzhiyun 
3608*4882a593Smuzhiyun 		rc = hashtab_map(&p->filename_trans, filename_write_helper, fp);
3609*4882a593Smuzhiyun 	}
3610*4882a593Smuzhiyun 	return rc;
3611*4882a593Smuzhiyun }
3612*4882a593Smuzhiyun 
3613*4882a593Smuzhiyun /*
3614*4882a593Smuzhiyun  * Write the configuration data in a policy database
3615*4882a593Smuzhiyun  * structure to a policy database binary representation
3616*4882a593Smuzhiyun  * file.
3617*4882a593Smuzhiyun  */
policydb_write(struct policydb * p,void * fp)3618*4882a593Smuzhiyun int policydb_write(struct policydb *p, void *fp)
3619*4882a593Smuzhiyun {
3620*4882a593Smuzhiyun 	unsigned int i, num_syms;
3621*4882a593Smuzhiyun 	int rc;
3622*4882a593Smuzhiyun 	__le32 buf[4];
3623*4882a593Smuzhiyun 	u32 config;
3624*4882a593Smuzhiyun 	size_t len;
3625*4882a593Smuzhiyun 	struct policydb_compat_info *info;
3626*4882a593Smuzhiyun 
3627*4882a593Smuzhiyun 	/*
3628*4882a593Smuzhiyun 	 * refuse to write policy older than compressed avtab
3629*4882a593Smuzhiyun 	 * to simplify the writer.  There are other tests dropped
3630*4882a593Smuzhiyun 	 * since we assume this throughout the writer code.  Be
3631*4882a593Smuzhiyun 	 * careful if you ever try to remove this restriction
3632*4882a593Smuzhiyun 	 */
3633*4882a593Smuzhiyun 	if (p->policyvers < POLICYDB_VERSION_AVTAB) {
3634*4882a593Smuzhiyun 		pr_err("SELinux: refusing to write policy version %d."
3635*4882a593Smuzhiyun 		       "  Because it is less than version %d\n", p->policyvers,
3636*4882a593Smuzhiyun 		       POLICYDB_VERSION_AVTAB);
3637*4882a593Smuzhiyun 		return -EINVAL;
3638*4882a593Smuzhiyun 	}
3639*4882a593Smuzhiyun 
3640*4882a593Smuzhiyun 	config = 0;
3641*4882a593Smuzhiyun 	if (p->mls_enabled)
3642*4882a593Smuzhiyun 		config |= POLICYDB_CONFIG_MLS;
3643*4882a593Smuzhiyun 
3644*4882a593Smuzhiyun 	if (p->reject_unknown)
3645*4882a593Smuzhiyun 		config |= REJECT_UNKNOWN;
3646*4882a593Smuzhiyun 	if (p->allow_unknown)
3647*4882a593Smuzhiyun 		config |= ALLOW_UNKNOWN;
3648*4882a593Smuzhiyun 
3649*4882a593Smuzhiyun 	/* Write the magic number and string identifiers. */
3650*4882a593Smuzhiyun 	buf[0] = cpu_to_le32(POLICYDB_MAGIC);
3651*4882a593Smuzhiyun 	len = strlen(POLICYDB_STRING);
3652*4882a593Smuzhiyun 	buf[1] = cpu_to_le32(len);
3653*4882a593Smuzhiyun 	rc = put_entry(buf, sizeof(u32), 2, fp);
3654*4882a593Smuzhiyun 	if (rc)
3655*4882a593Smuzhiyun 		return rc;
3656*4882a593Smuzhiyun 	rc = put_entry(POLICYDB_STRING, 1, len, fp);
3657*4882a593Smuzhiyun 	if (rc)
3658*4882a593Smuzhiyun 		return rc;
3659*4882a593Smuzhiyun 
3660*4882a593Smuzhiyun 	/* Write the version, config, and table sizes. */
3661*4882a593Smuzhiyun 	info = policydb_lookup_compat(p->policyvers);
3662*4882a593Smuzhiyun 	if (!info) {
3663*4882a593Smuzhiyun 		pr_err("SELinux: compatibility lookup failed for policy "
3664*4882a593Smuzhiyun 		    "version %d", p->policyvers);
3665*4882a593Smuzhiyun 		return -EINVAL;
3666*4882a593Smuzhiyun 	}
3667*4882a593Smuzhiyun 
3668*4882a593Smuzhiyun 	buf[0] = cpu_to_le32(p->policyvers);
3669*4882a593Smuzhiyun 	buf[1] = cpu_to_le32(config);
3670*4882a593Smuzhiyun 	buf[2] = cpu_to_le32(info->sym_num);
3671*4882a593Smuzhiyun 	buf[3] = cpu_to_le32(info->ocon_num);
3672*4882a593Smuzhiyun 
3673*4882a593Smuzhiyun 	rc = put_entry(buf, sizeof(u32), 4, fp);
3674*4882a593Smuzhiyun 	if (rc)
3675*4882a593Smuzhiyun 		return rc;
3676*4882a593Smuzhiyun 
3677*4882a593Smuzhiyun 	if (p->policyvers >= POLICYDB_VERSION_POLCAP) {
3678*4882a593Smuzhiyun 		rc = ebitmap_write(&p->policycaps, fp);
3679*4882a593Smuzhiyun 		if (rc)
3680*4882a593Smuzhiyun 			return rc;
3681*4882a593Smuzhiyun 	}
3682*4882a593Smuzhiyun 
3683*4882a593Smuzhiyun 	if (p->policyvers >= POLICYDB_VERSION_PERMISSIVE) {
3684*4882a593Smuzhiyun 		rc = ebitmap_write(&p->permissive_map, fp);
3685*4882a593Smuzhiyun 		if (rc)
3686*4882a593Smuzhiyun 			return rc;
3687*4882a593Smuzhiyun 	}
3688*4882a593Smuzhiyun 
3689*4882a593Smuzhiyun 	num_syms = info->sym_num;
3690*4882a593Smuzhiyun 	for (i = 0; i < num_syms; i++) {
3691*4882a593Smuzhiyun 		struct policy_data pd;
3692*4882a593Smuzhiyun 
3693*4882a593Smuzhiyun 		pd.fp = fp;
3694*4882a593Smuzhiyun 		pd.p = p;
3695*4882a593Smuzhiyun 
3696*4882a593Smuzhiyun 		buf[0] = cpu_to_le32(p->symtab[i].nprim);
3697*4882a593Smuzhiyun 		buf[1] = cpu_to_le32(p->symtab[i].table.nel);
3698*4882a593Smuzhiyun 
3699*4882a593Smuzhiyun 		rc = put_entry(buf, sizeof(u32), 2, fp);
3700*4882a593Smuzhiyun 		if (rc)
3701*4882a593Smuzhiyun 			return rc;
3702*4882a593Smuzhiyun 		rc = hashtab_map(&p->symtab[i].table, write_f[i], &pd);
3703*4882a593Smuzhiyun 		if (rc)
3704*4882a593Smuzhiyun 			return rc;
3705*4882a593Smuzhiyun 	}
3706*4882a593Smuzhiyun 
3707*4882a593Smuzhiyun 	rc = avtab_write(p, &p->te_avtab, fp);
3708*4882a593Smuzhiyun 	if (rc)
3709*4882a593Smuzhiyun 		return rc;
3710*4882a593Smuzhiyun 
3711*4882a593Smuzhiyun 	rc = cond_write_list(p, fp);
3712*4882a593Smuzhiyun 	if (rc)
3713*4882a593Smuzhiyun 		return rc;
3714*4882a593Smuzhiyun 
3715*4882a593Smuzhiyun 	rc = role_trans_write(p, fp);
3716*4882a593Smuzhiyun 	if (rc)
3717*4882a593Smuzhiyun 		return rc;
3718*4882a593Smuzhiyun 
3719*4882a593Smuzhiyun 	rc = role_allow_write(p->role_allow, fp);
3720*4882a593Smuzhiyun 	if (rc)
3721*4882a593Smuzhiyun 		return rc;
3722*4882a593Smuzhiyun 
3723*4882a593Smuzhiyun 	rc = filename_trans_write(p, fp);
3724*4882a593Smuzhiyun 	if (rc)
3725*4882a593Smuzhiyun 		return rc;
3726*4882a593Smuzhiyun 
3727*4882a593Smuzhiyun 	rc = ocontext_write(p, info, fp);
3728*4882a593Smuzhiyun 	if (rc)
3729*4882a593Smuzhiyun 		return rc;
3730*4882a593Smuzhiyun 
3731*4882a593Smuzhiyun 	rc = genfs_write(p, fp);
3732*4882a593Smuzhiyun 	if (rc)
3733*4882a593Smuzhiyun 		return rc;
3734*4882a593Smuzhiyun 
3735*4882a593Smuzhiyun 	rc = range_write(p, fp);
3736*4882a593Smuzhiyun 	if (rc)
3737*4882a593Smuzhiyun 		return rc;
3738*4882a593Smuzhiyun 
3739*4882a593Smuzhiyun 	for (i = 0; i < p->p_types.nprim; i++) {
3740*4882a593Smuzhiyun 		struct ebitmap *e = &p->type_attr_map_array[i];
3741*4882a593Smuzhiyun 
3742*4882a593Smuzhiyun 		rc = ebitmap_write(e, fp);
3743*4882a593Smuzhiyun 		if (rc)
3744*4882a593Smuzhiyun 			return rc;
3745*4882a593Smuzhiyun 	}
3746*4882a593Smuzhiyun 
3747*4882a593Smuzhiyun 	return 0;
3748*4882a593Smuzhiyun }
3749