blob: 4c1811972b8b2c63b5a4e0c05cb3db19aa968e1b [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * Implementation of the policy database.
3 *
4 * Author : Stephen Smalley, <sds@epoch.ncsc.mil>
5 */
6
7/*
8 * Updated: Trusted Computer Solutions, Inc. <dgoeddel@trustedcs.com>
9 *
10 * Support for enhanced MLS infrastructure.
11 *
12 * Updated: Frank Mayer <mayerf@tresys.com> and Karl MacMillan <kmacmillan@tresys.com>
13 *
Eric Paris2ced3df2008-04-17 13:37:12 -040014 * Added conditional policy language extensions
Linus Torvalds1da177e2005-04-16 15:20:36 -070015 *
Paul Moore3bb56b22008-01-29 08:38:19 -050016 * Updated: Hewlett-Packard <paul.moore@hp.com>
17 *
18 * Added support for the policy capability bitmap
19 *
20 * Copyright (C) 2007 Hewlett-Packard Development Company, L.P.
Linus Torvalds1da177e2005-04-16 15:20:36 -070021 * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc.
22 * Copyright (C) 2003 - 2004 Tresys Technology, LLC
23 * This program is free software; you can redistribute it and/or modify
Eric Paris2ced3df2008-04-17 13:37:12 -040024 * it under the terms of the GNU General Public License as published by
Linus Torvalds1da177e2005-04-16 15:20:36 -070025 * the Free Software Foundation, version 2.
26 */
27
28#include <linux/kernel.h>
Eric Paris9dc99782007-06-04 17:41:22 -040029#include <linux/sched.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070030#include <linux/slab.h>
31#include <linux/string.h>
32#include <linux/errno.h>
KaiGai Koheid9250de2008-08-28 16:35:57 +090033#include <linux/audit.h>
Eric Paris6371dcd2010-07-29 23:02:34 -040034#include <linux/flex_array.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070035#include "security.h"
36
37#include "policydb.h"
38#include "conditional.h"
39#include "mls.h"
Eric Pariscee74f42010-10-13 17:50:25 -040040#include "services.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070041
42#define _DEBUG_HASHES
43
44#ifdef DEBUG_HASHES
Stephen Hemminger634a5392010-03-04 21:59:03 -080045static const char *symtab_name[SYM_NUM] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -070046 "common prefixes",
47 "classes",
48 "roles",
49 "types",
50 "users",
51 "bools",
52 "levels",
53 "categories",
54};
55#endif
56
Linus Torvalds1da177e2005-04-16 15:20:36 -070057static unsigned int symtab_sizes[SYM_NUM] = {
58 2,
59 32,
60 16,
61 512,
62 128,
63 16,
64 16,
65 16,
66};
67
68struct policydb_compat_info {
69 int version;
70 int sym_num;
71 int ocon_num;
72};
73
74/* These need to be updated if SYM_NUM or OCON_NUM changes */
75static struct policydb_compat_info policydb_compat[] = {
76 {
Eric Paris2ced3df2008-04-17 13:37:12 -040077 .version = POLICYDB_VERSION_BASE,
78 .sym_num = SYM_NUM - 3,
79 .ocon_num = OCON_NUM - 1,
Linus Torvalds1da177e2005-04-16 15:20:36 -070080 },
81 {
Eric Paris2ced3df2008-04-17 13:37:12 -040082 .version = POLICYDB_VERSION_BOOL,
83 .sym_num = SYM_NUM - 2,
84 .ocon_num = OCON_NUM - 1,
Linus Torvalds1da177e2005-04-16 15:20:36 -070085 },
86 {
Eric Paris2ced3df2008-04-17 13:37:12 -040087 .version = POLICYDB_VERSION_IPV6,
88 .sym_num = SYM_NUM - 2,
89 .ocon_num = OCON_NUM,
Linus Torvalds1da177e2005-04-16 15:20:36 -070090 },
91 {
Eric Paris2ced3df2008-04-17 13:37:12 -040092 .version = POLICYDB_VERSION_NLCLASS,
93 .sym_num = SYM_NUM - 2,
94 .ocon_num = OCON_NUM,
Linus Torvalds1da177e2005-04-16 15:20:36 -070095 },
96 {
Eric Paris2ced3df2008-04-17 13:37:12 -040097 .version = POLICYDB_VERSION_MLS,
98 .sym_num = SYM_NUM,
99 .ocon_num = OCON_NUM,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700100 },
Stephen Smalley782ebb92005-09-03 15:55:16 -0700101 {
Eric Paris2ced3df2008-04-17 13:37:12 -0400102 .version = POLICYDB_VERSION_AVTAB,
103 .sym_num = SYM_NUM,
104 .ocon_num = OCON_NUM,
Stephen Smalley782ebb92005-09-03 15:55:16 -0700105 },
Darrel Goeddelf3f87712006-09-25 23:31:59 -0700106 {
Eric Paris2ced3df2008-04-17 13:37:12 -0400107 .version = POLICYDB_VERSION_RANGETRANS,
108 .sym_num = SYM_NUM,
109 .ocon_num = OCON_NUM,
Darrel Goeddelf3f87712006-09-25 23:31:59 -0700110 },
Paul Moore3bb56b22008-01-29 08:38:19 -0500111 {
112 .version = POLICYDB_VERSION_POLCAP,
113 .sym_num = SYM_NUM,
114 .ocon_num = OCON_NUM,
Eric Paris64dbf072008-03-31 12:17:33 +1100115 },
116 {
117 .version = POLICYDB_VERSION_PERMISSIVE,
118 .sym_num = SYM_NUM,
119 .ocon_num = OCON_NUM,
KaiGai Koheid9250de2008-08-28 16:35:57 +0900120 },
121 {
122 .version = POLICYDB_VERSION_BOUNDARY,
123 .sym_num = SYM_NUM,
124 .ocon_num = OCON_NUM,
125 },
Eric Paris652bb9b2011-02-01 11:05:40 -0500126 {
127 .version = POLICYDB_VERSION_FILENAME_TRANS,
128 .sym_num = SYM_NUM,
129 .ocon_num = OCON_NUM,
130 },
Harry Ciao80239762011-03-25 13:51:56 +0800131 {
132 .version = POLICYDB_VERSION_ROLETRANS,
133 .sym_num = SYM_NUM,
134 .ocon_num = OCON_NUM,
135 },
Linus Torvalds1da177e2005-04-16 15:20:36 -0700136};
137
138static struct policydb_compat_info *policydb_lookup_compat(int version)
139{
140 int i;
141 struct policydb_compat_info *info = NULL;
142
Tobias Klauser32725ad2006-01-06 00:11:23 -0800143 for (i = 0; i < ARRAY_SIZE(policydb_compat); i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700144 if (policydb_compat[i].version == version) {
145 info = &policydb_compat[i];
146 break;
147 }
148 }
149 return info;
150}
151
152/*
153 * Initialize the role table.
154 */
155static int roles_init(struct policydb *p)
156{
157 char *key = NULL;
158 int rc;
159 struct role_datum *role;
160
Eric Paris9398c7f2010-11-23 11:40:08 -0500161 rc = -ENOMEM;
James Morris89d155e2005-10-30 14:59:21 -0800162 role = kzalloc(sizeof(*role), GFP_KERNEL);
Eric Paris9398c7f2010-11-23 11:40:08 -0500163 if (!role)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700164 goto out;
Eric Paris9398c7f2010-11-23 11:40:08 -0500165
166 rc = -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700167 role->value = ++p->p_roles.nprim;
Eric Paris9398c7f2010-11-23 11:40:08 -0500168 if (role->value != OBJECT_R_VAL)
169 goto out;
170
171 rc = -ENOMEM;
Julia Lawallb3139bb2010-05-14 21:30:30 +0200172 key = kstrdup(OBJECT_R, GFP_KERNEL);
Eric Paris9398c7f2010-11-23 11:40:08 -0500173 if (!key)
174 goto out;
175
Linus Torvalds1da177e2005-04-16 15:20:36 -0700176 rc = hashtab_insert(p->p_roles.table, key, role);
177 if (rc)
Eric Paris9398c7f2010-11-23 11:40:08 -0500178 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700179
Eric Paris9398c7f2010-11-23 11:40:08 -0500180 return 0;
181out:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700182 kfree(key);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700183 kfree(role);
Eric Paris9398c7f2010-11-23 11:40:08 -0500184 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700185}
186
Stephen Smalley2f3e82d2010-01-07 15:55:16 -0500187static u32 rangetr_hash(struct hashtab *h, const void *k)
188{
189 const struct range_trans *key = k;
190 return (key->source_type + (key->target_type << 3) +
191 (key->target_class << 5)) & (h->size - 1);
192}
193
194static int rangetr_cmp(struct hashtab *h, const void *k1, const void *k2)
195{
196 const struct range_trans *key1 = k1, *key2 = k2;
Eric Paris4419aae2010-10-13 17:50:14 -0400197 int v;
198
199 v = key1->source_type - key2->source_type;
200 if (v)
201 return v;
202
203 v = key1->target_type - key2->target_type;
204 if (v)
205 return v;
206
207 v = key1->target_class - key2->target_class;
208
209 return v;
Stephen Smalley2f3e82d2010-01-07 15:55:16 -0500210}
211
Linus Torvalds1da177e2005-04-16 15:20:36 -0700212/*
213 * Initialize a policy database structure.
214 */
215static int policydb_init(struct policydb *p)
216{
217 int i, rc;
218
219 memset(p, 0, sizeof(*p));
220
221 for (i = 0; i < SYM_NUM; i++) {
222 rc = symtab_init(&p->symtab[i], symtab_sizes[i]);
223 if (rc)
Eric Paris9398c7f2010-11-23 11:40:08 -0500224 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700225 }
226
227 rc = avtab_init(&p->te_avtab);
228 if (rc)
Eric Paris9398c7f2010-11-23 11:40:08 -0500229 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700230
231 rc = roles_init(p);
232 if (rc)
Eric Paris9398c7f2010-11-23 11:40:08 -0500233 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700234
235 rc = cond_policydb_init(p);
236 if (rc)
Eric Paris9398c7f2010-11-23 11:40:08 -0500237 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700238
Stephen Smalley2f3e82d2010-01-07 15:55:16 -0500239 p->range_tr = hashtab_create(rangetr_hash, rangetr_cmp, 256);
240 if (!p->range_tr)
Eric Paris9398c7f2010-11-23 11:40:08 -0500241 goto out;
Stephen Smalley2f3e82d2010-01-07 15:55:16 -0500242
Eric Paris03a4c012011-04-28 15:11:21 -0400243 ebitmap_init(&p->filename_trans_ttypes);
Paul Moore3bb56b22008-01-29 08:38:19 -0500244 ebitmap_init(&p->policycaps);
Eric Paris64dbf072008-03-31 12:17:33 +1100245 ebitmap_init(&p->permissive_map);
Paul Moore3bb56b22008-01-29 08:38:19 -0500246
Eric Paris9398c7f2010-11-23 11:40:08 -0500247 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700248out:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700249 for (i = 0; i < SYM_NUM; i++)
250 hashtab_destroy(p->symtab[i].table);
Eric Paris9398c7f2010-11-23 11:40:08 -0500251 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700252}
253
254/*
255 * The following *_index functions are used to
256 * define the val_to_name and val_to_struct arrays
257 * in a policy database structure. The val_to_name
258 * arrays are used when converting security context
259 * structures into string representations. The
260 * val_to_struct arrays are used when the attributes
261 * of a class, role, or user are needed.
262 */
263
264static int common_index(void *key, void *datum, void *datap)
265{
266 struct policydb *p;
267 struct common_datum *comdatum;
Eric Parisac76c05b2010-11-29 15:47:09 -0500268 struct flex_array *fa;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700269
270 comdatum = datum;
271 p = datap;
272 if (!comdatum->value || comdatum->value > p->p_commons.nprim)
273 return -EINVAL;
Eric Parisac76c05b2010-11-29 15:47:09 -0500274
275 fa = p->sym_val_to_name[SYM_COMMONS];
276 if (flex_array_put_ptr(fa, comdatum->value - 1, key,
277 GFP_KERNEL | __GFP_ZERO))
278 BUG();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700279 return 0;
280}
281
282static int class_index(void *key, void *datum, void *datap)
283{
284 struct policydb *p;
285 struct class_datum *cladatum;
Eric Parisac76c05b2010-11-29 15:47:09 -0500286 struct flex_array *fa;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700287
288 cladatum = datum;
289 p = datap;
290 if (!cladatum->value || cladatum->value > p->p_classes.nprim)
291 return -EINVAL;
Eric Parisac76c05b2010-11-29 15:47:09 -0500292 fa = p->sym_val_to_name[SYM_CLASSES];
293 if (flex_array_put_ptr(fa, cladatum->value - 1, key,
294 GFP_KERNEL | __GFP_ZERO))
295 BUG();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700296 p->class_val_to_struct[cladatum->value - 1] = cladatum;
297 return 0;
298}
299
300static int role_index(void *key, void *datum, void *datap)
301{
302 struct policydb *p;
303 struct role_datum *role;
Eric Parisac76c05b2010-11-29 15:47:09 -0500304 struct flex_array *fa;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700305
306 role = datum;
307 p = datap;
KaiGai Koheid9250de2008-08-28 16:35:57 +0900308 if (!role->value
309 || role->value > p->p_roles.nprim
310 || role->bounds > p->p_roles.nprim)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700311 return -EINVAL;
Eric Parisac76c05b2010-11-29 15:47:09 -0500312
313 fa = p->sym_val_to_name[SYM_ROLES];
314 if (flex_array_put_ptr(fa, role->value - 1, key,
315 GFP_KERNEL | __GFP_ZERO))
316 BUG();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700317 p->role_val_to_struct[role->value - 1] = role;
318 return 0;
319}
320
321static int type_index(void *key, void *datum, void *datap)
322{
323 struct policydb *p;
324 struct type_datum *typdatum;
Eric Parisac76c05b2010-11-29 15:47:09 -0500325 struct flex_array *fa;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700326
327 typdatum = datum;
328 p = datap;
329
330 if (typdatum->primary) {
KaiGai Koheid9250de2008-08-28 16:35:57 +0900331 if (!typdatum->value
332 || typdatum->value > p->p_types.nprim
333 || typdatum->bounds > p->p_types.nprim)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700334 return -EINVAL;
Eric Parisac76c05b2010-11-29 15:47:09 -0500335 fa = p->sym_val_to_name[SYM_TYPES];
336 if (flex_array_put_ptr(fa, typdatum->value - 1, key,
337 GFP_KERNEL | __GFP_ZERO))
338 BUG();
339
340 fa = p->type_val_to_struct_array;
341 if (flex_array_put_ptr(fa, typdatum->value - 1, typdatum,
Eric Paris23bdecb2010-11-29 15:47:09 -0500342 GFP_KERNEL | __GFP_ZERO))
343 BUG();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700344 }
345
346 return 0;
347}
348
349static int user_index(void *key, void *datum, void *datap)
350{
351 struct policydb *p;
352 struct user_datum *usrdatum;
Eric Parisac76c05b2010-11-29 15:47:09 -0500353 struct flex_array *fa;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700354
355 usrdatum = datum;
356 p = datap;
KaiGai Koheid9250de2008-08-28 16:35:57 +0900357 if (!usrdatum->value
358 || usrdatum->value > p->p_users.nprim
359 || usrdatum->bounds > p->p_users.nprim)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700360 return -EINVAL;
Eric Parisac76c05b2010-11-29 15:47:09 -0500361
362 fa = p->sym_val_to_name[SYM_USERS];
363 if (flex_array_put_ptr(fa, usrdatum->value - 1, key,
364 GFP_KERNEL | __GFP_ZERO))
365 BUG();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700366 p->user_val_to_struct[usrdatum->value - 1] = usrdatum;
367 return 0;
368}
369
370static int sens_index(void *key, void *datum, void *datap)
371{
372 struct policydb *p;
373 struct level_datum *levdatum;
Eric Parisac76c05b2010-11-29 15:47:09 -0500374 struct flex_array *fa;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700375
376 levdatum = datum;
377 p = datap;
378
379 if (!levdatum->isalias) {
380 if (!levdatum->level->sens ||
381 levdatum->level->sens > p->p_levels.nprim)
382 return -EINVAL;
Eric Parisac76c05b2010-11-29 15:47:09 -0500383 fa = p->sym_val_to_name[SYM_LEVELS];
384 if (flex_array_put_ptr(fa, levdatum->level->sens - 1, key,
385 GFP_KERNEL | __GFP_ZERO))
386 BUG();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700387 }
388
389 return 0;
390}
391
392static int cat_index(void *key, void *datum, void *datap)
393{
394 struct policydb *p;
395 struct cat_datum *catdatum;
Eric Parisac76c05b2010-11-29 15:47:09 -0500396 struct flex_array *fa;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700397
398 catdatum = datum;
399 p = datap;
400
401 if (!catdatum->isalias) {
402 if (!catdatum->value || catdatum->value > p->p_cats.nprim)
403 return -EINVAL;
Eric Parisac76c05b2010-11-29 15:47:09 -0500404 fa = p->sym_val_to_name[SYM_CATS];
405 if (flex_array_put_ptr(fa, catdatum->value - 1, key,
406 GFP_KERNEL | __GFP_ZERO))
407 BUG();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700408 }
409
410 return 0;
411}
412
413static int (*index_f[SYM_NUM]) (void *key, void *datum, void *datap) =
414{
415 common_index,
416 class_index,
417 role_index,
418 type_index,
419 user_index,
420 cond_index_bool,
421 sens_index,
422 cat_index,
423};
424
Linus Torvalds1da177e2005-04-16 15:20:36 -0700425#ifdef DEBUG_HASHES
426static void symtab_hash_eval(struct symtab *s)
427{
428 int i;
429
430 for (i = 0; i < SYM_NUM; i++) {
431 struct hashtab *h = s[i].table;
432 struct hashtab_info info;
433
434 hashtab_stat(h, &info);
Eric Paris744ba352008-04-17 11:52:44 -0400435 printk(KERN_DEBUG "SELinux: %s: %d entries and %d/%d buckets used, "
Linus Torvalds1da177e2005-04-16 15:20:36 -0700436 "longest chain length %d\n", symtab_name[i], h->nel,
437 info.slots_used, h->size, info.max_chain_len);
438 }
439}
Stephen Smalley2f3e82d2010-01-07 15:55:16 -0500440
441static void rangetr_hash_eval(struct hashtab *h)
442{
443 struct hashtab_info info;
444
445 hashtab_stat(h, &info);
446 printk(KERN_DEBUG "SELinux: rangetr: %d entries and %d/%d buckets used, "
447 "longest chain length %d\n", h->nel,
448 info.slots_used, h->size, info.max_chain_len);
449}
450#else
451static inline void rangetr_hash_eval(struct hashtab *h)
452{
453}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700454#endif
455
456/*
457 * Define the other val_to_name and val_to_struct arrays
458 * in a policy database structure.
459 *
460 * Caller must clean up on failure.
461 */
Eric Paris1d9bc6dc2010-11-29 15:47:09 -0500462static int policydb_index(struct policydb *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700463{
Eric Paris9398c7f2010-11-23 11:40:08 -0500464 int i, rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700465
James Morris454d9722008-02-26 20:42:02 +1100466 printk(KERN_DEBUG "SELinux: %d users, %d roles, %d types, %d bools",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700467 p->p_users.nprim, p->p_roles.nprim, p->p_types.nprim, p->p_bools.nprim);
Guido Trentalancia0719aaf2010-02-03 16:40:20 +0100468 if (p->mls_enabled)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700469 printk(", %d sens, %d cats", p->p_levels.nprim,
470 p->p_cats.nprim);
471 printk("\n");
472
James Morris454d9722008-02-26 20:42:02 +1100473 printk(KERN_DEBUG "SELinux: %d classes, %d rules\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700474 p->p_classes.nprim, p->te_avtab.nel);
475
476#ifdef DEBUG_HASHES
477 avtab_hash_eval(&p->te_avtab, "rules");
478 symtab_hash_eval(p->symtab);
479#endif
480
Eric Paris9398c7f2010-11-23 11:40:08 -0500481 rc = -ENOMEM;
Eric Paris1d9bc6dc2010-11-29 15:47:09 -0500482 p->class_val_to_struct =
483 kmalloc(p->p_classes.nprim * sizeof(*(p->class_val_to_struct)),
484 GFP_KERNEL);
485 if (!p->class_val_to_struct)
486 goto out;
487
488 rc = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700489 p->role_val_to_struct =
490 kmalloc(p->p_roles.nprim * sizeof(*(p->role_val_to_struct)),
Eric Paris2ced3df2008-04-17 13:37:12 -0400491 GFP_KERNEL);
Eric Paris9398c7f2010-11-23 11:40:08 -0500492 if (!p->role_val_to_struct)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700493 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700494
Eric Paris9398c7f2010-11-23 11:40:08 -0500495 rc = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700496 p->user_val_to_struct =
497 kmalloc(p->p_users.nprim * sizeof(*(p->user_val_to_struct)),
Eric Paris2ced3df2008-04-17 13:37:12 -0400498 GFP_KERNEL);
Eric Paris9398c7f2010-11-23 11:40:08 -0500499 if (!p->user_val_to_struct)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700500 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700501
Eric Paris23bdecb2010-11-29 15:47:09 -0500502 /* Yes, I want the sizeof the pointer, not the structure */
Eric Paris9398c7f2010-11-23 11:40:08 -0500503 rc = -ENOMEM;
Eric Paris23bdecb2010-11-29 15:47:09 -0500504 p->type_val_to_struct_array = flex_array_alloc(sizeof(struct type_datum *),
505 p->p_types.nprim,
506 GFP_KERNEL | __GFP_ZERO);
507 if (!p->type_val_to_struct_array)
508 goto out;
509
510 rc = flex_array_prealloc(p->type_val_to_struct_array, 0,
511 p->p_types.nprim - 1, GFP_KERNEL | __GFP_ZERO);
512 if (rc)
KaiGai Koheid9250de2008-08-28 16:35:57 +0900513 goto out;
KaiGai Koheid9250de2008-08-28 16:35:57 +0900514
Davidlohr Bueso3ac285ff2011-01-21 12:28:04 -0300515 rc = cond_init_bool_indexes(p);
516 if (rc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700517 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700518
Eric Paris1d9bc6dc2010-11-29 15:47:09 -0500519 for (i = 0; i < SYM_NUM; i++) {
Eric Paris9398c7f2010-11-23 11:40:08 -0500520 rc = -ENOMEM;
Eric Parisac76c05b2010-11-29 15:47:09 -0500521 p->sym_val_to_name[i] = flex_array_alloc(sizeof(char *),
522 p->symtab[i].nprim,
523 GFP_KERNEL | __GFP_ZERO);
Eric Paris9398c7f2010-11-23 11:40:08 -0500524 if (!p->sym_val_to_name[i])
Linus Torvalds1da177e2005-04-16 15:20:36 -0700525 goto out;
Eric Parisac76c05b2010-11-29 15:47:09 -0500526
527 rc = flex_array_prealloc(p->sym_val_to_name[i],
528 0, p->symtab[i].nprim - 1,
529 GFP_KERNEL | __GFP_ZERO);
530 if (rc)
531 goto out;
532
Linus Torvalds1da177e2005-04-16 15:20:36 -0700533 rc = hashtab_map(p->symtab[i].table, index_f[i], p);
534 if (rc)
535 goto out;
536 }
Eric Paris9398c7f2010-11-23 11:40:08 -0500537 rc = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700538out:
539 return rc;
540}
541
542/*
543 * The following *_destroy functions are used to
544 * free any memory allocated for each kind of
545 * symbol data in the policy database.
546 */
547
548static int perm_destroy(void *key, void *datum, void *p)
549{
550 kfree(key);
551 kfree(datum);
552 return 0;
553}
554
555static int common_destroy(void *key, void *datum, void *p)
556{
557 struct common_datum *comdatum;
558
559 kfree(key);
Eric Paris9398c7f2010-11-23 11:40:08 -0500560 if (datum) {
561 comdatum = datum;
562 hashtab_map(comdatum->permissions.table, perm_destroy, NULL);
563 hashtab_destroy(comdatum->permissions.table);
564 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700565 kfree(datum);
566 return 0;
567}
568
James Morris6cbda6b2006-11-29 16:50:27 -0500569static int cls_destroy(void *key, void *datum, void *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700570{
571 struct class_datum *cladatum;
572 struct constraint_node *constraint, *ctemp;
573 struct constraint_expr *e, *etmp;
574
575 kfree(key);
Eric Paris9398c7f2010-11-23 11:40:08 -0500576 if (datum) {
577 cladatum = datum;
578 hashtab_map(cladatum->permissions.table, perm_destroy, NULL);
579 hashtab_destroy(cladatum->permissions.table);
580 constraint = cladatum->constraints;
581 while (constraint) {
582 e = constraint->expr;
583 while (e) {
584 ebitmap_destroy(&e->names);
585 etmp = e;
586 e = e->next;
587 kfree(etmp);
588 }
589 ctemp = constraint;
590 constraint = constraint->next;
591 kfree(ctemp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700592 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700593
Eric Paris9398c7f2010-11-23 11:40:08 -0500594 constraint = cladatum->validatetrans;
595 while (constraint) {
596 e = constraint->expr;
597 while (e) {
598 ebitmap_destroy(&e->names);
599 etmp = e;
600 e = e->next;
601 kfree(etmp);
602 }
603 ctemp = constraint;
604 constraint = constraint->next;
605 kfree(ctemp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700606 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700607
Eric Paris9398c7f2010-11-23 11:40:08 -0500608 kfree(cladatum->comkey);
609 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700610 kfree(datum);
611 return 0;
612}
613
614static int role_destroy(void *key, void *datum, void *p)
615{
616 struct role_datum *role;
617
618 kfree(key);
Eric Paris9398c7f2010-11-23 11:40:08 -0500619 if (datum) {
620 role = datum;
621 ebitmap_destroy(&role->dominates);
622 ebitmap_destroy(&role->types);
623 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700624 kfree(datum);
625 return 0;
626}
627
628static int type_destroy(void *key, void *datum, void *p)
629{
630 kfree(key);
631 kfree(datum);
632 return 0;
633}
634
635static int user_destroy(void *key, void *datum, void *p)
636{
637 struct user_datum *usrdatum;
638
639 kfree(key);
Eric Paris9398c7f2010-11-23 11:40:08 -0500640 if (datum) {
641 usrdatum = datum;
642 ebitmap_destroy(&usrdatum->roles);
643 ebitmap_destroy(&usrdatum->range.level[0].cat);
644 ebitmap_destroy(&usrdatum->range.level[1].cat);
645 ebitmap_destroy(&usrdatum->dfltlevel.cat);
646 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700647 kfree(datum);
648 return 0;
649}
650
651static int sens_destroy(void *key, void *datum, void *p)
652{
653 struct level_datum *levdatum;
654
655 kfree(key);
Eric Paris9398c7f2010-11-23 11:40:08 -0500656 if (datum) {
657 levdatum = datum;
658 ebitmap_destroy(&levdatum->level->cat);
659 kfree(levdatum->level);
660 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700661 kfree(datum);
662 return 0;
663}
664
665static int cat_destroy(void *key, void *datum, void *p)
666{
667 kfree(key);
668 kfree(datum);
669 return 0;
670}
671
672static int (*destroy_f[SYM_NUM]) (void *key, void *datum, void *datap) =
673{
674 common_destroy,
James Morris6cbda6b2006-11-29 16:50:27 -0500675 cls_destroy,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700676 role_destroy,
677 type_destroy,
678 user_destroy,
679 cond_destroy_bool,
680 sens_destroy,
681 cat_destroy,
682};
683
Stephen Smalley2f3e82d2010-01-07 15:55:16 -0500684static int range_tr_destroy(void *key, void *datum, void *p)
685{
686 struct mls_range *rt = datum;
687 kfree(key);
688 ebitmap_destroy(&rt->level[0].cat);
689 ebitmap_destroy(&rt->level[1].cat);
690 kfree(datum);
691 cond_resched();
692 return 0;
693}
694
Linus Torvalds1da177e2005-04-16 15:20:36 -0700695static void ocontext_destroy(struct ocontext *c, int i)
696{
Eric Parisd1b43542010-07-21 12:50:57 -0400697 if (!c)
698 return;
699
Linus Torvalds1da177e2005-04-16 15:20:36 -0700700 context_destroy(&c->context[0]);
701 context_destroy(&c->context[1]);
702 if (i == OCON_ISID || i == OCON_FS ||
703 i == OCON_NETIF || i == OCON_FSUSE)
704 kfree(c->u.name);
705 kfree(c);
706}
707
708/*
709 * Free any memory allocated by a policy database structure.
710 */
711void policydb_destroy(struct policydb *p)
712{
713 struct ocontext *c, *ctmp;
714 struct genfs *g, *gtmp;
715 int i;
Stephen Smalley782ebb92005-09-03 15:55:16 -0700716 struct role_allow *ra, *lra = NULL;
717 struct role_trans *tr, *ltr = NULL;
Eric Paris652bb9b2011-02-01 11:05:40 -0500718 struct filename_trans *ft, *nft;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700719
720 for (i = 0; i < SYM_NUM; i++) {
Eric Paris9dc99782007-06-04 17:41:22 -0400721 cond_resched();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700722 hashtab_map(p->symtab[i].table, destroy_f[i], NULL);
723 hashtab_destroy(p->symtab[i].table);
724 }
725
Eric Parisac76c05b2010-11-29 15:47:09 -0500726 for (i = 0; i < SYM_NUM; i++) {
727 if (p->sym_val_to_name[i])
728 flex_array_free(p->sym_val_to_name[i]);
729 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700730
Jesper Juhl9a5f04b2005-06-25 14:58:51 -0700731 kfree(p->class_val_to_struct);
732 kfree(p->role_val_to_struct);
733 kfree(p->user_val_to_struct);
Eric Paris23bdecb2010-11-29 15:47:09 -0500734 if (p->type_val_to_struct_array)
735 flex_array_free(p->type_val_to_struct_array);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700736
737 avtab_destroy(&p->te_avtab);
738
739 for (i = 0; i < OCON_NUM; i++) {
Eric Paris9dc99782007-06-04 17:41:22 -0400740 cond_resched();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700741 c = p->ocontexts[i];
742 while (c) {
743 ctmp = c;
744 c = c->next;
Eric Paris2ced3df2008-04-17 13:37:12 -0400745 ocontext_destroy(ctmp, i);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700746 }
Chad Sellers6e8c7512006-10-06 16:09:52 -0400747 p->ocontexts[i] = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700748 }
749
750 g = p->genfs;
751 while (g) {
Eric Paris9dc99782007-06-04 17:41:22 -0400752 cond_resched();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700753 kfree(g->fstype);
754 c = g->head;
755 while (c) {
756 ctmp = c;
757 c = c->next;
Eric Paris2ced3df2008-04-17 13:37:12 -0400758 ocontext_destroy(ctmp, OCON_FSUSE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700759 }
760 gtmp = g;
761 g = g->next;
762 kfree(gtmp);
763 }
Chad Sellers6e8c7512006-10-06 16:09:52 -0400764 p->genfs = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700765
766 cond_policydb_destroy(p);
767
Stephen Smalley782ebb92005-09-03 15:55:16 -0700768 for (tr = p->role_tr; tr; tr = tr->next) {
Eric Paris9dc99782007-06-04 17:41:22 -0400769 cond_resched();
Jesper Juhla7f988b2005-11-07 01:01:35 -0800770 kfree(ltr);
Stephen Smalley782ebb92005-09-03 15:55:16 -0700771 ltr = tr;
772 }
Jesper Juhla7f988b2005-11-07 01:01:35 -0800773 kfree(ltr);
Stephen Smalley782ebb92005-09-03 15:55:16 -0700774
Eric Paris2ced3df2008-04-17 13:37:12 -0400775 for (ra = p->role_allow; ra; ra = ra->next) {
Eric Paris9dc99782007-06-04 17:41:22 -0400776 cond_resched();
Jesper Juhla7f988b2005-11-07 01:01:35 -0800777 kfree(lra);
Stephen Smalley782ebb92005-09-03 15:55:16 -0700778 lra = ra;
779 }
Jesper Juhla7f988b2005-11-07 01:01:35 -0800780 kfree(lra);
Stephen Smalley782ebb92005-09-03 15:55:16 -0700781
Stephen Smalley2f3e82d2010-01-07 15:55:16 -0500782 hashtab_map(p->range_tr, range_tr_destroy, NULL);
783 hashtab_destroy(p->range_tr);
Stephen Smalley782ebb92005-09-03 15:55:16 -0700784
Eric Paris6371dcd2010-07-29 23:02:34 -0400785 if (p->type_attr_map_array) {
786 for (i = 0; i < p->p_types.nprim; i++) {
787 struct ebitmap *e;
788
789 e = flex_array_get(p->type_attr_map_array, i);
790 if (!e)
791 continue;
792 ebitmap_destroy(e);
793 }
794 flex_array_free(p->type_attr_map_array);
Stephen Smalley282c1f52005-10-23 12:57:15 -0700795 }
Eric Paris652bb9b2011-02-01 11:05:40 -0500796
797 ft = p->filename_trans;
798 while (ft) {
799 nft = ft->next;
800 kfree(ft->name);
801 kfree(ft);
802 ft = nft;
803 }
804
Eric Paris03a4c012011-04-28 15:11:21 -0400805 ebitmap_destroy(&p->filename_trans_ttypes);
Paul Moore3bb56b22008-01-29 08:38:19 -0500806 ebitmap_destroy(&p->policycaps);
Eric Paris64dbf072008-03-31 12:17:33 +1100807 ebitmap_destroy(&p->permissive_map);
Eric Paris3f120702007-09-21 14:37:10 -0400808
Linus Torvalds1da177e2005-04-16 15:20:36 -0700809 return;
810}
811
812/*
813 * Load the initial SIDs specified in a policy database
814 * structure into a SID table.
815 */
816int policydb_load_isids(struct policydb *p, struct sidtab *s)
817{
818 struct ocontext *head, *c;
819 int rc;
820
821 rc = sidtab_init(s);
822 if (rc) {
James Morris454d9722008-02-26 20:42:02 +1100823 printk(KERN_ERR "SELinux: out of memory on SID table init\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700824 goto out;
825 }
826
827 head = p->ocontexts[OCON_ISID];
828 for (c = head; c; c = c->next) {
Eric Paris9398c7f2010-11-23 11:40:08 -0500829 rc = -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700830 if (!c->context[0].user) {
Eric Paris9398c7f2010-11-23 11:40:08 -0500831 printk(KERN_ERR "SELinux: SID %s was never defined.\n",
832 c->u.name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700833 goto out;
834 }
Eric Paris9398c7f2010-11-23 11:40:08 -0500835
836 rc = sidtab_insert(s, c->sid[0], &c->context[0]);
837 if (rc) {
838 printk(KERN_ERR "SELinux: unable to load initial SID %s.\n",
839 c->u.name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700840 goto out;
841 }
842 }
Eric Paris9398c7f2010-11-23 11:40:08 -0500843 rc = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700844out:
845 return rc;
846}
847
Stephen Smalley45e54212007-11-07 10:08:00 -0500848int policydb_class_isvalid(struct policydb *p, unsigned int class)
849{
850 if (!class || class > p->p_classes.nprim)
851 return 0;
852 return 1;
853}
854
855int policydb_role_isvalid(struct policydb *p, unsigned int role)
856{
857 if (!role || role > p->p_roles.nprim)
858 return 0;
859 return 1;
860}
861
862int policydb_type_isvalid(struct policydb *p, unsigned int type)
863{
864 if (!type || type > p->p_types.nprim)
865 return 0;
866 return 1;
867}
868
Linus Torvalds1da177e2005-04-16 15:20:36 -0700869/*
870 * Return 1 if the fields in the security context
871 * structure `c' are valid. Return 0 otherwise.
872 */
873int policydb_context_isvalid(struct policydb *p, struct context *c)
874{
875 struct role_datum *role;
876 struct user_datum *usrdatum;
877
878 if (!c->role || c->role > p->p_roles.nprim)
879 return 0;
880
881 if (!c->user || c->user > p->p_users.nprim)
882 return 0;
883
884 if (!c->type || c->type > p->p_types.nprim)
885 return 0;
886
887 if (c->role != OBJECT_R_VAL) {
888 /*
889 * Role must be authorized for the type.
890 */
891 role = p->role_val_to_struct[c->role - 1];
Eric Paris9398c7f2010-11-23 11:40:08 -0500892 if (!ebitmap_get_bit(&role->types, c->type - 1))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700893 /* role may not be associated with type */
894 return 0;
895
896 /*
897 * User must be authorized for the role.
898 */
899 usrdatum = p->user_val_to_struct[c->user - 1];
900 if (!usrdatum)
901 return 0;
902
Eric Paris9398c7f2010-11-23 11:40:08 -0500903 if (!ebitmap_get_bit(&usrdatum->roles, c->role - 1))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700904 /* user may not be associated with role */
905 return 0;
906 }
907
908 if (!mls_context_isvalid(p, c))
909 return 0;
910
911 return 1;
912}
913
914/*
915 * Read a MLS range structure from a policydb binary
916 * representation file.
917 */
918static int mls_read_range_helper(struct mls_range *r, void *fp)
919{
Alexey Dobriyanb5bf6c52005-09-03 15:55:17 -0700920 __le32 buf[2];
921 u32 items;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700922 int rc;
923
924 rc = next_entry(buf, fp, sizeof(u32));
Eric Paris9398c7f2010-11-23 11:40:08 -0500925 if (rc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700926 goto out;
927
Eric Paris9398c7f2010-11-23 11:40:08 -0500928 rc = -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700929 items = le32_to_cpu(buf[0]);
930 if (items > ARRAY_SIZE(buf)) {
James Morris454d9722008-02-26 20:42:02 +1100931 printk(KERN_ERR "SELinux: mls: range overflow\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700932 goto out;
933 }
Eric Paris9398c7f2010-11-23 11:40:08 -0500934
Linus Torvalds1da177e2005-04-16 15:20:36 -0700935 rc = next_entry(buf, fp, sizeof(u32) * items);
Eric Paris9398c7f2010-11-23 11:40:08 -0500936 if (rc) {
James Morris454d9722008-02-26 20:42:02 +1100937 printk(KERN_ERR "SELinux: mls: truncated range\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700938 goto out;
939 }
Eric Paris9398c7f2010-11-23 11:40:08 -0500940
Linus Torvalds1da177e2005-04-16 15:20:36 -0700941 r->level[0].sens = le32_to_cpu(buf[0]);
942 if (items > 1)
943 r->level[1].sens = le32_to_cpu(buf[1]);
944 else
945 r->level[1].sens = r->level[0].sens;
946
947 rc = ebitmap_read(&r->level[0].cat, fp);
948 if (rc) {
Eric Paris9398c7f2010-11-23 11:40:08 -0500949 printk(KERN_ERR "SELinux: mls: error reading low categories\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700950 goto out;
951 }
952 if (items > 1) {
953 rc = ebitmap_read(&r->level[1].cat, fp);
954 if (rc) {
Eric Paris9398c7f2010-11-23 11:40:08 -0500955 printk(KERN_ERR "SELinux: mls: error reading high categories\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700956 goto bad_high;
957 }
958 } else {
959 rc = ebitmap_cpy(&r->level[1].cat, &r->level[0].cat);
960 if (rc) {
James Morris454d9722008-02-26 20:42:02 +1100961 printk(KERN_ERR "SELinux: mls: out of memory\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700962 goto bad_high;
963 }
964 }
965
Eric Paris9398c7f2010-11-23 11:40:08 -0500966 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700967bad_high:
968 ebitmap_destroy(&r->level[0].cat);
Eric Paris9398c7f2010-11-23 11:40:08 -0500969out:
970 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700971}
972
973/*
974 * Read and validate a security context structure
975 * from a policydb binary representation file.
976 */
977static int context_read_and_validate(struct context *c,
978 struct policydb *p,
979 void *fp)
980{
Alexey Dobriyanb5bf6c52005-09-03 15:55:17 -0700981 __le32 buf[3];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700982 int rc;
983
984 rc = next_entry(buf, fp, sizeof buf);
Eric Paris9398c7f2010-11-23 11:40:08 -0500985 if (rc) {
James Morris454d9722008-02-26 20:42:02 +1100986 printk(KERN_ERR "SELinux: context truncated\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700987 goto out;
988 }
989 c->user = le32_to_cpu(buf[0]);
990 c->role = le32_to_cpu(buf[1]);
991 c->type = le32_to_cpu(buf[2]);
992 if (p->policyvers >= POLICYDB_VERSION_MLS) {
Eric Paris9398c7f2010-11-23 11:40:08 -0500993 rc = mls_read_range_helper(&c->range, fp);
994 if (rc) {
995 printk(KERN_ERR "SELinux: error reading MLS range of context\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700996 goto out;
997 }
998 }
999
Eric Paris9398c7f2010-11-23 11:40:08 -05001000 rc = -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001001 if (!policydb_context_isvalid(p, c)) {
James Morris454d9722008-02-26 20:42:02 +11001002 printk(KERN_ERR "SELinux: invalid security context\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001003 context_destroy(c);
Eric Paris9398c7f2010-11-23 11:40:08 -05001004 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001005 }
Eric Paris9398c7f2010-11-23 11:40:08 -05001006 rc = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001007out:
1008 return rc;
1009}
1010
1011/*
1012 * The following *_read functions are used to
1013 * read the symbol data from a policy database
1014 * binary representation file.
1015 */
1016
1017static int perm_read(struct policydb *p, struct hashtab *h, void *fp)
1018{
1019 char *key = NULL;
1020 struct perm_datum *perdatum;
1021 int rc;
Alexey Dobriyanb5bf6c52005-09-03 15:55:17 -07001022 __le32 buf[2];
1023 u32 len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001024
Eric Paris9398c7f2010-11-23 11:40:08 -05001025 rc = -ENOMEM;
James Morris89d155e2005-10-30 14:59:21 -08001026 perdatum = kzalloc(sizeof(*perdatum), GFP_KERNEL);
Eric Paris9398c7f2010-11-23 11:40:08 -05001027 if (!perdatum)
1028 goto bad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001029
1030 rc = next_entry(buf, fp, sizeof buf);
Eric Paris9398c7f2010-11-23 11:40:08 -05001031 if (rc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001032 goto bad;
1033
1034 len = le32_to_cpu(buf[0]);
1035 perdatum->value = le32_to_cpu(buf[1]);
1036
Eric Paris9398c7f2010-11-23 11:40:08 -05001037 rc = -ENOMEM;
Eric Paris2ced3df2008-04-17 13:37:12 -04001038 key = kmalloc(len + 1, GFP_KERNEL);
Eric Paris9398c7f2010-11-23 11:40:08 -05001039 if (!key)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001040 goto bad;
Eric Paris9398c7f2010-11-23 11:40:08 -05001041
Linus Torvalds1da177e2005-04-16 15:20:36 -07001042 rc = next_entry(key, fp, len);
Eric Paris9398c7f2010-11-23 11:40:08 -05001043 if (rc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001044 goto bad;
Vesa-Matti J Karidf4ea862008-07-20 23:57:01 +03001045 key[len] = '\0';
Linus Torvalds1da177e2005-04-16 15:20:36 -07001046
1047 rc = hashtab_insert(h, key, perdatum);
1048 if (rc)
1049 goto bad;
Eric Paris9398c7f2010-11-23 11:40:08 -05001050
1051 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001052bad:
1053 perm_destroy(key, perdatum, NULL);
Eric Paris9398c7f2010-11-23 11:40:08 -05001054 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001055}
1056
1057static int common_read(struct policydb *p, struct hashtab *h, void *fp)
1058{
1059 char *key = NULL;
1060 struct common_datum *comdatum;
Alexey Dobriyanb5bf6c52005-09-03 15:55:17 -07001061 __le32 buf[4];
1062 u32 len, nel;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001063 int i, rc;
1064
Eric Paris9398c7f2010-11-23 11:40:08 -05001065 rc = -ENOMEM;
James Morris89d155e2005-10-30 14:59:21 -08001066 comdatum = kzalloc(sizeof(*comdatum), GFP_KERNEL);
Eric Paris9398c7f2010-11-23 11:40:08 -05001067 if (!comdatum)
1068 goto bad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001069
1070 rc = next_entry(buf, fp, sizeof buf);
Eric Paris9398c7f2010-11-23 11:40:08 -05001071 if (rc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001072 goto bad;
1073
1074 len = le32_to_cpu(buf[0]);
1075 comdatum->value = le32_to_cpu(buf[1]);
1076
1077 rc = symtab_init(&comdatum->permissions, PERM_SYMTAB_SIZE);
1078 if (rc)
1079 goto bad;
1080 comdatum->permissions.nprim = le32_to_cpu(buf[2]);
1081 nel = le32_to_cpu(buf[3]);
1082
Eric Paris9398c7f2010-11-23 11:40:08 -05001083 rc = -ENOMEM;
Eric Paris2ced3df2008-04-17 13:37:12 -04001084 key = kmalloc(len + 1, GFP_KERNEL);
Eric Paris9398c7f2010-11-23 11:40:08 -05001085 if (!key)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001086 goto bad;
Eric Paris9398c7f2010-11-23 11:40:08 -05001087
Linus Torvalds1da177e2005-04-16 15:20:36 -07001088 rc = next_entry(key, fp, len);
Eric Paris9398c7f2010-11-23 11:40:08 -05001089 if (rc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001090 goto bad;
Vesa-Matti J Karidf4ea862008-07-20 23:57:01 +03001091 key[len] = '\0';
Linus Torvalds1da177e2005-04-16 15:20:36 -07001092
1093 for (i = 0; i < nel; i++) {
1094 rc = perm_read(p, comdatum->permissions.table, fp);
1095 if (rc)
1096 goto bad;
1097 }
1098
1099 rc = hashtab_insert(h, key, comdatum);
1100 if (rc)
1101 goto bad;
Eric Paris9398c7f2010-11-23 11:40:08 -05001102 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001103bad:
1104 common_destroy(key, comdatum, NULL);
Eric Paris9398c7f2010-11-23 11:40:08 -05001105 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001106}
1107
1108static int read_cons_helper(struct constraint_node **nodep, int ncons,
Eric Paris2ced3df2008-04-17 13:37:12 -04001109 int allowxtarget, void *fp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001110{
1111 struct constraint_node *c, *lc;
1112 struct constraint_expr *e, *le;
Alexey Dobriyanb5bf6c52005-09-03 15:55:17 -07001113 __le32 buf[3];
1114 u32 nexpr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001115 int rc, i, j, depth;
1116
1117 lc = NULL;
1118 for (i = 0; i < ncons; i++) {
James Morris89d155e2005-10-30 14:59:21 -08001119 c = kzalloc(sizeof(*c), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001120 if (!c)
1121 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001122
Eric Paris2ced3df2008-04-17 13:37:12 -04001123 if (lc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001124 lc->next = c;
Eric Paris2ced3df2008-04-17 13:37:12 -04001125 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001126 *nodep = c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001127
1128 rc = next_entry(buf, fp, (sizeof(u32) * 2));
Eric Paris9398c7f2010-11-23 11:40:08 -05001129 if (rc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001130 return rc;
1131 c->permissions = le32_to_cpu(buf[0]);
1132 nexpr = le32_to_cpu(buf[1]);
1133 le = NULL;
1134 depth = -1;
1135 for (j = 0; j < nexpr; j++) {
James Morris89d155e2005-10-30 14:59:21 -08001136 e = kzalloc(sizeof(*e), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001137 if (!e)
1138 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001139
Eric Paris2ced3df2008-04-17 13:37:12 -04001140 if (le)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001141 le->next = e;
Eric Paris2ced3df2008-04-17 13:37:12 -04001142 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001143 c->expr = e;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001144
1145 rc = next_entry(buf, fp, (sizeof(u32) * 3));
Eric Paris9398c7f2010-11-23 11:40:08 -05001146 if (rc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001147 return rc;
1148 e->expr_type = le32_to_cpu(buf[0]);
1149 e->attr = le32_to_cpu(buf[1]);
1150 e->op = le32_to_cpu(buf[2]);
1151
1152 switch (e->expr_type) {
1153 case CEXPR_NOT:
1154 if (depth < 0)
1155 return -EINVAL;
1156 break;
1157 case CEXPR_AND:
1158 case CEXPR_OR:
1159 if (depth < 1)
1160 return -EINVAL;
1161 depth--;
1162 break;
1163 case CEXPR_ATTR:
1164 if (depth == (CEXPR_MAXDEPTH - 1))
1165 return -EINVAL;
1166 depth++;
1167 break;
1168 case CEXPR_NAMES:
1169 if (!allowxtarget && (e->attr & CEXPR_XTARGET))
1170 return -EINVAL;
1171 if (depth == (CEXPR_MAXDEPTH - 1))
1172 return -EINVAL;
1173 depth++;
Eric Paris9398c7f2010-11-23 11:40:08 -05001174 rc = ebitmap_read(&e->names, fp);
1175 if (rc)
1176 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001177 break;
1178 default:
1179 return -EINVAL;
1180 }
1181 le = e;
1182 }
1183 if (depth != 0)
1184 return -EINVAL;
1185 lc = c;
1186 }
1187
1188 return 0;
1189}
1190
1191static int class_read(struct policydb *p, struct hashtab *h, void *fp)
1192{
1193 char *key = NULL;
1194 struct class_datum *cladatum;
Alexey Dobriyanb5bf6c52005-09-03 15:55:17 -07001195 __le32 buf[6];
1196 u32 len, len2, ncons, nel;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001197 int i, rc;
1198
Eric Paris9398c7f2010-11-23 11:40:08 -05001199 rc = -ENOMEM;
James Morris89d155e2005-10-30 14:59:21 -08001200 cladatum = kzalloc(sizeof(*cladatum), GFP_KERNEL);
Eric Paris9398c7f2010-11-23 11:40:08 -05001201 if (!cladatum)
1202 goto bad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001203
1204 rc = next_entry(buf, fp, sizeof(u32)*6);
Eric Paris9398c7f2010-11-23 11:40:08 -05001205 if (rc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001206 goto bad;
1207
1208 len = le32_to_cpu(buf[0]);
1209 len2 = le32_to_cpu(buf[1]);
1210 cladatum->value = le32_to_cpu(buf[2]);
1211
1212 rc = symtab_init(&cladatum->permissions, PERM_SYMTAB_SIZE);
1213 if (rc)
1214 goto bad;
1215 cladatum->permissions.nprim = le32_to_cpu(buf[3]);
1216 nel = le32_to_cpu(buf[4]);
1217
1218 ncons = le32_to_cpu(buf[5]);
1219
Eric Paris9398c7f2010-11-23 11:40:08 -05001220 rc = -ENOMEM;
Eric Paris2ced3df2008-04-17 13:37:12 -04001221 key = kmalloc(len + 1, GFP_KERNEL);
Eric Paris9398c7f2010-11-23 11:40:08 -05001222 if (!key)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001223 goto bad;
Eric Paris9398c7f2010-11-23 11:40:08 -05001224
Linus Torvalds1da177e2005-04-16 15:20:36 -07001225 rc = next_entry(key, fp, len);
Eric Paris9398c7f2010-11-23 11:40:08 -05001226 if (rc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001227 goto bad;
Vesa-Matti J Karidf4ea862008-07-20 23:57:01 +03001228 key[len] = '\0';
Linus Torvalds1da177e2005-04-16 15:20:36 -07001229
1230 if (len2) {
Eric Paris9398c7f2010-11-23 11:40:08 -05001231 rc = -ENOMEM;
Eric Paris2ced3df2008-04-17 13:37:12 -04001232 cladatum->comkey = kmalloc(len2 + 1, GFP_KERNEL);
Eric Paris9398c7f2010-11-23 11:40:08 -05001233 if (!cladatum->comkey)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001234 goto bad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001235 rc = next_entry(cladatum->comkey, fp, len2);
Eric Paris9398c7f2010-11-23 11:40:08 -05001236 if (rc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001237 goto bad;
Vesa-Matti J Karidf4ea862008-07-20 23:57:01 +03001238 cladatum->comkey[len2] = '\0';
Linus Torvalds1da177e2005-04-16 15:20:36 -07001239
Eric Paris9398c7f2010-11-23 11:40:08 -05001240 rc = -EINVAL;
1241 cladatum->comdatum = hashtab_search(p->p_commons.table, cladatum->comkey);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001242 if (!cladatum->comdatum) {
Eric Paris9398c7f2010-11-23 11:40:08 -05001243 printk(KERN_ERR "SELinux: unknown common %s\n", cladatum->comkey);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001244 goto bad;
1245 }
1246 }
1247 for (i = 0; i < nel; i++) {
1248 rc = perm_read(p, cladatum->permissions.table, fp);
1249 if (rc)
1250 goto bad;
1251 }
1252
1253 rc = read_cons_helper(&cladatum->constraints, ncons, 0, fp);
1254 if (rc)
1255 goto bad;
1256
1257 if (p->policyvers >= POLICYDB_VERSION_VALIDATETRANS) {
1258 /* grab the validatetrans rules */
1259 rc = next_entry(buf, fp, sizeof(u32));
Eric Paris9398c7f2010-11-23 11:40:08 -05001260 if (rc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001261 goto bad;
1262 ncons = le32_to_cpu(buf[0]);
1263 rc = read_cons_helper(&cladatum->validatetrans, ncons, 1, fp);
1264 if (rc)
1265 goto bad;
1266 }
1267
1268 rc = hashtab_insert(h, key, cladatum);
1269 if (rc)
1270 goto bad;
1271
Eric Paris9398c7f2010-11-23 11:40:08 -05001272 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001273bad:
James Morris6cbda6b2006-11-29 16:50:27 -05001274 cls_destroy(key, cladatum, NULL);
Eric Paris9398c7f2010-11-23 11:40:08 -05001275 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001276}
1277
1278static int role_read(struct policydb *p, struct hashtab *h, void *fp)
1279{
1280 char *key = NULL;
1281 struct role_datum *role;
KaiGai Koheid9250de2008-08-28 16:35:57 +09001282 int rc, to_read = 2;
1283 __le32 buf[3];
Alexey Dobriyanb5bf6c52005-09-03 15:55:17 -07001284 u32 len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001285
Eric Paris9398c7f2010-11-23 11:40:08 -05001286 rc = -ENOMEM;
James Morris89d155e2005-10-30 14:59:21 -08001287 role = kzalloc(sizeof(*role), GFP_KERNEL);
Eric Paris9398c7f2010-11-23 11:40:08 -05001288 if (!role)
1289 goto bad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001290
KaiGai Koheid9250de2008-08-28 16:35:57 +09001291 if (p->policyvers >= POLICYDB_VERSION_BOUNDARY)
1292 to_read = 3;
1293
1294 rc = next_entry(buf, fp, sizeof(buf[0]) * to_read);
Eric Paris9398c7f2010-11-23 11:40:08 -05001295 if (rc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001296 goto bad;
1297
1298 len = le32_to_cpu(buf[0]);
1299 role->value = le32_to_cpu(buf[1]);
KaiGai Koheid9250de2008-08-28 16:35:57 +09001300 if (p->policyvers >= POLICYDB_VERSION_BOUNDARY)
1301 role->bounds = le32_to_cpu(buf[2]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001302
Eric Paris9398c7f2010-11-23 11:40:08 -05001303 rc = -ENOMEM;
Eric Paris2ced3df2008-04-17 13:37:12 -04001304 key = kmalloc(len + 1, GFP_KERNEL);
Eric Paris9398c7f2010-11-23 11:40:08 -05001305 if (!key)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001306 goto bad;
Eric Paris9398c7f2010-11-23 11:40:08 -05001307
Linus Torvalds1da177e2005-04-16 15:20:36 -07001308 rc = next_entry(key, fp, len);
Eric Paris9398c7f2010-11-23 11:40:08 -05001309 if (rc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001310 goto bad;
Vesa-Matti J Karidf4ea862008-07-20 23:57:01 +03001311 key[len] = '\0';
Linus Torvalds1da177e2005-04-16 15:20:36 -07001312
1313 rc = ebitmap_read(&role->dominates, fp);
1314 if (rc)
1315 goto bad;
1316
1317 rc = ebitmap_read(&role->types, fp);
1318 if (rc)
1319 goto bad;
1320
1321 if (strcmp(key, OBJECT_R) == 0) {
Eric Paris9398c7f2010-11-23 11:40:08 -05001322 rc = -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001323 if (role->value != OBJECT_R_VAL) {
Eric Paris744ba352008-04-17 11:52:44 -04001324 printk(KERN_ERR "SELinux: Role %s has wrong value %d\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001325 OBJECT_R, role->value);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001326 goto bad;
1327 }
1328 rc = 0;
1329 goto bad;
1330 }
1331
1332 rc = hashtab_insert(h, key, role);
1333 if (rc)
1334 goto bad;
Eric Paris9398c7f2010-11-23 11:40:08 -05001335 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001336bad:
1337 role_destroy(key, role, NULL);
Eric Paris9398c7f2010-11-23 11:40:08 -05001338 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001339}
1340
1341static int type_read(struct policydb *p, struct hashtab *h, void *fp)
1342{
1343 char *key = NULL;
1344 struct type_datum *typdatum;
KaiGai Koheid9250de2008-08-28 16:35:57 +09001345 int rc, to_read = 3;
1346 __le32 buf[4];
Alexey Dobriyanb5bf6c52005-09-03 15:55:17 -07001347 u32 len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001348
Eric Paris9398c7f2010-11-23 11:40:08 -05001349 rc = -ENOMEM;
Eric Paris2ced3df2008-04-17 13:37:12 -04001350 typdatum = kzalloc(sizeof(*typdatum), GFP_KERNEL);
Eric Paris9398c7f2010-11-23 11:40:08 -05001351 if (!typdatum)
1352 goto bad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001353
KaiGai Koheid9250de2008-08-28 16:35:57 +09001354 if (p->policyvers >= POLICYDB_VERSION_BOUNDARY)
1355 to_read = 4;
1356
1357 rc = next_entry(buf, fp, sizeof(buf[0]) * to_read);
Eric Paris9398c7f2010-11-23 11:40:08 -05001358 if (rc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001359 goto bad;
1360
1361 len = le32_to_cpu(buf[0]);
1362 typdatum->value = le32_to_cpu(buf[1]);
KaiGai Koheid9250de2008-08-28 16:35:57 +09001363 if (p->policyvers >= POLICYDB_VERSION_BOUNDARY) {
1364 u32 prop = le32_to_cpu(buf[2]);
1365
1366 if (prop & TYPEDATUM_PROPERTY_PRIMARY)
1367 typdatum->primary = 1;
1368 if (prop & TYPEDATUM_PROPERTY_ATTRIBUTE)
1369 typdatum->attribute = 1;
1370
1371 typdatum->bounds = le32_to_cpu(buf[3]);
1372 } else {
1373 typdatum->primary = le32_to_cpu(buf[2]);
1374 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001375
Eric Paris9398c7f2010-11-23 11:40:08 -05001376 rc = -ENOMEM;
Eric Paris2ced3df2008-04-17 13:37:12 -04001377 key = kmalloc(len + 1, GFP_KERNEL);
Eric Paris9398c7f2010-11-23 11:40:08 -05001378 if (!key)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001379 goto bad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001380 rc = next_entry(key, fp, len);
Eric Paris9398c7f2010-11-23 11:40:08 -05001381 if (rc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001382 goto bad;
Vesa-Matti J Karidf4ea862008-07-20 23:57:01 +03001383 key[len] = '\0';
Linus Torvalds1da177e2005-04-16 15:20:36 -07001384
1385 rc = hashtab_insert(h, key, typdatum);
1386 if (rc)
1387 goto bad;
Eric Paris9398c7f2010-11-23 11:40:08 -05001388 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001389bad:
1390 type_destroy(key, typdatum, NULL);
Eric Paris9398c7f2010-11-23 11:40:08 -05001391 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001392}
1393
1394
1395/*
1396 * Read a MLS level structure from a policydb binary
1397 * representation file.
1398 */
1399static int mls_read_level(struct mls_level *lp, void *fp)
1400{
Alexey Dobriyanb5bf6c52005-09-03 15:55:17 -07001401 __le32 buf[1];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001402 int rc;
1403
1404 memset(lp, 0, sizeof(*lp));
1405
1406 rc = next_entry(buf, fp, sizeof buf);
Eric Paris9398c7f2010-11-23 11:40:08 -05001407 if (rc) {
James Morris454d9722008-02-26 20:42:02 +11001408 printk(KERN_ERR "SELinux: mls: truncated level\n");
Eric Paris9398c7f2010-11-23 11:40:08 -05001409 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001410 }
1411 lp->sens = le32_to_cpu(buf[0]);
1412
Eric Paris9398c7f2010-11-23 11:40:08 -05001413 rc = ebitmap_read(&lp->cat, fp);
1414 if (rc) {
1415 printk(KERN_ERR "SELinux: mls: error reading level categories\n");
1416 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001417 }
1418 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001419}
1420
1421static int user_read(struct policydb *p, struct hashtab *h, void *fp)
1422{
1423 char *key = NULL;
1424 struct user_datum *usrdatum;
KaiGai Koheid9250de2008-08-28 16:35:57 +09001425 int rc, to_read = 2;
1426 __le32 buf[3];
Alexey Dobriyanb5bf6c52005-09-03 15:55:17 -07001427 u32 len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001428
Eric Paris9398c7f2010-11-23 11:40:08 -05001429 rc = -ENOMEM;
James Morris89d155e2005-10-30 14:59:21 -08001430 usrdatum = kzalloc(sizeof(*usrdatum), GFP_KERNEL);
Eric Paris9398c7f2010-11-23 11:40:08 -05001431 if (!usrdatum)
1432 goto bad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001433
KaiGai Koheid9250de2008-08-28 16:35:57 +09001434 if (p->policyvers >= POLICYDB_VERSION_BOUNDARY)
1435 to_read = 3;
1436
1437 rc = next_entry(buf, fp, sizeof(buf[0]) * to_read);
Eric Paris9398c7f2010-11-23 11:40:08 -05001438 if (rc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001439 goto bad;
1440
1441 len = le32_to_cpu(buf[0]);
1442 usrdatum->value = le32_to_cpu(buf[1]);
KaiGai Koheid9250de2008-08-28 16:35:57 +09001443 if (p->policyvers >= POLICYDB_VERSION_BOUNDARY)
1444 usrdatum->bounds = le32_to_cpu(buf[2]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001445
Eric Paris9398c7f2010-11-23 11:40:08 -05001446 rc = -ENOMEM;
Eric Paris2ced3df2008-04-17 13:37:12 -04001447 key = kmalloc(len + 1, GFP_KERNEL);
Eric Paris9398c7f2010-11-23 11:40:08 -05001448 if (!key)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001449 goto bad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001450 rc = next_entry(key, fp, len);
Eric Paris9398c7f2010-11-23 11:40:08 -05001451 if (rc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001452 goto bad;
Vesa-Matti J Karidf4ea862008-07-20 23:57:01 +03001453 key[len] = '\0';
Linus Torvalds1da177e2005-04-16 15:20:36 -07001454
1455 rc = ebitmap_read(&usrdatum->roles, fp);
1456 if (rc)
1457 goto bad;
1458
1459 if (p->policyvers >= POLICYDB_VERSION_MLS) {
1460 rc = mls_read_range_helper(&usrdatum->range, fp);
1461 if (rc)
1462 goto bad;
1463 rc = mls_read_level(&usrdatum->dfltlevel, fp);
1464 if (rc)
1465 goto bad;
1466 }
1467
1468 rc = hashtab_insert(h, key, usrdatum);
1469 if (rc)
1470 goto bad;
Eric Paris9398c7f2010-11-23 11:40:08 -05001471 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001472bad:
1473 user_destroy(key, usrdatum, NULL);
Eric Paris9398c7f2010-11-23 11:40:08 -05001474 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001475}
1476
1477static int sens_read(struct policydb *p, struct hashtab *h, void *fp)
1478{
1479 char *key = NULL;
1480 struct level_datum *levdatum;
1481 int rc;
Alexey Dobriyanb5bf6c52005-09-03 15:55:17 -07001482 __le32 buf[2];
1483 u32 len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001484
Eric Paris9398c7f2010-11-23 11:40:08 -05001485 rc = -ENOMEM;
James Morris89d155e2005-10-30 14:59:21 -08001486 levdatum = kzalloc(sizeof(*levdatum), GFP_ATOMIC);
Eric Paris9398c7f2010-11-23 11:40:08 -05001487 if (!levdatum)
1488 goto bad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001489
1490 rc = next_entry(buf, fp, sizeof buf);
Eric Paris9398c7f2010-11-23 11:40:08 -05001491 if (rc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001492 goto bad;
1493
1494 len = le32_to_cpu(buf[0]);
1495 levdatum->isalias = le32_to_cpu(buf[1]);
1496
Eric Paris9398c7f2010-11-23 11:40:08 -05001497 rc = -ENOMEM;
Eric Paris2ced3df2008-04-17 13:37:12 -04001498 key = kmalloc(len + 1, GFP_ATOMIC);
Eric Paris9398c7f2010-11-23 11:40:08 -05001499 if (!key)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001500 goto bad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001501 rc = next_entry(key, fp, len);
Eric Paris9398c7f2010-11-23 11:40:08 -05001502 if (rc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001503 goto bad;
Vesa-Matti J Karidf4ea862008-07-20 23:57:01 +03001504 key[len] = '\0';
Linus Torvalds1da177e2005-04-16 15:20:36 -07001505
Eric Paris9398c7f2010-11-23 11:40:08 -05001506 rc = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001507 levdatum->level = kmalloc(sizeof(struct mls_level), GFP_ATOMIC);
Eric Paris9398c7f2010-11-23 11:40:08 -05001508 if (!levdatum->level)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001509 goto bad;
Eric Paris9398c7f2010-11-23 11:40:08 -05001510
1511 rc = mls_read_level(levdatum->level, fp);
1512 if (rc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001513 goto bad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001514
1515 rc = hashtab_insert(h, key, levdatum);
1516 if (rc)
1517 goto bad;
Eric Paris9398c7f2010-11-23 11:40:08 -05001518 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001519bad:
1520 sens_destroy(key, levdatum, NULL);
Eric Paris9398c7f2010-11-23 11:40:08 -05001521 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001522}
1523
1524static int cat_read(struct policydb *p, struct hashtab *h, void *fp)
1525{
1526 char *key = NULL;
1527 struct cat_datum *catdatum;
1528 int rc;
Alexey Dobriyanb5bf6c52005-09-03 15:55:17 -07001529 __le32 buf[3];
1530 u32 len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001531
Eric Paris9398c7f2010-11-23 11:40:08 -05001532 rc = -ENOMEM;
James Morris89d155e2005-10-30 14:59:21 -08001533 catdatum = kzalloc(sizeof(*catdatum), GFP_ATOMIC);
Eric Paris9398c7f2010-11-23 11:40:08 -05001534 if (!catdatum)
1535 goto bad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001536
1537 rc = next_entry(buf, fp, sizeof buf);
Eric Paris9398c7f2010-11-23 11:40:08 -05001538 if (rc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001539 goto bad;
1540
1541 len = le32_to_cpu(buf[0]);
1542 catdatum->value = le32_to_cpu(buf[1]);
1543 catdatum->isalias = le32_to_cpu(buf[2]);
1544
Eric Paris9398c7f2010-11-23 11:40:08 -05001545 rc = -ENOMEM;
Eric Paris2ced3df2008-04-17 13:37:12 -04001546 key = kmalloc(len + 1, GFP_ATOMIC);
Eric Paris9398c7f2010-11-23 11:40:08 -05001547 if (!key)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001548 goto bad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001549 rc = next_entry(key, fp, len);
Eric Paris9398c7f2010-11-23 11:40:08 -05001550 if (rc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001551 goto bad;
Vesa-Matti J Karidf4ea862008-07-20 23:57:01 +03001552 key[len] = '\0';
Linus Torvalds1da177e2005-04-16 15:20:36 -07001553
1554 rc = hashtab_insert(h, key, catdatum);
1555 if (rc)
1556 goto bad;
Eric Paris9398c7f2010-11-23 11:40:08 -05001557 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001558bad:
1559 cat_destroy(key, catdatum, NULL);
Eric Paris9398c7f2010-11-23 11:40:08 -05001560 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001561}
1562
1563static int (*read_f[SYM_NUM]) (struct policydb *p, struct hashtab *h, void *fp) =
1564{
1565 common_read,
1566 class_read,
1567 role_read,
1568 type_read,
1569 user_read,
1570 cond_read_bool,
1571 sens_read,
1572 cat_read,
1573};
1574
KaiGai Koheid9250de2008-08-28 16:35:57 +09001575static int user_bounds_sanity_check(void *key, void *datum, void *datap)
1576{
1577 struct user_datum *upper, *user;
1578 struct policydb *p = datap;
1579 int depth = 0;
1580
1581 upper = user = datum;
1582 while (upper->bounds) {
1583 struct ebitmap_node *node;
1584 unsigned long bit;
1585
1586 if (++depth == POLICYDB_BOUNDS_MAXDEPTH) {
1587 printk(KERN_ERR "SELinux: user %s: "
1588 "too deep or looped boundary",
1589 (char *) key);
1590 return -EINVAL;
1591 }
1592
1593 upper = p->user_val_to_struct[upper->bounds - 1];
1594 ebitmap_for_each_positive_bit(&user->roles, node, bit) {
1595 if (ebitmap_get_bit(&upper->roles, bit))
1596 continue;
1597
1598 printk(KERN_ERR
1599 "SELinux: boundary violated policy: "
1600 "user=%s role=%s bounds=%s\n",
Eric Parisac76c05b2010-11-29 15:47:09 -05001601 sym_name(p, SYM_USERS, user->value - 1),
1602 sym_name(p, SYM_ROLES, bit),
1603 sym_name(p, SYM_USERS, upper->value - 1));
KaiGai Koheid9250de2008-08-28 16:35:57 +09001604
1605 return -EINVAL;
1606 }
1607 }
1608
1609 return 0;
1610}
1611
1612static int role_bounds_sanity_check(void *key, void *datum, void *datap)
1613{
1614 struct role_datum *upper, *role;
1615 struct policydb *p = datap;
1616 int depth = 0;
1617
1618 upper = role = datum;
1619 while (upper->bounds) {
1620 struct ebitmap_node *node;
1621 unsigned long bit;
1622
1623 if (++depth == POLICYDB_BOUNDS_MAXDEPTH) {
1624 printk(KERN_ERR "SELinux: role %s: "
1625 "too deep or looped bounds\n",
1626 (char *) key);
1627 return -EINVAL;
1628 }
1629
1630 upper = p->role_val_to_struct[upper->bounds - 1];
1631 ebitmap_for_each_positive_bit(&role->types, node, bit) {
1632 if (ebitmap_get_bit(&upper->types, bit))
1633 continue;
1634
1635 printk(KERN_ERR
1636 "SELinux: boundary violated policy: "
1637 "role=%s type=%s bounds=%s\n",
Eric Parisac76c05b2010-11-29 15:47:09 -05001638 sym_name(p, SYM_ROLES, role->value - 1),
1639 sym_name(p, SYM_TYPES, bit),
1640 sym_name(p, SYM_ROLES, upper->value - 1));
KaiGai Koheid9250de2008-08-28 16:35:57 +09001641
1642 return -EINVAL;
1643 }
1644 }
1645
1646 return 0;
1647}
1648
1649static int type_bounds_sanity_check(void *key, void *datum, void *datap)
1650{
Eric Parisdaa6d832010-08-03 15:26:05 -04001651 struct type_datum *upper;
KaiGai Koheid9250de2008-08-28 16:35:57 +09001652 struct policydb *p = datap;
1653 int depth = 0;
1654
Eric Parisdaa6d832010-08-03 15:26:05 -04001655 upper = datum;
KaiGai Koheid9250de2008-08-28 16:35:57 +09001656 while (upper->bounds) {
1657 if (++depth == POLICYDB_BOUNDS_MAXDEPTH) {
1658 printk(KERN_ERR "SELinux: type %s: "
1659 "too deep or looped boundary\n",
1660 (char *) key);
1661 return -EINVAL;
1662 }
1663
Eric Paris23bdecb2010-11-29 15:47:09 -05001664 upper = flex_array_get_ptr(p->type_val_to_struct_array,
1665 upper->bounds - 1);
1666 BUG_ON(!upper);
1667
KaiGai Koheid9250de2008-08-28 16:35:57 +09001668 if (upper->attribute) {
1669 printk(KERN_ERR "SELinux: type %s: "
1670 "bounded by attribute %s",
1671 (char *) key,
Eric Parisac76c05b2010-11-29 15:47:09 -05001672 sym_name(p, SYM_TYPES, upper->value - 1));
KaiGai Koheid9250de2008-08-28 16:35:57 +09001673 return -EINVAL;
1674 }
1675 }
1676
1677 return 0;
1678}
1679
1680static int policydb_bounds_sanity_check(struct policydb *p)
1681{
1682 int rc;
1683
1684 if (p->policyvers < POLICYDB_VERSION_BOUNDARY)
1685 return 0;
1686
1687 rc = hashtab_map(p->p_users.table,
1688 user_bounds_sanity_check, p);
1689 if (rc)
1690 return rc;
1691
1692 rc = hashtab_map(p->p_roles.table,
1693 role_bounds_sanity_check, p);
1694 if (rc)
1695 return rc;
1696
1697 rc = hashtab_map(p->p_types.table,
1698 type_bounds_sanity_check, p);
1699 if (rc)
1700 return rc;
1701
1702 return 0;
1703}
1704
Linus Torvalds1da177e2005-04-16 15:20:36 -07001705extern int ss_initialized;
1706
Stephen Smalleyc6d3aaa2009-09-30 13:37:50 -04001707u16 string_to_security_class(struct policydb *p, const char *name)
1708{
1709 struct class_datum *cladatum;
1710
1711 cladatum = hashtab_search(p->p_classes.table, name);
1712 if (!cladatum)
1713 return 0;
1714
1715 return cladatum->value;
1716}
1717
1718u32 string_to_av_perm(struct policydb *p, u16 tclass, const char *name)
1719{
1720 struct class_datum *cladatum;
1721 struct perm_datum *perdatum = NULL;
1722 struct common_datum *comdatum;
1723
1724 if (!tclass || tclass > p->p_classes.nprim)
1725 return 0;
1726
1727 cladatum = p->class_val_to_struct[tclass-1];
1728 comdatum = cladatum->comdatum;
1729 if (comdatum)
1730 perdatum = hashtab_search(comdatum->permissions.table,
1731 name);
1732 if (!perdatum)
1733 perdatum = hashtab_search(cladatum->permissions.table,
1734 name);
1735 if (!perdatum)
1736 return 0;
1737
1738 return 1U << (perdatum->value-1);
1739}
1740
Eric Paris9ee0c822010-06-11 12:37:05 -04001741static int range_read(struct policydb *p, void *fp)
1742{
1743 struct range_trans *rt = NULL;
1744 struct mls_range *r = NULL;
1745 int i, rc;
1746 __le32 buf[2];
1747 u32 nel;
1748
1749 if (p->policyvers < POLICYDB_VERSION_MLS)
1750 return 0;
1751
1752 rc = next_entry(buf, fp, sizeof(u32));
1753 if (rc)
1754 goto out;
1755
1756 nel = le32_to_cpu(buf[0]);
1757 for (i = 0; i < nel; i++) {
1758 rc = -ENOMEM;
1759 rt = kzalloc(sizeof(*rt), GFP_KERNEL);
1760 if (!rt)
1761 goto out;
1762
1763 rc = next_entry(buf, fp, (sizeof(u32) * 2));
1764 if (rc)
1765 goto out;
1766
1767 rt->source_type = le32_to_cpu(buf[0]);
1768 rt->target_type = le32_to_cpu(buf[1]);
1769 if (p->policyvers >= POLICYDB_VERSION_RANGETRANS) {
1770 rc = next_entry(buf, fp, sizeof(u32));
1771 if (rc)
1772 goto out;
1773 rt->target_class = le32_to_cpu(buf[0]);
1774 } else
1775 rt->target_class = p->process_class;
1776
1777 rc = -EINVAL;
1778 if (!policydb_type_isvalid(p, rt->source_type) ||
1779 !policydb_type_isvalid(p, rt->target_type) ||
1780 !policydb_class_isvalid(p, rt->target_class))
1781 goto out;
1782
1783 rc = -ENOMEM;
1784 r = kzalloc(sizeof(*r), GFP_KERNEL);
1785 if (!r)
1786 goto out;
1787
1788 rc = mls_read_range_helper(r, fp);
1789 if (rc)
1790 goto out;
1791
1792 rc = -EINVAL;
1793 if (!mls_range_isvalid(p, r)) {
1794 printk(KERN_WARNING "SELinux: rangetrans: invalid range\n");
1795 goto out;
1796 }
1797
1798 rc = hashtab_insert(p->range_tr, rt, r);
1799 if (rc)
1800 goto out;
1801
1802 rt = NULL;
1803 r = NULL;
1804 }
1805 rangetr_hash_eval(p->range_tr);
1806 rc = 0;
1807out:
1808 kfree(rt);
1809 kfree(r);
1810 return rc;
1811}
1812
Eric Paris652bb9b2011-02-01 11:05:40 -05001813static int filename_trans_read(struct policydb *p, void *fp)
1814{
1815 struct filename_trans *ft, *last;
1816 u32 nel, len;
1817 char *name;
1818 __le32 buf[4];
1819 int rc, i;
1820
1821 if (p->policyvers < POLICYDB_VERSION_FILENAME_TRANS)
1822 return 0;
1823
1824 rc = next_entry(buf, fp, sizeof(u32));
1825 if (rc)
1826 goto out;
1827 nel = le32_to_cpu(buf[0]);
1828
Eric Paris652bb9b2011-02-01 11:05:40 -05001829 last = p->filename_trans;
1830 while (last && last->next)
1831 last = last->next;
1832
1833 for (i = 0; i < nel; i++) {
1834 rc = -ENOMEM;
1835 ft = kzalloc(sizeof(*ft), GFP_KERNEL);
1836 if (!ft)
1837 goto out;
1838
1839 /* add it to the tail of the list */
1840 if (!last)
1841 p->filename_trans = ft;
1842 else
1843 last->next = ft;
1844 last = ft;
1845
1846 /* length of the path component string */
1847 rc = next_entry(buf, fp, sizeof(u32));
1848 if (rc)
1849 goto out;
1850 len = le32_to_cpu(buf[0]);
1851
1852 rc = -ENOMEM;
1853 name = kmalloc(len + 1, GFP_KERNEL);
1854 if (!name)
1855 goto out;
1856
1857 ft->name = name;
1858
1859 /* path component string */
1860 rc = next_entry(name, fp, len);
1861 if (rc)
1862 goto out;
1863 name[len] = 0;
1864
Eric Paris652bb9b2011-02-01 11:05:40 -05001865 rc = next_entry(buf, fp, sizeof(u32) * 4);
1866 if (rc)
1867 goto out;
1868
1869 ft->stype = le32_to_cpu(buf[0]);
1870 ft->ttype = le32_to_cpu(buf[1]);
1871 ft->tclass = le32_to_cpu(buf[2]);
1872 ft->otype = le32_to_cpu(buf[3]);
Eric Paris03a4c012011-04-28 15:11:21 -04001873
1874 rc = ebitmap_set_bit(&p->filename_trans_ttypes, ft->ttype, 1);
1875 if (rc)
1876 goto out;
Eric Paris652bb9b2011-02-01 11:05:40 -05001877 }
1878 rc = 0;
1879out:
1880 return rc;
1881}
1882
Eric Parisd1b43542010-07-21 12:50:57 -04001883static int genfs_read(struct policydb *p, void *fp)
1884{
1885 int i, j, rc;
1886 u32 nel, nel2, len, len2;
1887 __le32 buf[1];
1888 struct ocontext *l, *c;
1889 struct ocontext *newc = NULL;
1890 struct genfs *genfs_p, *genfs;
1891 struct genfs *newgenfs = NULL;
1892
1893 rc = next_entry(buf, fp, sizeof(u32));
1894 if (rc)
1895 goto out;
1896 nel = le32_to_cpu(buf[0]);
1897
1898 for (i = 0; i < nel; i++) {
1899 rc = next_entry(buf, fp, sizeof(u32));
1900 if (rc)
1901 goto out;
1902 len = le32_to_cpu(buf[0]);
1903
1904 rc = -ENOMEM;
1905 newgenfs = kzalloc(sizeof(*newgenfs), GFP_KERNEL);
1906 if (!newgenfs)
1907 goto out;
1908
1909 rc = -ENOMEM;
1910 newgenfs->fstype = kmalloc(len + 1, GFP_KERNEL);
1911 if (!newgenfs->fstype)
1912 goto out;
1913
1914 rc = next_entry(newgenfs->fstype, fp, len);
1915 if (rc)
1916 goto out;
1917
1918 newgenfs->fstype[len] = 0;
1919
1920 for (genfs_p = NULL, genfs = p->genfs; genfs;
1921 genfs_p = genfs, genfs = genfs->next) {
1922 rc = -EINVAL;
1923 if (strcmp(newgenfs->fstype, genfs->fstype) == 0) {
1924 printk(KERN_ERR "SELinux: dup genfs fstype %s\n",
1925 newgenfs->fstype);
1926 goto out;
1927 }
1928 if (strcmp(newgenfs->fstype, genfs->fstype) < 0)
1929 break;
1930 }
1931 newgenfs->next = genfs;
1932 if (genfs_p)
1933 genfs_p->next = newgenfs;
1934 else
1935 p->genfs = newgenfs;
1936 genfs = newgenfs;
1937 newgenfs = NULL;
1938
1939 rc = next_entry(buf, fp, sizeof(u32));
1940 if (rc)
1941 goto out;
1942
1943 nel2 = le32_to_cpu(buf[0]);
1944 for (j = 0; j < nel2; j++) {
1945 rc = next_entry(buf, fp, sizeof(u32));
1946 if (rc)
1947 goto out;
1948 len = le32_to_cpu(buf[0]);
1949
1950 rc = -ENOMEM;
1951 newc = kzalloc(sizeof(*newc), GFP_KERNEL);
1952 if (!newc)
1953 goto out;
1954
1955 rc = -ENOMEM;
1956 newc->u.name = kmalloc(len + 1, GFP_KERNEL);
1957 if (!newc->u.name)
1958 goto out;
1959
1960 rc = next_entry(newc->u.name, fp, len);
1961 if (rc)
1962 goto out;
1963 newc->u.name[len] = 0;
1964
1965 rc = next_entry(buf, fp, sizeof(u32));
1966 if (rc)
1967 goto out;
1968
1969 newc->v.sclass = le32_to_cpu(buf[0]);
1970 rc = context_read_and_validate(&newc->context[0], p, fp);
1971 if (rc)
1972 goto out;
1973
1974 for (l = NULL, c = genfs->head; c;
1975 l = c, c = c->next) {
1976 rc = -EINVAL;
1977 if (!strcmp(newc->u.name, c->u.name) &&
1978 (!c->v.sclass || !newc->v.sclass ||
1979 newc->v.sclass == c->v.sclass)) {
1980 printk(KERN_ERR "SELinux: dup genfs entry (%s,%s)\n",
1981 genfs->fstype, c->u.name);
1982 goto out;
1983 }
1984 len = strlen(newc->u.name);
1985 len2 = strlen(c->u.name);
1986 if (len > len2)
1987 break;
1988 }
1989
1990 newc->next = c;
1991 if (l)
1992 l->next = newc;
1993 else
1994 genfs->head = newc;
1995 newc = NULL;
1996 }
1997 }
1998 rc = 0;
1999out:
2000 if (newgenfs)
2001 kfree(newgenfs->fstype);
2002 kfree(newgenfs);
2003 ocontext_destroy(newc, OCON_FSUSE);
2004
2005 return rc;
2006}
2007
Eric Paris692a8a22010-07-21 12:51:03 -04002008static int ocontext_read(struct policydb *p, struct policydb_compat_info *info,
2009 void *fp)
2010{
2011 int i, j, rc;
2012 u32 nel, len;
2013 __le32 buf[3];
2014 struct ocontext *l, *c;
2015 u32 nodebuf[8];
2016
2017 for (i = 0; i < info->ocon_num; i++) {
2018 rc = next_entry(buf, fp, sizeof(u32));
2019 if (rc)
2020 goto out;
2021 nel = le32_to_cpu(buf[0]);
2022
2023 l = NULL;
2024 for (j = 0; j < nel; j++) {
2025 rc = -ENOMEM;
2026 c = kzalloc(sizeof(*c), GFP_KERNEL);
2027 if (!c)
2028 goto out;
2029 if (l)
2030 l->next = c;
2031 else
2032 p->ocontexts[i] = c;
2033 l = c;
2034
2035 switch (i) {
2036 case OCON_ISID:
2037 rc = next_entry(buf, fp, sizeof(u32));
2038 if (rc)
2039 goto out;
2040
2041 c->sid[0] = le32_to_cpu(buf[0]);
2042 rc = context_read_and_validate(&c->context[0], p, fp);
2043 if (rc)
2044 goto out;
2045 break;
2046 case OCON_FS:
2047 case OCON_NETIF:
2048 rc = next_entry(buf, fp, sizeof(u32));
2049 if (rc)
2050 goto out;
2051 len = le32_to_cpu(buf[0]);
2052
2053 rc = -ENOMEM;
2054 c->u.name = kmalloc(len + 1, GFP_KERNEL);
2055 if (!c->u.name)
2056 goto out;
2057
2058 rc = next_entry(c->u.name, fp, len);
2059 if (rc)
2060 goto out;
2061
2062 c->u.name[len] = 0;
2063 rc = context_read_and_validate(&c->context[0], p, fp);
2064 if (rc)
2065 goto out;
2066 rc = context_read_and_validate(&c->context[1], p, fp);
2067 if (rc)
2068 goto out;
2069 break;
2070 case OCON_PORT:
2071 rc = next_entry(buf, fp, sizeof(u32)*3);
2072 if (rc)
2073 goto out;
2074 c->u.port.protocol = le32_to_cpu(buf[0]);
2075 c->u.port.low_port = le32_to_cpu(buf[1]);
2076 c->u.port.high_port = le32_to_cpu(buf[2]);
2077 rc = context_read_and_validate(&c->context[0], p, fp);
2078 if (rc)
2079 goto out;
2080 break;
2081 case OCON_NODE:
2082 rc = next_entry(nodebuf, fp, sizeof(u32) * 2);
2083 if (rc)
2084 goto out;
2085 c->u.node.addr = nodebuf[0]; /* network order */
2086 c->u.node.mask = nodebuf[1]; /* network order */
2087 rc = context_read_and_validate(&c->context[0], p, fp);
2088 if (rc)
2089 goto out;
2090 break;
2091 case OCON_FSUSE:
2092 rc = next_entry(buf, fp, sizeof(u32)*2);
2093 if (rc)
2094 goto out;
2095
2096 rc = -EINVAL;
2097 c->v.behavior = le32_to_cpu(buf[0]);
2098 if (c->v.behavior > SECURITY_FS_USE_NONE)
2099 goto out;
2100
2101 rc = -ENOMEM;
2102 len = le32_to_cpu(buf[1]);
2103 c->u.name = kmalloc(len + 1, GFP_KERNEL);
2104 if (!c->u.name)
2105 goto out;
2106
2107 rc = next_entry(c->u.name, fp, len);
2108 if (rc)
2109 goto out;
2110 c->u.name[len] = 0;
2111 rc = context_read_and_validate(&c->context[0], p, fp);
2112 if (rc)
2113 goto out;
2114 break;
2115 case OCON_NODE6: {
2116 int k;
2117
2118 rc = next_entry(nodebuf, fp, sizeof(u32) * 8);
2119 if (rc)
2120 goto out;
2121 for (k = 0; k < 4; k++)
2122 c->u.node6.addr[k] = nodebuf[k];
2123 for (k = 0; k < 4; k++)
2124 c->u.node6.mask[k] = nodebuf[k+4];
2125 rc = context_read_and_validate(&c->context[0], p, fp);
2126 if (rc)
2127 goto out;
2128 break;
2129 }
2130 }
2131 }
2132 }
2133 rc = 0;
2134out:
2135 return rc;
2136}
2137
Linus Torvalds1da177e2005-04-16 15:20:36 -07002138/*
2139 * Read the configuration data from a policy database binary
2140 * representation file into a policy database structure.
2141 */
2142int policydb_read(struct policydb *p, void *fp)
2143{
2144 struct role_allow *ra, *lra;
2145 struct role_trans *tr, *ltr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002146 int i, j, rc;
Stephen Smalley59dbd1b2008-06-05 09:48:51 -04002147 __le32 buf[4];
Eric Parisd1b43542010-07-21 12:50:57 -04002148 u32 len, nprim, nel;
2149
Linus Torvalds1da177e2005-04-16 15:20:36 -07002150 char *policydb_str;
2151 struct policydb_compat_info *info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002152
Linus Torvalds1da177e2005-04-16 15:20:36 -07002153 rc = policydb_init(p);
2154 if (rc)
Eric Paris9398c7f2010-11-23 11:40:08 -05002155 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002156
2157 /* Read the magic number and string length. */
Eric Paris2ced3df2008-04-17 13:37:12 -04002158 rc = next_entry(buf, fp, sizeof(u32) * 2);
Eric Paris9398c7f2010-11-23 11:40:08 -05002159 if (rc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002160 goto bad;
2161
Eric Paris9398c7f2010-11-23 11:40:08 -05002162 rc = -EINVAL;
Alexey Dobriyanb5bf6c52005-09-03 15:55:17 -07002163 if (le32_to_cpu(buf[0]) != POLICYDB_MAGIC) {
James Morris454d9722008-02-26 20:42:02 +11002164 printk(KERN_ERR "SELinux: policydb magic number 0x%x does "
Linus Torvalds1da177e2005-04-16 15:20:36 -07002165 "not match expected magic number 0x%x\n",
Alexey Dobriyanb5bf6c52005-09-03 15:55:17 -07002166 le32_to_cpu(buf[0]), POLICYDB_MAGIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002167 goto bad;
2168 }
2169
Eric Paris9398c7f2010-11-23 11:40:08 -05002170 rc = -EINVAL;
Alexey Dobriyanb5bf6c52005-09-03 15:55:17 -07002171 len = le32_to_cpu(buf[1]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002172 if (len != strlen(POLICYDB_STRING)) {
James Morris454d9722008-02-26 20:42:02 +11002173 printk(KERN_ERR "SELinux: policydb string length %d does not "
Linus Torvalds1da177e2005-04-16 15:20:36 -07002174 "match expected length %Zu\n",
2175 len, strlen(POLICYDB_STRING));
2176 goto bad;
2177 }
Eric Paris9398c7f2010-11-23 11:40:08 -05002178
2179 rc = -ENOMEM;
Eric Paris2ced3df2008-04-17 13:37:12 -04002180 policydb_str = kmalloc(len + 1, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002181 if (!policydb_str) {
James Morris454d9722008-02-26 20:42:02 +11002182 printk(KERN_ERR "SELinux: unable to allocate memory for policydb "
Linus Torvalds1da177e2005-04-16 15:20:36 -07002183 "string of length %d\n", len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002184 goto bad;
2185 }
Eric Paris9398c7f2010-11-23 11:40:08 -05002186
Linus Torvalds1da177e2005-04-16 15:20:36 -07002187 rc = next_entry(policydb_str, fp, len);
Eric Paris9398c7f2010-11-23 11:40:08 -05002188 if (rc) {
James Morris454d9722008-02-26 20:42:02 +11002189 printk(KERN_ERR "SELinux: truncated policydb string identifier\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002190 kfree(policydb_str);
2191 goto bad;
2192 }
Eric Paris9398c7f2010-11-23 11:40:08 -05002193
2194 rc = -EINVAL;
Vesa-Matti J Karidf4ea862008-07-20 23:57:01 +03002195 policydb_str[len] = '\0';
Linus Torvalds1da177e2005-04-16 15:20:36 -07002196 if (strcmp(policydb_str, POLICYDB_STRING)) {
James Morris454d9722008-02-26 20:42:02 +11002197 printk(KERN_ERR "SELinux: policydb string %s does not match "
Linus Torvalds1da177e2005-04-16 15:20:36 -07002198 "my string %s\n", policydb_str, POLICYDB_STRING);
2199 kfree(policydb_str);
2200 goto bad;
2201 }
2202 /* Done with policydb_str. */
2203 kfree(policydb_str);
2204 policydb_str = NULL;
2205
Guido Trentalancia0719aaf2010-02-03 16:40:20 +01002206 /* Read the version and table sizes. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002207 rc = next_entry(buf, fp, sizeof(u32)*4);
Eric Paris9398c7f2010-11-23 11:40:08 -05002208 if (rc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002209 goto bad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002210
Eric Paris9398c7f2010-11-23 11:40:08 -05002211 rc = -EINVAL;
Alexey Dobriyanb5bf6c52005-09-03 15:55:17 -07002212 p->policyvers = le32_to_cpu(buf[0]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002213 if (p->policyvers < POLICYDB_VERSION_MIN ||
2214 p->policyvers > POLICYDB_VERSION_MAX) {
James Morris454d9722008-02-26 20:42:02 +11002215 printk(KERN_ERR "SELinux: policydb version %d does not match "
Eric Paris2ced3df2008-04-17 13:37:12 -04002216 "my version range %d-%d\n",
2217 le32_to_cpu(buf[0]), POLICYDB_VERSION_MIN, POLICYDB_VERSION_MAX);
2218 goto bad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002219 }
2220
Alexey Dobriyanb5bf6c52005-09-03 15:55:17 -07002221 if ((le32_to_cpu(buf[1]) & POLICYDB_CONFIG_MLS)) {
Guido Trentalancia0719aaf2010-02-03 16:40:20 +01002222 p->mls_enabled = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002223
Eric Paris9398c7f2010-11-23 11:40:08 -05002224 rc = -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002225 if (p->policyvers < POLICYDB_VERSION_MLS) {
Eric Paris744ba352008-04-17 11:52:44 -04002226 printk(KERN_ERR "SELinux: security policydb version %d "
2227 "(MLS) not backwards compatible\n",
2228 p->policyvers);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002229 goto bad;
2230 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002231 }
Eric Paris3f120702007-09-21 14:37:10 -04002232 p->reject_unknown = !!(le32_to_cpu(buf[1]) & REJECT_UNKNOWN);
2233 p->allow_unknown = !!(le32_to_cpu(buf[1]) & ALLOW_UNKNOWN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002234
Eric Paris9398c7f2010-11-23 11:40:08 -05002235 if (p->policyvers >= POLICYDB_VERSION_POLCAP) {
2236 rc = ebitmap_read(&p->policycaps, fp);
2237 if (rc)
2238 goto bad;
2239 }
Paul Moore3bb56b22008-01-29 08:38:19 -05002240
Eric Paris9398c7f2010-11-23 11:40:08 -05002241 if (p->policyvers >= POLICYDB_VERSION_PERMISSIVE) {
2242 rc = ebitmap_read(&p->permissive_map, fp);
2243 if (rc)
2244 goto bad;
2245 }
Eric Paris64dbf072008-03-31 12:17:33 +11002246
Eric Paris9398c7f2010-11-23 11:40:08 -05002247 rc = -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002248 info = policydb_lookup_compat(p->policyvers);
2249 if (!info) {
James Morris454d9722008-02-26 20:42:02 +11002250 printk(KERN_ERR "SELinux: unable to find policy compat info "
Linus Torvalds1da177e2005-04-16 15:20:36 -07002251 "for version %d\n", p->policyvers);
2252 goto bad;
2253 }
2254
Eric Paris9398c7f2010-11-23 11:40:08 -05002255 rc = -EINVAL;
Alexey Dobriyanb5bf6c52005-09-03 15:55:17 -07002256 if (le32_to_cpu(buf[2]) != info->sym_num ||
2257 le32_to_cpu(buf[3]) != info->ocon_num) {
James Morris454d9722008-02-26 20:42:02 +11002258 printk(KERN_ERR "SELinux: policydb table sizes (%d,%d) do "
Alexey Dobriyanb5bf6c52005-09-03 15:55:17 -07002259 "not match mine (%d,%d)\n", le32_to_cpu(buf[2]),
2260 le32_to_cpu(buf[3]),
Linus Torvalds1da177e2005-04-16 15:20:36 -07002261 info->sym_num, info->ocon_num);
2262 goto bad;
2263 }
2264
2265 for (i = 0; i < info->sym_num; i++) {
2266 rc = next_entry(buf, fp, sizeof(u32)*2);
Eric Paris9398c7f2010-11-23 11:40:08 -05002267 if (rc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002268 goto bad;
2269 nprim = le32_to_cpu(buf[0]);
2270 nel = le32_to_cpu(buf[1]);
2271 for (j = 0; j < nel; j++) {
2272 rc = read_f[i](p, p->symtab[i].table, fp);
2273 if (rc)
2274 goto bad;
2275 }
2276
2277 p->symtab[i].nprim = nprim;
2278 }
2279
Harry Ciao1214eac2011-04-07 14:12:57 +08002280 rc = -EINVAL;
2281 p->process_class = string_to_security_class(p, "process");
2282 if (!p->process_class)
2283 goto bad;
2284
Stephen Smalley45e54212007-11-07 10:08:00 -05002285 rc = avtab_read(&p->te_avtab, fp, p);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002286 if (rc)
2287 goto bad;
2288
2289 if (p->policyvers >= POLICYDB_VERSION_BOOL) {
2290 rc = cond_read_list(p, fp);
2291 if (rc)
2292 goto bad;
2293 }
2294
2295 rc = next_entry(buf, fp, sizeof(u32));
Eric Paris9398c7f2010-11-23 11:40:08 -05002296 if (rc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002297 goto bad;
2298 nel = le32_to_cpu(buf[0]);
2299 ltr = NULL;
2300 for (i = 0; i < nel; i++) {
Eric Paris9398c7f2010-11-23 11:40:08 -05002301 rc = -ENOMEM;
James Morris89d155e2005-10-30 14:59:21 -08002302 tr = kzalloc(sizeof(*tr), GFP_KERNEL);
Eric Paris9398c7f2010-11-23 11:40:08 -05002303 if (!tr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002304 goto bad;
Eric Paris2ced3df2008-04-17 13:37:12 -04002305 if (ltr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002306 ltr->next = tr;
Eric Paris2ced3df2008-04-17 13:37:12 -04002307 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002308 p->role_tr = tr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002309 rc = next_entry(buf, fp, sizeof(u32)*3);
Eric Paris9398c7f2010-11-23 11:40:08 -05002310 if (rc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002311 goto bad;
Eric Paris9398c7f2010-11-23 11:40:08 -05002312
2313 rc = -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002314 tr->role = le32_to_cpu(buf[0]);
2315 tr->type = le32_to_cpu(buf[1]);
2316 tr->new_role = le32_to_cpu(buf[2]);
Harry Ciao80239762011-03-25 13:51:56 +08002317 if (p->policyvers >= POLICYDB_VERSION_ROLETRANS) {
2318 rc = next_entry(buf, fp, sizeof(u32));
2319 if (rc)
2320 goto bad;
2321 tr->tclass = le32_to_cpu(buf[0]);
2322 } else
2323 tr->tclass = p->process_class;
2324
Stephen Smalley45e54212007-11-07 10:08:00 -05002325 if (!policydb_role_isvalid(p, tr->role) ||
2326 !policydb_type_isvalid(p, tr->type) ||
Harry Ciao80239762011-03-25 13:51:56 +08002327 !policydb_class_isvalid(p, tr->tclass) ||
Eric Paris9398c7f2010-11-23 11:40:08 -05002328 !policydb_role_isvalid(p, tr->new_role))
Stephen Smalley45e54212007-11-07 10:08:00 -05002329 goto bad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002330 ltr = tr;
2331 }
2332
2333 rc = next_entry(buf, fp, sizeof(u32));
Eric Paris9398c7f2010-11-23 11:40:08 -05002334 if (rc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002335 goto bad;
2336 nel = le32_to_cpu(buf[0]);
2337 lra = NULL;
2338 for (i = 0; i < nel; i++) {
Eric Paris9398c7f2010-11-23 11:40:08 -05002339 rc = -ENOMEM;
James Morris89d155e2005-10-30 14:59:21 -08002340 ra = kzalloc(sizeof(*ra), GFP_KERNEL);
Eric Paris9398c7f2010-11-23 11:40:08 -05002341 if (!ra)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002342 goto bad;
Eric Paris2ced3df2008-04-17 13:37:12 -04002343 if (lra)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002344 lra->next = ra;
Eric Paris2ced3df2008-04-17 13:37:12 -04002345 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002346 p->role_allow = ra;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002347 rc = next_entry(buf, fp, sizeof(u32)*2);
Eric Paris9398c7f2010-11-23 11:40:08 -05002348 if (rc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002349 goto bad;
Eric Paris9398c7f2010-11-23 11:40:08 -05002350
2351 rc = -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002352 ra->role = le32_to_cpu(buf[0]);
2353 ra->new_role = le32_to_cpu(buf[1]);
Stephen Smalley45e54212007-11-07 10:08:00 -05002354 if (!policydb_role_isvalid(p, ra->role) ||
Eric Paris9398c7f2010-11-23 11:40:08 -05002355 !policydb_role_isvalid(p, ra->new_role))
Stephen Smalley45e54212007-11-07 10:08:00 -05002356 goto bad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002357 lra = ra;
2358 }
2359
Eric Paris652bb9b2011-02-01 11:05:40 -05002360 rc = filename_trans_read(p, fp);
2361 if (rc)
2362 goto bad;
2363
Eric Paris1d9bc6dc2010-11-29 15:47:09 -05002364 rc = policydb_index(p);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002365 if (rc)
2366 goto bad;
2367
Eric Paris9398c7f2010-11-23 11:40:08 -05002368 rc = -EINVAL;
Eric Paris9398c7f2010-11-23 11:40:08 -05002369 p->process_trans_perms = string_to_av_perm(p, p->process_class, "transition");
2370 p->process_trans_perms |= string_to_av_perm(p, p->process_class, "dyntransition");
Stephen Smalleyc6d3aaa2009-09-30 13:37:50 -04002371 if (!p->process_trans_perms)
2372 goto bad;
2373
Eric Paris692a8a22010-07-21 12:51:03 -04002374 rc = ocontext_read(p, info, fp);
2375 if (rc)
2376 goto bad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002377
Eric Parisd1b43542010-07-21 12:50:57 -04002378 rc = genfs_read(p, fp);
2379 if (rc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002380 goto bad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002381
Eric Paris9ee0c822010-06-11 12:37:05 -04002382 rc = range_read(p, fp);
2383 if (rc)
2384 goto bad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002385
Eric Paris6371dcd2010-07-29 23:02:34 -04002386 rc = -ENOMEM;
2387 p->type_attr_map_array = flex_array_alloc(sizeof(struct ebitmap),
2388 p->p_types.nprim,
2389 GFP_KERNEL | __GFP_ZERO);
2390 if (!p->type_attr_map_array)
2391 goto bad;
2392
2393 /* preallocate so we don't have to worry about the put ever failing */
2394 rc = flex_array_prealloc(p->type_attr_map_array, 0, p->p_types.nprim - 1,
2395 GFP_KERNEL | __GFP_ZERO);
2396 if (rc)
Stephen Smalley782ebb92005-09-03 15:55:16 -07002397 goto bad;
2398
2399 for (i = 0; i < p->p_types.nprim; i++) {
Eric Paris6371dcd2010-07-29 23:02:34 -04002400 struct ebitmap *e = flex_array_get(p->type_attr_map_array, i);
2401
2402 BUG_ON(!e);
2403 ebitmap_init(e);
Stephen Smalley782ebb92005-09-03 15:55:16 -07002404 if (p->policyvers >= POLICYDB_VERSION_AVTAB) {
Eric Paris6371dcd2010-07-29 23:02:34 -04002405 rc = ebitmap_read(e, fp);
2406 if (rc)
Stephen Smalley782ebb92005-09-03 15:55:16 -07002407 goto bad;
2408 }
2409 /* add the type itself as the degenerate case */
Eric Paris6371dcd2010-07-29 23:02:34 -04002410 rc = ebitmap_set_bit(e, i, 1);
2411 if (rc)
2412 goto bad;
Stephen Smalley782ebb92005-09-03 15:55:16 -07002413 }
2414
KaiGai Koheid9250de2008-08-28 16:35:57 +09002415 rc = policydb_bounds_sanity_check(p);
2416 if (rc)
2417 goto bad;
2418
Linus Torvalds1da177e2005-04-16 15:20:36 -07002419 rc = 0;
2420out:
2421 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002422bad:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002423 policydb_destroy(p);
2424 goto out;
2425}
Eric Pariscee74f42010-10-13 17:50:25 -04002426
2427/*
2428 * Write a MLS level structure to a policydb binary
2429 * representation file.
2430 */
2431static int mls_write_level(struct mls_level *l, void *fp)
2432{
2433 __le32 buf[1];
2434 int rc;
2435
2436 buf[0] = cpu_to_le32(l->sens);
2437 rc = put_entry(buf, sizeof(u32), 1, fp);
2438 if (rc)
2439 return rc;
2440
2441 rc = ebitmap_write(&l->cat, fp);
2442 if (rc)
2443 return rc;
2444
2445 return 0;
2446}
2447
2448/*
2449 * Write a MLS range structure to a policydb binary
2450 * representation file.
2451 */
2452static int mls_write_range_helper(struct mls_range *r, void *fp)
2453{
2454 __le32 buf[3];
2455 size_t items;
2456 int rc, eq;
2457
2458 eq = mls_level_eq(&r->level[1], &r->level[0]);
2459
2460 if (eq)
2461 items = 2;
2462 else
2463 items = 3;
2464 buf[0] = cpu_to_le32(items-1);
2465 buf[1] = cpu_to_le32(r->level[0].sens);
2466 if (!eq)
2467 buf[2] = cpu_to_le32(r->level[1].sens);
2468
2469 BUG_ON(items > (sizeof(buf)/sizeof(buf[0])));
2470
2471 rc = put_entry(buf, sizeof(u32), items, fp);
2472 if (rc)
2473 return rc;
2474
2475 rc = ebitmap_write(&r->level[0].cat, fp);
2476 if (rc)
2477 return rc;
2478 if (!eq) {
2479 rc = ebitmap_write(&r->level[1].cat, fp);
2480 if (rc)
2481 return rc;
2482 }
2483
2484 return 0;
2485}
2486
2487static int sens_write(void *vkey, void *datum, void *ptr)
2488{
2489 char *key = vkey;
2490 struct level_datum *levdatum = datum;
2491 struct policy_data *pd = ptr;
2492 void *fp = pd->fp;
2493 __le32 buf[2];
2494 size_t len;
2495 int rc;
2496
2497 len = strlen(key);
2498 buf[0] = cpu_to_le32(len);
2499 buf[1] = cpu_to_le32(levdatum->isalias);
2500 rc = put_entry(buf, sizeof(u32), 2, fp);
2501 if (rc)
2502 return rc;
2503
2504 rc = put_entry(key, 1, len, fp);
2505 if (rc)
2506 return rc;
2507
2508 rc = mls_write_level(levdatum->level, fp);
2509 if (rc)
2510 return rc;
2511
2512 return 0;
2513}
2514
2515static int cat_write(void *vkey, void *datum, void *ptr)
2516{
2517 char *key = vkey;
2518 struct cat_datum *catdatum = datum;
2519 struct policy_data *pd = ptr;
2520 void *fp = pd->fp;
2521 __le32 buf[3];
2522 size_t len;
2523 int rc;
2524
2525 len = strlen(key);
2526 buf[0] = cpu_to_le32(len);
2527 buf[1] = cpu_to_le32(catdatum->value);
2528 buf[2] = cpu_to_le32(catdatum->isalias);
2529 rc = put_entry(buf, sizeof(u32), 3, fp);
2530 if (rc)
2531 return rc;
2532
2533 rc = put_entry(key, 1, len, fp);
2534 if (rc)
2535 return rc;
2536
2537 return 0;
2538}
2539
Harry Ciaoc900ff32011-03-25 13:52:00 +08002540static int role_trans_write(struct policydb *p, void *fp)
Eric Pariscee74f42010-10-13 17:50:25 -04002541{
Harry Ciaoc900ff32011-03-25 13:52:00 +08002542 struct role_trans *r = p->role_tr;
Eric Pariscee74f42010-10-13 17:50:25 -04002543 struct role_trans *tr;
2544 u32 buf[3];
2545 size_t nel;
2546 int rc;
2547
2548 nel = 0;
2549 for (tr = r; tr; tr = tr->next)
2550 nel++;
2551 buf[0] = cpu_to_le32(nel);
2552 rc = put_entry(buf, sizeof(u32), 1, fp);
2553 if (rc)
2554 return rc;
2555 for (tr = r; tr; tr = tr->next) {
2556 buf[0] = cpu_to_le32(tr->role);
2557 buf[1] = cpu_to_le32(tr->type);
2558 buf[2] = cpu_to_le32(tr->new_role);
2559 rc = put_entry(buf, sizeof(u32), 3, fp);
2560 if (rc)
2561 return rc;
Harry Ciaoc900ff32011-03-25 13:52:00 +08002562 if (p->policyvers >= POLICYDB_VERSION_ROLETRANS) {
2563 buf[0] = cpu_to_le32(tr->tclass);
2564 rc = put_entry(buf, sizeof(u32), 1, fp);
2565 if (rc)
2566 return rc;
2567 }
Eric Pariscee74f42010-10-13 17:50:25 -04002568 }
2569
2570 return 0;
2571}
2572
2573static int role_allow_write(struct role_allow *r, void *fp)
2574{
2575 struct role_allow *ra;
2576 u32 buf[2];
2577 size_t nel;
2578 int rc;
2579
2580 nel = 0;
2581 for (ra = r; ra; ra = ra->next)
2582 nel++;
2583 buf[0] = cpu_to_le32(nel);
2584 rc = put_entry(buf, sizeof(u32), 1, fp);
2585 if (rc)
2586 return rc;
2587 for (ra = r; ra; ra = ra->next) {
2588 buf[0] = cpu_to_le32(ra->role);
2589 buf[1] = cpu_to_le32(ra->new_role);
2590 rc = put_entry(buf, sizeof(u32), 2, fp);
2591 if (rc)
2592 return rc;
2593 }
2594 return 0;
2595}
2596
2597/*
2598 * Write a security context structure
2599 * to a policydb binary representation file.
2600 */
2601static int context_write(struct policydb *p, struct context *c,
2602 void *fp)
2603{
2604 int rc;
2605 __le32 buf[3];
2606
2607 buf[0] = cpu_to_le32(c->user);
2608 buf[1] = cpu_to_le32(c->role);
2609 buf[2] = cpu_to_le32(c->type);
2610
2611 rc = put_entry(buf, sizeof(u32), 3, fp);
2612 if (rc)
2613 return rc;
2614
2615 rc = mls_write_range_helper(&c->range, fp);
2616 if (rc)
2617 return rc;
2618
2619 return 0;
2620}
2621
2622/*
2623 * The following *_write functions are used to
2624 * write the symbol data to a policy database
2625 * binary representation file.
2626 */
2627
2628static int perm_write(void *vkey, void *datum, void *fp)
2629{
2630 char *key = vkey;
2631 struct perm_datum *perdatum = datum;
2632 __le32 buf[2];
2633 size_t len;
2634 int rc;
2635
2636 len = strlen(key);
2637 buf[0] = cpu_to_le32(len);
2638 buf[1] = cpu_to_le32(perdatum->value);
2639 rc = put_entry(buf, sizeof(u32), 2, fp);
2640 if (rc)
2641 return rc;
2642
2643 rc = put_entry(key, 1, len, fp);
2644 if (rc)
2645 return rc;
2646
2647 return 0;
2648}
2649
2650static int common_write(void *vkey, void *datum, void *ptr)
2651{
2652 char *key = vkey;
2653 struct common_datum *comdatum = datum;
2654 struct policy_data *pd = ptr;
2655 void *fp = pd->fp;
2656 __le32 buf[4];
2657 size_t len;
2658 int rc;
2659
2660 len = strlen(key);
2661 buf[0] = cpu_to_le32(len);
2662 buf[1] = cpu_to_le32(comdatum->value);
2663 buf[2] = cpu_to_le32(comdatum->permissions.nprim);
2664 buf[3] = cpu_to_le32(comdatum->permissions.table->nel);
2665 rc = put_entry(buf, sizeof(u32), 4, fp);
2666 if (rc)
2667 return rc;
2668
2669 rc = put_entry(key, 1, len, fp);
2670 if (rc)
2671 return rc;
2672
2673 rc = hashtab_map(comdatum->permissions.table, perm_write, fp);
2674 if (rc)
2675 return rc;
2676
2677 return 0;
2678}
2679
2680static int write_cons_helper(struct policydb *p, struct constraint_node *node,
2681 void *fp)
2682{
2683 struct constraint_node *c;
2684 struct constraint_expr *e;
2685 __le32 buf[3];
2686 u32 nel;
2687 int rc;
2688
2689 for (c = node; c; c = c->next) {
2690 nel = 0;
2691 for (e = c->expr; e; e = e->next)
2692 nel++;
2693 buf[0] = cpu_to_le32(c->permissions);
2694 buf[1] = cpu_to_le32(nel);
2695 rc = put_entry(buf, sizeof(u32), 2, fp);
2696 if (rc)
2697 return rc;
2698 for (e = c->expr; e; e = e->next) {
2699 buf[0] = cpu_to_le32(e->expr_type);
2700 buf[1] = cpu_to_le32(e->attr);
2701 buf[2] = cpu_to_le32(e->op);
2702 rc = put_entry(buf, sizeof(u32), 3, fp);
2703 if (rc)
2704 return rc;
2705
2706 switch (e->expr_type) {
2707 case CEXPR_NAMES:
2708 rc = ebitmap_write(&e->names, fp);
2709 if (rc)
2710 return rc;
2711 break;
2712 default:
2713 break;
2714 }
2715 }
2716 }
2717
2718 return 0;
2719}
2720
2721static int class_write(void *vkey, void *datum, void *ptr)
2722{
2723 char *key = vkey;
2724 struct class_datum *cladatum = datum;
2725 struct policy_data *pd = ptr;
2726 void *fp = pd->fp;
2727 struct policydb *p = pd->p;
2728 struct constraint_node *c;
2729 __le32 buf[6];
2730 u32 ncons;
2731 size_t len, len2;
2732 int rc;
2733
2734 len = strlen(key);
2735 if (cladatum->comkey)
2736 len2 = strlen(cladatum->comkey);
2737 else
2738 len2 = 0;
2739
2740 ncons = 0;
2741 for (c = cladatum->constraints; c; c = c->next)
2742 ncons++;
2743
2744 buf[0] = cpu_to_le32(len);
2745 buf[1] = cpu_to_le32(len2);
2746 buf[2] = cpu_to_le32(cladatum->value);
2747 buf[3] = cpu_to_le32(cladatum->permissions.nprim);
2748 if (cladatum->permissions.table)
2749 buf[4] = cpu_to_le32(cladatum->permissions.table->nel);
2750 else
2751 buf[4] = 0;
2752 buf[5] = cpu_to_le32(ncons);
2753 rc = put_entry(buf, sizeof(u32), 6, fp);
2754 if (rc)
2755 return rc;
2756
2757 rc = put_entry(key, 1, len, fp);
2758 if (rc)
2759 return rc;
2760
2761 if (cladatum->comkey) {
2762 rc = put_entry(cladatum->comkey, 1, len2, fp);
2763 if (rc)
2764 return rc;
2765 }
2766
2767 rc = hashtab_map(cladatum->permissions.table, perm_write, fp);
2768 if (rc)
2769 return rc;
2770
2771 rc = write_cons_helper(p, cladatum->constraints, fp);
2772 if (rc)
2773 return rc;
2774
2775 /* write out the validatetrans rule */
2776 ncons = 0;
2777 for (c = cladatum->validatetrans; c; c = c->next)
2778 ncons++;
2779
2780 buf[0] = cpu_to_le32(ncons);
2781 rc = put_entry(buf, sizeof(u32), 1, fp);
2782 if (rc)
2783 return rc;
2784
2785 rc = write_cons_helper(p, cladatum->validatetrans, fp);
2786 if (rc)
2787 return rc;
2788
2789 return 0;
2790}
2791
2792static int role_write(void *vkey, void *datum, void *ptr)
2793{
2794 char *key = vkey;
2795 struct role_datum *role = datum;
2796 struct policy_data *pd = ptr;
2797 void *fp = pd->fp;
2798 struct policydb *p = pd->p;
2799 __le32 buf[3];
2800 size_t items, len;
2801 int rc;
2802
2803 len = strlen(key);
2804 items = 0;
2805 buf[items++] = cpu_to_le32(len);
2806 buf[items++] = cpu_to_le32(role->value);
2807 if (p->policyvers >= POLICYDB_VERSION_BOUNDARY)
2808 buf[items++] = cpu_to_le32(role->bounds);
2809
2810 BUG_ON(items > (sizeof(buf)/sizeof(buf[0])));
2811
2812 rc = put_entry(buf, sizeof(u32), items, fp);
2813 if (rc)
2814 return rc;
2815
2816 rc = put_entry(key, 1, len, fp);
2817 if (rc)
2818 return rc;
2819
2820 rc = ebitmap_write(&role->dominates, fp);
2821 if (rc)
2822 return rc;
2823
2824 rc = ebitmap_write(&role->types, fp);
2825 if (rc)
2826 return rc;
2827
2828 return 0;
2829}
2830
2831static int type_write(void *vkey, void *datum, void *ptr)
2832{
2833 char *key = vkey;
2834 struct type_datum *typdatum = datum;
2835 struct policy_data *pd = ptr;
2836 struct policydb *p = pd->p;
2837 void *fp = pd->fp;
2838 __le32 buf[4];
2839 int rc;
2840 size_t items, len;
2841
2842 len = strlen(key);
2843 items = 0;
2844 buf[items++] = cpu_to_le32(len);
2845 buf[items++] = cpu_to_le32(typdatum->value);
2846 if (p->policyvers >= POLICYDB_VERSION_BOUNDARY) {
2847 u32 properties = 0;
2848
2849 if (typdatum->primary)
2850 properties |= TYPEDATUM_PROPERTY_PRIMARY;
2851
2852 if (typdatum->attribute)
2853 properties |= TYPEDATUM_PROPERTY_ATTRIBUTE;
2854
2855 buf[items++] = cpu_to_le32(properties);
2856 buf[items++] = cpu_to_le32(typdatum->bounds);
2857 } else {
2858 buf[items++] = cpu_to_le32(typdatum->primary);
2859 }
2860 BUG_ON(items > (sizeof(buf) / sizeof(buf[0])));
2861 rc = put_entry(buf, sizeof(u32), items, fp);
2862 if (rc)
2863 return rc;
2864
2865 rc = put_entry(key, 1, len, fp);
2866 if (rc)
2867 return rc;
2868
2869 return 0;
2870}
2871
2872static int user_write(void *vkey, void *datum, void *ptr)
2873{
2874 char *key = vkey;
2875 struct user_datum *usrdatum = datum;
2876 struct policy_data *pd = ptr;
2877 struct policydb *p = pd->p;
2878 void *fp = pd->fp;
2879 __le32 buf[3];
2880 size_t items, len;
2881 int rc;
2882
2883 len = strlen(key);
2884 items = 0;
2885 buf[items++] = cpu_to_le32(len);
2886 buf[items++] = cpu_to_le32(usrdatum->value);
2887 if (p->policyvers >= POLICYDB_VERSION_BOUNDARY)
2888 buf[items++] = cpu_to_le32(usrdatum->bounds);
2889 BUG_ON(items > (sizeof(buf) / sizeof(buf[0])));
2890 rc = put_entry(buf, sizeof(u32), items, fp);
2891 if (rc)
2892 return rc;
2893
2894 rc = put_entry(key, 1, len, fp);
2895 if (rc)
2896 return rc;
2897
2898 rc = ebitmap_write(&usrdatum->roles, fp);
2899 if (rc)
2900 return rc;
2901
2902 rc = mls_write_range_helper(&usrdatum->range, fp);
2903 if (rc)
2904 return rc;
2905
2906 rc = mls_write_level(&usrdatum->dfltlevel, fp);
2907 if (rc)
2908 return rc;
2909
2910 return 0;
2911}
2912
2913static int (*write_f[SYM_NUM]) (void *key, void *datum,
2914 void *datap) =
2915{
2916 common_write,
2917 class_write,
2918 role_write,
2919 type_write,
2920 user_write,
2921 cond_write_bool,
2922 sens_write,
2923 cat_write,
2924};
2925
2926static int ocontext_write(struct policydb *p, struct policydb_compat_info *info,
2927 void *fp)
2928{
2929 unsigned int i, j, rc;
2930 size_t nel, len;
2931 __le32 buf[3];
2932 u32 nodebuf[8];
2933 struct ocontext *c;
2934 for (i = 0; i < info->ocon_num; i++) {
2935 nel = 0;
2936 for (c = p->ocontexts[i]; c; c = c->next)
2937 nel++;
2938 buf[0] = cpu_to_le32(nel);
2939 rc = put_entry(buf, sizeof(u32), 1, fp);
2940 if (rc)
2941 return rc;
2942 for (c = p->ocontexts[i]; c; c = c->next) {
2943 switch (i) {
2944 case OCON_ISID:
2945 buf[0] = cpu_to_le32(c->sid[0]);
2946 rc = put_entry(buf, sizeof(u32), 1, fp);
2947 if (rc)
2948 return rc;
2949 rc = context_write(p, &c->context[0], fp);
2950 if (rc)
2951 return rc;
2952 break;
2953 case OCON_FS:
2954 case OCON_NETIF:
2955 len = strlen(c->u.name);
2956 buf[0] = cpu_to_le32(len);
2957 rc = put_entry(buf, sizeof(u32), 1, fp);
2958 if (rc)
2959 return rc;
2960 rc = put_entry(c->u.name, 1, len, fp);
2961 if (rc)
2962 return rc;
2963 rc = context_write(p, &c->context[0], fp);
2964 if (rc)
2965 return rc;
2966 rc = context_write(p, &c->context[1], fp);
2967 if (rc)
2968 return rc;
2969 break;
2970 case OCON_PORT:
2971 buf[0] = cpu_to_le32(c->u.port.protocol);
2972 buf[1] = cpu_to_le32(c->u.port.low_port);
2973 buf[2] = cpu_to_le32(c->u.port.high_port);
2974 rc = put_entry(buf, sizeof(u32), 3, fp);
2975 if (rc)
2976 return rc;
2977 rc = context_write(p, &c->context[0], fp);
2978 if (rc)
2979 return rc;
2980 break;
2981 case OCON_NODE:
2982 nodebuf[0] = c->u.node.addr; /* network order */
2983 nodebuf[1] = c->u.node.mask; /* network order */
2984 rc = put_entry(nodebuf, sizeof(u32), 2, fp);
2985 if (rc)
2986 return rc;
2987 rc = context_write(p, &c->context[0], fp);
2988 if (rc)
2989 return rc;
2990 break;
2991 case OCON_FSUSE:
2992 buf[0] = cpu_to_le32(c->v.behavior);
2993 len = strlen(c->u.name);
2994 buf[1] = cpu_to_le32(len);
2995 rc = put_entry(buf, sizeof(u32), 2, fp);
2996 if (rc)
2997 return rc;
2998 rc = put_entry(c->u.name, 1, len, fp);
2999 if (rc)
3000 return rc;
3001 rc = context_write(p, &c->context[0], fp);
3002 if (rc)
3003 return rc;
3004 break;
3005 case OCON_NODE6:
3006 for (j = 0; j < 4; j++)
3007 nodebuf[j] = c->u.node6.addr[j]; /* network order */
3008 for (j = 0; j < 4; j++)
3009 nodebuf[j + 4] = c->u.node6.mask[j]; /* network order */
3010 rc = put_entry(nodebuf, sizeof(u32), 8, fp);
3011 if (rc)
3012 return rc;
3013 rc = context_write(p, &c->context[0], fp);
3014 if (rc)
3015 return rc;
3016 break;
3017 }
3018 }
3019 }
3020 return 0;
3021}
3022
3023static int genfs_write(struct policydb *p, void *fp)
3024{
3025 struct genfs *genfs;
3026 struct ocontext *c;
3027 size_t len;
3028 __le32 buf[1];
3029 int rc;
3030
3031 len = 0;
3032 for (genfs = p->genfs; genfs; genfs = genfs->next)
3033 len++;
3034 buf[0] = cpu_to_le32(len);
3035 rc = put_entry(buf, sizeof(u32), 1, fp);
3036 if (rc)
3037 return rc;
3038 for (genfs = p->genfs; genfs; genfs = genfs->next) {
3039 len = strlen(genfs->fstype);
3040 buf[0] = cpu_to_le32(len);
3041 rc = put_entry(buf, sizeof(u32), 1, fp);
3042 if (rc)
3043 return rc;
3044 rc = put_entry(genfs->fstype, 1, len, fp);
3045 if (rc)
3046 return rc;
3047 len = 0;
3048 for (c = genfs->head; c; c = c->next)
3049 len++;
3050 buf[0] = cpu_to_le32(len);
3051 rc = put_entry(buf, sizeof(u32), 1, fp);
3052 if (rc)
3053 return rc;
3054 for (c = genfs->head; c; c = c->next) {
3055 len = strlen(c->u.name);
3056 buf[0] = cpu_to_le32(len);
3057 rc = put_entry(buf, sizeof(u32), 1, fp);
3058 if (rc)
3059 return rc;
3060 rc = put_entry(c->u.name, 1, len, fp);
3061 if (rc)
3062 return rc;
3063 buf[0] = cpu_to_le32(c->v.sclass);
3064 rc = put_entry(buf, sizeof(u32), 1, fp);
3065 if (rc)
3066 return rc;
3067 rc = context_write(p, &c->context[0], fp);
3068 if (rc)
3069 return rc;
3070 }
3071 }
3072 return 0;
3073}
3074
3075static int range_count(void *key, void *data, void *ptr)
3076{
3077 int *cnt = ptr;
3078 *cnt = *cnt + 1;
3079
3080 return 0;
3081}
3082
3083static int range_write_helper(void *key, void *data, void *ptr)
3084{
3085 __le32 buf[2];
3086 struct range_trans *rt = key;
3087 struct mls_range *r = data;
3088 struct policy_data *pd = ptr;
3089 void *fp = pd->fp;
3090 struct policydb *p = pd->p;
3091 int rc;
3092
3093 buf[0] = cpu_to_le32(rt->source_type);
3094 buf[1] = cpu_to_le32(rt->target_type);
3095 rc = put_entry(buf, sizeof(u32), 2, fp);
3096 if (rc)
3097 return rc;
3098 if (p->policyvers >= POLICYDB_VERSION_RANGETRANS) {
3099 buf[0] = cpu_to_le32(rt->target_class);
3100 rc = put_entry(buf, sizeof(u32), 1, fp);
3101 if (rc)
3102 return rc;
3103 }
3104 rc = mls_write_range_helper(r, fp);
3105 if (rc)
3106 return rc;
3107
3108 return 0;
3109}
3110
3111static int range_write(struct policydb *p, void *fp)
3112{
3113 size_t nel;
3114 __le32 buf[1];
3115 int rc;
3116 struct policy_data pd;
3117
3118 pd.p = p;
3119 pd.fp = fp;
3120
3121 /* count the number of entries in the hashtab */
3122 nel = 0;
3123 rc = hashtab_map(p->range_tr, range_count, &nel);
3124 if (rc)
3125 return rc;
3126
3127 buf[0] = cpu_to_le32(nel);
3128 rc = put_entry(buf, sizeof(u32), 1, fp);
3129 if (rc)
3130 return rc;
3131
3132 /* actually write all of the entries */
3133 rc = hashtab_map(p->range_tr, range_write_helper, &pd);
3134 if (rc)
3135 return rc;
3136
3137 return 0;
3138}
3139
Eric Paris652bb9b2011-02-01 11:05:40 -05003140static int filename_trans_write(struct policydb *p, void *fp)
3141{
3142 struct filename_trans *ft;
3143 u32 len, nel = 0;
3144 __le32 buf[4];
3145 int rc;
3146
3147 for (ft = p->filename_trans; ft; ft = ft->next)
3148 nel++;
3149
3150 buf[0] = cpu_to_le32(nel);
3151 rc = put_entry(buf, sizeof(u32), 1, fp);
3152 if (rc)
3153 return rc;
3154
3155 for (ft = p->filename_trans; ft; ft = ft->next) {
3156 len = strlen(ft->name);
3157 buf[0] = cpu_to_le32(len);
3158 rc = put_entry(buf, sizeof(u32), 1, fp);
3159 if (rc)
3160 return rc;
3161
3162 rc = put_entry(ft->name, sizeof(char), len, fp);
3163 if (rc)
3164 return rc;
3165
3166 buf[0] = ft->stype;
3167 buf[1] = ft->ttype;
3168 buf[2] = ft->tclass;
3169 buf[3] = ft->otype;
3170
3171 rc = put_entry(buf, sizeof(u32), 4, fp);
3172 if (rc)
3173 return rc;
3174 }
3175 return 0;
3176}
Eric Pariscee74f42010-10-13 17:50:25 -04003177/*
3178 * Write the configuration data in a policy database
3179 * structure to a policy database binary representation
3180 * file.
3181 */
3182int policydb_write(struct policydb *p, void *fp)
3183{
3184 unsigned int i, num_syms;
3185 int rc;
3186 __le32 buf[4];
3187 u32 config;
3188 size_t len;
3189 struct policydb_compat_info *info;
3190
3191 /*
3192 * refuse to write policy older than compressed avtab
3193 * to simplify the writer. There are other tests dropped
3194 * since we assume this throughout the writer code. Be
3195 * careful if you ever try to remove this restriction
3196 */
3197 if (p->policyvers < POLICYDB_VERSION_AVTAB) {
3198 printk(KERN_ERR "SELinux: refusing to write policy version %d."
3199 " Because it is less than version %d\n", p->policyvers,
3200 POLICYDB_VERSION_AVTAB);
3201 return -EINVAL;
3202 }
3203
3204 config = 0;
3205 if (p->mls_enabled)
3206 config |= POLICYDB_CONFIG_MLS;
3207
3208 if (p->reject_unknown)
3209 config |= REJECT_UNKNOWN;
3210 if (p->allow_unknown)
3211 config |= ALLOW_UNKNOWN;
3212
3213 /* Write the magic number and string identifiers. */
3214 buf[0] = cpu_to_le32(POLICYDB_MAGIC);
3215 len = strlen(POLICYDB_STRING);
3216 buf[1] = cpu_to_le32(len);
3217 rc = put_entry(buf, sizeof(u32), 2, fp);
3218 if (rc)
3219 return rc;
3220 rc = put_entry(POLICYDB_STRING, 1, len, fp);
3221 if (rc)
3222 return rc;
3223
3224 /* Write the version, config, and table sizes. */
3225 info = policydb_lookup_compat(p->policyvers);
3226 if (!info) {
3227 printk(KERN_ERR "SELinux: compatibility lookup failed for policy "
3228 "version %d", p->policyvers);
Eric Paris9398c7f2010-11-23 11:40:08 -05003229 return -EINVAL;
Eric Pariscee74f42010-10-13 17:50:25 -04003230 }
3231
3232 buf[0] = cpu_to_le32(p->policyvers);
3233 buf[1] = cpu_to_le32(config);
3234 buf[2] = cpu_to_le32(info->sym_num);
3235 buf[3] = cpu_to_le32(info->ocon_num);
3236
3237 rc = put_entry(buf, sizeof(u32), 4, fp);
3238 if (rc)
3239 return rc;
3240
3241 if (p->policyvers >= POLICYDB_VERSION_POLCAP) {
3242 rc = ebitmap_write(&p->policycaps, fp);
3243 if (rc)
3244 return rc;
3245 }
3246
3247 if (p->policyvers >= POLICYDB_VERSION_PERMISSIVE) {
3248 rc = ebitmap_write(&p->permissive_map, fp);
3249 if (rc)
3250 return rc;
3251 }
3252
3253 num_syms = info->sym_num;
3254 for (i = 0; i < num_syms; i++) {
3255 struct policy_data pd;
3256
3257 pd.fp = fp;
3258 pd.p = p;
3259
3260 buf[0] = cpu_to_le32(p->symtab[i].nprim);
3261 buf[1] = cpu_to_le32(p->symtab[i].table->nel);
3262
3263 rc = put_entry(buf, sizeof(u32), 2, fp);
3264 if (rc)
3265 return rc;
3266 rc = hashtab_map(p->symtab[i].table, write_f[i], &pd);
3267 if (rc)
3268 return rc;
3269 }
3270
3271 rc = avtab_write(p, &p->te_avtab, fp);
3272 if (rc)
3273 return rc;
3274
3275 rc = cond_write_list(p, p->cond_list, fp);
3276 if (rc)
3277 return rc;
3278
Harry Ciaoc900ff32011-03-25 13:52:00 +08003279 rc = role_trans_write(p, fp);
Eric Pariscee74f42010-10-13 17:50:25 -04003280 if (rc)
3281 return rc;
3282
3283 rc = role_allow_write(p->role_allow, fp);
3284 if (rc)
3285 return rc;
3286
Eric Paris652bb9b2011-02-01 11:05:40 -05003287 rc = filename_trans_write(p, fp);
3288 if (rc)
3289 return rc;
3290
Eric Pariscee74f42010-10-13 17:50:25 -04003291 rc = ocontext_write(p, info, fp);
3292 if (rc)
3293 return rc;
3294
3295 rc = genfs_write(p, fp);
3296 if (rc)
3297 return rc;
3298
3299 rc = range_write(p, fp);
3300 if (rc)
3301 return rc;
3302
3303 for (i = 0; i < p->p_types.nprim; i++) {
3304 struct ebitmap *e = flex_array_get(p->type_attr_map_array, i);
3305
3306 BUG_ON(!e);
3307 rc = ebitmap_write(e, fp);
3308 if (rc)
3309 return rc;
3310 }
3311
3312 return 0;
3313}