blob: 97fb0cf0eb6955f5b68a0e57a8791ad819d126ca [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"
40
41#define _DEBUG_HASHES
42
43#ifdef DEBUG_HASHES
Stephen Hemminger634a5392010-03-04 21:59:03 -080044static const char *symtab_name[SYM_NUM] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -070045 "common prefixes",
46 "classes",
47 "roles",
48 "types",
49 "users",
50 "bools",
51 "levels",
52 "categories",
53};
54#endif
55
Linus Torvalds1da177e2005-04-16 15:20:36 -070056static unsigned int symtab_sizes[SYM_NUM] = {
57 2,
58 32,
59 16,
60 512,
61 128,
62 16,
63 16,
64 16,
65};
66
67struct policydb_compat_info {
68 int version;
69 int sym_num;
70 int ocon_num;
71};
72
73/* These need to be updated if SYM_NUM or OCON_NUM changes */
74static struct policydb_compat_info policydb_compat[] = {
75 {
Eric Paris2ced3df2008-04-17 13:37:12 -040076 .version = POLICYDB_VERSION_BASE,
77 .sym_num = SYM_NUM - 3,
78 .ocon_num = OCON_NUM - 1,
Linus Torvalds1da177e2005-04-16 15:20:36 -070079 },
80 {
Eric Paris2ced3df2008-04-17 13:37:12 -040081 .version = POLICYDB_VERSION_BOOL,
82 .sym_num = SYM_NUM - 2,
83 .ocon_num = OCON_NUM - 1,
Linus Torvalds1da177e2005-04-16 15:20:36 -070084 },
85 {
Eric Paris2ced3df2008-04-17 13:37:12 -040086 .version = POLICYDB_VERSION_IPV6,
87 .sym_num = SYM_NUM - 2,
88 .ocon_num = OCON_NUM,
Linus Torvalds1da177e2005-04-16 15:20:36 -070089 },
90 {
Eric Paris2ced3df2008-04-17 13:37:12 -040091 .version = POLICYDB_VERSION_NLCLASS,
92 .sym_num = SYM_NUM - 2,
93 .ocon_num = OCON_NUM,
Linus Torvalds1da177e2005-04-16 15:20:36 -070094 },
95 {
Eric Paris2ced3df2008-04-17 13:37:12 -040096 .version = POLICYDB_VERSION_MLS,
97 .sym_num = SYM_NUM,
98 .ocon_num = OCON_NUM,
Linus Torvalds1da177e2005-04-16 15:20:36 -070099 },
Stephen Smalley782ebb92005-09-03 15:55:16 -0700100 {
Eric Paris2ced3df2008-04-17 13:37:12 -0400101 .version = POLICYDB_VERSION_AVTAB,
102 .sym_num = SYM_NUM,
103 .ocon_num = OCON_NUM,
Stephen Smalley782ebb92005-09-03 15:55:16 -0700104 },
Darrel Goeddelf3f87712006-09-25 23:31:59 -0700105 {
Eric Paris2ced3df2008-04-17 13:37:12 -0400106 .version = POLICYDB_VERSION_RANGETRANS,
107 .sym_num = SYM_NUM,
108 .ocon_num = OCON_NUM,
Darrel Goeddelf3f87712006-09-25 23:31:59 -0700109 },
Paul Moore3bb56b22008-01-29 08:38:19 -0500110 {
111 .version = POLICYDB_VERSION_POLCAP,
112 .sym_num = SYM_NUM,
113 .ocon_num = OCON_NUM,
Eric Paris64dbf072008-03-31 12:17:33 +1100114 },
115 {
116 .version = POLICYDB_VERSION_PERMISSIVE,
117 .sym_num = SYM_NUM,
118 .ocon_num = OCON_NUM,
KaiGai Koheid9250de2008-08-28 16:35:57 +0900119 },
120 {
121 .version = POLICYDB_VERSION_BOUNDARY,
122 .sym_num = SYM_NUM,
123 .ocon_num = OCON_NUM,
124 },
Linus Torvalds1da177e2005-04-16 15:20:36 -0700125};
126
127static struct policydb_compat_info *policydb_lookup_compat(int version)
128{
129 int i;
130 struct policydb_compat_info *info = NULL;
131
Tobias Klauser32725ad2006-01-06 00:11:23 -0800132 for (i = 0; i < ARRAY_SIZE(policydb_compat); i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700133 if (policydb_compat[i].version == version) {
134 info = &policydb_compat[i];
135 break;
136 }
137 }
138 return info;
139}
140
141/*
142 * Initialize the role table.
143 */
144static int roles_init(struct policydb *p)
145{
146 char *key = NULL;
147 int rc;
148 struct role_datum *role;
149
James Morris89d155e2005-10-30 14:59:21 -0800150 role = kzalloc(sizeof(*role), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700151 if (!role) {
152 rc = -ENOMEM;
153 goto out;
154 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700155 role->value = ++p->p_roles.nprim;
156 if (role->value != OBJECT_R_VAL) {
157 rc = -EINVAL;
158 goto out_free_role;
159 }
Julia Lawallb3139bb2010-05-14 21:30:30 +0200160 key = kstrdup(OBJECT_R, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700161 if (!key) {
162 rc = -ENOMEM;
163 goto out_free_role;
164 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700165 rc = hashtab_insert(p->p_roles.table, key, role);
166 if (rc)
167 goto out_free_key;
168out:
169 return rc;
170
171out_free_key:
172 kfree(key);
173out_free_role:
174 kfree(role);
175 goto out;
176}
177
Stephen Smalley2f3e82d2010-01-07 15:55:16 -0500178static u32 rangetr_hash(struct hashtab *h, const void *k)
179{
180 const struct range_trans *key = k;
181 return (key->source_type + (key->target_type << 3) +
182 (key->target_class << 5)) & (h->size - 1);
183}
184
185static int rangetr_cmp(struct hashtab *h, const void *k1, const void *k2)
186{
187 const struct range_trans *key1 = k1, *key2 = k2;
Eric Paris4419aae2010-10-13 17:50:14 -0400188 int v;
189
190 v = key1->source_type - key2->source_type;
191 if (v)
192 return v;
193
194 v = key1->target_type - key2->target_type;
195 if (v)
196 return v;
197
198 v = key1->target_class - key2->target_class;
199
200 return v;
Stephen Smalley2f3e82d2010-01-07 15:55:16 -0500201}
202
Linus Torvalds1da177e2005-04-16 15:20:36 -0700203/*
204 * Initialize a policy database structure.
205 */
206static int policydb_init(struct policydb *p)
207{
208 int i, rc;
209
210 memset(p, 0, sizeof(*p));
211
212 for (i = 0; i < SYM_NUM; i++) {
213 rc = symtab_init(&p->symtab[i], symtab_sizes[i]);
214 if (rc)
215 goto out_free_symtab;
216 }
217
218 rc = avtab_init(&p->te_avtab);
219 if (rc)
220 goto out_free_symtab;
221
222 rc = roles_init(p);
223 if (rc)
Yuichi Nakamura3232c112007-08-24 11:55:11 +0900224 goto out_free_symtab;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700225
226 rc = cond_policydb_init(p);
227 if (rc)
Yuichi Nakamura3232c112007-08-24 11:55:11 +0900228 goto out_free_symtab;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700229
Stephen Smalley2f3e82d2010-01-07 15:55:16 -0500230 p->range_tr = hashtab_create(rangetr_hash, rangetr_cmp, 256);
231 if (!p->range_tr)
232 goto out_free_symtab;
233
Paul Moore3bb56b22008-01-29 08:38:19 -0500234 ebitmap_init(&p->policycaps);
Eric Paris64dbf072008-03-31 12:17:33 +1100235 ebitmap_init(&p->permissive_map);
Paul Moore3bb56b22008-01-29 08:38:19 -0500236
Linus Torvalds1da177e2005-04-16 15:20:36 -0700237out:
238 return rc;
239
Linus Torvalds1da177e2005-04-16 15:20:36 -0700240out_free_symtab:
241 for (i = 0; i < SYM_NUM; i++)
242 hashtab_destroy(p->symtab[i].table);
243 goto out;
244}
245
246/*
247 * The following *_index functions are used to
248 * define the val_to_name and val_to_struct arrays
249 * in a policy database structure. The val_to_name
250 * arrays are used when converting security context
251 * structures into string representations. The
252 * val_to_struct arrays are used when the attributes
253 * of a class, role, or user are needed.
254 */
255
256static int common_index(void *key, void *datum, void *datap)
257{
258 struct policydb *p;
259 struct common_datum *comdatum;
260
261 comdatum = datum;
262 p = datap;
263 if (!comdatum->value || comdatum->value > p->p_commons.nprim)
264 return -EINVAL;
265 p->p_common_val_to_name[comdatum->value - 1] = key;
266 return 0;
267}
268
269static int class_index(void *key, void *datum, void *datap)
270{
271 struct policydb *p;
272 struct class_datum *cladatum;
273
274 cladatum = datum;
275 p = datap;
276 if (!cladatum->value || cladatum->value > p->p_classes.nprim)
277 return -EINVAL;
278 p->p_class_val_to_name[cladatum->value - 1] = key;
279 p->class_val_to_struct[cladatum->value - 1] = cladatum;
280 return 0;
281}
282
283static int role_index(void *key, void *datum, void *datap)
284{
285 struct policydb *p;
286 struct role_datum *role;
287
288 role = datum;
289 p = datap;
KaiGai Koheid9250de2008-08-28 16:35:57 +0900290 if (!role->value
291 || role->value > p->p_roles.nprim
292 || role->bounds > p->p_roles.nprim)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700293 return -EINVAL;
294 p->p_role_val_to_name[role->value - 1] = key;
295 p->role_val_to_struct[role->value - 1] = role;
296 return 0;
297}
298
299static int type_index(void *key, void *datum, void *datap)
300{
301 struct policydb *p;
302 struct type_datum *typdatum;
303
304 typdatum = datum;
305 p = datap;
306
307 if (typdatum->primary) {
KaiGai Koheid9250de2008-08-28 16:35:57 +0900308 if (!typdatum->value
309 || typdatum->value > p->p_types.nprim
310 || typdatum->bounds > p->p_types.nprim)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700311 return -EINVAL;
312 p->p_type_val_to_name[typdatum->value - 1] = key;
KaiGai Koheid9250de2008-08-28 16:35:57 +0900313 p->type_val_to_struct[typdatum->value - 1] = typdatum;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700314 }
315
316 return 0;
317}
318
319static int user_index(void *key, void *datum, void *datap)
320{
321 struct policydb *p;
322 struct user_datum *usrdatum;
323
324 usrdatum = datum;
325 p = datap;
KaiGai Koheid9250de2008-08-28 16:35:57 +0900326 if (!usrdatum->value
327 || usrdatum->value > p->p_users.nprim
328 || usrdatum->bounds > p->p_users.nprim)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700329 return -EINVAL;
330 p->p_user_val_to_name[usrdatum->value - 1] = key;
331 p->user_val_to_struct[usrdatum->value - 1] = usrdatum;
332 return 0;
333}
334
335static int sens_index(void *key, void *datum, void *datap)
336{
337 struct policydb *p;
338 struct level_datum *levdatum;
339
340 levdatum = datum;
341 p = datap;
342
343 if (!levdatum->isalias) {
344 if (!levdatum->level->sens ||
345 levdatum->level->sens > p->p_levels.nprim)
346 return -EINVAL;
347 p->p_sens_val_to_name[levdatum->level->sens - 1] = key;
348 }
349
350 return 0;
351}
352
353static int cat_index(void *key, void *datum, void *datap)
354{
355 struct policydb *p;
356 struct cat_datum *catdatum;
357
358 catdatum = datum;
359 p = datap;
360
361 if (!catdatum->isalias) {
362 if (!catdatum->value || catdatum->value > p->p_cats.nprim)
363 return -EINVAL;
364 p->p_cat_val_to_name[catdatum->value - 1] = key;
365 }
366
367 return 0;
368}
369
370static int (*index_f[SYM_NUM]) (void *key, void *datum, void *datap) =
371{
372 common_index,
373 class_index,
374 role_index,
375 type_index,
376 user_index,
377 cond_index_bool,
378 sens_index,
379 cat_index,
380};
381
382/*
383 * Define the common val_to_name array and the class
384 * val_to_name and val_to_struct arrays in a policy
385 * database structure.
386 *
387 * Caller must clean up upon failure.
388 */
389static int policydb_index_classes(struct policydb *p)
390{
391 int rc;
392
393 p->p_common_val_to_name =
394 kmalloc(p->p_commons.nprim * sizeof(char *), GFP_KERNEL);
395 if (!p->p_common_val_to_name) {
396 rc = -ENOMEM;
397 goto out;
398 }
399
400 rc = hashtab_map(p->p_commons.table, common_index, p);
401 if (rc)
402 goto out;
403
404 p->class_val_to_struct =
405 kmalloc(p->p_classes.nprim * sizeof(*(p->class_val_to_struct)), GFP_KERNEL);
406 if (!p->class_val_to_struct) {
407 rc = -ENOMEM;
408 goto out;
409 }
410
411 p->p_class_val_to_name =
412 kmalloc(p->p_classes.nprim * sizeof(char *), GFP_KERNEL);
413 if (!p->p_class_val_to_name) {
414 rc = -ENOMEM;
415 goto out;
416 }
417
418 rc = hashtab_map(p->p_classes.table, class_index, p);
419out:
420 return rc;
421}
422
423#ifdef DEBUG_HASHES
424static void symtab_hash_eval(struct symtab *s)
425{
426 int i;
427
428 for (i = 0; i < SYM_NUM; i++) {
429 struct hashtab *h = s[i].table;
430 struct hashtab_info info;
431
432 hashtab_stat(h, &info);
Eric Paris744ba352008-04-17 11:52:44 -0400433 printk(KERN_DEBUG "SELinux: %s: %d entries and %d/%d buckets used, "
Linus Torvalds1da177e2005-04-16 15:20:36 -0700434 "longest chain length %d\n", symtab_name[i], h->nel,
435 info.slots_used, h->size, info.max_chain_len);
436 }
437}
Stephen Smalley2f3e82d2010-01-07 15:55:16 -0500438
439static void rangetr_hash_eval(struct hashtab *h)
440{
441 struct hashtab_info info;
442
443 hashtab_stat(h, &info);
444 printk(KERN_DEBUG "SELinux: rangetr: %d entries and %d/%d buckets used, "
445 "longest chain length %d\n", h->nel,
446 info.slots_used, h->size, info.max_chain_len);
447}
448#else
449static inline void rangetr_hash_eval(struct hashtab *h)
450{
451}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700452#endif
453
454/*
455 * Define the other val_to_name and val_to_struct arrays
456 * in a policy database structure.
457 *
458 * Caller must clean up on failure.
459 */
460static int policydb_index_others(struct policydb *p)
461{
462 int i, rc = 0;
463
James Morris454d9722008-02-26 20:42:02 +1100464 printk(KERN_DEBUG "SELinux: %d users, %d roles, %d types, %d bools",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700465 p->p_users.nprim, p->p_roles.nprim, p->p_types.nprim, p->p_bools.nprim);
Guido Trentalancia0719aaf2010-02-03 16:40:20 +0100466 if (p->mls_enabled)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700467 printk(", %d sens, %d cats", p->p_levels.nprim,
468 p->p_cats.nprim);
469 printk("\n");
470
James Morris454d9722008-02-26 20:42:02 +1100471 printk(KERN_DEBUG "SELinux: %d classes, %d rules\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700472 p->p_classes.nprim, p->te_avtab.nel);
473
474#ifdef DEBUG_HASHES
475 avtab_hash_eval(&p->te_avtab, "rules");
476 symtab_hash_eval(p->symtab);
477#endif
478
479 p->role_val_to_struct =
480 kmalloc(p->p_roles.nprim * sizeof(*(p->role_val_to_struct)),
Eric Paris2ced3df2008-04-17 13:37:12 -0400481 GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700482 if (!p->role_val_to_struct) {
483 rc = -ENOMEM;
484 goto out;
485 }
486
487 p->user_val_to_struct =
488 kmalloc(p->p_users.nprim * sizeof(*(p->user_val_to_struct)),
Eric Paris2ced3df2008-04-17 13:37:12 -0400489 GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700490 if (!p->user_val_to_struct) {
491 rc = -ENOMEM;
492 goto out;
493 }
494
KaiGai Koheid9250de2008-08-28 16:35:57 +0900495 p->type_val_to_struct =
496 kmalloc(p->p_types.nprim * sizeof(*(p->type_val_to_struct)),
497 GFP_KERNEL);
498 if (!p->type_val_to_struct) {
499 rc = -ENOMEM;
500 goto out;
501 }
502
Linus Torvalds1da177e2005-04-16 15:20:36 -0700503 if (cond_init_bool_indexes(p)) {
504 rc = -ENOMEM;
505 goto out;
506 }
507
508 for (i = SYM_ROLES; i < SYM_NUM; i++) {
509 p->sym_val_to_name[i] =
510 kmalloc(p->symtab[i].nprim * sizeof(char *), GFP_KERNEL);
511 if (!p->sym_val_to_name[i]) {
512 rc = -ENOMEM;
513 goto out;
514 }
515 rc = hashtab_map(p->symtab[i].table, index_f[i], p);
516 if (rc)
517 goto out;
518 }
519
520out:
521 return rc;
522}
523
524/*
525 * The following *_destroy functions are used to
526 * free any memory allocated for each kind of
527 * symbol data in the policy database.
528 */
529
530static int perm_destroy(void *key, void *datum, void *p)
531{
532 kfree(key);
533 kfree(datum);
534 return 0;
535}
536
537static int common_destroy(void *key, void *datum, void *p)
538{
539 struct common_datum *comdatum;
540
541 kfree(key);
542 comdatum = datum;
543 hashtab_map(comdatum->permissions.table, perm_destroy, NULL);
544 hashtab_destroy(comdatum->permissions.table);
545 kfree(datum);
546 return 0;
547}
548
James Morris6cbda6b2006-11-29 16:50:27 -0500549static int cls_destroy(void *key, void *datum, void *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700550{
551 struct class_datum *cladatum;
552 struct constraint_node *constraint, *ctemp;
553 struct constraint_expr *e, *etmp;
554
555 kfree(key);
556 cladatum = datum;
557 hashtab_map(cladatum->permissions.table, perm_destroy, NULL);
558 hashtab_destroy(cladatum->permissions.table);
559 constraint = cladatum->constraints;
560 while (constraint) {
561 e = constraint->expr;
562 while (e) {
563 ebitmap_destroy(&e->names);
564 etmp = e;
565 e = e->next;
566 kfree(etmp);
567 }
568 ctemp = constraint;
569 constraint = constraint->next;
570 kfree(ctemp);
571 }
572
573 constraint = cladatum->validatetrans;
574 while (constraint) {
575 e = constraint->expr;
576 while (e) {
577 ebitmap_destroy(&e->names);
578 etmp = e;
579 e = e->next;
580 kfree(etmp);
581 }
582 ctemp = constraint;
583 constraint = constraint->next;
584 kfree(ctemp);
585 }
586
587 kfree(cladatum->comkey);
588 kfree(datum);
589 return 0;
590}
591
592static int role_destroy(void *key, void *datum, void *p)
593{
594 struct role_datum *role;
595
596 kfree(key);
597 role = datum;
598 ebitmap_destroy(&role->dominates);
599 ebitmap_destroy(&role->types);
600 kfree(datum);
601 return 0;
602}
603
604static int type_destroy(void *key, void *datum, void *p)
605{
606 kfree(key);
607 kfree(datum);
608 return 0;
609}
610
611static int user_destroy(void *key, void *datum, void *p)
612{
613 struct user_datum *usrdatum;
614
615 kfree(key);
616 usrdatum = datum;
617 ebitmap_destroy(&usrdatum->roles);
618 ebitmap_destroy(&usrdatum->range.level[0].cat);
619 ebitmap_destroy(&usrdatum->range.level[1].cat);
620 ebitmap_destroy(&usrdatum->dfltlevel.cat);
621 kfree(datum);
622 return 0;
623}
624
625static int sens_destroy(void *key, void *datum, void *p)
626{
627 struct level_datum *levdatum;
628
629 kfree(key);
630 levdatum = datum;
631 ebitmap_destroy(&levdatum->level->cat);
632 kfree(levdatum->level);
633 kfree(datum);
634 return 0;
635}
636
637static int cat_destroy(void *key, void *datum, void *p)
638{
639 kfree(key);
640 kfree(datum);
641 return 0;
642}
643
644static int (*destroy_f[SYM_NUM]) (void *key, void *datum, void *datap) =
645{
646 common_destroy,
James Morris6cbda6b2006-11-29 16:50:27 -0500647 cls_destroy,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700648 role_destroy,
649 type_destroy,
650 user_destroy,
651 cond_destroy_bool,
652 sens_destroy,
653 cat_destroy,
654};
655
Stephen Smalley2f3e82d2010-01-07 15:55:16 -0500656static int range_tr_destroy(void *key, void *datum, void *p)
657{
658 struct mls_range *rt = datum;
659 kfree(key);
660 ebitmap_destroy(&rt->level[0].cat);
661 ebitmap_destroy(&rt->level[1].cat);
662 kfree(datum);
663 cond_resched();
664 return 0;
665}
666
Linus Torvalds1da177e2005-04-16 15:20:36 -0700667static void ocontext_destroy(struct ocontext *c, int i)
668{
Eric Parisd1b43542010-07-21 12:50:57 -0400669 if (!c)
670 return;
671
Linus Torvalds1da177e2005-04-16 15:20:36 -0700672 context_destroy(&c->context[0]);
673 context_destroy(&c->context[1]);
674 if (i == OCON_ISID || i == OCON_FS ||
675 i == OCON_NETIF || i == OCON_FSUSE)
676 kfree(c->u.name);
677 kfree(c);
678}
679
680/*
681 * Free any memory allocated by a policy database structure.
682 */
683void policydb_destroy(struct policydb *p)
684{
685 struct ocontext *c, *ctmp;
686 struct genfs *g, *gtmp;
687 int i;
Stephen Smalley782ebb92005-09-03 15:55:16 -0700688 struct role_allow *ra, *lra = NULL;
689 struct role_trans *tr, *ltr = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700690
691 for (i = 0; i < SYM_NUM; i++) {
Eric Paris9dc99782007-06-04 17:41:22 -0400692 cond_resched();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700693 hashtab_map(p->symtab[i].table, destroy_f[i], NULL);
694 hashtab_destroy(p->symtab[i].table);
695 }
696
Jesper Juhl9a5f04b2005-06-25 14:58:51 -0700697 for (i = 0; i < SYM_NUM; i++)
698 kfree(p->sym_val_to_name[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700699
Jesper Juhl9a5f04b2005-06-25 14:58:51 -0700700 kfree(p->class_val_to_struct);
701 kfree(p->role_val_to_struct);
702 kfree(p->user_val_to_struct);
KaiGai Koheid9250de2008-08-28 16:35:57 +0900703 kfree(p->type_val_to_struct);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700704
705 avtab_destroy(&p->te_avtab);
706
707 for (i = 0; i < OCON_NUM; i++) {
Eric Paris9dc99782007-06-04 17:41:22 -0400708 cond_resched();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700709 c = p->ocontexts[i];
710 while (c) {
711 ctmp = c;
712 c = c->next;
Eric Paris2ced3df2008-04-17 13:37:12 -0400713 ocontext_destroy(ctmp, i);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700714 }
Chad Sellers6e8c7512006-10-06 16:09:52 -0400715 p->ocontexts[i] = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700716 }
717
718 g = p->genfs;
719 while (g) {
Eric Paris9dc99782007-06-04 17:41:22 -0400720 cond_resched();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700721 kfree(g->fstype);
722 c = g->head;
723 while (c) {
724 ctmp = c;
725 c = c->next;
Eric Paris2ced3df2008-04-17 13:37:12 -0400726 ocontext_destroy(ctmp, OCON_FSUSE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700727 }
728 gtmp = g;
729 g = g->next;
730 kfree(gtmp);
731 }
Chad Sellers6e8c7512006-10-06 16:09:52 -0400732 p->genfs = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700733
734 cond_policydb_destroy(p);
735
Stephen Smalley782ebb92005-09-03 15:55:16 -0700736 for (tr = p->role_tr; tr; tr = tr->next) {
Eric Paris9dc99782007-06-04 17:41:22 -0400737 cond_resched();
Jesper Juhla7f988b2005-11-07 01:01:35 -0800738 kfree(ltr);
Stephen Smalley782ebb92005-09-03 15:55:16 -0700739 ltr = tr;
740 }
Jesper Juhla7f988b2005-11-07 01:01:35 -0800741 kfree(ltr);
Stephen Smalley782ebb92005-09-03 15:55:16 -0700742
Eric Paris2ced3df2008-04-17 13:37:12 -0400743 for (ra = p->role_allow; ra; ra = ra->next) {
Eric Paris9dc99782007-06-04 17:41:22 -0400744 cond_resched();
Jesper Juhla7f988b2005-11-07 01:01:35 -0800745 kfree(lra);
Stephen Smalley782ebb92005-09-03 15:55:16 -0700746 lra = ra;
747 }
Jesper Juhla7f988b2005-11-07 01:01:35 -0800748 kfree(lra);
Stephen Smalley782ebb92005-09-03 15:55:16 -0700749
Stephen Smalley2f3e82d2010-01-07 15:55:16 -0500750 hashtab_map(p->range_tr, range_tr_destroy, NULL);
751 hashtab_destroy(p->range_tr);
Stephen Smalley782ebb92005-09-03 15:55:16 -0700752
Eric Paris6371dcd2010-07-29 23:02:34 -0400753 if (p->type_attr_map_array) {
754 for (i = 0; i < p->p_types.nprim; i++) {
755 struct ebitmap *e;
756
757 e = flex_array_get(p->type_attr_map_array, i);
758 if (!e)
759 continue;
760 ebitmap_destroy(e);
761 }
762 flex_array_free(p->type_attr_map_array);
Stephen Smalley282c1f52005-10-23 12:57:15 -0700763 }
Paul Moore3bb56b22008-01-29 08:38:19 -0500764 ebitmap_destroy(&p->policycaps);
Eric Paris64dbf072008-03-31 12:17:33 +1100765 ebitmap_destroy(&p->permissive_map);
Eric Paris3f120702007-09-21 14:37:10 -0400766
Linus Torvalds1da177e2005-04-16 15:20:36 -0700767 return;
768}
769
770/*
771 * Load the initial SIDs specified in a policy database
772 * structure into a SID table.
773 */
774int policydb_load_isids(struct policydb *p, struct sidtab *s)
775{
776 struct ocontext *head, *c;
777 int rc;
778
779 rc = sidtab_init(s);
780 if (rc) {
James Morris454d9722008-02-26 20:42:02 +1100781 printk(KERN_ERR "SELinux: out of memory on SID table init\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700782 goto out;
783 }
784
785 head = p->ocontexts[OCON_ISID];
786 for (c = head; c; c = c->next) {
787 if (!c->context[0].user) {
James Morris454d9722008-02-26 20:42:02 +1100788 printk(KERN_ERR "SELinux: SID %s was never "
Linus Torvalds1da177e2005-04-16 15:20:36 -0700789 "defined.\n", c->u.name);
790 rc = -EINVAL;
791 goto out;
792 }
793 if (sidtab_insert(s, c->sid[0], &c->context[0])) {
James Morris454d9722008-02-26 20:42:02 +1100794 printk(KERN_ERR "SELinux: unable to load initial "
Linus Torvalds1da177e2005-04-16 15:20:36 -0700795 "SID %s.\n", c->u.name);
796 rc = -EINVAL;
797 goto out;
798 }
799 }
800out:
801 return rc;
802}
803
Stephen Smalley45e54212007-11-07 10:08:00 -0500804int policydb_class_isvalid(struct policydb *p, unsigned int class)
805{
806 if (!class || class > p->p_classes.nprim)
807 return 0;
808 return 1;
809}
810
811int policydb_role_isvalid(struct policydb *p, unsigned int role)
812{
813 if (!role || role > p->p_roles.nprim)
814 return 0;
815 return 1;
816}
817
818int policydb_type_isvalid(struct policydb *p, unsigned int type)
819{
820 if (!type || type > p->p_types.nprim)
821 return 0;
822 return 1;
823}
824
Linus Torvalds1da177e2005-04-16 15:20:36 -0700825/*
826 * Return 1 if the fields in the security context
827 * structure `c' are valid. Return 0 otherwise.
828 */
829int policydb_context_isvalid(struct policydb *p, struct context *c)
830{
831 struct role_datum *role;
832 struct user_datum *usrdatum;
833
834 if (!c->role || c->role > p->p_roles.nprim)
835 return 0;
836
837 if (!c->user || c->user > p->p_users.nprim)
838 return 0;
839
840 if (!c->type || c->type > p->p_types.nprim)
841 return 0;
842
843 if (c->role != OBJECT_R_VAL) {
844 /*
845 * Role must be authorized for the type.
846 */
847 role = p->role_val_to_struct[c->role - 1];
848 if (!ebitmap_get_bit(&role->types,
849 c->type - 1))
850 /* role may not be associated with type */
851 return 0;
852
853 /*
854 * User must be authorized for the role.
855 */
856 usrdatum = p->user_val_to_struct[c->user - 1];
857 if (!usrdatum)
858 return 0;
859
860 if (!ebitmap_get_bit(&usrdatum->roles,
861 c->role - 1))
862 /* user may not be associated with role */
863 return 0;
864 }
865
866 if (!mls_context_isvalid(p, c))
867 return 0;
868
869 return 1;
870}
871
872/*
873 * Read a MLS range structure from a policydb binary
874 * representation file.
875 */
876static int mls_read_range_helper(struct mls_range *r, void *fp)
877{
Alexey Dobriyanb5bf6c52005-09-03 15:55:17 -0700878 __le32 buf[2];
879 u32 items;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700880 int rc;
881
882 rc = next_entry(buf, fp, sizeof(u32));
883 if (rc < 0)
884 goto out;
885
886 items = le32_to_cpu(buf[0]);
887 if (items > ARRAY_SIZE(buf)) {
James Morris454d9722008-02-26 20:42:02 +1100888 printk(KERN_ERR "SELinux: mls: range overflow\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700889 rc = -EINVAL;
890 goto out;
891 }
892 rc = next_entry(buf, fp, sizeof(u32) * items);
893 if (rc < 0) {
James Morris454d9722008-02-26 20:42:02 +1100894 printk(KERN_ERR "SELinux: mls: truncated range\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700895 goto out;
896 }
897 r->level[0].sens = le32_to_cpu(buf[0]);
898 if (items > 1)
899 r->level[1].sens = le32_to_cpu(buf[1]);
900 else
901 r->level[1].sens = r->level[0].sens;
902
903 rc = ebitmap_read(&r->level[0].cat, fp);
904 if (rc) {
James Morris454d9722008-02-26 20:42:02 +1100905 printk(KERN_ERR "SELinux: mls: error reading low "
Linus Torvalds1da177e2005-04-16 15:20:36 -0700906 "categories\n");
907 goto out;
908 }
909 if (items > 1) {
910 rc = ebitmap_read(&r->level[1].cat, fp);
911 if (rc) {
James Morris454d9722008-02-26 20:42:02 +1100912 printk(KERN_ERR "SELinux: mls: error reading high "
Linus Torvalds1da177e2005-04-16 15:20:36 -0700913 "categories\n");
914 goto bad_high;
915 }
916 } else {
917 rc = ebitmap_cpy(&r->level[1].cat, &r->level[0].cat);
918 if (rc) {
James Morris454d9722008-02-26 20:42:02 +1100919 printk(KERN_ERR "SELinux: mls: out of memory\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700920 goto bad_high;
921 }
922 }
923
924 rc = 0;
925out:
926 return rc;
927bad_high:
928 ebitmap_destroy(&r->level[0].cat);
929 goto out;
930}
931
932/*
933 * Read and validate a security context structure
934 * from a policydb binary representation file.
935 */
936static int context_read_and_validate(struct context *c,
937 struct policydb *p,
938 void *fp)
939{
Alexey Dobriyanb5bf6c52005-09-03 15:55:17 -0700940 __le32 buf[3];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700941 int rc;
942
943 rc = next_entry(buf, fp, sizeof buf);
944 if (rc < 0) {
James Morris454d9722008-02-26 20:42:02 +1100945 printk(KERN_ERR "SELinux: context truncated\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700946 goto out;
947 }
948 c->user = le32_to_cpu(buf[0]);
949 c->role = le32_to_cpu(buf[1]);
950 c->type = le32_to_cpu(buf[2]);
951 if (p->policyvers >= POLICYDB_VERSION_MLS) {
952 if (mls_read_range_helper(&c->range, fp)) {
James Morris454d9722008-02-26 20:42:02 +1100953 printk(KERN_ERR "SELinux: error reading MLS range of "
Linus Torvalds1da177e2005-04-16 15:20:36 -0700954 "context\n");
955 rc = -EINVAL;
956 goto out;
957 }
958 }
959
960 if (!policydb_context_isvalid(p, c)) {
James Morris454d9722008-02-26 20:42:02 +1100961 printk(KERN_ERR "SELinux: invalid security context\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700962 context_destroy(c);
963 rc = -EINVAL;
964 }
965out:
966 return rc;
967}
968
969/*
970 * The following *_read functions are used to
971 * read the symbol data from a policy database
972 * binary representation file.
973 */
974
975static int perm_read(struct policydb *p, struct hashtab *h, void *fp)
976{
977 char *key = NULL;
978 struct perm_datum *perdatum;
979 int rc;
Alexey Dobriyanb5bf6c52005-09-03 15:55:17 -0700980 __le32 buf[2];
981 u32 len;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700982
James Morris89d155e2005-10-30 14:59:21 -0800983 perdatum = kzalloc(sizeof(*perdatum), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700984 if (!perdatum) {
985 rc = -ENOMEM;
986 goto out;
987 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700988
989 rc = next_entry(buf, fp, sizeof buf);
990 if (rc < 0)
991 goto bad;
992
993 len = le32_to_cpu(buf[0]);
994 perdatum->value = le32_to_cpu(buf[1]);
995
Eric Paris2ced3df2008-04-17 13:37:12 -0400996 key = kmalloc(len + 1, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700997 if (!key) {
998 rc = -ENOMEM;
999 goto bad;
1000 }
1001 rc = next_entry(key, fp, len);
1002 if (rc < 0)
1003 goto bad;
Vesa-Matti J Karidf4ea862008-07-20 23:57:01 +03001004 key[len] = '\0';
Linus Torvalds1da177e2005-04-16 15:20:36 -07001005
1006 rc = hashtab_insert(h, key, perdatum);
1007 if (rc)
1008 goto bad;
1009out:
1010 return rc;
1011bad:
1012 perm_destroy(key, perdatum, NULL);
1013 goto out;
1014}
1015
1016static int common_read(struct policydb *p, struct hashtab *h, void *fp)
1017{
1018 char *key = NULL;
1019 struct common_datum *comdatum;
Alexey Dobriyanb5bf6c52005-09-03 15:55:17 -07001020 __le32 buf[4];
1021 u32 len, nel;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001022 int i, rc;
1023
James Morris89d155e2005-10-30 14:59:21 -08001024 comdatum = kzalloc(sizeof(*comdatum), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001025 if (!comdatum) {
1026 rc = -ENOMEM;
1027 goto out;
1028 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001029
1030 rc = next_entry(buf, fp, sizeof buf);
1031 if (rc < 0)
1032 goto bad;
1033
1034 len = le32_to_cpu(buf[0]);
1035 comdatum->value = le32_to_cpu(buf[1]);
1036
1037 rc = symtab_init(&comdatum->permissions, PERM_SYMTAB_SIZE);
1038 if (rc)
1039 goto bad;
1040 comdatum->permissions.nprim = le32_to_cpu(buf[2]);
1041 nel = le32_to_cpu(buf[3]);
1042
Eric Paris2ced3df2008-04-17 13:37:12 -04001043 key = kmalloc(len + 1, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001044 if (!key) {
1045 rc = -ENOMEM;
1046 goto bad;
1047 }
1048 rc = next_entry(key, fp, len);
1049 if (rc < 0)
1050 goto bad;
Vesa-Matti J Karidf4ea862008-07-20 23:57:01 +03001051 key[len] = '\0';
Linus Torvalds1da177e2005-04-16 15:20:36 -07001052
1053 for (i = 0; i < nel; i++) {
1054 rc = perm_read(p, comdatum->permissions.table, fp);
1055 if (rc)
1056 goto bad;
1057 }
1058
1059 rc = hashtab_insert(h, key, comdatum);
1060 if (rc)
1061 goto bad;
1062out:
1063 return rc;
1064bad:
1065 common_destroy(key, comdatum, NULL);
1066 goto out;
1067}
1068
1069static int read_cons_helper(struct constraint_node **nodep, int ncons,
Eric Paris2ced3df2008-04-17 13:37:12 -04001070 int allowxtarget, void *fp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001071{
1072 struct constraint_node *c, *lc;
1073 struct constraint_expr *e, *le;
Alexey Dobriyanb5bf6c52005-09-03 15:55:17 -07001074 __le32 buf[3];
1075 u32 nexpr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001076 int rc, i, j, depth;
1077
1078 lc = NULL;
1079 for (i = 0; i < ncons; i++) {
James Morris89d155e2005-10-30 14:59:21 -08001080 c = kzalloc(sizeof(*c), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001081 if (!c)
1082 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001083
Eric Paris2ced3df2008-04-17 13:37:12 -04001084 if (lc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001085 lc->next = c;
Eric Paris2ced3df2008-04-17 13:37:12 -04001086 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001087 *nodep = c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001088
1089 rc = next_entry(buf, fp, (sizeof(u32) * 2));
1090 if (rc < 0)
1091 return rc;
1092 c->permissions = le32_to_cpu(buf[0]);
1093 nexpr = le32_to_cpu(buf[1]);
1094 le = NULL;
1095 depth = -1;
1096 for (j = 0; j < nexpr; j++) {
James Morris89d155e2005-10-30 14:59:21 -08001097 e = kzalloc(sizeof(*e), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001098 if (!e)
1099 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001100
Eric Paris2ced3df2008-04-17 13:37:12 -04001101 if (le)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001102 le->next = e;
Eric Paris2ced3df2008-04-17 13:37:12 -04001103 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001104 c->expr = e;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001105
1106 rc = next_entry(buf, fp, (sizeof(u32) * 3));
1107 if (rc < 0)
1108 return rc;
1109 e->expr_type = le32_to_cpu(buf[0]);
1110 e->attr = le32_to_cpu(buf[1]);
1111 e->op = le32_to_cpu(buf[2]);
1112
1113 switch (e->expr_type) {
1114 case CEXPR_NOT:
1115 if (depth < 0)
1116 return -EINVAL;
1117 break;
1118 case CEXPR_AND:
1119 case CEXPR_OR:
1120 if (depth < 1)
1121 return -EINVAL;
1122 depth--;
1123 break;
1124 case CEXPR_ATTR:
1125 if (depth == (CEXPR_MAXDEPTH - 1))
1126 return -EINVAL;
1127 depth++;
1128 break;
1129 case CEXPR_NAMES:
1130 if (!allowxtarget && (e->attr & CEXPR_XTARGET))
1131 return -EINVAL;
1132 if (depth == (CEXPR_MAXDEPTH - 1))
1133 return -EINVAL;
1134 depth++;
1135 if (ebitmap_read(&e->names, fp))
1136 return -EINVAL;
1137 break;
1138 default:
1139 return -EINVAL;
1140 }
1141 le = e;
1142 }
1143 if (depth != 0)
1144 return -EINVAL;
1145 lc = c;
1146 }
1147
1148 return 0;
1149}
1150
1151static int class_read(struct policydb *p, struct hashtab *h, void *fp)
1152{
1153 char *key = NULL;
1154 struct class_datum *cladatum;
Alexey Dobriyanb5bf6c52005-09-03 15:55:17 -07001155 __le32 buf[6];
1156 u32 len, len2, ncons, nel;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001157 int i, rc;
1158
James Morris89d155e2005-10-30 14:59:21 -08001159 cladatum = kzalloc(sizeof(*cladatum), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001160 if (!cladatum) {
1161 rc = -ENOMEM;
1162 goto out;
1163 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001164
1165 rc = next_entry(buf, fp, sizeof(u32)*6);
1166 if (rc < 0)
1167 goto bad;
1168
1169 len = le32_to_cpu(buf[0]);
1170 len2 = le32_to_cpu(buf[1]);
1171 cladatum->value = le32_to_cpu(buf[2]);
1172
1173 rc = symtab_init(&cladatum->permissions, PERM_SYMTAB_SIZE);
1174 if (rc)
1175 goto bad;
1176 cladatum->permissions.nprim = le32_to_cpu(buf[3]);
1177 nel = le32_to_cpu(buf[4]);
1178
1179 ncons = le32_to_cpu(buf[5]);
1180
Eric Paris2ced3df2008-04-17 13:37:12 -04001181 key = kmalloc(len + 1, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001182 if (!key) {
1183 rc = -ENOMEM;
1184 goto bad;
1185 }
1186 rc = next_entry(key, fp, len);
1187 if (rc < 0)
1188 goto bad;
Vesa-Matti J Karidf4ea862008-07-20 23:57:01 +03001189 key[len] = '\0';
Linus Torvalds1da177e2005-04-16 15:20:36 -07001190
1191 if (len2) {
Eric Paris2ced3df2008-04-17 13:37:12 -04001192 cladatum->comkey = kmalloc(len2 + 1, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001193 if (!cladatum->comkey) {
1194 rc = -ENOMEM;
1195 goto bad;
1196 }
1197 rc = next_entry(cladatum->comkey, fp, len2);
1198 if (rc < 0)
1199 goto bad;
Vesa-Matti J Karidf4ea862008-07-20 23:57:01 +03001200 cladatum->comkey[len2] = '\0';
Linus Torvalds1da177e2005-04-16 15:20:36 -07001201
1202 cladatum->comdatum = hashtab_search(p->p_commons.table,
1203 cladatum->comkey);
1204 if (!cladatum->comdatum) {
James Morris454d9722008-02-26 20:42:02 +11001205 printk(KERN_ERR "SELinux: unknown common %s\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001206 cladatum->comkey);
1207 rc = -EINVAL;
1208 goto bad;
1209 }
1210 }
1211 for (i = 0; i < nel; i++) {
1212 rc = perm_read(p, cladatum->permissions.table, fp);
1213 if (rc)
1214 goto bad;
1215 }
1216
1217 rc = read_cons_helper(&cladatum->constraints, ncons, 0, fp);
1218 if (rc)
1219 goto bad;
1220
1221 if (p->policyvers >= POLICYDB_VERSION_VALIDATETRANS) {
1222 /* grab the validatetrans rules */
1223 rc = next_entry(buf, fp, sizeof(u32));
1224 if (rc < 0)
1225 goto bad;
1226 ncons = le32_to_cpu(buf[0]);
1227 rc = read_cons_helper(&cladatum->validatetrans, ncons, 1, fp);
1228 if (rc)
1229 goto bad;
1230 }
1231
1232 rc = hashtab_insert(h, key, cladatum);
1233 if (rc)
1234 goto bad;
1235
1236 rc = 0;
1237out:
1238 return rc;
1239bad:
James Morris6cbda6b2006-11-29 16:50:27 -05001240 cls_destroy(key, cladatum, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001241 goto out;
1242}
1243
1244static int role_read(struct policydb *p, struct hashtab *h, void *fp)
1245{
1246 char *key = NULL;
1247 struct role_datum *role;
KaiGai Koheid9250de2008-08-28 16:35:57 +09001248 int rc, to_read = 2;
1249 __le32 buf[3];
Alexey Dobriyanb5bf6c52005-09-03 15:55:17 -07001250 u32 len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001251
James Morris89d155e2005-10-30 14:59:21 -08001252 role = kzalloc(sizeof(*role), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001253 if (!role) {
1254 rc = -ENOMEM;
1255 goto out;
1256 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001257
KaiGai Koheid9250de2008-08-28 16:35:57 +09001258 if (p->policyvers >= POLICYDB_VERSION_BOUNDARY)
1259 to_read = 3;
1260
1261 rc = next_entry(buf, fp, sizeof(buf[0]) * to_read);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001262 if (rc < 0)
1263 goto bad;
1264
1265 len = le32_to_cpu(buf[0]);
1266 role->value = le32_to_cpu(buf[1]);
KaiGai Koheid9250de2008-08-28 16:35:57 +09001267 if (p->policyvers >= POLICYDB_VERSION_BOUNDARY)
1268 role->bounds = le32_to_cpu(buf[2]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001269
Eric Paris2ced3df2008-04-17 13:37:12 -04001270 key = kmalloc(len + 1, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001271 if (!key) {
1272 rc = -ENOMEM;
1273 goto bad;
1274 }
1275 rc = next_entry(key, fp, len);
1276 if (rc < 0)
1277 goto bad;
Vesa-Matti J Karidf4ea862008-07-20 23:57:01 +03001278 key[len] = '\0';
Linus Torvalds1da177e2005-04-16 15:20:36 -07001279
1280 rc = ebitmap_read(&role->dominates, fp);
1281 if (rc)
1282 goto bad;
1283
1284 rc = ebitmap_read(&role->types, fp);
1285 if (rc)
1286 goto bad;
1287
1288 if (strcmp(key, OBJECT_R) == 0) {
1289 if (role->value != OBJECT_R_VAL) {
Eric Paris744ba352008-04-17 11:52:44 -04001290 printk(KERN_ERR "SELinux: Role %s has wrong value %d\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001291 OBJECT_R, role->value);
1292 rc = -EINVAL;
1293 goto bad;
1294 }
1295 rc = 0;
1296 goto bad;
1297 }
1298
1299 rc = hashtab_insert(h, key, role);
1300 if (rc)
1301 goto bad;
1302out:
1303 return rc;
1304bad:
1305 role_destroy(key, role, NULL);
1306 goto out;
1307}
1308
1309static int type_read(struct policydb *p, struct hashtab *h, void *fp)
1310{
1311 char *key = NULL;
1312 struct type_datum *typdatum;
KaiGai Koheid9250de2008-08-28 16:35:57 +09001313 int rc, to_read = 3;
1314 __le32 buf[4];
Alexey Dobriyanb5bf6c52005-09-03 15:55:17 -07001315 u32 len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001316
Eric Paris2ced3df2008-04-17 13:37:12 -04001317 typdatum = kzalloc(sizeof(*typdatum), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001318 if (!typdatum) {
1319 rc = -ENOMEM;
1320 return rc;
1321 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001322
KaiGai Koheid9250de2008-08-28 16:35:57 +09001323 if (p->policyvers >= POLICYDB_VERSION_BOUNDARY)
1324 to_read = 4;
1325
1326 rc = next_entry(buf, fp, sizeof(buf[0]) * to_read);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001327 if (rc < 0)
1328 goto bad;
1329
1330 len = le32_to_cpu(buf[0]);
1331 typdatum->value = le32_to_cpu(buf[1]);
KaiGai Koheid9250de2008-08-28 16:35:57 +09001332 if (p->policyvers >= POLICYDB_VERSION_BOUNDARY) {
1333 u32 prop = le32_to_cpu(buf[2]);
1334
1335 if (prop & TYPEDATUM_PROPERTY_PRIMARY)
1336 typdatum->primary = 1;
1337 if (prop & TYPEDATUM_PROPERTY_ATTRIBUTE)
1338 typdatum->attribute = 1;
1339
1340 typdatum->bounds = le32_to_cpu(buf[3]);
1341 } else {
1342 typdatum->primary = le32_to_cpu(buf[2]);
1343 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001344
Eric Paris2ced3df2008-04-17 13:37:12 -04001345 key = kmalloc(len + 1, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001346 if (!key) {
1347 rc = -ENOMEM;
1348 goto bad;
1349 }
1350 rc = next_entry(key, fp, len);
1351 if (rc < 0)
1352 goto bad;
Vesa-Matti J Karidf4ea862008-07-20 23:57:01 +03001353 key[len] = '\0';
Linus Torvalds1da177e2005-04-16 15:20:36 -07001354
1355 rc = hashtab_insert(h, key, typdatum);
1356 if (rc)
1357 goto bad;
1358out:
1359 return rc;
1360bad:
1361 type_destroy(key, typdatum, NULL);
1362 goto out;
1363}
1364
1365
1366/*
1367 * Read a MLS level structure from a policydb binary
1368 * representation file.
1369 */
1370static int mls_read_level(struct mls_level *lp, void *fp)
1371{
Alexey Dobriyanb5bf6c52005-09-03 15:55:17 -07001372 __le32 buf[1];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001373 int rc;
1374
1375 memset(lp, 0, sizeof(*lp));
1376
1377 rc = next_entry(buf, fp, sizeof buf);
1378 if (rc < 0) {
James Morris454d9722008-02-26 20:42:02 +11001379 printk(KERN_ERR "SELinux: mls: truncated level\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001380 goto bad;
1381 }
1382 lp->sens = le32_to_cpu(buf[0]);
1383
1384 if (ebitmap_read(&lp->cat, fp)) {
James Morris454d9722008-02-26 20:42:02 +11001385 printk(KERN_ERR "SELinux: mls: error reading level "
Linus Torvalds1da177e2005-04-16 15:20:36 -07001386 "categories\n");
1387 goto bad;
1388 }
Stephen Smalley45e54212007-11-07 10:08:00 -05001389
Linus Torvalds1da177e2005-04-16 15:20:36 -07001390 return 0;
1391
1392bad:
1393 return -EINVAL;
1394}
1395
1396static int user_read(struct policydb *p, struct hashtab *h, void *fp)
1397{
1398 char *key = NULL;
1399 struct user_datum *usrdatum;
KaiGai Koheid9250de2008-08-28 16:35:57 +09001400 int rc, to_read = 2;
1401 __le32 buf[3];
Alexey Dobriyanb5bf6c52005-09-03 15:55:17 -07001402 u32 len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001403
James Morris89d155e2005-10-30 14:59:21 -08001404 usrdatum = kzalloc(sizeof(*usrdatum), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001405 if (!usrdatum) {
1406 rc = -ENOMEM;
1407 goto out;
1408 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001409
KaiGai Koheid9250de2008-08-28 16:35:57 +09001410 if (p->policyvers >= POLICYDB_VERSION_BOUNDARY)
1411 to_read = 3;
1412
1413 rc = next_entry(buf, fp, sizeof(buf[0]) * to_read);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001414 if (rc < 0)
1415 goto bad;
1416
1417 len = le32_to_cpu(buf[0]);
1418 usrdatum->value = le32_to_cpu(buf[1]);
KaiGai Koheid9250de2008-08-28 16:35:57 +09001419 if (p->policyvers >= POLICYDB_VERSION_BOUNDARY)
1420 usrdatum->bounds = le32_to_cpu(buf[2]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001421
Eric Paris2ced3df2008-04-17 13:37:12 -04001422 key = kmalloc(len + 1, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001423 if (!key) {
1424 rc = -ENOMEM;
1425 goto bad;
1426 }
1427 rc = next_entry(key, fp, len);
1428 if (rc < 0)
1429 goto bad;
Vesa-Matti J Karidf4ea862008-07-20 23:57:01 +03001430 key[len] = '\0';
Linus Torvalds1da177e2005-04-16 15:20:36 -07001431
1432 rc = ebitmap_read(&usrdatum->roles, fp);
1433 if (rc)
1434 goto bad;
1435
1436 if (p->policyvers >= POLICYDB_VERSION_MLS) {
1437 rc = mls_read_range_helper(&usrdatum->range, fp);
1438 if (rc)
1439 goto bad;
1440 rc = mls_read_level(&usrdatum->dfltlevel, fp);
1441 if (rc)
1442 goto bad;
1443 }
1444
1445 rc = hashtab_insert(h, key, usrdatum);
1446 if (rc)
1447 goto bad;
1448out:
1449 return rc;
1450bad:
1451 user_destroy(key, usrdatum, NULL);
1452 goto out;
1453}
1454
1455static int sens_read(struct policydb *p, struct hashtab *h, void *fp)
1456{
1457 char *key = NULL;
1458 struct level_datum *levdatum;
1459 int rc;
Alexey Dobriyanb5bf6c52005-09-03 15:55:17 -07001460 __le32 buf[2];
1461 u32 len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001462
James Morris89d155e2005-10-30 14:59:21 -08001463 levdatum = kzalloc(sizeof(*levdatum), GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001464 if (!levdatum) {
1465 rc = -ENOMEM;
1466 goto out;
1467 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001468
1469 rc = next_entry(buf, fp, sizeof buf);
1470 if (rc < 0)
1471 goto bad;
1472
1473 len = le32_to_cpu(buf[0]);
1474 levdatum->isalias = le32_to_cpu(buf[1]);
1475
Eric Paris2ced3df2008-04-17 13:37:12 -04001476 key = kmalloc(len + 1, GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001477 if (!key) {
1478 rc = -ENOMEM;
1479 goto bad;
1480 }
1481 rc = next_entry(key, fp, len);
1482 if (rc < 0)
1483 goto bad;
Vesa-Matti J Karidf4ea862008-07-20 23:57:01 +03001484 key[len] = '\0';
Linus Torvalds1da177e2005-04-16 15:20:36 -07001485
1486 levdatum->level = kmalloc(sizeof(struct mls_level), GFP_ATOMIC);
1487 if (!levdatum->level) {
1488 rc = -ENOMEM;
1489 goto bad;
1490 }
1491 if (mls_read_level(levdatum->level, fp)) {
1492 rc = -EINVAL;
1493 goto bad;
1494 }
1495
1496 rc = hashtab_insert(h, key, levdatum);
1497 if (rc)
1498 goto bad;
1499out:
1500 return rc;
1501bad:
1502 sens_destroy(key, levdatum, NULL);
1503 goto out;
1504}
1505
1506static int cat_read(struct policydb *p, struct hashtab *h, void *fp)
1507{
1508 char *key = NULL;
1509 struct cat_datum *catdatum;
1510 int rc;
Alexey Dobriyanb5bf6c52005-09-03 15:55:17 -07001511 __le32 buf[3];
1512 u32 len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001513
James Morris89d155e2005-10-30 14:59:21 -08001514 catdatum = kzalloc(sizeof(*catdatum), GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001515 if (!catdatum) {
1516 rc = -ENOMEM;
1517 goto out;
1518 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001519
1520 rc = next_entry(buf, fp, sizeof buf);
1521 if (rc < 0)
1522 goto bad;
1523
1524 len = le32_to_cpu(buf[0]);
1525 catdatum->value = le32_to_cpu(buf[1]);
1526 catdatum->isalias = le32_to_cpu(buf[2]);
1527
Eric Paris2ced3df2008-04-17 13:37:12 -04001528 key = kmalloc(len + 1, GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001529 if (!key) {
1530 rc = -ENOMEM;
1531 goto bad;
1532 }
1533 rc = next_entry(key, fp, len);
1534 if (rc < 0)
1535 goto bad;
Vesa-Matti J Karidf4ea862008-07-20 23:57:01 +03001536 key[len] = '\0';
Linus Torvalds1da177e2005-04-16 15:20:36 -07001537
1538 rc = hashtab_insert(h, key, catdatum);
1539 if (rc)
1540 goto bad;
1541out:
1542 return rc;
1543
1544bad:
1545 cat_destroy(key, catdatum, NULL);
1546 goto out;
1547}
1548
1549static int (*read_f[SYM_NUM]) (struct policydb *p, struct hashtab *h, void *fp) =
1550{
1551 common_read,
1552 class_read,
1553 role_read,
1554 type_read,
1555 user_read,
1556 cond_read_bool,
1557 sens_read,
1558 cat_read,
1559};
1560
KaiGai Koheid9250de2008-08-28 16:35:57 +09001561static int user_bounds_sanity_check(void *key, void *datum, void *datap)
1562{
1563 struct user_datum *upper, *user;
1564 struct policydb *p = datap;
1565 int depth = 0;
1566
1567 upper = user = datum;
1568 while (upper->bounds) {
1569 struct ebitmap_node *node;
1570 unsigned long bit;
1571
1572 if (++depth == POLICYDB_BOUNDS_MAXDEPTH) {
1573 printk(KERN_ERR "SELinux: user %s: "
1574 "too deep or looped boundary",
1575 (char *) key);
1576 return -EINVAL;
1577 }
1578
1579 upper = p->user_val_to_struct[upper->bounds - 1];
1580 ebitmap_for_each_positive_bit(&user->roles, node, bit) {
1581 if (ebitmap_get_bit(&upper->roles, bit))
1582 continue;
1583
1584 printk(KERN_ERR
1585 "SELinux: boundary violated policy: "
1586 "user=%s role=%s bounds=%s\n",
1587 p->p_user_val_to_name[user->value - 1],
1588 p->p_role_val_to_name[bit],
1589 p->p_user_val_to_name[upper->value - 1]);
1590
1591 return -EINVAL;
1592 }
1593 }
1594
1595 return 0;
1596}
1597
1598static int role_bounds_sanity_check(void *key, void *datum, void *datap)
1599{
1600 struct role_datum *upper, *role;
1601 struct policydb *p = datap;
1602 int depth = 0;
1603
1604 upper = role = datum;
1605 while (upper->bounds) {
1606 struct ebitmap_node *node;
1607 unsigned long bit;
1608
1609 if (++depth == POLICYDB_BOUNDS_MAXDEPTH) {
1610 printk(KERN_ERR "SELinux: role %s: "
1611 "too deep or looped bounds\n",
1612 (char *) key);
1613 return -EINVAL;
1614 }
1615
1616 upper = p->role_val_to_struct[upper->bounds - 1];
1617 ebitmap_for_each_positive_bit(&role->types, node, bit) {
1618 if (ebitmap_get_bit(&upper->types, bit))
1619 continue;
1620
1621 printk(KERN_ERR
1622 "SELinux: boundary violated policy: "
1623 "role=%s type=%s bounds=%s\n",
1624 p->p_role_val_to_name[role->value - 1],
1625 p->p_type_val_to_name[bit],
1626 p->p_role_val_to_name[upper->value - 1]);
1627
1628 return -EINVAL;
1629 }
1630 }
1631
1632 return 0;
1633}
1634
1635static int type_bounds_sanity_check(void *key, void *datum, void *datap)
1636{
Eric Parisdaa6d832010-08-03 15:26:05 -04001637 struct type_datum *upper;
KaiGai Koheid9250de2008-08-28 16:35:57 +09001638 struct policydb *p = datap;
1639 int depth = 0;
1640
Eric Parisdaa6d832010-08-03 15:26:05 -04001641 upper = datum;
KaiGai Koheid9250de2008-08-28 16:35:57 +09001642 while (upper->bounds) {
1643 if (++depth == POLICYDB_BOUNDS_MAXDEPTH) {
1644 printk(KERN_ERR "SELinux: type %s: "
1645 "too deep or looped boundary\n",
1646 (char *) key);
1647 return -EINVAL;
1648 }
1649
1650 upper = p->type_val_to_struct[upper->bounds - 1];
1651 if (upper->attribute) {
1652 printk(KERN_ERR "SELinux: type %s: "
1653 "bounded by attribute %s",
1654 (char *) key,
1655 p->p_type_val_to_name[upper->value - 1]);
1656 return -EINVAL;
1657 }
1658 }
1659
1660 return 0;
1661}
1662
1663static int policydb_bounds_sanity_check(struct policydb *p)
1664{
1665 int rc;
1666
1667 if (p->policyvers < POLICYDB_VERSION_BOUNDARY)
1668 return 0;
1669
1670 rc = hashtab_map(p->p_users.table,
1671 user_bounds_sanity_check, p);
1672 if (rc)
1673 return rc;
1674
1675 rc = hashtab_map(p->p_roles.table,
1676 role_bounds_sanity_check, p);
1677 if (rc)
1678 return rc;
1679
1680 rc = hashtab_map(p->p_types.table,
1681 type_bounds_sanity_check, p);
1682 if (rc)
1683 return rc;
1684
1685 return 0;
1686}
1687
Linus Torvalds1da177e2005-04-16 15:20:36 -07001688extern int ss_initialized;
1689
Stephen Smalleyc6d3aaa2009-09-30 13:37:50 -04001690u16 string_to_security_class(struct policydb *p, const char *name)
1691{
1692 struct class_datum *cladatum;
1693
1694 cladatum = hashtab_search(p->p_classes.table, name);
1695 if (!cladatum)
1696 return 0;
1697
1698 return cladatum->value;
1699}
1700
1701u32 string_to_av_perm(struct policydb *p, u16 tclass, const char *name)
1702{
1703 struct class_datum *cladatum;
1704 struct perm_datum *perdatum = NULL;
1705 struct common_datum *comdatum;
1706
1707 if (!tclass || tclass > p->p_classes.nprim)
1708 return 0;
1709
1710 cladatum = p->class_val_to_struct[tclass-1];
1711 comdatum = cladatum->comdatum;
1712 if (comdatum)
1713 perdatum = hashtab_search(comdatum->permissions.table,
1714 name);
1715 if (!perdatum)
1716 perdatum = hashtab_search(cladatum->permissions.table,
1717 name);
1718 if (!perdatum)
1719 return 0;
1720
1721 return 1U << (perdatum->value-1);
1722}
1723
Eric Paris9ee0c822010-06-11 12:37:05 -04001724static int range_read(struct policydb *p, void *fp)
1725{
1726 struct range_trans *rt = NULL;
1727 struct mls_range *r = NULL;
1728 int i, rc;
1729 __le32 buf[2];
1730 u32 nel;
1731
1732 if (p->policyvers < POLICYDB_VERSION_MLS)
1733 return 0;
1734
1735 rc = next_entry(buf, fp, sizeof(u32));
1736 if (rc)
1737 goto out;
1738
1739 nel = le32_to_cpu(buf[0]);
1740 for (i = 0; i < nel; i++) {
1741 rc = -ENOMEM;
1742 rt = kzalloc(sizeof(*rt), GFP_KERNEL);
1743 if (!rt)
1744 goto out;
1745
1746 rc = next_entry(buf, fp, (sizeof(u32) * 2));
1747 if (rc)
1748 goto out;
1749
1750 rt->source_type = le32_to_cpu(buf[0]);
1751 rt->target_type = le32_to_cpu(buf[1]);
1752 if (p->policyvers >= POLICYDB_VERSION_RANGETRANS) {
1753 rc = next_entry(buf, fp, sizeof(u32));
1754 if (rc)
1755 goto out;
1756 rt->target_class = le32_to_cpu(buf[0]);
1757 } else
1758 rt->target_class = p->process_class;
1759
1760 rc = -EINVAL;
1761 if (!policydb_type_isvalid(p, rt->source_type) ||
1762 !policydb_type_isvalid(p, rt->target_type) ||
1763 !policydb_class_isvalid(p, rt->target_class))
1764 goto out;
1765
1766 rc = -ENOMEM;
1767 r = kzalloc(sizeof(*r), GFP_KERNEL);
1768 if (!r)
1769 goto out;
1770
1771 rc = mls_read_range_helper(r, fp);
1772 if (rc)
1773 goto out;
1774
1775 rc = -EINVAL;
1776 if (!mls_range_isvalid(p, r)) {
1777 printk(KERN_WARNING "SELinux: rangetrans: invalid range\n");
1778 goto out;
1779 }
1780
1781 rc = hashtab_insert(p->range_tr, rt, r);
1782 if (rc)
1783 goto out;
1784
1785 rt = NULL;
1786 r = NULL;
1787 }
1788 rangetr_hash_eval(p->range_tr);
1789 rc = 0;
1790out:
1791 kfree(rt);
1792 kfree(r);
1793 return rc;
1794}
1795
Eric Parisd1b43542010-07-21 12:50:57 -04001796static int genfs_read(struct policydb *p, void *fp)
1797{
1798 int i, j, rc;
1799 u32 nel, nel2, len, len2;
1800 __le32 buf[1];
1801 struct ocontext *l, *c;
1802 struct ocontext *newc = NULL;
1803 struct genfs *genfs_p, *genfs;
1804 struct genfs *newgenfs = NULL;
1805
1806 rc = next_entry(buf, fp, sizeof(u32));
1807 if (rc)
1808 goto out;
1809 nel = le32_to_cpu(buf[0]);
1810
1811 for (i = 0; i < nel; i++) {
1812 rc = next_entry(buf, fp, sizeof(u32));
1813 if (rc)
1814 goto out;
1815 len = le32_to_cpu(buf[0]);
1816
1817 rc = -ENOMEM;
1818 newgenfs = kzalloc(sizeof(*newgenfs), GFP_KERNEL);
1819 if (!newgenfs)
1820 goto out;
1821
1822 rc = -ENOMEM;
1823 newgenfs->fstype = kmalloc(len + 1, GFP_KERNEL);
1824 if (!newgenfs->fstype)
1825 goto out;
1826
1827 rc = next_entry(newgenfs->fstype, fp, len);
1828 if (rc)
1829 goto out;
1830
1831 newgenfs->fstype[len] = 0;
1832
1833 for (genfs_p = NULL, genfs = p->genfs; genfs;
1834 genfs_p = genfs, genfs = genfs->next) {
1835 rc = -EINVAL;
1836 if (strcmp(newgenfs->fstype, genfs->fstype) == 0) {
1837 printk(KERN_ERR "SELinux: dup genfs fstype %s\n",
1838 newgenfs->fstype);
1839 goto out;
1840 }
1841 if (strcmp(newgenfs->fstype, genfs->fstype) < 0)
1842 break;
1843 }
1844 newgenfs->next = genfs;
1845 if (genfs_p)
1846 genfs_p->next = newgenfs;
1847 else
1848 p->genfs = newgenfs;
1849 genfs = newgenfs;
1850 newgenfs = NULL;
1851
1852 rc = next_entry(buf, fp, sizeof(u32));
1853 if (rc)
1854 goto out;
1855
1856 nel2 = le32_to_cpu(buf[0]);
1857 for (j = 0; j < nel2; j++) {
1858 rc = next_entry(buf, fp, sizeof(u32));
1859 if (rc)
1860 goto out;
1861 len = le32_to_cpu(buf[0]);
1862
1863 rc = -ENOMEM;
1864 newc = kzalloc(sizeof(*newc), GFP_KERNEL);
1865 if (!newc)
1866 goto out;
1867
1868 rc = -ENOMEM;
1869 newc->u.name = kmalloc(len + 1, GFP_KERNEL);
1870 if (!newc->u.name)
1871 goto out;
1872
1873 rc = next_entry(newc->u.name, fp, len);
1874 if (rc)
1875 goto out;
1876 newc->u.name[len] = 0;
1877
1878 rc = next_entry(buf, fp, sizeof(u32));
1879 if (rc)
1880 goto out;
1881
1882 newc->v.sclass = le32_to_cpu(buf[0]);
1883 rc = context_read_and_validate(&newc->context[0], p, fp);
1884 if (rc)
1885 goto out;
1886
1887 for (l = NULL, c = genfs->head; c;
1888 l = c, c = c->next) {
1889 rc = -EINVAL;
1890 if (!strcmp(newc->u.name, c->u.name) &&
1891 (!c->v.sclass || !newc->v.sclass ||
1892 newc->v.sclass == c->v.sclass)) {
1893 printk(KERN_ERR "SELinux: dup genfs entry (%s,%s)\n",
1894 genfs->fstype, c->u.name);
1895 goto out;
1896 }
1897 len = strlen(newc->u.name);
1898 len2 = strlen(c->u.name);
1899 if (len > len2)
1900 break;
1901 }
1902
1903 newc->next = c;
1904 if (l)
1905 l->next = newc;
1906 else
1907 genfs->head = newc;
1908 newc = NULL;
1909 }
1910 }
1911 rc = 0;
1912out:
1913 if (newgenfs)
1914 kfree(newgenfs->fstype);
1915 kfree(newgenfs);
1916 ocontext_destroy(newc, OCON_FSUSE);
1917
1918 return rc;
1919}
1920
Eric Paris692a8a22010-07-21 12:51:03 -04001921static int ocontext_read(struct policydb *p, struct policydb_compat_info *info,
1922 void *fp)
1923{
1924 int i, j, rc;
1925 u32 nel, len;
1926 __le32 buf[3];
1927 struct ocontext *l, *c;
1928 u32 nodebuf[8];
1929
1930 for (i = 0; i < info->ocon_num; i++) {
1931 rc = next_entry(buf, fp, sizeof(u32));
1932 if (rc)
1933 goto out;
1934 nel = le32_to_cpu(buf[0]);
1935
1936 l = NULL;
1937 for (j = 0; j < nel; j++) {
1938 rc = -ENOMEM;
1939 c = kzalloc(sizeof(*c), GFP_KERNEL);
1940 if (!c)
1941 goto out;
1942 if (l)
1943 l->next = c;
1944 else
1945 p->ocontexts[i] = c;
1946 l = c;
1947
1948 switch (i) {
1949 case OCON_ISID:
1950 rc = next_entry(buf, fp, sizeof(u32));
1951 if (rc)
1952 goto out;
1953
1954 c->sid[0] = le32_to_cpu(buf[0]);
1955 rc = context_read_and_validate(&c->context[0], p, fp);
1956 if (rc)
1957 goto out;
1958 break;
1959 case OCON_FS:
1960 case OCON_NETIF:
1961 rc = next_entry(buf, fp, sizeof(u32));
1962 if (rc)
1963 goto out;
1964 len = le32_to_cpu(buf[0]);
1965
1966 rc = -ENOMEM;
1967 c->u.name = kmalloc(len + 1, GFP_KERNEL);
1968 if (!c->u.name)
1969 goto out;
1970
1971 rc = next_entry(c->u.name, fp, len);
1972 if (rc)
1973 goto out;
1974
1975 c->u.name[len] = 0;
1976 rc = context_read_and_validate(&c->context[0], p, fp);
1977 if (rc)
1978 goto out;
1979 rc = context_read_and_validate(&c->context[1], p, fp);
1980 if (rc)
1981 goto out;
1982 break;
1983 case OCON_PORT:
1984 rc = next_entry(buf, fp, sizeof(u32)*3);
1985 if (rc)
1986 goto out;
1987 c->u.port.protocol = le32_to_cpu(buf[0]);
1988 c->u.port.low_port = le32_to_cpu(buf[1]);
1989 c->u.port.high_port = le32_to_cpu(buf[2]);
1990 rc = context_read_and_validate(&c->context[0], p, fp);
1991 if (rc)
1992 goto out;
1993 break;
1994 case OCON_NODE:
1995 rc = next_entry(nodebuf, fp, sizeof(u32) * 2);
1996 if (rc)
1997 goto out;
1998 c->u.node.addr = nodebuf[0]; /* network order */
1999 c->u.node.mask = nodebuf[1]; /* network order */
2000 rc = context_read_and_validate(&c->context[0], p, fp);
2001 if (rc)
2002 goto out;
2003 break;
2004 case OCON_FSUSE:
2005 rc = next_entry(buf, fp, sizeof(u32)*2);
2006 if (rc)
2007 goto out;
2008
2009 rc = -EINVAL;
2010 c->v.behavior = le32_to_cpu(buf[0]);
2011 if (c->v.behavior > SECURITY_FS_USE_NONE)
2012 goto out;
2013
2014 rc = -ENOMEM;
2015 len = le32_to_cpu(buf[1]);
2016 c->u.name = kmalloc(len + 1, GFP_KERNEL);
2017 if (!c->u.name)
2018 goto out;
2019
2020 rc = next_entry(c->u.name, fp, len);
2021 if (rc)
2022 goto out;
2023 c->u.name[len] = 0;
2024 rc = context_read_and_validate(&c->context[0], p, fp);
2025 if (rc)
2026 goto out;
2027 break;
2028 case OCON_NODE6: {
2029 int k;
2030
2031 rc = next_entry(nodebuf, fp, sizeof(u32) * 8);
2032 if (rc)
2033 goto out;
2034 for (k = 0; k < 4; k++)
2035 c->u.node6.addr[k] = nodebuf[k];
2036 for (k = 0; k < 4; k++)
2037 c->u.node6.mask[k] = nodebuf[k+4];
2038 rc = context_read_and_validate(&c->context[0], p, fp);
2039 if (rc)
2040 goto out;
2041 break;
2042 }
2043 }
2044 }
2045 }
2046 rc = 0;
2047out:
2048 return rc;
2049}
2050
Linus Torvalds1da177e2005-04-16 15:20:36 -07002051/*
2052 * Read the configuration data from a policy database binary
2053 * representation file into a policy database structure.
2054 */
2055int policydb_read(struct policydb *p, void *fp)
2056{
2057 struct role_allow *ra, *lra;
2058 struct role_trans *tr, *ltr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002059 int i, j, rc;
Stephen Smalley59dbd1b2008-06-05 09:48:51 -04002060 __le32 buf[4];
Eric Parisd1b43542010-07-21 12:50:57 -04002061 u32 len, nprim, nel;
2062
Linus Torvalds1da177e2005-04-16 15:20:36 -07002063 char *policydb_str;
2064 struct policydb_compat_info *info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002065
Linus Torvalds1da177e2005-04-16 15:20:36 -07002066 rc = policydb_init(p);
2067 if (rc)
2068 goto out;
2069
2070 /* Read the magic number and string length. */
Eric Paris2ced3df2008-04-17 13:37:12 -04002071 rc = next_entry(buf, fp, sizeof(u32) * 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002072 if (rc < 0)
2073 goto bad;
2074
Alexey Dobriyanb5bf6c52005-09-03 15:55:17 -07002075 if (le32_to_cpu(buf[0]) != POLICYDB_MAGIC) {
James Morris454d9722008-02-26 20:42:02 +11002076 printk(KERN_ERR "SELinux: policydb magic number 0x%x does "
Linus Torvalds1da177e2005-04-16 15:20:36 -07002077 "not match expected magic number 0x%x\n",
Alexey Dobriyanb5bf6c52005-09-03 15:55:17 -07002078 le32_to_cpu(buf[0]), POLICYDB_MAGIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002079 goto bad;
2080 }
2081
Alexey Dobriyanb5bf6c52005-09-03 15:55:17 -07002082 len = le32_to_cpu(buf[1]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002083 if (len != strlen(POLICYDB_STRING)) {
James Morris454d9722008-02-26 20:42:02 +11002084 printk(KERN_ERR "SELinux: policydb string length %d does not "
Linus Torvalds1da177e2005-04-16 15:20:36 -07002085 "match expected length %Zu\n",
2086 len, strlen(POLICYDB_STRING));
2087 goto bad;
2088 }
Eric Paris2ced3df2008-04-17 13:37:12 -04002089 policydb_str = kmalloc(len + 1, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002090 if (!policydb_str) {
James Morris454d9722008-02-26 20:42:02 +11002091 printk(KERN_ERR "SELinux: unable to allocate memory for policydb "
Linus Torvalds1da177e2005-04-16 15:20:36 -07002092 "string of length %d\n", len);
2093 rc = -ENOMEM;
2094 goto bad;
2095 }
2096 rc = next_entry(policydb_str, fp, len);
2097 if (rc < 0) {
James Morris454d9722008-02-26 20:42:02 +11002098 printk(KERN_ERR "SELinux: truncated policydb string identifier\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002099 kfree(policydb_str);
2100 goto bad;
2101 }
Vesa-Matti J Karidf4ea862008-07-20 23:57:01 +03002102 policydb_str[len] = '\0';
Linus Torvalds1da177e2005-04-16 15:20:36 -07002103 if (strcmp(policydb_str, POLICYDB_STRING)) {
James Morris454d9722008-02-26 20:42:02 +11002104 printk(KERN_ERR "SELinux: policydb string %s does not match "
Linus Torvalds1da177e2005-04-16 15:20:36 -07002105 "my string %s\n", policydb_str, POLICYDB_STRING);
2106 kfree(policydb_str);
2107 goto bad;
2108 }
2109 /* Done with policydb_str. */
2110 kfree(policydb_str);
2111 policydb_str = NULL;
2112
Guido Trentalancia0719aaf2010-02-03 16:40:20 +01002113 /* Read the version and table sizes. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002114 rc = next_entry(buf, fp, sizeof(u32)*4);
2115 if (rc < 0)
2116 goto bad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002117
Alexey Dobriyanb5bf6c52005-09-03 15:55:17 -07002118 p->policyvers = le32_to_cpu(buf[0]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002119 if (p->policyvers < POLICYDB_VERSION_MIN ||
2120 p->policyvers > POLICYDB_VERSION_MAX) {
James Morris454d9722008-02-26 20:42:02 +11002121 printk(KERN_ERR "SELinux: policydb version %d does not match "
Eric Paris2ced3df2008-04-17 13:37:12 -04002122 "my version range %d-%d\n",
2123 le32_to_cpu(buf[0]), POLICYDB_VERSION_MIN, POLICYDB_VERSION_MAX);
2124 goto bad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002125 }
2126
Alexey Dobriyanb5bf6c52005-09-03 15:55:17 -07002127 if ((le32_to_cpu(buf[1]) & POLICYDB_CONFIG_MLS)) {
Guido Trentalancia0719aaf2010-02-03 16:40:20 +01002128 p->mls_enabled = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002129
2130 if (p->policyvers < POLICYDB_VERSION_MLS) {
Eric Paris744ba352008-04-17 11:52:44 -04002131 printk(KERN_ERR "SELinux: security policydb version %d "
2132 "(MLS) not backwards compatible\n",
2133 p->policyvers);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002134 goto bad;
2135 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002136 }
Eric Paris3f120702007-09-21 14:37:10 -04002137 p->reject_unknown = !!(le32_to_cpu(buf[1]) & REJECT_UNKNOWN);
2138 p->allow_unknown = !!(le32_to_cpu(buf[1]) & ALLOW_UNKNOWN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002139
Paul Moore3bb56b22008-01-29 08:38:19 -05002140 if (p->policyvers >= POLICYDB_VERSION_POLCAP &&
2141 ebitmap_read(&p->policycaps, fp) != 0)
2142 goto bad;
2143
Eric Paris64dbf072008-03-31 12:17:33 +11002144 if (p->policyvers >= POLICYDB_VERSION_PERMISSIVE &&
2145 ebitmap_read(&p->permissive_map, fp) != 0)
2146 goto bad;
2147
Linus Torvalds1da177e2005-04-16 15:20:36 -07002148 info = policydb_lookup_compat(p->policyvers);
2149 if (!info) {
James Morris454d9722008-02-26 20:42:02 +11002150 printk(KERN_ERR "SELinux: unable to find policy compat info "
Linus Torvalds1da177e2005-04-16 15:20:36 -07002151 "for version %d\n", p->policyvers);
2152 goto bad;
2153 }
2154
Alexey Dobriyanb5bf6c52005-09-03 15:55:17 -07002155 if (le32_to_cpu(buf[2]) != info->sym_num ||
2156 le32_to_cpu(buf[3]) != info->ocon_num) {
James Morris454d9722008-02-26 20:42:02 +11002157 printk(KERN_ERR "SELinux: policydb table sizes (%d,%d) do "
Alexey Dobriyanb5bf6c52005-09-03 15:55:17 -07002158 "not match mine (%d,%d)\n", le32_to_cpu(buf[2]),
2159 le32_to_cpu(buf[3]),
Linus Torvalds1da177e2005-04-16 15:20:36 -07002160 info->sym_num, info->ocon_num);
2161 goto bad;
2162 }
2163
2164 for (i = 0; i < info->sym_num; i++) {
2165 rc = next_entry(buf, fp, sizeof(u32)*2);
2166 if (rc < 0)
2167 goto bad;
2168 nprim = le32_to_cpu(buf[0]);
2169 nel = le32_to_cpu(buf[1]);
2170 for (j = 0; j < nel; j++) {
2171 rc = read_f[i](p, p->symtab[i].table, fp);
2172 if (rc)
2173 goto bad;
2174 }
2175
2176 p->symtab[i].nprim = nprim;
2177 }
2178
Stephen Smalley45e54212007-11-07 10:08:00 -05002179 rc = avtab_read(&p->te_avtab, fp, p);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002180 if (rc)
2181 goto bad;
2182
2183 if (p->policyvers >= POLICYDB_VERSION_BOOL) {
2184 rc = cond_read_list(p, fp);
2185 if (rc)
2186 goto bad;
2187 }
2188
2189 rc = next_entry(buf, fp, sizeof(u32));
2190 if (rc < 0)
2191 goto bad;
2192 nel = le32_to_cpu(buf[0]);
2193 ltr = NULL;
2194 for (i = 0; i < nel; i++) {
James Morris89d155e2005-10-30 14:59:21 -08002195 tr = kzalloc(sizeof(*tr), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002196 if (!tr) {
2197 rc = -ENOMEM;
2198 goto bad;
2199 }
Eric Paris2ced3df2008-04-17 13:37:12 -04002200 if (ltr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002201 ltr->next = tr;
Eric Paris2ced3df2008-04-17 13:37:12 -04002202 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002203 p->role_tr = tr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002204 rc = next_entry(buf, fp, sizeof(u32)*3);
2205 if (rc < 0)
2206 goto bad;
2207 tr->role = le32_to_cpu(buf[0]);
2208 tr->type = le32_to_cpu(buf[1]);
2209 tr->new_role = le32_to_cpu(buf[2]);
Stephen Smalley45e54212007-11-07 10:08:00 -05002210 if (!policydb_role_isvalid(p, tr->role) ||
2211 !policydb_type_isvalid(p, tr->type) ||
2212 !policydb_role_isvalid(p, tr->new_role)) {
2213 rc = -EINVAL;
2214 goto bad;
2215 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002216 ltr = tr;
2217 }
2218
2219 rc = next_entry(buf, fp, sizeof(u32));
2220 if (rc < 0)
2221 goto bad;
2222 nel = le32_to_cpu(buf[0]);
2223 lra = NULL;
2224 for (i = 0; i < nel; i++) {
James Morris89d155e2005-10-30 14:59:21 -08002225 ra = kzalloc(sizeof(*ra), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002226 if (!ra) {
2227 rc = -ENOMEM;
2228 goto bad;
2229 }
Eric Paris2ced3df2008-04-17 13:37:12 -04002230 if (lra)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002231 lra->next = ra;
Eric Paris2ced3df2008-04-17 13:37:12 -04002232 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002233 p->role_allow = ra;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002234 rc = next_entry(buf, fp, sizeof(u32)*2);
2235 if (rc < 0)
2236 goto bad;
2237 ra->role = le32_to_cpu(buf[0]);
2238 ra->new_role = le32_to_cpu(buf[1]);
Stephen Smalley45e54212007-11-07 10:08:00 -05002239 if (!policydb_role_isvalid(p, ra->role) ||
2240 !policydb_role_isvalid(p, ra->new_role)) {
2241 rc = -EINVAL;
2242 goto bad;
2243 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002244 lra = ra;
2245 }
2246
2247 rc = policydb_index_classes(p);
2248 if (rc)
2249 goto bad;
2250
2251 rc = policydb_index_others(p);
2252 if (rc)
2253 goto bad;
2254
Stephen Smalleyc6d3aaa2009-09-30 13:37:50 -04002255 p->process_class = string_to_security_class(p, "process");
2256 if (!p->process_class)
2257 goto bad;
2258 p->process_trans_perms = string_to_av_perm(p, p->process_class,
2259 "transition");
2260 p->process_trans_perms |= string_to_av_perm(p, p->process_class,
2261 "dyntransition");
2262 if (!p->process_trans_perms)
2263 goto bad;
2264
Eric Paris692a8a22010-07-21 12:51:03 -04002265 rc = ocontext_read(p, info, fp);
2266 if (rc)
2267 goto bad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002268
Eric Parisd1b43542010-07-21 12:50:57 -04002269 rc = genfs_read(p, fp);
2270 if (rc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002271 goto bad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002272
Eric Paris9ee0c822010-06-11 12:37:05 -04002273 rc = range_read(p, fp);
2274 if (rc)
2275 goto bad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002276
Eric Paris6371dcd2010-07-29 23:02:34 -04002277 rc = -ENOMEM;
2278 p->type_attr_map_array = flex_array_alloc(sizeof(struct ebitmap),
2279 p->p_types.nprim,
2280 GFP_KERNEL | __GFP_ZERO);
2281 if (!p->type_attr_map_array)
2282 goto bad;
2283
2284 /* preallocate so we don't have to worry about the put ever failing */
2285 rc = flex_array_prealloc(p->type_attr_map_array, 0, p->p_types.nprim - 1,
2286 GFP_KERNEL | __GFP_ZERO);
2287 if (rc)
Stephen Smalley782ebb92005-09-03 15:55:16 -07002288 goto bad;
2289
2290 for (i = 0; i < p->p_types.nprim; i++) {
Eric Paris6371dcd2010-07-29 23:02:34 -04002291 struct ebitmap *e = flex_array_get(p->type_attr_map_array, i);
2292
2293 BUG_ON(!e);
2294 ebitmap_init(e);
Stephen Smalley782ebb92005-09-03 15:55:16 -07002295 if (p->policyvers >= POLICYDB_VERSION_AVTAB) {
Eric Paris6371dcd2010-07-29 23:02:34 -04002296 rc = ebitmap_read(e, fp);
2297 if (rc)
Stephen Smalley782ebb92005-09-03 15:55:16 -07002298 goto bad;
2299 }
2300 /* add the type itself as the degenerate case */
Eric Paris6371dcd2010-07-29 23:02:34 -04002301 rc = ebitmap_set_bit(e, i, 1);
2302 if (rc)
2303 goto bad;
Stephen Smalley782ebb92005-09-03 15:55:16 -07002304 }
2305
KaiGai Koheid9250de2008-08-28 16:35:57 +09002306 rc = policydb_bounds_sanity_check(p);
2307 if (rc)
2308 goto bad;
2309
Linus Torvalds1da177e2005-04-16 15:20:36 -07002310 rc = 0;
2311out:
2312 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002313bad:
2314 if (!rc)
2315 rc = -EINVAL;
2316 policydb_destroy(p);
2317 goto out;
2318}