blob: 23c6e53c102c1c5b8ff6265e1c9bc77e5671b4a0 [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>
Linus Torvalds1da177e2005-04-16 15:20:36 -070034#include "security.h"
35
36#include "policydb.h"
37#include "conditional.h"
38#include "mls.h"
39
40#define _DEBUG_HASHES
41
42#ifdef DEBUG_HASHES
43static char *symtab_name[SYM_NUM] = {
44 "common prefixes",
45 "classes",
46 "roles",
47 "types",
48 "users",
49 "bools",
50 "levels",
51 "categories",
52};
53#endif
54
Linus Torvalds1da177e2005-04-16 15:20:36 -070055static unsigned int symtab_sizes[SYM_NUM] = {
56 2,
57 32,
58 16,
59 512,
60 128,
61 16,
62 16,
63 16,
64};
65
66struct policydb_compat_info {
67 int version;
68 int sym_num;
69 int ocon_num;
70};
71
72/* These need to be updated if SYM_NUM or OCON_NUM changes */
73static struct policydb_compat_info policydb_compat[] = {
74 {
Eric Paris2ced3df2008-04-17 13:37:12 -040075 .version = POLICYDB_VERSION_BASE,
76 .sym_num = SYM_NUM - 3,
77 .ocon_num = OCON_NUM - 1,
Linus Torvalds1da177e2005-04-16 15:20:36 -070078 },
79 {
Eric Paris2ced3df2008-04-17 13:37:12 -040080 .version = POLICYDB_VERSION_BOOL,
81 .sym_num = SYM_NUM - 2,
82 .ocon_num = OCON_NUM - 1,
Linus Torvalds1da177e2005-04-16 15:20:36 -070083 },
84 {
Eric Paris2ced3df2008-04-17 13:37:12 -040085 .version = POLICYDB_VERSION_IPV6,
86 .sym_num = SYM_NUM - 2,
87 .ocon_num = OCON_NUM,
Linus Torvalds1da177e2005-04-16 15:20:36 -070088 },
89 {
Eric Paris2ced3df2008-04-17 13:37:12 -040090 .version = POLICYDB_VERSION_NLCLASS,
91 .sym_num = SYM_NUM - 2,
92 .ocon_num = OCON_NUM,
Linus Torvalds1da177e2005-04-16 15:20:36 -070093 },
94 {
Eric Paris2ced3df2008-04-17 13:37:12 -040095 .version = POLICYDB_VERSION_MLS,
96 .sym_num = SYM_NUM,
97 .ocon_num = OCON_NUM,
Linus Torvalds1da177e2005-04-16 15:20:36 -070098 },
Stephen Smalley782ebb92005-09-03 15:55:16 -070099 {
Eric Paris2ced3df2008-04-17 13:37:12 -0400100 .version = POLICYDB_VERSION_AVTAB,
101 .sym_num = SYM_NUM,
102 .ocon_num = OCON_NUM,
Stephen Smalley782ebb92005-09-03 15:55:16 -0700103 },
Darrel Goeddelf3f87712006-09-25 23:31:59 -0700104 {
Eric Paris2ced3df2008-04-17 13:37:12 -0400105 .version = POLICYDB_VERSION_RANGETRANS,
106 .sym_num = SYM_NUM,
107 .ocon_num = OCON_NUM,
Darrel Goeddelf3f87712006-09-25 23:31:59 -0700108 },
Paul Moore3bb56b22008-01-29 08:38:19 -0500109 {
110 .version = POLICYDB_VERSION_POLCAP,
111 .sym_num = SYM_NUM,
112 .ocon_num = OCON_NUM,
Eric Paris64dbf072008-03-31 12:17:33 +1100113 },
114 {
115 .version = POLICYDB_VERSION_PERMISSIVE,
116 .sym_num = SYM_NUM,
117 .ocon_num = OCON_NUM,
KaiGai Koheid9250de2008-08-28 16:35:57 +0900118 },
119 {
120 .version = POLICYDB_VERSION_BOUNDARY,
121 .sym_num = SYM_NUM,
122 .ocon_num = OCON_NUM,
123 },
Linus Torvalds1da177e2005-04-16 15:20:36 -0700124};
125
126static struct policydb_compat_info *policydb_lookup_compat(int version)
127{
128 int i;
129 struct policydb_compat_info *info = NULL;
130
Tobias Klauser32725ad2006-01-06 00:11:23 -0800131 for (i = 0; i < ARRAY_SIZE(policydb_compat); i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700132 if (policydb_compat[i].version == version) {
133 info = &policydb_compat[i];
134 break;
135 }
136 }
137 return info;
138}
139
140/*
141 * Initialize the role table.
142 */
143static int roles_init(struct policydb *p)
144{
145 char *key = NULL;
146 int rc;
147 struct role_datum *role;
148
James Morris89d155e2005-10-30 14:59:21 -0800149 role = kzalloc(sizeof(*role), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700150 if (!role) {
151 rc = -ENOMEM;
152 goto out;
153 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700154 role->value = ++p->p_roles.nprim;
155 if (role->value != OBJECT_R_VAL) {
156 rc = -EINVAL;
157 goto out_free_role;
158 }
Eric Paris2ced3df2008-04-17 13:37:12 -0400159 key = kmalloc(strlen(OBJECT_R)+1, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700160 if (!key) {
161 rc = -ENOMEM;
162 goto out_free_role;
163 }
164 strcpy(key, OBJECT_R);
165 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;
188 return (key1->source_type != key2->source_type ||
189 key1->target_type != key2->target_type ||
190 key1->target_class != key2->target_class);
191}
192
Linus Torvalds1da177e2005-04-16 15:20:36 -0700193/*
194 * Initialize a policy database structure.
195 */
196static int policydb_init(struct policydb *p)
197{
198 int i, rc;
199
200 memset(p, 0, sizeof(*p));
201
202 for (i = 0; i < SYM_NUM; i++) {
203 rc = symtab_init(&p->symtab[i], symtab_sizes[i]);
204 if (rc)
205 goto out_free_symtab;
206 }
207
208 rc = avtab_init(&p->te_avtab);
209 if (rc)
210 goto out_free_symtab;
211
212 rc = roles_init(p);
213 if (rc)
Yuichi Nakamura3232c112007-08-24 11:55:11 +0900214 goto out_free_symtab;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700215
216 rc = cond_policydb_init(p);
217 if (rc)
Yuichi Nakamura3232c112007-08-24 11:55:11 +0900218 goto out_free_symtab;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700219
Stephen Smalley2f3e82d2010-01-07 15:55:16 -0500220 p->range_tr = hashtab_create(rangetr_hash, rangetr_cmp, 256);
221 if (!p->range_tr)
222 goto out_free_symtab;
223
Paul Moore3bb56b22008-01-29 08:38:19 -0500224 ebitmap_init(&p->policycaps);
Eric Paris64dbf072008-03-31 12:17:33 +1100225 ebitmap_init(&p->permissive_map);
Paul Moore3bb56b22008-01-29 08:38:19 -0500226
Linus Torvalds1da177e2005-04-16 15:20:36 -0700227out:
228 return rc;
229
Linus Torvalds1da177e2005-04-16 15:20:36 -0700230out_free_symtab:
231 for (i = 0; i < SYM_NUM; i++)
232 hashtab_destroy(p->symtab[i].table);
233 goto out;
234}
235
236/*
237 * The following *_index functions are used to
238 * define the val_to_name and val_to_struct arrays
239 * in a policy database structure. The val_to_name
240 * arrays are used when converting security context
241 * structures into string representations. The
242 * val_to_struct arrays are used when the attributes
243 * of a class, role, or user are needed.
244 */
245
246static int common_index(void *key, void *datum, void *datap)
247{
248 struct policydb *p;
249 struct common_datum *comdatum;
250
251 comdatum = datum;
252 p = datap;
253 if (!comdatum->value || comdatum->value > p->p_commons.nprim)
254 return -EINVAL;
255 p->p_common_val_to_name[comdatum->value - 1] = key;
256 return 0;
257}
258
259static int class_index(void *key, void *datum, void *datap)
260{
261 struct policydb *p;
262 struct class_datum *cladatum;
263
264 cladatum = datum;
265 p = datap;
266 if (!cladatum->value || cladatum->value > p->p_classes.nprim)
267 return -EINVAL;
268 p->p_class_val_to_name[cladatum->value - 1] = key;
269 p->class_val_to_struct[cladatum->value - 1] = cladatum;
270 return 0;
271}
272
273static int role_index(void *key, void *datum, void *datap)
274{
275 struct policydb *p;
276 struct role_datum *role;
277
278 role = datum;
279 p = datap;
KaiGai Koheid9250de2008-08-28 16:35:57 +0900280 if (!role->value
281 || role->value > p->p_roles.nprim
282 || role->bounds > p->p_roles.nprim)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700283 return -EINVAL;
284 p->p_role_val_to_name[role->value - 1] = key;
285 p->role_val_to_struct[role->value - 1] = role;
286 return 0;
287}
288
289static int type_index(void *key, void *datum, void *datap)
290{
291 struct policydb *p;
292 struct type_datum *typdatum;
293
294 typdatum = datum;
295 p = datap;
296
297 if (typdatum->primary) {
KaiGai Koheid9250de2008-08-28 16:35:57 +0900298 if (!typdatum->value
299 || typdatum->value > p->p_types.nprim
300 || typdatum->bounds > p->p_types.nprim)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700301 return -EINVAL;
302 p->p_type_val_to_name[typdatum->value - 1] = key;
KaiGai Koheid9250de2008-08-28 16:35:57 +0900303 p->type_val_to_struct[typdatum->value - 1] = typdatum;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700304 }
305
306 return 0;
307}
308
309static int user_index(void *key, void *datum, void *datap)
310{
311 struct policydb *p;
312 struct user_datum *usrdatum;
313
314 usrdatum = datum;
315 p = datap;
KaiGai Koheid9250de2008-08-28 16:35:57 +0900316 if (!usrdatum->value
317 || usrdatum->value > p->p_users.nprim
318 || usrdatum->bounds > p->p_users.nprim)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700319 return -EINVAL;
320 p->p_user_val_to_name[usrdatum->value - 1] = key;
321 p->user_val_to_struct[usrdatum->value - 1] = usrdatum;
322 return 0;
323}
324
325static int sens_index(void *key, void *datum, void *datap)
326{
327 struct policydb *p;
328 struct level_datum *levdatum;
329
330 levdatum = datum;
331 p = datap;
332
333 if (!levdatum->isalias) {
334 if (!levdatum->level->sens ||
335 levdatum->level->sens > p->p_levels.nprim)
336 return -EINVAL;
337 p->p_sens_val_to_name[levdatum->level->sens - 1] = key;
338 }
339
340 return 0;
341}
342
343static int cat_index(void *key, void *datum, void *datap)
344{
345 struct policydb *p;
346 struct cat_datum *catdatum;
347
348 catdatum = datum;
349 p = datap;
350
351 if (!catdatum->isalias) {
352 if (!catdatum->value || catdatum->value > p->p_cats.nprim)
353 return -EINVAL;
354 p->p_cat_val_to_name[catdatum->value - 1] = key;
355 }
356
357 return 0;
358}
359
360static int (*index_f[SYM_NUM]) (void *key, void *datum, void *datap) =
361{
362 common_index,
363 class_index,
364 role_index,
365 type_index,
366 user_index,
367 cond_index_bool,
368 sens_index,
369 cat_index,
370};
371
372/*
373 * Define the common val_to_name array and the class
374 * val_to_name and val_to_struct arrays in a policy
375 * database structure.
376 *
377 * Caller must clean up upon failure.
378 */
379static int policydb_index_classes(struct policydb *p)
380{
381 int rc;
382
383 p->p_common_val_to_name =
384 kmalloc(p->p_commons.nprim * sizeof(char *), GFP_KERNEL);
385 if (!p->p_common_val_to_name) {
386 rc = -ENOMEM;
387 goto out;
388 }
389
390 rc = hashtab_map(p->p_commons.table, common_index, p);
391 if (rc)
392 goto out;
393
394 p->class_val_to_struct =
395 kmalloc(p->p_classes.nprim * sizeof(*(p->class_val_to_struct)), GFP_KERNEL);
396 if (!p->class_val_to_struct) {
397 rc = -ENOMEM;
398 goto out;
399 }
400
401 p->p_class_val_to_name =
402 kmalloc(p->p_classes.nprim * sizeof(char *), GFP_KERNEL);
403 if (!p->p_class_val_to_name) {
404 rc = -ENOMEM;
405 goto out;
406 }
407
408 rc = hashtab_map(p->p_classes.table, class_index, p);
409out:
410 return rc;
411}
412
413#ifdef DEBUG_HASHES
414static void symtab_hash_eval(struct symtab *s)
415{
416 int i;
417
418 for (i = 0; i < SYM_NUM; i++) {
419 struct hashtab *h = s[i].table;
420 struct hashtab_info info;
421
422 hashtab_stat(h, &info);
Eric Paris744ba352008-04-17 11:52:44 -0400423 printk(KERN_DEBUG "SELinux: %s: %d entries and %d/%d buckets used, "
Linus Torvalds1da177e2005-04-16 15:20:36 -0700424 "longest chain length %d\n", symtab_name[i], h->nel,
425 info.slots_used, h->size, info.max_chain_len);
426 }
427}
Stephen Smalley2f3e82d2010-01-07 15:55:16 -0500428
429static void rangetr_hash_eval(struct hashtab *h)
430{
431 struct hashtab_info info;
432
433 hashtab_stat(h, &info);
434 printk(KERN_DEBUG "SELinux: rangetr: %d entries and %d/%d buckets used, "
435 "longest chain length %d\n", h->nel,
436 info.slots_used, h->size, info.max_chain_len);
437}
438#else
439static inline void rangetr_hash_eval(struct hashtab *h)
440{
441}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700442#endif
443
444/*
445 * Define the other val_to_name and val_to_struct arrays
446 * in a policy database structure.
447 *
448 * Caller must clean up on failure.
449 */
450static int policydb_index_others(struct policydb *p)
451{
452 int i, rc = 0;
453
James Morris454d9722008-02-26 20:42:02 +1100454 printk(KERN_DEBUG "SELinux: %d users, %d roles, %d types, %d bools",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700455 p->p_users.nprim, p->p_roles.nprim, p->p_types.nprim, p->p_bools.nprim);
Guido Trentalancia0719aaf52010-02-03 16:40:20 +0100456 if (p->mls_enabled)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700457 printk(", %d sens, %d cats", p->p_levels.nprim,
458 p->p_cats.nprim);
459 printk("\n");
460
James Morris454d9722008-02-26 20:42:02 +1100461 printk(KERN_DEBUG "SELinux: %d classes, %d rules\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700462 p->p_classes.nprim, p->te_avtab.nel);
463
464#ifdef DEBUG_HASHES
465 avtab_hash_eval(&p->te_avtab, "rules");
466 symtab_hash_eval(p->symtab);
467#endif
468
469 p->role_val_to_struct =
470 kmalloc(p->p_roles.nprim * sizeof(*(p->role_val_to_struct)),
Eric Paris2ced3df2008-04-17 13:37:12 -0400471 GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700472 if (!p->role_val_to_struct) {
473 rc = -ENOMEM;
474 goto out;
475 }
476
477 p->user_val_to_struct =
478 kmalloc(p->p_users.nprim * sizeof(*(p->user_val_to_struct)),
Eric Paris2ced3df2008-04-17 13:37:12 -0400479 GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700480 if (!p->user_val_to_struct) {
481 rc = -ENOMEM;
482 goto out;
483 }
484
KaiGai Koheid9250de2008-08-28 16:35:57 +0900485 p->type_val_to_struct =
486 kmalloc(p->p_types.nprim * sizeof(*(p->type_val_to_struct)),
487 GFP_KERNEL);
488 if (!p->type_val_to_struct) {
489 rc = -ENOMEM;
490 goto out;
491 }
492
Linus Torvalds1da177e2005-04-16 15:20:36 -0700493 if (cond_init_bool_indexes(p)) {
494 rc = -ENOMEM;
495 goto out;
496 }
497
498 for (i = SYM_ROLES; i < SYM_NUM; i++) {
499 p->sym_val_to_name[i] =
500 kmalloc(p->symtab[i].nprim * sizeof(char *), GFP_KERNEL);
501 if (!p->sym_val_to_name[i]) {
502 rc = -ENOMEM;
503 goto out;
504 }
505 rc = hashtab_map(p->symtab[i].table, index_f[i], p);
506 if (rc)
507 goto out;
508 }
509
510out:
511 return rc;
512}
513
514/*
515 * The following *_destroy functions are used to
516 * free any memory allocated for each kind of
517 * symbol data in the policy database.
518 */
519
520static int perm_destroy(void *key, void *datum, void *p)
521{
522 kfree(key);
523 kfree(datum);
524 return 0;
525}
526
527static int common_destroy(void *key, void *datum, void *p)
528{
529 struct common_datum *comdatum;
530
531 kfree(key);
532 comdatum = datum;
533 hashtab_map(comdatum->permissions.table, perm_destroy, NULL);
534 hashtab_destroy(comdatum->permissions.table);
535 kfree(datum);
536 return 0;
537}
538
James Morris6cbda6b2006-11-29 16:50:27 -0500539static int cls_destroy(void *key, void *datum, void *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700540{
541 struct class_datum *cladatum;
542 struct constraint_node *constraint, *ctemp;
543 struct constraint_expr *e, *etmp;
544
545 kfree(key);
546 cladatum = datum;
547 hashtab_map(cladatum->permissions.table, perm_destroy, NULL);
548 hashtab_destroy(cladatum->permissions.table);
549 constraint = cladatum->constraints;
550 while (constraint) {
551 e = constraint->expr;
552 while (e) {
553 ebitmap_destroy(&e->names);
554 etmp = e;
555 e = e->next;
556 kfree(etmp);
557 }
558 ctemp = constraint;
559 constraint = constraint->next;
560 kfree(ctemp);
561 }
562
563 constraint = cladatum->validatetrans;
564 while (constraint) {
565 e = constraint->expr;
566 while (e) {
567 ebitmap_destroy(&e->names);
568 etmp = e;
569 e = e->next;
570 kfree(etmp);
571 }
572 ctemp = constraint;
573 constraint = constraint->next;
574 kfree(ctemp);
575 }
576
577 kfree(cladatum->comkey);
578 kfree(datum);
579 return 0;
580}
581
582static int role_destroy(void *key, void *datum, void *p)
583{
584 struct role_datum *role;
585
586 kfree(key);
587 role = datum;
588 ebitmap_destroy(&role->dominates);
589 ebitmap_destroy(&role->types);
590 kfree(datum);
591 return 0;
592}
593
594static int type_destroy(void *key, void *datum, void *p)
595{
596 kfree(key);
597 kfree(datum);
598 return 0;
599}
600
601static int user_destroy(void *key, void *datum, void *p)
602{
603 struct user_datum *usrdatum;
604
605 kfree(key);
606 usrdatum = datum;
607 ebitmap_destroy(&usrdatum->roles);
608 ebitmap_destroy(&usrdatum->range.level[0].cat);
609 ebitmap_destroy(&usrdatum->range.level[1].cat);
610 ebitmap_destroy(&usrdatum->dfltlevel.cat);
611 kfree(datum);
612 return 0;
613}
614
615static int sens_destroy(void *key, void *datum, void *p)
616{
617 struct level_datum *levdatum;
618
619 kfree(key);
620 levdatum = datum;
621 ebitmap_destroy(&levdatum->level->cat);
622 kfree(levdatum->level);
623 kfree(datum);
624 return 0;
625}
626
627static int cat_destroy(void *key, void *datum, void *p)
628{
629 kfree(key);
630 kfree(datum);
631 return 0;
632}
633
634static int (*destroy_f[SYM_NUM]) (void *key, void *datum, void *datap) =
635{
636 common_destroy,
James Morris6cbda6b2006-11-29 16:50:27 -0500637 cls_destroy,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700638 role_destroy,
639 type_destroy,
640 user_destroy,
641 cond_destroy_bool,
642 sens_destroy,
643 cat_destroy,
644};
645
Stephen Smalley2f3e82d2010-01-07 15:55:16 -0500646static int range_tr_destroy(void *key, void *datum, void *p)
647{
648 struct mls_range *rt = datum;
649 kfree(key);
650 ebitmap_destroy(&rt->level[0].cat);
651 ebitmap_destroy(&rt->level[1].cat);
652 kfree(datum);
653 cond_resched();
654 return 0;
655}
656
Linus Torvalds1da177e2005-04-16 15:20:36 -0700657static void ocontext_destroy(struct ocontext *c, int i)
658{
659 context_destroy(&c->context[0]);
660 context_destroy(&c->context[1]);
661 if (i == OCON_ISID || i == OCON_FS ||
662 i == OCON_NETIF || i == OCON_FSUSE)
663 kfree(c->u.name);
664 kfree(c);
665}
666
667/*
668 * Free any memory allocated by a policy database structure.
669 */
670void policydb_destroy(struct policydb *p)
671{
672 struct ocontext *c, *ctmp;
673 struct genfs *g, *gtmp;
674 int i;
Stephen Smalley782ebb92005-09-03 15:55:16 -0700675 struct role_allow *ra, *lra = NULL;
676 struct role_trans *tr, *ltr = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700677
678 for (i = 0; i < SYM_NUM; i++) {
Eric Paris9dc99782007-06-04 17:41:22 -0400679 cond_resched();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700680 hashtab_map(p->symtab[i].table, destroy_f[i], NULL);
681 hashtab_destroy(p->symtab[i].table);
682 }
683
Jesper Juhl9a5f04b2005-06-25 14:58:51 -0700684 for (i = 0; i < SYM_NUM; i++)
685 kfree(p->sym_val_to_name[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700686
Jesper Juhl9a5f04b2005-06-25 14:58:51 -0700687 kfree(p->class_val_to_struct);
688 kfree(p->role_val_to_struct);
689 kfree(p->user_val_to_struct);
KaiGai Koheid9250de2008-08-28 16:35:57 +0900690 kfree(p->type_val_to_struct);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700691
692 avtab_destroy(&p->te_avtab);
693
694 for (i = 0; i < OCON_NUM; i++) {
Eric Paris9dc99782007-06-04 17:41:22 -0400695 cond_resched();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700696 c = p->ocontexts[i];
697 while (c) {
698 ctmp = c;
699 c = c->next;
Eric Paris2ced3df2008-04-17 13:37:12 -0400700 ocontext_destroy(ctmp, i);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700701 }
Chad Sellers6e8c7512006-10-06 16:09:52 -0400702 p->ocontexts[i] = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700703 }
704
705 g = p->genfs;
706 while (g) {
Eric Paris9dc99782007-06-04 17:41:22 -0400707 cond_resched();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700708 kfree(g->fstype);
709 c = g->head;
710 while (c) {
711 ctmp = c;
712 c = c->next;
Eric Paris2ced3df2008-04-17 13:37:12 -0400713 ocontext_destroy(ctmp, OCON_FSUSE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700714 }
715 gtmp = g;
716 g = g->next;
717 kfree(gtmp);
718 }
Chad Sellers6e8c7512006-10-06 16:09:52 -0400719 p->genfs = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700720
721 cond_policydb_destroy(p);
722
Stephen Smalley782ebb92005-09-03 15:55:16 -0700723 for (tr = p->role_tr; tr; tr = tr->next) {
Eric Paris9dc99782007-06-04 17:41:22 -0400724 cond_resched();
Jesper Juhla7f988b2005-11-07 01:01:35 -0800725 kfree(ltr);
Stephen Smalley782ebb92005-09-03 15:55:16 -0700726 ltr = tr;
727 }
Jesper Juhla7f988b2005-11-07 01:01:35 -0800728 kfree(ltr);
Stephen Smalley782ebb92005-09-03 15:55:16 -0700729
Eric Paris2ced3df2008-04-17 13:37:12 -0400730 for (ra = p->role_allow; ra; ra = ra->next) {
Eric Paris9dc99782007-06-04 17:41:22 -0400731 cond_resched();
Jesper Juhla7f988b2005-11-07 01:01:35 -0800732 kfree(lra);
Stephen Smalley782ebb92005-09-03 15:55:16 -0700733 lra = ra;
734 }
Jesper Juhla7f988b2005-11-07 01:01:35 -0800735 kfree(lra);
Stephen Smalley782ebb92005-09-03 15:55:16 -0700736
Stephen Smalley2f3e82d2010-01-07 15:55:16 -0500737 hashtab_map(p->range_tr, range_tr_destroy, NULL);
738 hashtab_destroy(p->range_tr);
Stephen Smalley782ebb92005-09-03 15:55:16 -0700739
Stephen Smalley282c1f52005-10-23 12:57:15 -0700740 if (p->type_attr_map) {
741 for (i = 0; i < p->p_types.nprim; i++)
742 ebitmap_destroy(&p->type_attr_map[i]);
743 }
Stephen Smalley782ebb92005-09-03 15:55:16 -0700744 kfree(p->type_attr_map);
Paul Moore3bb56b22008-01-29 08:38:19 -0500745 ebitmap_destroy(&p->policycaps);
Eric Paris64dbf072008-03-31 12:17:33 +1100746 ebitmap_destroy(&p->permissive_map);
Eric Paris3f120702007-09-21 14:37:10 -0400747
Linus Torvalds1da177e2005-04-16 15:20:36 -0700748 return;
749}
750
751/*
752 * Load the initial SIDs specified in a policy database
753 * structure into a SID table.
754 */
755int policydb_load_isids(struct policydb *p, struct sidtab *s)
756{
757 struct ocontext *head, *c;
758 int rc;
759
760 rc = sidtab_init(s);
761 if (rc) {
James Morris454d9722008-02-26 20:42:02 +1100762 printk(KERN_ERR "SELinux: out of memory on SID table init\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700763 goto out;
764 }
765
766 head = p->ocontexts[OCON_ISID];
767 for (c = head; c; c = c->next) {
768 if (!c->context[0].user) {
James Morris454d9722008-02-26 20:42:02 +1100769 printk(KERN_ERR "SELinux: SID %s was never "
Linus Torvalds1da177e2005-04-16 15:20:36 -0700770 "defined.\n", c->u.name);
771 rc = -EINVAL;
772 goto out;
773 }
774 if (sidtab_insert(s, c->sid[0], &c->context[0])) {
James Morris454d9722008-02-26 20:42:02 +1100775 printk(KERN_ERR "SELinux: unable to load initial "
Linus Torvalds1da177e2005-04-16 15:20:36 -0700776 "SID %s.\n", c->u.name);
777 rc = -EINVAL;
778 goto out;
779 }
780 }
781out:
782 return rc;
783}
784
Stephen Smalley45e54212007-11-07 10:08:00 -0500785int policydb_class_isvalid(struct policydb *p, unsigned int class)
786{
787 if (!class || class > p->p_classes.nprim)
788 return 0;
789 return 1;
790}
791
792int policydb_role_isvalid(struct policydb *p, unsigned int role)
793{
794 if (!role || role > p->p_roles.nprim)
795 return 0;
796 return 1;
797}
798
799int policydb_type_isvalid(struct policydb *p, unsigned int type)
800{
801 if (!type || type > p->p_types.nprim)
802 return 0;
803 return 1;
804}
805
Linus Torvalds1da177e2005-04-16 15:20:36 -0700806/*
807 * Return 1 if the fields in the security context
808 * structure `c' are valid. Return 0 otherwise.
809 */
810int policydb_context_isvalid(struct policydb *p, struct context *c)
811{
812 struct role_datum *role;
813 struct user_datum *usrdatum;
814
815 if (!c->role || c->role > p->p_roles.nprim)
816 return 0;
817
818 if (!c->user || c->user > p->p_users.nprim)
819 return 0;
820
821 if (!c->type || c->type > p->p_types.nprim)
822 return 0;
823
824 if (c->role != OBJECT_R_VAL) {
825 /*
826 * Role must be authorized for the type.
827 */
828 role = p->role_val_to_struct[c->role - 1];
829 if (!ebitmap_get_bit(&role->types,
830 c->type - 1))
831 /* role may not be associated with type */
832 return 0;
833
834 /*
835 * User must be authorized for the role.
836 */
837 usrdatum = p->user_val_to_struct[c->user - 1];
838 if (!usrdatum)
839 return 0;
840
841 if (!ebitmap_get_bit(&usrdatum->roles,
842 c->role - 1))
843 /* user may not be associated with role */
844 return 0;
845 }
846
847 if (!mls_context_isvalid(p, c))
848 return 0;
849
850 return 1;
851}
852
853/*
854 * Read a MLS range structure from a policydb binary
855 * representation file.
856 */
857static int mls_read_range_helper(struct mls_range *r, void *fp)
858{
Alexey Dobriyanb5bf6c52005-09-03 15:55:17 -0700859 __le32 buf[2];
860 u32 items;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700861 int rc;
862
863 rc = next_entry(buf, fp, sizeof(u32));
864 if (rc < 0)
865 goto out;
866
867 items = le32_to_cpu(buf[0]);
868 if (items > ARRAY_SIZE(buf)) {
James Morris454d9722008-02-26 20:42:02 +1100869 printk(KERN_ERR "SELinux: mls: range overflow\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700870 rc = -EINVAL;
871 goto out;
872 }
873 rc = next_entry(buf, fp, sizeof(u32) * items);
874 if (rc < 0) {
James Morris454d9722008-02-26 20:42:02 +1100875 printk(KERN_ERR "SELinux: mls: truncated range\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700876 goto out;
877 }
878 r->level[0].sens = le32_to_cpu(buf[0]);
879 if (items > 1)
880 r->level[1].sens = le32_to_cpu(buf[1]);
881 else
882 r->level[1].sens = r->level[0].sens;
883
884 rc = ebitmap_read(&r->level[0].cat, fp);
885 if (rc) {
James Morris454d9722008-02-26 20:42:02 +1100886 printk(KERN_ERR "SELinux: mls: error reading low "
Linus Torvalds1da177e2005-04-16 15:20:36 -0700887 "categories\n");
888 goto out;
889 }
890 if (items > 1) {
891 rc = ebitmap_read(&r->level[1].cat, fp);
892 if (rc) {
James Morris454d9722008-02-26 20:42:02 +1100893 printk(KERN_ERR "SELinux: mls: error reading high "
Linus Torvalds1da177e2005-04-16 15:20:36 -0700894 "categories\n");
895 goto bad_high;
896 }
897 } else {
898 rc = ebitmap_cpy(&r->level[1].cat, &r->level[0].cat);
899 if (rc) {
James Morris454d9722008-02-26 20:42:02 +1100900 printk(KERN_ERR "SELinux: mls: out of memory\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700901 goto bad_high;
902 }
903 }
904
905 rc = 0;
906out:
907 return rc;
908bad_high:
909 ebitmap_destroy(&r->level[0].cat);
910 goto out;
911}
912
913/*
914 * Read and validate a security context structure
915 * from a policydb binary representation file.
916 */
917static int context_read_and_validate(struct context *c,
918 struct policydb *p,
919 void *fp)
920{
Alexey Dobriyanb5bf6c52005-09-03 15:55:17 -0700921 __le32 buf[3];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700922 int rc;
923
924 rc = next_entry(buf, fp, sizeof buf);
925 if (rc < 0) {
James Morris454d9722008-02-26 20:42:02 +1100926 printk(KERN_ERR "SELinux: context truncated\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700927 goto out;
928 }
929 c->user = le32_to_cpu(buf[0]);
930 c->role = le32_to_cpu(buf[1]);
931 c->type = le32_to_cpu(buf[2]);
932 if (p->policyvers >= POLICYDB_VERSION_MLS) {
933 if (mls_read_range_helper(&c->range, fp)) {
James Morris454d9722008-02-26 20:42:02 +1100934 printk(KERN_ERR "SELinux: error reading MLS range of "
Linus Torvalds1da177e2005-04-16 15:20:36 -0700935 "context\n");
936 rc = -EINVAL;
937 goto out;
938 }
939 }
940
941 if (!policydb_context_isvalid(p, c)) {
James Morris454d9722008-02-26 20:42:02 +1100942 printk(KERN_ERR "SELinux: invalid security context\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700943 context_destroy(c);
944 rc = -EINVAL;
945 }
946out:
947 return rc;
948}
949
950/*
951 * The following *_read functions are used to
952 * read the symbol data from a policy database
953 * binary representation file.
954 */
955
956static int perm_read(struct policydb *p, struct hashtab *h, void *fp)
957{
958 char *key = NULL;
959 struct perm_datum *perdatum;
960 int rc;
Alexey Dobriyanb5bf6c52005-09-03 15:55:17 -0700961 __le32 buf[2];
962 u32 len;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700963
James Morris89d155e2005-10-30 14:59:21 -0800964 perdatum = kzalloc(sizeof(*perdatum), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700965 if (!perdatum) {
966 rc = -ENOMEM;
967 goto out;
968 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700969
970 rc = next_entry(buf, fp, sizeof buf);
971 if (rc < 0)
972 goto bad;
973
974 len = le32_to_cpu(buf[0]);
975 perdatum->value = le32_to_cpu(buf[1]);
976
Eric Paris2ced3df2008-04-17 13:37:12 -0400977 key = kmalloc(len + 1, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700978 if (!key) {
979 rc = -ENOMEM;
980 goto bad;
981 }
982 rc = next_entry(key, fp, len);
983 if (rc < 0)
984 goto bad;
Vesa-Matti J Karidf4ea862008-07-20 23:57:01 +0300985 key[len] = '\0';
Linus Torvalds1da177e2005-04-16 15:20:36 -0700986
987 rc = hashtab_insert(h, key, perdatum);
988 if (rc)
989 goto bad;
990out:
991 return rc;
992bad:
993 perm_destroy(key, perdatum, NULL);
994 goto out;
995}
996
997static int common_read(struct policydb *p, struct hashtab *h, void *fp)
998{
999 char *key = NULL;
1000 struct common_datum *comdatum;
Alexey Dobriyanb5bf6c52005-09-03 15:55:17 -07001001 __le32 buf[4];
1002 u32 len, nel;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001003 int i, rc;
1004
James Morris89d155e2005-10-30 14:59:21 -08001005 comdatum = kzalloc(sizeof(*comdatum), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001006 if (!comdatum) {
1007 rc = -ENOMEM;
1008 goto out;
1009 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001010
1011 rc = next_entry(buf, fp, sizeof buf);
1012 if (rc < 0)
1013 goto bad;
1014
1015 len = le32_to_cpu(buf[0]);
1016 comdatum->value = le32_to_cpu(buf[1]);
1017
1018 rc = symtab_init(&comdatum->permissions, PERM_SYMTAB_SIZE);
1019 if (rc)
1020 goto bad;
1021 comdatum->permissions.nprim = le32_to_cpu(buf[2]);
1022 nel = le32_to_cpu(buf[3]);
1023
Eric Paris2ced3df2008-04-17 13:37:12 -04001024 key = kmalloc(len + 1, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001025 if (!key) {
1026 rc = -ENOMEM;
1027 goto bad;
1028 }
1029 rc = next_entry(key, fp, len);
1030 if (rc < 0)
1031 goto bad;
Vesa-Matti J Karidf4ea862008-07-20 23:57:01 +03001032 key[len] = '\0';
Linus Torvalds1da177e2005-04-16 15:20:36 -07001033
1034 for (i = 0; i < nel; i++) {
1035 rc = perm_read(p, comdatum->permissions.table, fp);
1036 if (rc)
1037 goto bad;
1038 }
1039
1040 rc = hashtab_insert(h, key, comdatum);
1041 if (rc)
1042 goto bad;
1043out:
1044 return rc;
1045bad:
1046 common_destroy(key, comdatum, NULL);
1047 goto out;
1048}
1049
1050static int read_cons_helper(struct constraint_node **nodep, int ncons,
Eric Paris2ced3df2008-04-17 13:37:12 -04001051 int allowxtarget, void *fp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001052{
1053 struct constraint_node *c, *lc;
1054 struct constraint_expr *e, *le;
Alexey Dobriyanb5bf6c52005-09-03 15:55:17 -07001055 __le32 buf[3];
1056 u32 nexpr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001057 int rc, i, j, depth;
1058
1059 lc = NULL;
1060 for (i = 0; i < ncons; i++) {
James Morris89d155e2005-10-30 14:59:21 -08001061 c = kzalloc(sizeof(*c), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001062 if (!c)
1063 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001064
Eric Paris2ced3df2008-04-17 13:37:12 -04001065 if (lc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001066 lc->next = c;
Eric Paris2ced3df2008-04-17 13:37:12 -04001067 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001068 *nodep = c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001069
1070 rc = next_entry(buf, fp, (sizeof(u32) * 2));
1071 if (rc < 0)
1072 return rc;
1073 c->permissions = le32_to_cpu(buf[0]);
1074 nexpr = le32_to_cpu(buf[1]);
1075 le = NULL;
1076 depth = -1;
1077 for (j = 0; j < nexpr; j++) {
James Morris89d155e2005-10-30 14:59:21 -08001078 e = kzalloc(sizeof(*e), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001079 if (!e)
1080 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001081
Eric Paris2ced3df2008-04-17 13:37:12 -04001082 if (le)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001083 le->next = e;
Eric Paris2ced3df2008-04-17 13:37:12 -04001084 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001085 c->expr = e;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001086
1087 rc = next_entry(buf, fp, (sizeof(u32) * 3));
1088 if (rc < 0)
1089 return rc;
1090 e->expr_type = le32_to_cpu(buf[0]);
1091 e->attr = le32_to_cpu(buf[1]);
1092 e->op = le32_to_cpu(buf[2]);
1093
1094 switch (e->expr_type) {
1095 case CEXPR_NOT:
1096 if (depth < 0)
1097 return -EINVAL;
1098 break;
1099 case CEXPR_AND:
1100 case CEXPR_OR:
1101 if (depth < 1)
1102 return -EINVAL;
1103 depth--;
1104 break;
1105 case CEXPR_ATTR:
1106 if (depth == (CEXPR_MAXDEPTH - 1))
1107 return -EINVAL;
1108 depth++;
1109 break;
1110 case CEXPR_NAMES:
1111 if (!allowxtarget && (e->attr & CEXPR_XTARGET))
1112 return -EINVAL;
1113 if (depth == (CEXPR_MAXDEPTH - 1))
1114 return -EINVAL;
1115 depth++;
1116 if (ebitmap_read(&e->names, fp))
1117 return -EINVAL;
1118 break;
1119 default:
1120 return -EINVAL;
1121 }
1122 le = e;
1123 }
1124 if (depth != 0)
1125 return -EINVAL;
1126 lc = c;
1127 }
1128
1129 return 0;
1130}
1131
1132static int class_read(struct policydb *p, struct hashtab *h, void *fp)
1133{
1134 char *key = NULL;
1135 struct class_datum *cladatum;
Alexey Dobriyanb5bf6c52005-09-03 15:55:17 -07001136 __le32 buf[6];
1137 u32 len, len2, ncons, nel;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001138 int i, rc;
1139
James Morris89d155e2005-10-30 14:59:21 -08001140 cladatum = kzalloc(sizeof(*cladatum), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001141 if (!cladatum) {
1142 rc = -ENOMEM;
1143 goto out;
1144 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001145
1146 rc = next_entry(buf, fp, sizeof(u32)*6);
1147 if (rc < 0)
1148 goto bad;
1149
1150 len = le32_to_cpu(buf[0]);
1151 len2 = le32_to_cpu(buf[1]);
1152 cladatum->value = le32_to_cpu(buf[2]);
1153
1154 rc = symtab_init(&cladatum->permissions, PERM_SYMTAB_SIZE);
1155 if (rc)
1156 goto bad;
1157 cladatum->permissions.nprim = le32_to_cpu(buf[3]);
1158 nel = le32_to_cpu(buf[4]);
1159
1160 ncons = le32_to_cpu(buf[5]);
1161
Eric Paris2ced3df2008-04-17 13:37:12 -04001162 key = kmalloc(len + 1, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001163 if (!key) {
1164 rc = -ENOMEM;
1165 goto bad;
1166 }
1167 rc = next_entry(key, fp, len);
1168 if (rc < 0)
1169 goto bad;
Vesa-Matti J Karidf4ea862008-07-20 23:57:01 +03001170 key[len] = '\0';
Linus Torvalds1da177e2005-04-16 15:20:36 -07001171
1172 if (len2) {
Eric Paris2ced3df2008-04-17 13:37:12 -04001173 cladatum->comkey = kmalloc(len2 + 1, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001174 if (!cladatum->comkey) {
1175 rc = -ENOMEM;
1176 goto bad;
1177 }
1178 rc = next_entry(cladatum->comkey, fp, len2);
1179 if (rc < 0)
1180 goto bad;
Vesa-Matti J Karidf4ea862008-07-20 23:57:01 +03001181 cladatum->comkey[len2] = '\0';
Linus Torvalds1da177e2005-04-16 15:20:36 -07001182
1183 cladatum->comdatum = hashtab_search(p->p_commons.table,
1184 cladatum->comkey);
1185 if (!cladatum->comdatum) {
James Morris454d9722008-02-26 20:42:02 +11001186 printk(KERN_ERR "SELinux: unknown common %s\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001187 cladatum->comkey);
1188 rc = -EINVAL;
1189 goto bad;
1190 }
1191 }
1192 for (i = 0; i < nel; i++) {
1193 rc = perm_read(p, cladatum->permissions.table, fp);
1194 if (rc)
1195 goto bad;
1196 }
1197
1198 rc = read_cons_helper(&cladatum->constraints, ncons, 0, fp);
1199 if (rc)
1200 goto bad;
1201
1202 if (p->policyvers >= POLICYDB_VERSION_VALIDATETRANS) {
1203 /* grab the validatetrans rules */
1204 rc = next_entry(buf, fp, sizeof(u32));
1205 if (rc < 0)
1206 goto bad;
1207 ncons = le32_to_cpu(buf[0]);
1208 rc = read_cons_helper(&cladatum->validatetrans, ncons, 1, fp);
1209 if (rc)
1210 goto bad;
1211 }
1212
1213 rc = hashtab_insert(h, key, cladatum);
1214 if (rc)
1215 goto bad;
1216
1217 rc = 0;
1218out:
1219 return rc;
1220bad:
James Morris6cbda6b2006-11-29 16:50:27 -05001221 cls_destroy(key, cladatum, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001222 goto out;
1223}
1224
1225static int role_read(struct policydb *p, struct hashtab *h, void *fp)
1226{
1227 char *key = NULL;
1228 struct role_datum *role;
KaiGai Koheid9250de2008-08-28 16:35:57 +09001229 int rc, to_read = 2;
1230 __le32 buf[3];
Alexey Dobriyanb5bf6c52005-09-03 15:55:17 -07001231 u32 len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001232
James Morris89d155e2005-10-30 14:59:21 -08001233 role = kzalloc(sizeof(*role), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001234 if (!role) {
1235 rc = -ENOMEM;
1236 goto out;
1237 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001238
KaiGai Koheid9250de2008-08-28 16:35:57 +09001239 if (p->policyvers >= POLICYDB_VERSION_BOUNDARY)
1240 to_read = 3;
1241
1242 rc = next_entry(buf, fp, sizeof(buf[0]) * to_read);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001243 if (rc < 0)
1244 goto bad;
1245
1246 len = le32_to_cpu(buf[0]);
1247 role->value = le32_to_cpu(buf[1]);
KaiGai Koheid9250de2008-08-28 16:35:57 +09001248 if (p->policyvers >= POLICYDB_VERSION_BOUNDARY)
1249 role->bounds = le32_to_cpu(buf[2]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001250
Eric Paris2ced3df2008-04-17 13:37:12 -04001251 key = kmalloc(len + 1, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001252 if (!key) {
1253 rc = -ENOMEM;
1254 goto bad;
1255 }
1256 rc = next_entry(key, fp, len);
1257 if (rc < 0)
1258 goto bad;
Vesa-Matti J Karidf4ea862008-07-20 23:57:01 +03001259 key[len] = '\0';
Linus Torvalds1da177e2005-04-16 15:20:36 -07001260
1261 rc = ebitmap_read(&role->dominates, fp);
1262 if (rc)
1263 goto bad;
1264
1265 rc = ebitmap_read(&role->types, fp);
1266 if (rc)
1267 goto bad;
1268
1269 if (strcmp(key, OBJECT_R) == 0) {
1270 if (role->value != OBJECT_R_VAL) {
Eric Paris744ba352008-04-17 11:52:44 -04001271 printk(KERN_ERR "SELinux: Role %s has wrong value %d\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001272 OBJECT_R, role->value);
1273 rc = -EINVAL;
1274 goto bad;
1275 }
1276 rc = 0;
1277 goto bad;
1278 }
1279
1280 rc = hashtab_insert(h, key, role);
1281 if (rc)
1282 goto bad;
1283out:
1284 return rc;
1285bad:
1286 role_destroy(key, role, NULL);
1287 goto out;
1288}
1289
1290static int type_read(struct policydb *p, struct hashtab *h, void *fp)
1291{
1292 char *key = NULL;
1293 struct type_datum *typdatum;
KaiGai Koheid9250de2008-08-28 16:35:57 +09001294 int rc, to_read = 3;
1295 __le32 buf[4];
Alexey Dobriyanb5bf6c52005-09-03 15:55:17 -07001296 u32 len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001297
Eric Paris2ced3df2008-04-17 13:37:12 -04001298 typdatum = kzalloc(sizeof(*typdatum), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001299 if (!typdatum) {
1300 rc = -ENOMEM;
1301 return rc;
1302 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001303
KaiGai Koheid9250de2008-08-28 16:35:57 +09001304 if (p->policyvers >= POLICYDB_VERSION_BOUNDARY)
1305 to_read = 4;
1306
1307 rc = next_entry(buf, fp, sizeof(buf[0]) * to_read);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001308 if (rc < 0)
1309 goto bad;
1310
1311 len = le32_to_cpu(buf[0]);
1312 typdatum->value = le32_to_cpu(buf[1]);
KaiGai Koheid9250de2008-08-28 16:35:57 +09001313 if (p->policyvers >= POLICYDB_VERSION_BOUNDARY) {
1314 u32 prop = le32_to_cpu(buf[2]);
1315
1316 if (prop & TYPEDATUM_PROPERTY_PRIMARY)
1317 typdatum->primary = 1;
1318 if (prop & TYPEDATUM_PROPERTY_ATTRIBUTE)
1319 typdatum->attribute = 1;
1320
1321 typdatum->bounds = le32_to_cpu(buf[3]);
1322 } else {
1323 typdatum->primary = le32_to_cpu(buf[2]);
1324 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001325
Eric Paris2ced3df2008-04-17 13:37:12 -04001326 key = kmalloc(len + 1, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001327 if (!key) {
1328 rc = -ENOMEM;
1329 goto bad;
1330 }
1331 rc = next_entry(key, fp, len);
1332 if (rc < 0)
1333 goto bad;
Vesa-Matti J Karidf4ea862008-07-20 23:57:01 +03001334 key[len] = '\0';
Linus Torvalds1da177e2005-04-16 15:20:36 -07001335
1336 rc = hashtab_insert(h, key, typdatum);
1337 if (rc)
1338 goto bad;
1339out:
1340 return rc;
1341bad:
1342 type_destroy(key, typdatum, NULL);
1343 goto out;
1344}
1345
1346
1347/*
1348 * Read a MLS level structure from a policydb binary
1349 * representation file.
1350 */
1351static int mls_read_level(struct mls_level *lp, void *fp)
1352{
Alexey Dobriyanb5bf6c52005-09-03 15:55:17 -07001353 __le32 buf[1];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001354 int rc;
1355
1356 memset(lp, 0, sizeof(*lp));
1357
1358 rc = next_entry(buf, fp, sizeof buf);
1359 if (rc < 0) {
James Morris454d9722008-02-26 20:42:02 +11001360 printk(KERN_ERR "SELinux: mls: truncated level\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001361 goto bad;
1362 }
1363 lp->sens = le32_to_cpu(buf[0]);
1364
1365 if (ebitmap_read(&lp->cat, fp)) {
James Morris454d9722008-02-26 20:42:02 +11001366 printk(KERN_ERR "SELinux: mls: error reading level "
Linus Torvalds1da177e2005-04-16 15:20:36 -07001367 "categories\n");
1368 goto bad;
1369 }
Stephen Smalley45e54212007-11-07 10:08:00 -05001370
Linus Torvalds1da177e2005-04-16 15:20:36 -07001371 return 0;
1372
1373bad:
1374 return -EINVAL;
1375}
1376
1377static int user_read(struct policydb *p, struct hashtab *h, void *fp)
1378{
1379 char *key = NULL;
1380 struct user_datum *usrdatum;
KaiGai Koheid9250de2008-08-28 16:35:57 +09001381 int rc, to_read = 2;
1382 __le32 buf[3];
Alexey Dobriyanb5bf6c52005-09-03 15:55:17 -07001383 u32 len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001384
James Morris89d155e2005-10-30 14:59:21 -08001385 usrdatum = kzalloc(sizeof(*usrdatum), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001386 if (!usrdatum) {
1387 rc = -ENOMEM;
1388 goto out;
1389 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001390
KaiGai Koheid9250de2008-08-28 16:35:57 +09001391 if (p->policyvers >= POLICYDB_VERSION_BOUNDARY)
1392 to_read = 3;
1393
1394 rc = next_entry(buf, fp, sizeof(buf[0]) * to_read);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001395 if (rc < 0)
1396 goto bad;
1397
1398 len = le32_to_cpu(buf[0]);
1399 usrdatum->value = le32_to_cpu(buf[1]);
KaiGai Koheid9250de2008-08-28 16:35:57 +09001400 if (p->policyvers >= POLICYDB_VERSION_BOUNDARY)
1401 usrdatum->bounds = le32_to_cpu(buf[2]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001402
Eric Paris2ced3df2008-04-17 13:37:12 -04001403 key = kmalloc(len + 1, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001404 if (!key) {
1405 rc = -ENOMEM;
1406 goto bad;
1407 }
1408 rc = next_entry(key, fp, len);
1409 if (rc < 0)
1410 goto bad;
Vesa-Matti J Karidf4ea862008-07-20 23:57:01 +03001411 key[len] = '\0';
Linus Torvalds1da177e2005-04-16 15:20:36 -07001412
1413 rc = ebitmap_read(&usrdatum->roles, fp);
1414 if (rc)
1415 goto bad;
1416
1417 if (p->policyvers >= POLICYDB_VERSION_MLS) {
1418 rc = mls_read_range_helper(&usrdatum->range, fp);
1419 if (rc)
1420 goto bad;
1421 rc = mls_read_level(&usrdatum->dfltlevel, fp);
1422 if (rc)
1423 goto bad;
1424 }
1425
1426 rc = hashtab_insert(h, key, usrdatum);
1427 if (rc)
1428 goto bad;
1429out:
1430 return rc;
1431bad:
1432 user_destroy(key, usrdatum, NULL);
1433 goto out;
1434}
1435
1436static int sens_read(struct policydb *p, struct hashtab *h, void *fp)
1437{
1438 char *key = NULL;
1439 struct level_datum *levdatum;
1440 int rc;
Alexey Dobriyanb5bf6c52005-09-03 15:55:17 -07001441 __le32 buf[2];
1442 u32 len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001443
James Morris89d155e2005-10-30 14:59:21 -08001444 levdatum = kzalloc(sizeof(*levdatum), GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001445 if (!levdatum) {
1446 rc = -ENOMEM;
1447 goto out;
1448 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001449
1450 rc = next_entry(buf, fp, sizeof buf);
1451 if (rc < 0)
1452 goto bad;
1453
1454 len = le32_to_cpu(buf[0]);
1455 levdatum->isalias = le32_to_cpu(buf[1]);
1456
Eric Paris2ced3df2008-04-17 13:37:12 -04001457 key = kmalloc(len + 1, GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001458 if (!key) {
1459 rc = -ENOMEM;
1460 goto bad;
1461 }
1462 rc = next_entry(key, fp, len);
1463 if (rc < 0)
1464 goto bad;
Vesa-Matti J Karidf4ea862008-07-20 23:57:01 +03001465 key[len] = '\0';
Linus Torvalds1da177e2005-04-16 15:20:36 -07001466
1467 levdatum->level = kmalloc(sizeof(struct mls_level), GFP_ATOMIC);
1468 if (!levdatum->level) {
1469 rc = -ENOMEM;
1470 goto bad;
1471 }
1472 if (mls_read_level(levdatum->level, fp)) {
1473 rc = -EINVAL;
1474 goto bad;
1475 }
1476
1477 rc = hashtab_insert(h, key, levdatum);
1478 if (rc)
1479 goto bad;
1480out:
1481 return rc;
1482bad:
1483 sens_destroy(key, levdatum, NULL);
1484 goto out;
1485}
1486
1487static int cat_read(struct policydb *p, struct hashtab *h, void *fp)
1488{
1489 char *key = NULL;
1490 struct cat_datum *catdatum;
1491 int rc;
Alexey Dobriyanb5bf6c52005-09-03 15:55:17 -07001492 __le32 buf[3];
1493 u32 len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001494
James Morris89d155e2005-10-30 14:59:21 -08001495 catdatum = kzalloc(sizeof(*catdatum), GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001496 if (!catdatum) {
1497 rc = -ENOMEM;
1498 goto out;
1499 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001500
1501 rc = next_entry(buf, fp, sizeof buf);
1502 if (rc < 0)
1503 goto bad;
1504
1505 len = le32_to_cpu(buf[0]);
1506 catdatum->value = le32_to_cpu(buf[1]);
1507 catdatum->isalias = le32_to_cpu(buf[2]);
1508
Eric Paris2ced3df2008-04-17 13:37:12 -04001509 key = kmalloc(len + 1, GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001510 if (!key) {
1511 rc = -ENOMEM;
1512 goto bad;
1513 }
1514 rc = next_entry(key, fp, len);
1515 if (rc < 0)
1516 goto bad;
Vesa-Matti J Karidf4ea862008-07-20 23:57:01 +03001517 key[len] = '\0';
Linus Torvalds1da177e2005-04-16 15:20:36 -07001518
1519 rc = hashtab_insert(h, key, catdatum);
1520 if (rc)
1521 goto bad;
1522out:
1523 return rc;
1524
1525bad:
1526 cat_destroy(key, catdatum, NULL);
1527 goto out;
1528}
1529
1530static int (*read_f[SYM_NUM]) (struct policydb *p, struct hashtab *h, void *fp) =
1531{
1532 common_read,
1533 class_read,
1534 role_read,
1535 type_read,
1536 user_read,
1537 cond_read_bool,
1538 sens_read,
1539 cat_read,
1540};
1541
KaiGai Koheid9250de2008-08-28 16:35:57 +09001542static int user_bounds_sanity_check(void *key, void *datum, void *datap)
1543{
1544 struct user_datum *upper, *user;
1545 struct policydb *p = datap;
1546 int depth = 0;
1547
1548 upper = user = datum;
1549 while (upper->bounds) {
1550 struct ebitmap_node *node;
1551 unsigned long bit;
1552
1553 if (++depth == POLICYDB_BOUNDS_MAXDEPTH) {
1554 printk(KERN_ERR "SELinux: user %s: "
1555 "too deep or looped boundary",
1556 (char *) key);
1557 return -EINVAL;
1558 }
1559
1560 upper = p->user_val_to_struct[upper->bounds - 1];
1561 ebitmap_for_each_positive_bit(&user->roles, node, bit) {
1562 if (ebitmap_get_bit(&upper->roles, bit))
1563 continue;
1564
1565 printk(KERN_ERR
1566 "SELinux: boundary violated policy: "
1567 "user=%s role=%s bounds=%s\n",
1568 p->p_user_val_to_name[user->value - 1],
1569 p->p_role_val_to_name[bit],
1570 p->p_user_val_to_name[upper->value - 1]);
1571
1572 return -EINVAL;
1573 }
1574 }
1575
1576 return 0;
1577}
1578
1579static int role_bounds_sanity_check(void *key, void *datum, void *datap)
1580{
1581 struct role_datum *upper, *role;
1582 struct policydb *p = datap;
1583 int depth = 0;
1584
1585 upper = role = datum;
1586 while (upper->bounds) {
1587 struct ebitmap_node *node;
1588 unsigned long bit;
1589
1590 if (++depth == POLICYDB_BOUNDS_MAXDEPTH) {
1591 printk(KERN_ERR "SELinux: role %s: "
1592 "too deep or looped bounds\n",
1593 (char *) key);
1594 return -EINVAL;
1595 }
1596
1597 upper = p->role_val_to_struct[upper->bounds - 1];
1598 ebitmap_for_each_positive_bit(&role->types, node, bit) {
1599 if (ebitmap_get_bit(&upper->types, bit))
1600 continue;
1601
1602 printk(KERN_ERR
1603 "SELinux: boundary violated policy: "
1604 "role=%s type=%s bounds=%s\n",
1605 p->p_role_val_to_name[role->value - 1],
1606 p->p_type_val_to_name[bit],
1607 p->p_role_val_to_name[upper->value - 1]);
1608
1609 return -EINVAL;
1610 }
1611 }
1612
1613 return 0;
1614}
1615
1616static int type_bounds_sanity_check(void *key, void *datum, void *datap)
1617{
1618 struct type_datum *upper, *type;
1619 struct policydb *p = datap;
1620 int depth = 0;
1621
1622 upper = type = datum;
1623 while (upper->bounds) {
1624 if (++depth == POLICYDB_BOUNDS_MAXDEPTH) {
1625 printk(KERN_ERR "SELinux: type %s: "
1626 "too deep or looped boundary\n",
1627 (char *) key);
1628 return -EINVAL;
1629 }
1630
1631 upper = p->type_val_to_struct[upper->bounds - 1];
1632 if (upper->attribute) {
1633 printk(KERN_ERR "SELinux: type %s: "
1634 "bounded by attribute %s",
1635 (char *) key,
1636 p->p_type_val_to_name[upper->value - 1]);
1637 return -EINVAL;
1638 }
1639 }
1640
1641 return 0;
1642}
1643
1644static int policydb_bounds_sanity_check(struct policydb *p)
1645{
1646 int rc;
1647
1648 if (p->policyvers < POLICYDB_VERSION_BOUNDARY)
1649 return 0;
1650
1651 rc = hashtab_map(p->p_users.table,
1652 user_bounds_sanity_check, p);
1653 if (rc)
1654 return rc;
1655
1656 rc = hashtab_map(p->p_roles.table,
1657 role_bounds_sanity_check, p);
1658 if (rc)
1659 return rc;
1660
1661 rc = hashtab_map(p->p_types.table,
1662 type_bounds_sanity_check, p);
1663 if (rc)
1664 return rc;
1665
1666 return 0;
1667}
1668
Linus Torvalds1da177e2005-04-16 15:20:36 -07001669extern int ss_initialized;
1670
Stephen Smalleyc6d3aaa2009-09-30 13:37:50 -04001671u16 string_to_security_class(struct policydb *p, const char *name)
1672{
1673 struct class_datum *cladatum;
1674
1675 cladatum = hashtab_search(p->p_classes.table, name);
1676 if (!cladatum)
1677 return 0;
1678
1679 return cladatum->value;
1680}
1681
1682u32 string_to_av_perm(struct policydb *p, u16 tclass, const char *name)
1683{
1684 struct class_datum *cladatum;
1685 struct perm_datum *perdatum = NULL;
1686 struct common_datum *comdatum;
1687
1688 if (!tclass || tclass > p->p_classes.nprim)
1689 return 0;
1690
1691 cladatum = p->class_val_to_struct[tclass-1];
1692 comdatum = cladatum->comdatum;
1693 if (comdatum)
1694 perdatum = hashtab_search(comdatum->permissions.table,
1695 name);
1696 if (!perdatum)
1697 perdatum = hashtab_search(cladatum->permissions.table,
1698 name);
1699 if (!perdatum)
1700 return 0;
1701
1702 return 1U << (perdatum->value-1);
1703}
1704
Linus Torvalds1da177e2005-04-16 15:20:36 -07001705/*
1706 * Read the configuration data from a policy database binary
1707 * representation file into a policy database structure.
1708 */
1709int policydb_read(struct policydb *p, void *fp)
1710{
1711 struct role_allow *ra, *lra;
1712 struct role_trans *tr, *ltr;
1713 struct ocontext *l, *c, *newc;
1714 struct genfs *genfs_p, *genfs, *newgenfs;
1715 int i, j, rc;
Stephen Smalley59dbd1b2008-06-05 09:48:51 -04001716 __le32 buf[4];
1717 u32 nodebuf[8];
Guido Trentalancia0719aaf52010-02-03 16:40:20 +01001718 u32 len, len2, nprim, nel, nel2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001719 char *policydb_str;
1720 struct policydb_compat_info *info;
Stephen Smalley2f3e82d2010-01-07 15:55:16 -05001721 struct range_trans *rt;
1722 struct mls_range *r;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001723
Linus Torvalds1da177e2005-04-16 15:20:36 -07001724 rc = policydb_init(p);
1725 if (rc)
1726 goto out;
1727
1728 /* Read the magic number and string length. */
Eric Paris2ced3df2008-04-17 13:37:12 -04001729 rc = next_entry(buf, fp, sizeof(u32) * 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001730 if (rc < 0)
1731 goto bad;
1732
Alexey Dobriyanb5bf6c52005-09-03 15:55:17 -07001733 if (le32_to_cpu(buf[0]) != POLICYDB_MAGIC) {
James Morris454d9722008-02-26 20:42:02 +11001734 printk(KERN_ERR "SELinux: policydb magic number 0x%x does "
Linus Torvalds1da177e2005-04-16 15:20:36 -07001735 "not match expected magic number 0x%x\n",
Alexey Dobriyanb5bf6c52005-09-03 15:55:17 -07001736 le32_to_cpu(buf[0]), POLICYDB_MAGIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001737 goto bad;
1738 }
1739
Alexey Dobriyanb5bf6c52005-09-03 15:55:17 -07001740 len = le32_to_cpu(buf[1]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001741 if (len != strlen(POLICYDB_STRING)) {
James Morris454d9722008-02-26 20:42:02 +11001742 printk(KERN_ERR "SELinux: policydb string length %d does not "
Linus Torvalds1da177e2005-04-16 15:20:36 -07001743 "match expected length %Zu\n",
1744 len, strlen(POLICYDB_STRING));
1745 goto bad;
1746 }
Eric Paris2ced3df2008-04-17 13:37:12 -04001747 policydb_str = kmalloc(len + 1, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001748 if (!policydb_str) {
James Morris454d9722008-02-26 20:42:02 +11001749 printk(KERN_ERR "SELinux: unable to allocate memory for policydb "
Linus Torvalds1da177e2005-04-16 15:20:36 -07001750 "string of length %d\n", len);
1751 rc = -ENOMEM;
1752 goto bad;
1753 }
1754 rc = next_entry(policydb_str, fp, len);
1755 if (rc < 0) {
James Morris454d9722008-02-26 20:42:02 +11001756 printk(KERN_ERR "SELinux: truncated policydb string identifier\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001757 kfree(policydb_str);
1758 goto bad;
1759 }
Vesa-Matti J Karidf4ea862008-07-20 23:57:01 +03001760 policydb_str[len] = '\0';
Linus Torvalds1da177e2005-04-16 15:20:36 -07001761 if (strcmp(policydb_str, POLICYDB_STRING)) {
James Morris454d9722008-02-26 20:42:02 +11001762 printk(KERN_ERR "SELinux: policydb string %s does not match "
Linus Torvalds1da177e2005-04-16 15:20:36 -07001763 "my string %s\n", policydb_str, POLICYDB_STRING);
1764 kfree(policydb_str);
1765 goto bad;
1766 }
1767 /* Done with policydb_str. */
1768 kfree(policydb_str);
1769 policydb_str = NULL;
1770
Guido Trentalancia0719aaf52010-02-03 16:40:20 +01001771 /* Read the version and table sizes. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001772 rc = next_entry(buf, fp, sizeof(u32)*4);
1773 if (rc < 0)
1774 goto bad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001775
Alexey Dobriyanb5bf6c52005-09-03 15:55:17 -07001776 p->policyvers = le32_to_cpu(buf[0]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001777 if (p->policyvers < POLICYDB_VERSION_MIN ||
1778 p->policyvers > POLICYDB_VERSION_MAX) {
James Morris454d9722008-02-26 20:42:02 +11001779 printk(KERN_ERR "SELinux: policydb version %d does not match "
Eric Paris2ced3df2008-04-17 13:37:12 -04001780 "my version range %d-%d\n",
1781 le32_to_cpu(buf[0]), POLICYDB_VERSION_MIN, POLICYDB_VERSION_MAX);
1782 goto bad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001783 }
1784
Alexey Dobriyanb5bf6c52005-09-03 15:55:17 -07001785 if ((le32_to_cpu(buf[1]) & POLICYDB_CONFIG_MLS)) {
Guido Trentalancia0719aaf52010-02-03 16:40:20 +01001786 p->mls_enabled = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001787
1788 if (p->policyvers < POLICYDB_VERSION_MLS) {
Eric Paris744ba352008-04-17 11:52:44 -04001789 printk(KERN_ERR "SELinux: security policydb version %d "
1790 "(MLS) not backwards compatible\n",
1791 p->policyvers);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001792 goto bad;
1793 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001794 }
Eric Paris3f120702007-09-21 14:37:10 -04001795 p->reject_unknown = !!(le32_to_cpu(buf[1]) & REJECT_UNKNOWN);
1796 p->allow_unknown = !!(le32_to_cpu(buf[1]) & ALLOW_UNKNOWN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001797
Paul Moore3bb56b22008-01-29 08:38:19 -05001798 if (p->policyvers >= POLICYDB_VERSION_POLCAP &&
1799 ebitmap_read(&p->policycaps, fp) != 0)
1800 goto bad;
1801
Eric Paris64dbf072008-03-31 12:17:33 +11001802 if (p->policyvers >= POLICYDB_VERSION_PERMISSIVE &&
1803 ebitmap_read(&p->permissive_map, fp) != 0)
1804 goto bad;
1805
Linus Torvalds1da177e2005-04-16 15:20:36 -07001806 info = policydb_lookup_compat(p->policyvers);
1807 if (!info) {
James Morris454d9722008-02-26 20:42:02 +11001808 printk(KERN_ERR "SELinux: unable to find policy compat info "
Linus Torvalds1da177e2005-04-16 15:20:36 -07001809 "for version %d\n", p->policyvers);
1810 goto bad;
1811 }
1812
Alexey Dobriyanb5bf6c52005-09-03 15:55:17 -07001813 if (le32_to_cpu(buf[2]) != info->sym_num ||
1814 le32_to_cpu(buf[3]) != info->ocon_num) {
James Morris454d9722008-02-26 20:42:02 +11001815 printk(KERN_ERR "SELinux: policydb table sizes (%d,%d) do "
Alexey Dobriyanb5bf6c52005-09-03 15:55:17 -07001816 "not match mine (%d,%d)\n", le32_to_cpu(buf[2]),
1817 le32_to_cpu(buf[3]),
Linus Torvalds1da177e2005-04-16 15:20:36 -07001818 info->sym_num, info->ocon_num);
1819 goto bad;
1820 }
1821
1822 for (i = 0; i < info->sym_num; i++) {
1823 rc = next_entry(buf, fp, sizeof(u32)*2);
1824 if (rc < 0)
1825 goto bad;
1826 nprim = le32_to_cpu(buf[0]);
1827 nel = le32_to_cpu(buf[1]);
1828 for (j = 0; j < nel; j++) {
1829 rc = read_f[i](p, p->symtab[i].table, fp);
1830 if (rc)
1831 goto bad;
1832 }
1833
1834 p->symtab[i].nprim = nprim;
1835 }
1836
Stephen Smalley45e54212007-11-07 10:08:00 -05001837 rc = avtab_read(&p->te_avtab, fp, p);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001838 if (rc)
1839 goto bad;
1840
1841 if (p->policyvers >= POLICYDB_VERSION_BOOL) {
1842 rc = cond_read_list(p, fp);
1843 if (rc)
1844 goto bad;
1845 }
1846
1847 rc = next_entry(buf, fp, sizeof(u32));
1848 if (rc < 0)
1849 goto bad;
1850 nel = le32_to_cpu(buf[0]);
1851 ltr = NULL;
1852 for (i = 0; i < nel; i++) {
James Morris89d155e2005-10-30 14:59:21 -08001853 tr = kzalloc(sizeof(*tr), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001854 if (!tr) {
1855 rc = -ENOMEM;
1856 goto bad;
1857 }
Eric Paris2ced3df2008-04-17 13:37:12 -04001858 if (ltr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001859 ltr->next = tr;
Eric Paris2ced3df2008-04-17 13:37:12 -04001860 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001861 p->role_tr = tr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001862 rc = next_entry(buf, fp, sizeof(u32)*3);
1863 if (rc < 0)
1864 goto bad;
1865 tr->role = le32_to_cpu(buf[0]);
1866 tr->type = le32_to_cpu(buf[1]);
1867 tr->new_role = le32_to_cpu(buf[2]);
Stephen Smalley45e54212007-11-07 10:08:00 -05001868 if (!policydb_role_isvalid(p, tr->role) ||
1869 !policydb_type_isvalid(p, tr->type) ||
1870 !policydb_role_isvalid(p, tr->new_role)) {
1871 rc = -EINVAL;
1872 goto bad;
1873 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001874 ltr = tr;
1875 }
1876
1877 rc = next_entry(buf, fp, sizeof(u32));
1878 if (rc < 0)
1879 goto bad;
1880 nel = le32_to_cpu(buf[0]);
1881 lra = NULL;
1882 for (i = 0; i < nel; i++) {
James Morris89d155e2005-10-30 14:59:21 -08001883 ra = kzalloc(sizeof(*ra), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001884 if (!ra) {
1885 rc = -ENOMEM;
1886 goto bad;
1887 }
Eric Paris2ced3df2008-04-17 13:37:12 -04001888 if (lra)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001889 lra->next = ra;
Eric Paris2ced3df2008-04-17 13:37:12 -04001890 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001891 p->role_allow = ra;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001892 rc = next_entry(buf, fp, sizeof(u32)*2);
1893 if (rc < 0)
1894 goto bad;
1895 ra->role = le32_to_cpu(buf[0]);
1896 ra->new_role = le32_to_cpu(buf[1]);
Stephen Smalley45e54212007-11-07 10:08:00 -05001897 if (!policydb_role_isvalid(p, ra->role) ||
1898 !policydb_role_isvalid(p, ra->new_role)) {
1899 rc = -EINVAL;
1900 goto bad;
1901 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001902 lra = ra;
1903 }
1904
1905 rc = policydb_index_classes(p);
1906 if (rc)
1907 goto bad;
1908
1909 rc = policydb_index_others(p);
1910 if (rc)
1911 goto bad;
1912
Stephen Smalleyc6d3aaa2009-09-30 13:37:50 -04001913 p->process_class = string_to_security_class(p, "process");
1914 if (!p->process_class)
1915 goto bad;
1916 p->process_trans_perms = string_to_av_perm(p, p->process_class,
1917 "transition");
1918 p->process_trans_perms |= string_to_av_perm(p, p->process_class,
1919 "dyntransition");
1920 if (!p->process_trans_perms)
1921 goto bad;
1922
Linus Torvalds1da177e2005-04-16 15:20:36 -07001923 for (i = 0; i < info->ocon_num; i++) {
1924 rc = next_entry(buf, fp, sizeof(u32));
1925 if (rc < 0)
1926 goto bad;
1927 nel = le32_to_cpu(buf[0]);
1928 l = NULL;
1929 for (j = 0; j < nel; j++) {
James Morris89d155e2005-10-30 14:59:21 -08001930 c = kzalloc(sizeof(*c), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001931 if (!c) {
1932 rc = -ENOMEM;
1933 goto bad;
1934 }
Eric Paris2ced3df2008-04-17 13:37:12 -04001935 if (l)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001936 l->next = c;
Eric Paris2ced3df2008-04-17 13:37:12 -04001937 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001938 p->ocontexts[i] = c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001939 l = c;
1940 rc = -EINVAL;
1941 switch (i) {
1942 case OCON_ISID:
1943 rc = next_entry(buf, fp, sizeof(u32));
1944 if (rc < 0)
1945 goto bad;
1946 c->sid[0] = le32_to_cpu(buf[0]);
1947 rc = context_read_and_validate(&c->context[0], p, fp);
1948 if (rc)
1949 goto bad;
1950 break;
1951 case OCON_FS:
1952 case OCON_NETIF:
1953 rc = next_entry(buf, fp, sizeof(u32));
1954 if (rc < 0)
1955 goto bad;
1956 len = le32_to_cpu(buf[0]);
Eric Paris2ced3df2008-04-17 13:37:12 -04001957 c->u.name = kmalloc(len + 1, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001958 if (!c->u.name) {
1959 rc = -ENOMEM;
1960 goto bad;
1961 }
1962 rc = next_entry(c->u.name, fp, len);
1963 if (rc < 0)
1964 goto bad;
1965 c->u.name[len] = 0;
1966 rc = context_read_and_validate(&c->context[0], p, fp);
1967 if (rc)
1968 goto bad;
1969 rc = context_read_and_validate(&c->context[1], p, fp);
1970 if (rc)
1971 goto bad;
1972 break;
1973 case OCON_PORT:
1974 rc = next_entry(buf, fp, sizeof(u32)*3);
1975 if (rc < 0)
1976 goto bad;
1977 c->u.port.protocol = le32_to_cpu(buf[0]);
1978 c->u.port.low_port = le32_to_cpu(buf[1]);
1979 c->u.port.high_port = le32_to_cpu(buf[2]);
1980 rc = context_read_and_validate(&c->context[0], p, fp);
1981 if (rc)
1982 goto bad;
1983 break;
1984 case OCON_NODE:
Stephen Smalley59dbd1b2008-06-05 09:48:51 -04001985 rc = next_entry(nodebuf, fp, sizeof(u32) * 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001986 if (rc < 0)
1987 goto bad;
Stephen Smalley59dbd1b2008-06-05 09:48:51 -04001988 c->u.node.addr = nodebuf[0]; /* network order */
1989 c->u.node.mask = nodebuf[1]; /* network order */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001990 rc = context_read_and_validate(&c->context[0], p, fp);
1991 if (rc)
1992 goto bad;
1993 break;
1994 case OCON_FSUSE:
1995 rc = next_entry(buf, fp, sizeof(u32)*2);
1996 if (rc < 0)
1997 goto bad;
1998 c->v.behavior = le32_to_cpu(buf[0]);
1999 if (c->v.behavior > SECURITY_FS_USE_NONE)
2000 goto bad;
2001 len = le32_to_cpu(buf[1]);
Eric Paris2ced3df2008-04-17 13:37:12 -04002002 c->u.name = kmalloc(len + 1, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002003 if (!c->u.name) {
2004 rc = -ENOMEM;
2005 goto bad;
2006 }
2007 rc = next_entry(c->u.name, fp, len);
2008 if (rc < 0)
2009 goto bad;
2010 c->u.name[len] = 0;
2011 rc = context_read_and_validate(&c->context[0], p, fp);
2012 if (rc)
2013 goto bad;
2014 break;
2015 case OCON_NODE6: {
2016 int k;
2017
Stephen Smalley59dbd1b2008-06-05 09:48:51 -04002018 rc = next_entry(nodebuf, fp, sizeof(u32) * 8);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002019 if (rc < 0)
2020 goto bad;
2021 for (k = 0; k < 4; k++)
Stephen Smalley59dbd1b2008-06-05 09:48:51 -04002022 c->u.node6.addr[k] = nodebuf[k];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002023 for (k = 0; k < 4; k++)
Stephen Smalley59dbd1b2008-06-05 09:48:51 -04002024 c->u.node6.mask[k] = nodebuf[k+4];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002025 if (context_read_and_validate(&c->context[0], p, fp))
2026 goto bad;
2027 break;
2028 }
2029 }
2030 }
2031 }
2032
2033 rc = next_entry(buf, fp, sizeof(u32));
2034 if (rc < 0)
2035 goto bad;
2036 nel = le32_to_cpu(buf[0]);
2037 genfs_p = NULL;
2038 rc = -EINVAL;
2039 for (i = 0; i < nel; i++) {
2040 rc = next_entry(buf, fp, sizeof(u32));
2041 if (rc < 0)
2042 goto bad;
2043 len = le32_to_cpu(buf[0]);
James Morris89d155e2005-10-30 14:59:21 -08002044 newgenfs = kzalloc(sizeof(*newgenfs), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002045 if (!newgenfs) {
2046 rc = -ENOMEM;
2047 goto bad;
2048 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002049
Eric Paris2ced3df2008-04-17 13:37:12 -04002050 newgenfs->fstype = kmalloc(len + 1, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002051 if (!newgenfs->fstype) {
2052 rc = -ENOMEM;
2053 kfree(newgenfs);
2054 goto bad;
2055 }
2056 rc = next_entry(newgenfs->fstype, fp, len);
2057 if (rc < 0) {
2058 kfree(newgenfs->fstype);
2059 kfree(newgenfs);
2060 goto bad;
2061 }
2062 newgenfs->fstype[len] = 0;
2063 for (genfs_p = NULL, genfs = p->genfs; genfs;
2064 genfs_p = genfs, genfs = genfs->next) {
2065 if (strcmp(newgenfs->fstype, genfs->fstype) == 0) {
James Morris454d9722008-02-26 20:42:02 +11002066 printk(KERN_ERR "SELinux: dup genfs "
Linus Torvalds1da177e2005-04-16 15:20:36 -07002067 "fstype %s\n", newgenfs->fstype);
2068 kfree(newgenfs->fstype);
2069 kfree(newgenfs);
2070 goto bad;
2071 }
2072 if (strcmp(newgenfs->fstype, genfs->fstype) < 0)
2073 break;
2074 }
2075 newgenfs->next = genfs;
2076 if (genfs_p)
2077 genfs_p->next = newgenfs;
2078 else
2079 p->genfs = newgenfs;
2080 rc = next_entry(buf, fp, sizeof(u32));
2081 if (rc < 0)
2082 goto bad;
2083 nel2 = le32_to_cpu(buf[0]);
2084 for (j = 0; j < nel2; j++) {
2085 rc = next_entry(buf, fp, sizeof(u32));
2086 if (rc < 0)
2087 goto bad;
2088 len = le32_to_cpu(buf[0]);
2089
James Morris89d155e2005-10-30 14:59:21 -08002090 newc = kzalloc(sizeof(*newc), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002091 if (!newc) {
2092 rc = -ENOMEM;
2093 goto bad;
2094 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002095
Eric Paris2ced3df2008-04-17 13:37:12 -04002096 newc->u.name = kmalloc(len + 1, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002097 if (!newc->u.name) {
2098 rc = -ENOMEM;
2099 goto bad_newc;
2100 }
2101 rc = next_entry(newc->u.name, fp, len);
2102 if (rc < 0)
2103 goto bad_newc;
2104 newc->u.name[len] = 0;
2105 rc = next_entry(buf, fp, sizeof(u32));
2106 if (rc < 0)
2107 goto bad_newc;
2108 newc->v.sclass = le32_to_cpu(buf[0]);
2109 if (context_read_and_validate(&newc->context[0], p, fp))
2110 goto bad_newc;
2111 for (l = NULL, c = newgenfs->head; c;
2112 l = c, c = c->next) {
2113 if (!strcmp(newc->u.name, c->u.name) &&
2114 (!c->v.sclass || !newc->v.sclass ||
2115 newc->v.sclass == c->v.sclass)) {
James Morris454d9722008-02-26 20:42:02 +11002116 printk(KERN_ERR "SELinux: dup genfs "
Linus Torvalds1da177e2005-04-16 15:20:36 -07002117 "entry (%s,%s)\n",
2118 newgenfs->fstype, c->u.name);
2119 goto bad_newc;
2120 }
2121 len = strlen(newc->u.name);
2122 len2 = strlen(c->u.name);
2123 if (len > len2)
2124 break;
2125 }
2126
2127 newc->next = c;
2128 if (l)
2129 l->next = newc;
2130 else
2131 newgenfs->head = newc;
2132 }
2133 }
2134
2135 if (p->policyvers >= POLICYDB_VERSION_MLS) {
Darrel Goeddelf3f87712006-09-25 23:31:59 -07002136 int new_rangetr = p->policyvers >= POLICYDB_VERSION_RANGETRANS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002137 rc = next_entry(buf, fp, sizeof(u32));
2138 if (rc < 0)
2139 goto bad;
2140 nel = le32_to_cpu(buf[0]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002141 for (i = 0; i < nel; i++) {
James Morris89d155e2005-10-30 14:59:21 -08002142 rt = kzalloc(sizeof(*rt), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002143 if (!rt) {
2144 rc = -ENOMEM;
2145 goto bad;
2146 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002147 rc = next_entry(buf, fp, (sizeof(u32) * 2));
Stephen Smalley2f3e82d2010-01-07 15:55:16 -05002148 if (rc < 0) {
2149 kfree(rt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002150 goto bad;
Stephen Smalley2f3e82d2010-01-07 15:55:16 -05002151 }
Darrel Goeddelf3f87712006-09-25 23:31:59 -07002152 rt->source_type = le32_to_cpu(buf[0]);
2153 rt->target_type = le32_to_cpu(buf[1]);
2154 if (new_rangetr) {
2155 rc = next_entry(buf, fp, sizeof(u32));
Stephen Smalley2f3e82d2010-01-07 15:55:16 -05002156 if (rc < 0) {
2157 kfree(rt);
Darrel Goeddelf3f87712006-09-25 23:31:59 -07002158 goto bad;
Stephen Smalley2f3e82d2010-01-07 15:55:16 -05002159 }
Darrel Goeddelf3f87712006-09-25 23:31:59 -07002160 rt->target_class = le32_to_cpu(buf[0]);
2161 } else
Stephen Smalleyc6d3aaa2009-09-30 13:37:50 -04002162 rt->target_class = p->process_class;
Stephen Smalley45e54212007-11-07 10:08:00 -05002163 if (!policydb_type_isvalid(p, rt->source_type) ||
2164 !policydb_type_isvalid(p, rt->target_type) ||
2165 !policydb_class_isvalid(p, rt->target_class)) {
Stephen Smalley2f3e82d2010-01-07 15:55:16 -05002166 kfree(rt);
Stephen Smalley45e54212007-11-07 10:08:00 -05002167 rc = -EINVAL;
2168 goto bad;
2169 }
Stephen Smalley2f3e82d2010-01-07 15:55:16 -05002170 r = kzalloc(sizeof(*r), GFP_KERNEL);
2171 if (!r) {
2172 kfree(rt);
2173 rc = -ENOMEM;
Stephen Smalley45e54212007-11-07 10:08:00 -05002174 goto bad;
2175 }
Stephen Smalley2f3e82d2010-01-07 15:55:16 -05002176 rc = mls_read_range_helper(r, fp);
2177 if (rc) {
2178 kfree(rt);
2179 kfree(r);
2180 goto bad;
2181 }
2182 if (!mls_range_isvalid(p, r)) {
2183 printk(KERN_WARNING "SELinux: rangetrans: invalid range\n");
2184 kfree(rt);
2185 kfree(r);
2186 goto bad;
2187 }
2188 rc = hashtab_insert(p->range_tr, rt, r);
2189 if (rc) {
2190 kfree(rt);
2191 kfree(r);
2192 goto bad;
2193 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002194 }
Stephen Smalley2f3e82d2010-01-07 15:55:16 -05002195 rangetr_hash_eval(p->range_tr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002196 }
2197
Stephen Smalley782ebb92005-09-03 15:55:16 -07002198 p->type_attr_map = kmalloc(p->p_types.nprim*sizeof(struct ebitmap), GFP_KERNEL);
2199 if (!p->type_attr_map)
2200 goto bad;
2201
2202 for (i = 0; i < p->p_types.nprim; i++) {
2203 ebitmap_init(&p->type_attr_map[i]);
2204 if (p->policyvers >= POLICYDB_VERSION_AVTAB) {
2205 if (ebitmap_read(&p->type_attr_map[i], fp))
2206 goto bad;
2207 }
2208 /* add the type itself as the degenerate case */
2209 if (ebitmap_set_bit(&p->type_attr_map[i], i, 1))
2210 goto bad;
2211 }
2212
KaiGai Koheid9250de2008-08-28 16:35:57 +09002213 rc = policydb_bounds_sanity_check(p);
2214 if (rc)
2215 goto bad;
2216
Linus Torvalds1da177e2005-04-16 15:20:36 -07002217 rc = 0;
2218out:
2219 return rc;
2220bad_newc:
Eric Paris2ced3df2008-04-17 13:37:12 -04002221 ocontext_destroy(newc, OCON_FSUSE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002222bad:
2223 if (!rc)
2224 rc = -EINVAL;
2225 policydb_destroy(p);
2226 goto out;
2227}