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