blob: 0ac1021734c01118a012b38ab7335b8eeeb2f4fa [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 *
14 * Added conditional policy language extensions
15 *
16 * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc.
17 * Copyright (C) 2003 - 2004 Tresys Technology, LLC
18 * This program is free software; you can redistribute it and/or modify
19 * it under the terms of the GNU General Public License as published by
20 * the Free Software Foundation, version 2.
21 */
22
23#include <linux/kernel.h>
24#include <linux/slab.h>
25#include <linux/string.h>
26#include <linux/errno.h>
27#include "security.h"
28
29#include "policydb.h"
30#include "conditional.h"
31#include "mls.h"
32
33#define _DEBUG_HASHES
34
35#ifdef DEBUG_HASHES
36static char *symtab_name[SYM_NUM] = {
37 "common prefixes",
38 "classes",
39 "roles",
40 "types",
41 "users",
42 "bools",
43 "levels",
44 "categories",
45};
46#endif
47
48int selinux_mls_enabled = 0;
49
50static unsigned int symtab_sizes[SYM_NUM] = {
51 2,
52 32,
53 16,
54 512,
55 128,
56 16,
57 16,
58 16,
59};
60
61struct policydb_compat_info {
62 int version;
63 int sym_num;
64 int ocon_num;
65};
66
67/* These need to be updated if SYM_NUM or OCON_NUM changes */
68static struct policydb_compat_info policydb_compat[] = {
69 {
70 .version = POLICYDB_VERSION_BASE,
71 .sym_num = SYM_NUM - 3,
72 .ocon_num = OCON_NUM - 1,
73 },
74 {
75 .version = POLICYDB_VERSION_BOOL,
76 .sym_num = SYM_NUM - 2,
77 .ocon_num = OCON_NUM - 1,
78 },
79 {
80 .version = POLICYDB_VERSION_IPV6,
81 .sym_num = SYM_NUM - 2,
82 .ocon_num = OCON_NUM,
83 },
84 {
85 .version = POLICYDB_VERSION_NLCLASS,
86 .sym_num = SYM_NUM - 2,
87 .ocon_num = OCON_NUM,
88 },
89 {
90 .version = POLICYDB_VERSION_MLS,
91 .sym_num = SYM_NUM,
92 .ocon_num = OCON_NUM,
93 },
Stephen Smalley782ebb92005-09-03 15:55:16 -070094 {
95 .version = POLICYDB_VERSION_AVTAB,
96 .sym_num = SYM_NUM,
97 .ocon_num = OCON_NUM,
98 },
Darrel Goeddelf3f87712006-09-25 23:31:59 -070099 {
100 .version = POLICYDB_VERSION_RANGETRANS,
101 .sym_num = SYM_NUM,
102 .ocon_num = OCON_NUM,
103 },
Linus Torvalds1da177e2005-04-16 15:20:36 -0700104};
105
106static struct policydb_compat_info *policydb_lookup_compat(int version)
107{
108 int i;
109 struct policydb_compat_info *info = NULL;
110
Tobias Klauser32725ad2006-01-06 00:11:23 -0800111 for (i = 0; i < ARRAY_SIZE(policydb_compat); i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700112 if (policydb_compat[i].version == version) {
113 info = &policydb_compat[i];
114 break;
115 }
116 }
117 return info;
118}
119
120/*
121 * Initialize the role table.
122 */
123static int roles_init(struct policydb *p)
124{
125 char *key = NULL;
126 int rc;
127 struct role_datum *role;
128
James Morris89d155e2005-10-30 14:59:21 -0800129 role = kzalloc(sizeof(*role), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700130 if (!role) {
131 rc = -ENOMEM;
132 goto out;
133 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700134 role->value = ++p->p_roles.nprim;
135 if (role->value != OBJECT_R_VAL) {
136 rc = -EINVAL;
137 goto out_free_role;
138 }
139 key = kmalloc(strlen(OBJECT_R)+1,GFP_KERNEL);
140 if (!key) {
141 rc = -ENOMEM;
142 goto out_free_role;
143 }
144 strcpy(key, OBJECT_R);
145 rc = hashtab_insert(p->p_roles.table, key, role);
146 if (rc)
147 goto out_free_key;
148out:
149 return rc;
150
151out_free_key:
152 kfree(key);
153out_free_role:
154 kfree(role);
155 goto out;
156}
157
158/*
159 * Initialize a policy database structure.
160 */
161static int policydb_init(struct policydb *p)
162{
163 int i, rc;
164
165 memset(p, 0, sizeof(*p));
166
167 for (i = 0; i < SYM_NUM; i++) {
168 rc = symtab_init(&p->symtab[i], symtab_sizes[i]);
169 if (rc)
170 goto out_free_symtab;
171 }
172
173 rc = avtab_init(&p->te_avtab);
174 if (rc)
175 goto out_free_symtab;
176
177 rc = roles_init(p);
178 if (rc)
179 goto out_free_avtab;
180
181 rc = cond_policydb_init(p);
182 if (rc)
183 goto out_free_avtab;
184
185out:
186 return rc;
187
188out_free_avtab:
189 avtab_destroy(&p->te_avtab);
190
191out_free_symtab:
192 for (i = 0; i < SYM_NUM; i++)
193 hashtab_destroy(p->symtab[i].table);
194 goto out;
195}
196
197/*
198 * The following *_index functions are used to
199 * define the val_to_name and val_to_struct arrays
200 * in a policy database structure. The val_to_name
201 * arrays are used when converting security context
202 * structures into string representations. The
203 * val_to_struct arrays are used when the attributes
204 * of a class, role, or user are needed.
205 */
206
207static int common_index(void *key, void *datum, void *datap)
208{
209 struct policydb *p;
210 struct common_datum *comdatum;
211
212 comdatum = datum;
213 p = datap;
214 if (!comdatum->value || comdatum->value > p->p_commons.nprim)
215 return -EINVAL;
216 p->p_common_val_to_name[comdatum->value - 1] = key;
217 return 0;
218}
219
220static int class_index(void *key, void *datum, void *datap)
221{
222 struct policydb *p;
223 struct class_datum *cladatum;
224
225 cladatum = datum;
226 p = datap;
227 if (!cladatum->value || cladatum->value > p->p_classes.nprim)
228 return -EINVAL;
229 p->p_class_val_to_name[cladatum->value - 1] = key;
230 p->class_val_to_struct[cladatum->value - 1] = cladatum;
231 return 0;
232}
233
234static int role_index(void *key, void *datum, void *datap)
235{
236 struct policydb *p;
237 struct role_datum *role;
238
239 role = datum;
240 p = datap;
241 if (!role->value || role->value > p->p_roles.nprim)
242 return -EINVAL;
243 p->p_role_val_to_name[role->value - 1] = key;
244 p->role_val_to_struct[role->value - 1] = role;
245 return 0;
246}
247
248static int type_index(void *key, void *datum, void *datap)
249{
250 struct policydb *p;
251 struct type_datum *typdatum;
252
253 typdatum = datum;
254 p = datap;
255
256 if (typdatum->primary) {
257 if (!typdatum->value || typdatum->value > p->p_types.nprim)
258 return -EINVAL;
259 p->p_type_val_to_name[typdatum->value - 1] = key;
260 }
261
262 return 0;
263}
264
265static int user_index(void *key, void *datum, void *datap)
266{
267 struct policydb *p;
268 struct user_datum *usrdatum;
269
270 usrdatum = datum;
271 p = datap;
272 if (!usrdatum->value || usrdatum->value > p->p_users.nprim)
273 return -EINVAL;
274 p->p_user_val_to_name[usrdatum->value - 1] = key;
275 p->user_val_to_struct[usrdatum->value - 1] = usrdatum;
276 return 0;
277}
278
279static int sens_index(void *key, void *datum, void *datap)
280{
281 struct policydb *p;
282 struct level_datum *levdatum;
283
284 levdatum = datum;
285 p = datap;
286
287 if (!levdatum->isalias) {
288 if (!levdatum->level->sens ||
289 levdatum->level->sens > p->p_levels.nprim)
290 return -EINVAL;
291 p->p_sens_val_to_name[levdatum->level->sens - 1] = key;
292 }
293
294 return 0;
295}
296
297static int cat_index(void *key, void *datum, void *datap)
298{
299 struct policydb *p;
300 struct cat_datum *catdatum;
301
302 catdatum = datum;
303 p = datap;
304
305 if (!catdatum->isalias) {
306 if (!catdatum->value || catdatum->value > p->p_cats.nprim)
307 return -EINVAL;
308 p->p_cat_val_to_name[catdatum->value - 1] = key;
309 }
310
311 return 0;
312}
313
314static int (*index_f[SYM_NUM]) (void *key, void *datum, void *datap) =
315{
316 common_index,
317 class_index,
318 role_index,
319 type_index,
320 user_index,
321 cond_index_bool,
322 sens_index,
323 cat_index,
324};
325
326/*
327 * Define the common val_to_name array and the class
328 * val_to_name and val_to_struct arrays in a policy
329 * database structure.
330 *
331 * Caller must clean up upon failure.
332 */
333static int policydb_index_classes(struct policydb *p)
334{
335 int rc;
336
337 p->p_common_val_to_name =
338 kmalloc(p->p_commons.nprim * sizeof(char *), GFP_KERNEL);
339 if (!p->p_common_val_to_name) {
340 rc = -ENOMEM;
341 goto out;
342 }
343
344 rc = hashtab_map(p->p_commons.table, common_index, p);
345 if (rc)
346 goto out;
347
348 p->class_val_to_struct =
349 kmalloc(p->p_classes.nprim * sizeof(*(p->class_val_to_struct)), GFP_KERNEL);
350 if (!p->class_val_to_struct) {
351 rc = -ENOMEM;
352 goto out;
353 }
354
355 p->p_class_val_to_name =
356 kmalloc(p->p_classes.nprim * sizeof(char *), GFP_KERNEL);
357 if (!p->p_class_val_to_name) {
358 rc = -ENOMEM;
359 goto out;
360 }
361
362 rc = hashtab_map(p->p_classes.table, class_index, p);
363out:
364 return rc;
365}
366
367#ifdef DEBUG_HASHES
368static void symtab_hash_eval(struct symtab *s)
369{
370 int i;
371
372 for (i = 0; i < SYM_NUM; i++) {
373 struct hashtab *h = s[i].table;
374 struct hashtab_info info;
375
376 hashtab_stat(h, &info);
Eric Parisfadcdb42007-02-22 18:11:31 -0500377 printk(KERN_DEBUG "%s: %d entries and %d/%d buckets used, "
Linus Torvalds1da177e2005-04-16 15:20:36 -0700378 "longest chain length %d\n", symtab_name[i], h->nel,
379 info.slots_used, h->size, info.max_chain_len);
380 }
381}
382#endif
383
384/*
385 * Define the other val_to_name and val_to_struct arrays
386 * in a policy database structure.
387 *
388 * Caller must clean up on failure.
389 */
390static int policydb_index_others(struct policydb *p)
391{
392 int i, rc = 0;
393
Eric Parisfadcdb42007-02-22 18:11:31 -0500394 printk(KERN_DEBUG "security: %d users, %d roles, %d types, %d bools",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700395 p->p_users.nprim, p->p_roles.nprim, p->p_types.nprim, p->p_bools.nprim);
396 if (selinux_mls_enabled)
397 printk(", %d sens, %d cats", p->p_levels.nprim,
398 p->p_cats.nprim);
399 printk("\n");
400
Eric Parisfadcdb42007-02-22 18:11:31 -0500401 printk(KERN_DEBUG "security: %d classes, %d rules\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700402 p->p_classes.nprim, p->te_avtab.nel);
403
404#ifdef DEBUG_HASHES
405 avtab_hash_eval(&p->te_avtab, "rules");
406 symtab_hash_eval(p->symtab);
407#endif
408
409 p->role_val_to_struct =
410 kmalloc(p->p_roles.nprim * sizeof(*(p->role_val_to_struct)),
411 GFP_KERNEL);
412 if (!p->role_val_to_struct) {
413 rc = -ENOMEM;
414 goto out;
415 }
416
417 p->user_val_to_struct =
418 kmalloc(p->p_users.nprim * sizeof(*(p->user_val_to_struct)),
419 GFP_KERNEL);
420 if (!p->user_val_to_struct) {
421 rc = -ENOMEM;
422 goto out;
423 }
424
425 if (cond_init_bool_indexes(p)) {
426 rc = -ENOMEM;
427 goto out;
428 }
429
430 for (i = SYM_ROLES; i < SYM_NUM; i++) {
431 p->sym_val_to_name[i] =
432 kmalloc(p->symtab[i].nprim * sizeof(char *), GFP_KERNEL);
433 if (!p->sym_val_to_name[i]) {
434 rc = -ENOMEM;
435 goto out;
436 }
437 rc = hashtab_map(p->symtab[i].table, index_f[i], p);
438 if (rc)
439 goto out;
440 }
441
442out:
443 return rc;
444}
445
446/*
447 * The following *_destroy functions are used to
448 * free any memory allocated for each kind of
449 * symbol data in the policy database.
450 */
451
452static int perm_destroy(void *key, void *datum, void *p)
453{
454 kfree(key);
455 kfree(datum);
456 return 0;
457}
458
459static int common_destroy(void *key, void *datum, void *p)
460{
461 struct common_datum *comdatum;
462
463 kfree(key);
464 comdatum = datum;
465 hashtab_map(comdatum->permissions.table, perm_destroy, NULL);
466 hashtab_destroy(comdatum->permissions.table);
467 kfree(datum);
468 return 0;
469}
470
James Morris6cbda6b2006-11-29 16:50:27 -0500471static int cls_destroy(void *key, void *datum, void *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700472{
473 struct class_datum *cladatum;
474 struct constraint_node *constraint, *ctemp;
475 struct constraint_expr *e, *etmp;
476
477 kfree(key);
478 cladatum = datum;
479 hashtab_map(cladatum->permissions.table, perm_destroy, NULL);
480 hashtab_destroy(cladatum->permissions.table);
481 constraint = cladatum->constraints;
482 while (constraint) {
483 e = constraint->expr;
484 while (e) {
485 ebitmap_destroy(&e->names);
486 etmp = e;
487 e = e->next;
488 kfree(etmp);
489 }
490 ctemp = constraint;
491 constraint = constraint->next;
492 kfree(ctemp);
493 }
494
495 constraint = cladatum->validatetrans;
496 while (constraint) {
497 e = constraint->expr;
498 while (e) {
499 ebitmap_destroy(&e->names);
500 etmp = e;
501 e = e->next;
502 kfree(etmp);
503 }
504 ctemp = constraint;
505 constraint = constraint->next;
506 kfree(ctemp);
507 }
508
509 kfree(cladatum->comkey);
510 kfree(datum);
511 return 0;
512}
513
514static int role_destroy(void *key, void *datum, void *p)
515{
516 struct role_datum *role;
517
518 kfree(key);
519 role = datum;
520 ebitmap_destroy(&role->dominates);
521 ebitmap_destroy(&role->types);
522 kfree(datum);
523 return 0;
524}
525
526static int type_destroy(void *key, void *datum, void *p)
527{
528 kfree(key);
529 kfree(datum);
530 return 0;
531}
532
533static int user_destroy(void *key, void *datum, void *p)
534{
535 struct user_datum *usrdatum;
536
537 kfree(key);
538 usrdatum = datum;
539 ebitmap_destroy(&usrdatum->roles);
540 ebitmap_destroy(&usrdatum->range.level[0].cat);
541 ebitmap_destroy(&usrdatum->range.level[1].cat);
542 ebitmap_destroy(&usrdatum->dfltlevel.cat);
543 kfree(datum);
544 return 0;
545}
546
547static int sens_destroy(void *key, void *datum, void *p)
548{
549 struct level_datum *levdatum;
550
551 kfree(key);
552 levdatum = datum;
553 ebitmap_destroy(&levdatum->level->cat);
554 kfree(levdatum->level);
555 kfree(datum);
556 return 0;
557}
558
559static int cat_destroy(void *key, void *datum, void *p)
560{
561 kfree(key);
562 kfree(datum);
563 return 0;
564}
565
566static int (*destroy_f[SYM_NUM]) (void *key, void *datum, void *datap) =
567{
568 common_destroy,
James Morris6cbda6b2006-11-29 16:50:27 -0500569 cls_destroy,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700570 role_destroy,
571 type_destroy,
572 user_destroy,
573 cond_destroy_bool,
574 sens_destroy,
575 cat_destroy,
576};
577
578static void ocontext_destroy(struct ocontext *c, int i)
579{
580 context_destroy(&c->context[0]);
581 context_destroy(&c->context[1]);
582 if (i == OCON_ISID || i == OCON_FS ||
583 i == OCON_NETIF || i == OCON_FSUSE)
584 kfree(c->u.name);
585 kfree(c);
586}
587
588/*
589 * Free any memory allocated by a policy database structure.
590 */
591void policydb_destroy(struct policydb *p)
592{
593 struct ocontext *c, *ctmp;
594 struct genfs *g, *gtmp;
595 int i;
Stephen Smalley782ebb92005-09-03 15:55:16 -0700596 struct role_allow *ra, *lra = NULL;
597 struct role_trans *tr, *ltr = NULL;
598 struct range_trans *rt, *lrt = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700599
600 for (i = 0; i < SYM_NUM; i++) {
601 hashtab_map(p->symtab[i].table, destroy_f[i], NULL);
602 hashtab_destroy(p->symtab[i].table);
603 }
604
Jesper Juhl9a5f04b2005-06-25 14:58:51 -0700605 for (i = 0; i < SYM_NUM; i++)
606 kfree(p->sym_val_to_name[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700607
Jesper Juhl9a5f04b2005-06-25 14:58:51 -0700608 kfree(p->class_val_to_struct);
609 kfree(p->role_val_to_struct);
610 kfree(p->user_val_to_struct);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700611
612 avtab_destroy(&p->te_avtab);
613
614 for (i = 0; i < OCON_NUM; i++) {
615 c = p->ocontexts[i];
616 while (c) {
617 ctmp = c;
618 c = c->next;
619 ocontext_destroy(ctmp,i);
620 }
Chad Sellers6e8c7512006-10-06 16:09:52 -0400621 p->ocontexts[i] = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700622 }
623
624 g = p->genfs;
625 while (g) {
626 kfree(g->fstype);
627 c = g->head;
628 while (c) {
629 ctmp = c;
630 c = c->next;
631 ocontext_destroy(ctmp,OCON_FSUSE);
632 }
633 gtmp = g;
634 g = g->next;
635 kfree(gtmp);
636 }
Chad Sellers6e8c7512006-10-06 16:09:52 -0400637 p->genfs = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700638
639 cond_policydb_destroy(p);
640
Stephen Smalley782ebb92005-09-03 15:55:16 -0700641 for (tr = p->role_tr; tr; tr = tr->next) {
Jesper Juhla7f988b2005-11-07 01:01:35 -0800642 kfree(ltr);
Stephen Smalley782ebb92005-09-03 15:55:16 -0700643 ltr = tr;
644 }
Jesper Juhla7f988b2005-11-07 01:01:35 -0800645 kfree(ltr);
Stephen Smalley782ebb92005-09-03 15:55:16 -0700646
647 for (ra = p->role_allow; ra; ra = ra -> next) {
Jesper Juhla7f988b2005-11-07 01:01:35 -0800648 kfree(lra);
Stephen Smalley782ebb92005-09-03 15:55:16 -0700649 lra = ra;
650 }
Jesper Juhla7f988b2005-11-07 01:01:35 -0800651 kfree(lra);
Stephen Smalley782ebb92005-09-03 15:55:16 -0700652
653 for (rt = p->range_tr; rt; rt = rt -> next) {
Darrel Goeddelddccef32006-07-30 03:03:17 -0700654 if (lrt) {
Darrel Goeddelf3f87712006-09-25 23:31:59 -0700655 ebitmap_destroy(&lrt->target_range.level[0].cat);
656 ebitmap_destroy(&lrt->target_range.level[1].cat);
Darrel Goeddelddccef32006-07-30 03:03:17 -0700657 kfree(lrt);
658 }
Stephen Smalley782ebb92005-09-03 15:55:16 -0700659 lrt = rt;
660 }
Darrel Goeddelddccef32006-07-30 03:03:17 -0700661 if (lrt) {
Darrel Goeddelf3f87712006-09-25 23:31:59 -0700662 ebitmap_destroy(&lrt->target_range.level[0].cat);
663 ebitmap_destroy(&lrt->target_range.level[1].cat);
Darrel Goeddelddccef32006-07-30 03:03:17 -0700664 kfree(lrt);
665 }
Stephen Smalley782ebb92005-09-03 15:55:16 -0700666
Stephen Smalley282c1f52005-10-23 12:57:15 -0700667 if (p->type_attr_map) {
668 for (i = 0; i < p->p_types.nprim; i++)
669 ebitmap_destroy(&p->type_attr_map[i]);
670 }
Stephen Smalley782ebb92005-09-03 15:55:16 -0700671 kfree(p->type_attr_map);
672
Linus Torvalds1da177e2005-04-16 15:20:36 -0700673 return;
674}
675
676/*
677 * Load the initial SIDs specified in a policy database
678 * structure into a SID table.
679 */
680int policydb_load_isids(struct policydb *p, struct sidtab *s)
681{
682 struct ocontext *head, *c;
683 int rc;
684
685 rc = sidtab_init(s);
686 if (rc) {
687 printk(KERN_ERR "security: out of memory on SID table init\n");
688 goto out;
689 }
690
691 head = p->ocontexts[OCON_ISID];
692 for (c = head; c; c = c->next) {
693 if (!c->context[0].user) {
694 printk(KERN_ERR "security: SID %s was never "
695 "defined.\n", c->u.name);
696 rc = -EINVAL;
697 goto out;
698 }
699 if (sidtab_insert(s, c->sid[0], &c->context[0])) {
700 printk(KERN_ERR "security: unable to load initial "
701 "SID %s.\n", c->u.name);
702 rc = -EINVAL;
703 goto out;
704 }
705 }
706out:
707 return rc;
708}
709
710/*
711 * Return 1 if the fields in the security context
712 * structure `c' are valid. Return 0 otherwise.
713 */
714int policydb_context_isvalid(struct policydb *p, struct context *c)
715{
716 struct role_datum *role;
717 struct user_datum *usrdatum;
718
719 if (!c->role || c->role > p->p_roles.nprim)
720 return 0;
721
722 if (!c->user || c->user > p->p_users.nprim)
723 return 0;
724
725 if (!c->type || c->type > p->p_types.nprim)
726 return 0;
727
728 if (c->role != OBJECT_R_VAL) {
729 /*
730 * Role must be authorized for the type.
731 */
732 role = p->role_val_to_struct[c->role - 1];
733 if (!ebitmap_get_bit(&role->types,
734 c->type - 1))
735 /* role may not be associated with type */
736 return 0;
737
738 /*
739 * User must be authorized for the role.
740 */
741 usrdatum = p->user_val_to_struct[c->user - 1];
742 if (!usrdatum)
743 return 0;
744
745 if (!ebitmap_get_bit(&usrdatum->roles,
746 c->role - 1))
747 /* user may not be associated with role */
748 return 0;
749 }
750
751 if (!mls_context_isvalid(p, c))
752 return 0;
753
754 return 1;
755}
756
757/*
758 * Read a MLS range structure from a policydb binary
759 * representation file.
760 */
761static int mls_read_range_helper(struct mls_range *r, void *fp)
762{
Alexey Dobriyanb5bf6c52005-09-03 15:55:17 -0700763 __le32 buf[2];
764 u32 items;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700765 int rc;
766
767 rc = next_entry(buf, fp, sizeof(u32));
768 if (rc < 0)
769 goto out;
770
771 items = le32_to_cpu(buf[0]);
772 if (items > ARRAY_SIZE(buf)) {
773 printk(KERN_ERR "security: mls: range overflow\n");
774 rc = -EINVAL;
775 goto out;
776 }
777 rc = next_entry(buf, fp, sizeof(u32) * items);
778 if (rc < 0) {
779 printk(KERN_ERR "security: mls: truncated range\n");
780 goto out;
781 }
782 r->level[0].sens = le32_to_cpu(buf[0]);
783 if (items > 1)
784 r->level[1].sens = le32_to_cpu(buf[1]);
785 else
786 r->level[1].sens = r->level[0].sens;
787
788 rc = ebitmap_read(&r->level[0].cat, fp);
789 if (rc) {
790 printk(KERN_ERR "security: mls: error reading low "
791 "categories\n");
792 goto out;
793 }
794 if (items > 1) {
795 rc = ebitmap_read(&r->level[1].cat, fp);
796 if (rc) {
797 printk(KERN_ERR "security: mls: error reading high "
798 "categories\n");
799 goto bad_high;
800 }
801 } else {
802 rc = ebitmap_cpy(&r->level[1].cat, &r->level[0].cat);
803 if (rc) {
804 printk(KERN_ERR "security: mls: out of memory\n");
805 goto bad_high;
806 }
807 }
808
809 rc = 0;
810out:
811 return rc;
812bad_high:
813 ebitmap_destroy(&r->level[0].cat);
814 goto out;
815}
816
817/*
818 * Read and validate a security context structure
819 * from a policydb binary representation file.
820 */
821static int context_read_and_validate(struct context *c,
822 struct policydb *p,
823 void *fp)
824{
Alexey Dobriyanb5bf6c52005-09-03 15:55:17 -0700825 __le32 buf[3];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700826 int rc;
827
828 rc = next_entry(buf, fp, sizeof buf);
829 if (rc < 0) {
830 printk(KERN_ERR "security: context truncated\n");
831 goto out;
832 }
833 c->user = le32_to_cpu(buf[0]);
834 c->role = le32_to_cpu(buf[1]);
835 c->type = le32_to_cpu(buf[2]);
836 if (p->policyvers >= POLICYDB_VERSION_MLS) {
837 if (mls_read_range_helper(&c->range, fp)) {
838 printk(KERN_ERR "security: error reading MLS range of "
839 "context\n");
840 rc = -EINVAL;
841 goto out;
842 }
843 }
844
845 if (!policydb_context_isvalid(p, c)) {
846 printk(KERN_ERR "security: invalid security context\n");
847 context_destroy(c);
848 rc = -EINVAL;
849 }
850out:
851 return rc;
852}
853
854/*
855 * The following *_read functions are used to
856 * read the symbol data from a policy database
857 * binary representation file.
858 */
859
860static int perm_read(struct policydb *p, struct hashtab *h, void *fp)
861{
862 char *key = NULL;
863 struct perm_datum *perdatum;
864 int rc;
Alexey Dobriyanb5bf6c52005-09-03 15:55:17 -0700865 __le32 buf[2];
866 u32 len;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700867
James Morris89d155e2005-10-30 14:59:21 -0800868 perdatum = kzalloc(sizeof(*perdatum), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700869 if (!perdatum) {
870 rc = -ENOMEM;
871 goto out;
872 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700873
874 rc = next_entry(buf, fp, sizeof buf);
875 if (rc < 0)
876 goto bad;
877
878 len = le32_to_cpu(buf[0]);
879 perdatum->value = le32_to_cpu(buf[1]);
880
881 key = kmalloc(len + 1,GFP_KERNEL);
882 if (!key) {
883 rc = -ENOMEM;
884 goto bad;
885 }
886 rc = next_entry(key, fp, len);
887 if (rc < 0)
888 goto bad;
889 key[len] = 0;
890
891 rc = hashtab_insert(h, key, perdatum);
892 if (rc)
893 goto bad;
894out:
895 return rc;
896bad:
897 perm_destroy(key, perdatum, NULL);
898 goto out;
899}
900
901static int common_read(struct policydb *p, struct hashtab *h, void *fp)
902{
903 char *key = NULL;
904 struct common_datum *comdatum;
Alexey Dobriyanb5bf6c52005-09-03 15:55:17 -0700905 __le32 buf[4];
906 u32 len, nel;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700907 int i, rc;
908
James Morris89d155e2005-10-30 14:59:21 -0800909 comdatum = kzalloc(sizeof(*comdatum), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700910 if (!comdatum) {
911 rc = -ENOMEM;
912 goto out;
913 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700914
915 rc = next_entry(buf, fp, sizeof buf);
916 if (rc < 0)
917 goto bad;
918
919 len = le32_to_cpu(buf[0]);
920 comdatum->value = le32_to_cpu(buf[1]);
921
922 rc = symtab_init(&comdatum->permissions, PERM_SYMTAB_SIZE);
923 if (rc)
924 goto bad;
925 comdatum->permissions.nprim = le32_to_cpu(buf[2]);
926 nel = le32_to_cpu(buf[3]);
927
928 key = kmalloc(len + 1,GFP_KERNEL);
929 if (!key) {
930 rc = -ENOMEM;
931 goto bad;
932 }
933 rc = next_entry(key, fp, len);
934 if (rc < 0)
935 goto bad;
936 key[len] = 0;
937
938 for (i = 0; i < nel; i++) {
939 rc = perm_read(p, comdatum->permissions.table, fp);
940 if (rc)
941 goto bad;
942 }
943
944 rc = hashtab_insert(h, key, comdatum);
945 if (rc)
946 goto bad;
947out:
948 return rc;
949bad:
950 common_destroy(key, comdatum, NULL);
951 goto out;
952}
953
954static int read_cons_helper(struct constraint_node **nodep, int ncons,
955 int allowxtarget, void *fp)
956{
957 struct constraint_node *c, *lc;
958 struct constraint_expr *e, *le;
Alexey Dobriyanb5bf6c52005-09-03 15:55:17 -0700959 __le32 buf[3];
960 u32 nexpr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700961 int rc, i, j, depth;
962
963 lc = NULL;
964 for (i = 0; i < ncons; i++) {
James Morris89d155e2005-10-30 14:59:21 -0800965 c = kzalloc(sizeof(*c), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700966 if (!c)
967 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700968
969 if (lc) {
970 lc->next = c;
971 } else {
972 *nodep = c;
973 }
974
975 rc = next_entry(buf, fp, (sizeof(u32) * 2));
976 if (rc < 0)
977 return rc;
978 c->permissions = le32_to_cpu(buf[0]);
979 nexpr = le32_to_cpu(buf[1]);
980 le = NULL;
981 depth = -1;
982 for (j = 0; j < nexpr; j++) {
James Morris89d155e2005-10-30 14:59:21 -0800983 e = kzalloc(sizeof(*e), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700984 if (!e)
985 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700986
987 if (le) {
988 le->next = e;
989 } else {
990 c->expr = e;
991 }
992
993 rc = next_entry(buf, fp, (sizeof(u32) * 3));
994 if (rc < 0)
995 return rc;
996 e->expr_type = le32_to_cpu(buf[0]);
997 e->attr = le32_to_cpu(buf[1]);
998 e->op = le32_to_cpu(buf[2]);
999
1000 switch (e->expr_type) {
1001 case CEXPR_NOT:
1002 if (depth < 0)
1003 return -EINVAL;
1004 break;
1005 case CEXPR_AND:
1006 case CEXPR_OR:
1007 if (depth < 1)
1008 return -EINVAL;
1009 depth--;
1010 break;
1011 case CEXPR_ATTR:
1012 if (depth == (CEXPR_MAXDEPTH - 1))
1013 return -EINVAL;
1014 depth++;
1015 break;
1016 case CEXPR_NAMES:
1017 if (!allowxtarget && (e->attr & CEXPR_XTARGET))
1018 return -EINVAL;
1019 if (depth == (CEXPR_MAXDEPTH - 1))
1020 return -EINVAL;
1021 depth++;
1022 if (ebitmap_read(&e->names, fp))
1023 return -EINVAL;
1024 break;
1025 default:
1026 return -EINVAL;
1027 }
1028 le = e;
1029 }
1030 if (depth != 0)
1031 return -EINVAL;
1032 lc = c;
1033 }
1034
1035 return 0;
1036}
1037
1038static int class_read(struct policydb *p, struct hashtab *h, void *fp)
1039{
1040 char *key = NULL;
1041 struct class_datum *cladatum;
Alexey Dobriyanb5bf6c52005-09-03 15:55:17 -07001042 __le32 buf[6];
1043 u32 len, len2, ncons, nel;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001044 int i, rc;
1045
James Morris89d155e2005-10-30 14:59:21 -08001046 cladatum = kzalloc(sizeof(*cladatum), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001047 if (!cladatum) {
1048 rc = -ENOMEM;
1049 goto out;
1050 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001051
1052 rc = next_entry(buf, fp, sizeof(u32)*6);
1053 if (rc < 0)
1054 goto bad;
1055
1056 len = le32_to_cpu(buf[0]);
1057 len2 = le32_to_cpu(buf[1]);
1058 cladatum->value = le32_to_cpu(buf[2]);
1059
1060 rc = symtab_init(&cladatum->permissions, PERM_SYMTAB_SIZE);
1061 if (rc)
1062 goto bad;
1063 cladatum->permissions.nprim = le32_to_cpu(buf[3]);
1064 nel = le32_to_cpu(buf[4]);
1065
1066 ncons = le32_to_cpu(buf[5]);
1067
1068 key = kmalloc(len + 1,GFP_KERNEL);
1069 if (!key) {
1070 rc = -ENOMEM;
1071 goto bad;
1072 }
1073 rc = next_entry(key, fp, len);
1074 if (rc < 0)
1075 goto bad;
1076 key[len] = 0;
1077
1078 if (len2) {
1079 cladatum->comkey = kmalloc(len2 + 1,GFP_KERNEL);
1080 if (!cladatum->comkey) {
1081 rc = -ENOMEM;
1082 goto bad;
1083 }
1084 rc = next_entry(cladatum->comkey, fp, len2);
1085 if (rc < 0)
1086 goto bad;
1087 cladatum->comkey[len2] = 0;
1088
1089 cladatum->comdatum = hashtab_search(p->p_commons.table,
1090 cladatum->comkey);
1091 if (!cladatum->comdatum) {
1092 printk(KERN_ERR "security: unknown common %s\n",
1093 cladatum->comkey);
1094 rc = -EINVAL;
1095 goto bad;
1096 }
1097 }
1098 for (i = 0; i < nel; i++) {
1099 rc = perm_read(p, cladatum->permissions.table, fp);
1100 if (rc)
1101 goto bad;
1102 }
1103
1104 rc = read_cons_helper(&cladatum->constraints, ncons, 0, fp);
1105 if (rc)
1106 goto bad;
1107
1108 if (p->policyvers >= POLICYDB_VERSION_VALIDATETRANS) {
1109 /* grab the validatetrans rules */
1110 rc = next_entry(buf, fp, sizeof(u32));
1111 if (rc < 0)
1112 goto bad;
1113 ncons = le32_to_cpu(buf[0]);
1114 rc = read_cons_helper(&cladatum->validatetrans, ncons, 1, fp);
1115 if (rc)
1116 goto bad;
1117 }
1118
1119 rc = hashtab_insert(h, key, cladatum);
1120 if (rc)
1121 goto bad;
1122
1123 rc = 0;
1124out:
1125 return rc;
1126bad:
James Morris6cbda6b2006-11-29 16:50:27 -05001127 cls_destroy(key, cladatum, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001128 goto out;
1129}
1130
1131static int role_read(struct policydb *p, struct hashtab *h, void *fp)
1132{
1133 char *key = NULL;
1134 struct role_datum *role;
1135 int rc;
Alexey Dobriyanb5bf6c52005-09-03 15:55:17 -07001136 __le32 buf[2];
1137 u32 len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001138
James Morris89d155e2005-10-30 14:59:21 -08001139 role = kzalloc(sizeof(*role), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001140 if (!role) {
1141 rc = -ENOMEM;
1142 goto out;
1143 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001144
1145 rc = next_entry(buf, fp, sizeof buf);
1146 if (rc < 0)
1147 goto bad;
1148
1149 len = le32_to_cpu(buf[0]);
1150 role->value = le32_to_cpu(buf[1]);
1151
1152 key = kmalloc(len + 1,GFP_KERNEL);
1153 if (!key) {
1154 rc = -ENOMEM;
1155 goto bad;
1156 }
1157 rc = next_entry(key, fp, len);
1158 if (rc < 0)
1159 goto bad;
1160 key[len] = 0;
1161
1162 rc = ebitmap_read(&role->dominates, fp);
1163 if (rc)
1164 goto bad;
1165
1166 rc = ebitmap_read(&role->types, fp);
1167 if (rc)
1168 goto bad;
1169
1170 if (strcmp(key, OBJECT_R) == 0) {
1171 if (role->value != OBJECT_R_VAL) {
1172 printk(KERN_ERR "Role %s has wrong value %d\n",
1173 OBJECT_R, role->value);
1174 rc = -EINVAL;
1175 goto bad;
1176 }
1177 rc = 0;
1178 goto bad;
1179 }
1180
1181 rc = hashtab_insert(h, key, role);
1182 if (rc)
1183 goto bad;
1184out:
1185 return rc;
1186bad:
1187 role_destroy(key, role, NULL);
1188 goto out;
1189}
1190
1191static int type_read(struct policydb *p, struct hashtab *h, void *fp)
1192{
1193 char *key = NULL;
1194 struct type_datum *typdatum;
1195 int rc;
Alexey Dobriyanb5bf6c52005-09-03 15:55:17 -07001196 __le32 buf[3];
1197 u32 len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001198
James Morris89d155e2005-10-30 14:59:21 -08001199 typdatum = kzalloc(sizeof(*typdatum),GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001200 if (!typdatum) {
1201 rc = -ENOMEM;
1202 return rc;
1203 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001204
1205 rc = next_entry(buf, fp, sizeof buf);
1206 if (rc < 0)
1207 goto bad;
1208
1209 len = le32_to_cpu(buf[0]);
1210 typdatum->value = le32_to_cpu(buf[1]);
1211 typdatum->primary = le32_to_cpu(buf[2]);
1212
1213 key = kmalloc(len + 1,GFP_KERNEL);
1214 if (!key) {
1215 rc = -ENOMEM;
1216 goto bad;
1217 }
1218 rc = next_entry(key, fp, len);
1219 if (rc < 0)
1220 goto bad;
1221 key[len] = 0;
1222
1223 rc = hashtab_insert(h, key, typdatum);
1224 if (rc)
1225 goto bad;
1226out:
1227 return rc;
1228bad:
1229 type_destroy(key, typdatum, NULL);
1230 goto out;
1231}
1232
1233
1234/*
1235 * Read a MLS level structure from a policydb binary
1236 * representation file.
1237 */
1238static int mls_read_level(struct mls_level *lp, void *fp)
1239{
Alexey Dobriyanb5bf6c52005-09-03 15:55:17 -07001240 __le32 buf[1];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001241 int rc;
1242
1243 memset(lp, 0, sizeof(*lp));
1244
1245 rc = next_entry(buf, fp, sizeof buf);
1246 if (rc < 0) {
1247 printk(KERN_ERR "security: mls: truncated level\n");
1248 goto bad;
1249 }
1250 lp->sens = le32_to_cpu(buf[0]);
1251
1252 if (ebitmap_read(&lp->cat, fp)) {
1253 printk(KERN_ERR "security: mls: error reading level "
1254 "categories\n");
1255 goto bad;
1256 }
1257 return 0;
1258
1259bad:
1260 return -EINVAL;
1261}
1262
1263static int user_read(struct policydb *p, struct hashtab *h, void *fp)
1264{
1265 char *key = NULL;
1266 struct user_datum *usrdatum;
1267 int rc;
Alexey Dobriyanb5bf6c52005-09-03 15:55:17 -07001268 __le32 buf[2];
1269 u32 len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001270
James Morris89d155e2005-10-30 14:59:21 -08001271 usrdatum = kzalloc(sizeof(*usrdatum), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001272 if (!usrdatum) {
1273 rc = -ENOMEM;
1274 goto out;
1275 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001276
1277 rc = next_entry(buf, fp, sizeof buf);
1278 if (rc < 0)
1279 goto bad;
1280
1281 len = le32_to_cpu(buf[0]);
1282 usrdatum->value = le32_to_cpu(buf[1]);
1283
1284 key = kmalloc(len + 1,GFP_KERNEL);
1285 if (!key) {
1286 rc = -ENOMEM;
1287 goto bad;
1288 }
1289 rc = next_entry(key, fp, len);
1290 if (rc < 0)
1291 goto bad;
1292 key[len] = 0;
1293
1294 rc = ebitmap_read(&usrdatum->roles, fp);
1295 if (rc)
1296 goto bad;
1297
1298 if (p->policyvers >= POLICYDB_VERSION_MLS) {
1299 rc = mls_read_range_helper(&usrdatum->range, fp);
1300 if (rc)
1301 goto bad;
1302 rc = mls_read_level(&usrdatum->dfltlevel, fp);
1303 if (rc)
1304 goto bad;
1305 }
1306
1307 rc = hashtab_insert(h, key, usrdatum);
1308 if (rc)
1309 goto bad;
1310out:
1311 return rc;
1312bad:
1313 user_destroy(key, usrdatum, NULL);
1314 goto out;
1315}
1316
1317static int sens_read(struct policydb *p, struct hashtab *h, void *fp)
1318{
1319 char *key = NULL;
1320 struct level_datum *levdatum;
1321 int rc;
Alexey Dobriyanb5bf6c52005-09-03 15:55:17 -07001322 __le32 buf[2];
1323 u32 len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001324
James Morris89d155e2005-10-30 14:59:21 -08001325 levdatum = kzalloc(sizeof(*levdatum), GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001326 if (!levdatum) {
1327 rc = -ENOMEM;
1328 goto out;
1329 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001330
1331 rc = next_entry(buf, fp, sizeof buf);
1332 if (rc < 0)
1333 goto bad;
1334
1335 len = le32_to_cpu(buf[0]);
1336 levdatum->isalias = le32_to_cpu(buf[1]);
1337
1338 key = kmalloc(len + 1,GFP_ATOMIC);
1339 if (!key) {
1340 rc = -ENOMEM;
1341 goto bad;
1342 }
1343 rc = next_entry(key, fp, len);
1344 if (rc < 0)
1345 goto bad;
1346 key[len] = 0;
1347
1348 levdatum->level = kmalloc(sizeof(struct mls_level), GFP_ATOMIC);
1349 if (!levdatum->level) {
1350 rc = -ENOMEM;
1351 goto bad;
1352 }
1353 if (mls_read_level(levdatum->level, fp)) {
1354 rc = -EINVAL;
1355 goto bad;
1356 }
1357
1358 rc = hashtab_insert(h, key, levdatum);
1359 if (rc)
1360 goto bad;
1361out:
1362 return rc;
1363bad:
1364 sens_destroy(key, levdatum, NULL);
1365 goto out;
1366}
1367
1368static int cat_read(struct policydb *p, struct hashtab *h, void *fp)
1369{
1370 char *key = NULL;
1371 struct cat_datum *catdatum;
1372 int rc;
Alexey Dobriyanb5bf6c52005-09-03 15:55:17 -07001373 __le32 buf[3];
1374 u32 len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001375
James Morris89d155e2005-10-30 14:59:21 -08001376 catdatum = kzalloc(sizeof(*catdatum), GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001377 if (!catdatum) {
1378 rc = -ENOMEM;
1379 goto out;
1380 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001381
1382 rc = next_entry(buf, fp, sizeof buf);
1383 if (rc < 0)
1384 goto bad;
1385
1386 len = le32_to_cpu(buf[0]);
1387 catdatum->value = le32_to_cpu(buf[1]);
1388 catdatum->isalias = le32_to_cpu(buf[2]);
1389
1390 key = kmalloc(len + 1,GFP_ATOMIC);
1391 if (!key) {
1392 rc = -ENOMEM;
1393 goto bad;
1394 }
1395 rc = next_entry(key, fp, len);
1396 if (rc < 0)
1397 goto bad;
1398 key[len] = 0;
1399
1400 rc = hashtab_insert(h, key, catdatum);
1401 if (rc)
1402 goto bad;
1403out:
1404 return rc;
1405
1406bad:
1407 cat_destroy(key, catdatum, NULL);
1408 goto out;
1409}
1410
1411static int (*read_f[SYM_NUM]) (struct policydb *p, struct hashtab *h, void *fp) =
1412{
1413 common_read,
1414 class_read,
1415 role_read,
1416 type_read,
1417 user_read,
1418 cond_read_bool,
1419 sens_read,
1420 cat_read,
1421};
1422
1423extern int ss_initialized;
1424
1425/*
1426 * Read the configuration data from a policy database binary
1427 * representation file into a policy database structure.
1428 */
1429int policydb_read(struct policydb *p, void *fp)
1430{
1431 struct role_allow *ra, *lra;
1432 struct role_trans *tr, *ltr;
1433 struct ocontext *l, *c, *newc;
1434 struct genfs *genfs_p, *genfs, *newgenfs;
1435 int i, j, rc;
Alexey Dobriyanb5bf6c52005-09-03 15:55:17 -07001436 __le32 buf[8];
1437 u32 len, len2, config, nprim, nel, nel2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001438 char *policydb_str;
1439 struct policydb_compat_info *info;
1440 struct range_trans *rt, *lrt;
1441
1442 config = 0;
1443
1444 rc = policydb_init(p);
1445 if (rc)
1446 goto out;
1447
1448 /* Read the magic number and string length. */
1449 rc = next_entry(buf, fp, sizeof(u32)* 2);
1450 if (rc < 0)
1451 goto bad;
1452
Alexey Dobriyanb5bf6c52005-09-03 15:55:17 -07001453 if (le32_to_cpu(buf[0]) != POLICYDB_MAGIC) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001454 printk(KERN_ERR "security: policydb magic number 0x%x does "
1455 "not match expected magic number 0x%x\n",
Alexey Dobriyanb5bf6c52005-09-03 15:55:17 -07001456 le32_to_cpu(buf[0]), POLICYDB_MAGIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001457 goto bad;
1458 }
1459
Alexey Dobriyanb5bf6c52005-09-03 15:55:17 -07001460 len = le32_to_cpu(buf[1]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001461 if (len != strlen(POLICYDB_STRING)) {
1462 printk(KERN_ERR "security: policydb string length %d does not "
1463 "match expected length %Zu\n",
1464 len, strlen(POLICYDB_STRING));
1465 goto bad;
1466 }
1467 policydb_str = kmalloc(len + 1,GFP_KERNEL);
1468 if (!policydb_str) {
1469 printk(KERN_ERR "security: unable to allocate memory for policydb "
1470 "string of length %d\n", len);
1471 rc = -ENOMEM;
1472 goto bad;
1473 }
1474 rc = next_entry(policydb_str, fp, len);
1475 if (rc < 0) {
1476 printk(KERN_ERR "security: truncated policydb string identifier\n");
1477 kfree(policydb_str);
1478 goto bad;
1479 }
1480 policydb_str[len] = 0;
1481 if (strcmp(policydb_str, POLICYDB_STRING)) {
1482 printk(KERN_ERR "security: policydb string %s does not match "
1483 "my string %s\n", policydb_str, POLICYDB_STRING);
1484 kfree(policydb_str);
1485 goto bad;
1486 }
1487 /* Done with policydb_str. */
1488 kfree(policydb_str);
1489 policydb_str = NULL;
1490
1491 /* Read the version, config, and table sizes. */
1492 rc = next_entry(buf, fp, sizeof(u32)*4);
1493 if (rc < 0)
1494 goto bad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001495
Alexey Dobriyanb5bf6c52005-09-03 15:55:17 -07001496 p->policyvers = le32_to_cpu(buf[0]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001497 if (p->policyvers < POLICYDB_VERSION_MIN ||
1498 p->policyvers > POLICYDB_VERSION_MAX) {
1499 printk(KERN_ERR "security: policydb version %d does not match "
1500 "my version range %d-%d\n",
Alexey Dobriyanb5bf6c52005-09-03 15:55:17 -07001501 le32_to_cpu(buf[0]), POLICYDB_VERSION_MIN, POLICYDB_VERSION_MAX);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001502 goto bad;
1503 }
1504
Alexey Dobriyanb5bf6c52005-09-03 15:55:17 -07001505 if ((le32_to_cpu(buf[1]) & POLICYDB_CONFIG_MLS)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001506 if (ss_initialized && !selinux_mls_enabled) {
1507 printk(KERN_ERR "Cannot switch between non-MLS and MLS "
1508 "policies\n");
1509 goto bad;
1510 }
1511 selinux_mls_enabled = 1;
1512 config |= POLICYDB_CONFIG_MLS;
1513
1514 if (p->policyvers < POLICYDB_VERSION_MLS) {
1515 printk(KERN_ERR "security policydb version %d (MLS) "
1516 "not backwards compatible\n", p->policyvers);
1517 goto bad;
1518 }
1519 } else {
1520 if (ss_initialized && selinux_mls_enabled) {
1521 printk(KERN_ERR "Cannot switch between MLS and non-MLS "
1522 "policies\n");
1523 goto bad;
1524 }
1525 }
1526
1527 info = policydb_lookup_compat(p->policyvers);
1528 if (!info) {
1529 printk(KERN_ERR "security: unable to find policy compat info "
1530 "for version %d\n", p->policyvers);
1531 goto bad;
1532 }
1533
Alexey Dobriyanb5bf6c52005-09-03 15:55:17 -07001534 if (le32_to_cpu(buf[2]) != info->sym_num ||
1535 le32_to_cpu(buf[3]) != info->ocon_num) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001536 printk(KERN_ERR "security: policydb table sizes (%d,%d) do "
Alexey Dobriyanb5bf6c52005-09-03 15:55:17 -07001537 "not match mine (%d,%d)\n", le32_to_cpu(buf[2]),
1538 le32_to_cpu(buf[3]),
Linus Torvalds1da177e2005-04-16 15:20:36 -07001539 info->sym_num, info->ocon_num);
1540 goto bad;
1541 }
1542
1543 for (i = 0; i < info->sym_num; i++) {
1544 rc = next_entry(buf, fp, sizeof(u32)*2);
1545 if (rc < 0)
1546 goto bad;
1547 nprim = le32_to_cpu(buf[0]);
1548 nel = le32_to_cpu(buf[1]);
1549 for (j = 0; j < nel; j++) {
1550 rc = read_f[i](p, p->symtab[i].table, fp);
1551 if (rc)
1552 goto bad;
1553 }
1554
1555 p->symtab[i].nprim = nprim;
1556 }
1557
Stephen Smalley782ebb92005-09-03 15:55:16 -07001558 rc = avtab_read(&p->te_avtab, fp, p->policyvers);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001559 if (rc)
1560 goto bad;
1561
1562 if (p->policyvers >= POLICYDB_VERSION_BOOL) {
1563 rc = cond_read_list(p, fp);
1564 if (rc)
1565 goto bad;
1566 }
1567
1568 rc = next_entry(buf, fp, sizeof(u32));
1569 if (rc < 0)
1570 goto bad;
1571 nel = le32_to_cpu(buf[0]);
1572 ltr = NULL;
1573 for (i = 0; i < nel; i++) {
James Morris89d155e2005-10-30 14:59:21 -08001574 tr = kzalloc(sizeof(*tr), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001575 if (!tr) {
1576 rc = -ENOMEM;
1577 goto bad;
1578 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001579 if (ltr) {
1580 ltr->next = tr;
1581 } else {
1582 p->role_tr = tr;
1583 }
1584 rc = next_entry(buf, fp, sizeof(u32)*3);
1585 if (rc < 0)
1586 goto bad;
1587 tr->role = le32_to_cpu(buf[0]);
1588 tr->type = le32_to_cpu(buf[1]);
1589 tr->new_role = le32_to_cpu(buf[2]);
1590 ltr = tr;
1591 }
1592
1593 rc = next_entry(buf, fp, sizeof(u32));
1594 if (rc < 0)
1595 goto bad;
1596 nel = le32_to_cpu(buf[0]);
1597 lra = NULL;
1598 for (i = 0; i < nel; i++) {
James Morris89d155e2005-10-30 14:59:21 -08001599 ra = kzalloc(sizeof(*ra), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001600 if (!ra) {
1601 rc = -ENOMEM;
1602 goto bad;
1603 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001604 if (lra) {
1605 lra->next = ra;
1606 } else {
1607 p->role_allow = ra;
1608 }
1609 rc = next_entry(buf, fp, sizeof(u32)*2);
1610 if (rc < 0)
1611 goto bad;
1612 ra->role = le32_to_cpu(buf[0]);
1613 ra->new_role = le32_to_cpu(buf[1]);
1614 lra = ra;
1615 }
1616
1617 rc = policydb_index_classes(p);
1618 if (rc)
1619 goto bad;
1620
1621 rc = policydb_index_others(p);
1622 if (rc)
1623 goto bad;
1624
1625 for (i = 0; i < info->ocon_num; i++) {
1626 rc = next_entry(buf, fp, sizeof(u32));
1627 if (rc < 0)
1628 goto bad;
1629 nel = le32_to_cpu(buf[0]);
1630 l = NULL;
1631 for (j = 0; j < nel; j++) {
James Morris89d155e2005-10-30 14:59:21 -08001632 c = kzalloc(sizeof(*c), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001633 if (!c) {
1634 rc = -ENOMEM;
1635 goto bad;
1636 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001637 if (l) {
1638 l->next = c;
1639 } else {
1640 p->ocontexts[i] = c;
1641 }
1642 l = c;
1643 rc = -EINVAL;
1644 switch (i) {
1645 case OCON_ISID:
1646 rc = next_entry(buf, fp, sizeof(u32));
1647 if (rc < 0)
1648 goto bad;
1649 c->sid[0] = le32_to_cpu(buf[0]);
1650 rc = context_read_and_validate(&c->context[0], p, fp);
1651 if (rc)
1652 goto bad;
1653 break;
1654 case OCON_FS:
1655 case OCON_NETIF:
1656 rc = next_entry(buf, fp, sizeof(u32));
1657 if (rc < 0)
1658 goto bad;
1659 len = le32_to_cpu(buf[0]);
1660 c->u.name = kmalloc(len + 1,GFP_KERNEL);
1661 if (!c->u.name) {
1662 rc = -ENOMEM;
1663 goto bad;
1664 }
1665 rc = next_entry(c->u.name, fp, len);
1666 if (rc < 0)
1667 goto bad;
1668 c->u.name[len] = 0;
1669 rc = context_read_and_validate(&c->context[0], p, fp);
1670 if (rc)
1671 goto bad;
1672 rc = context_read_and_validate(&c->context[1], p, fp);
1673 if (rc)
1674 goto bad;
1675 break;
1676 case OCON_PORT:
1677 rc = next_entry(buf, fp, sizeof(u32)*3);
1678 if (rc < 0)
1679 goto bad;
1680 c->u.port.protocol = le32_to_cpu(buf[0]);
1681 c->u.port.low_port = le32_to_cpu(buf[1]);
1682 c->u.port.high_port = le32_to_cpu(buf[2]);
1683 rc = context_read_and_validate(&c->context[0], p, fp);
1684 if (rc)
1685 goto bad;
1686 break;
1687 case OCON_NODE:
1688 rc = next_entry(buf, fp, sizeof(u32)* 2);
1689 if (rc < 0)
1690 goto bad;
1691 c->u.node.addr = le32_to_cpu(buf[0]);
1692 c->u.node.mask = le32_to_cpu(buf[1]);
1693 rc = context_read_and_validate(&c->context[0], p, fp);
1694 if (rc)
1695 goto bad;
1696 break;
1697 case OCON_FSUSE:
1698 rc = next_entry(buf, fp, sizeof(u32)*2);
1699 if (rc < 0)
1700 goto bad;
1701 c->v.behavior = le32_to_cpu(buf[0]);
1702 if (c->v.behavior > SECURITY_FS_USE_NONE)
1703 goto bad;
1704 len = le32_to_cpu(buf[1]);
1705 c->u.name = kmalloc(len + 1,GFP_KERNEL);
1706 if (!c->u.name) {
1707 rc = -ENOMEM;
1708 goto bad;
1709 }
1710 rc = next_entry(c->u.name, fp, len);
1711 if (rc < 0)
1712 goto bad;
1713 c->u.name[len] = 0;
1714 rc = context_read_and_validate(&c->context[0], p, fp);
1715 if (rc)
1716 goto bad;
1717 break;
1718 case OCON_NODE6: {
1719 int k;
1720
1721 rc = next_entry(buf, fp, sizeof(u32) * 8);
1722 if (rc < 0)
1723 goto bad;
1724 for (k = 0; k < 4; k++)
1725 c->u.node6.addr[k] = le32_to_cpu(buf[k]);
1726 for (k = 0; k < 4; k++)
1727 c->u.node6.mask[k] = le32_to_cpu(buf[k+4]);
1728 if (context_read_and_validate(&c->context[0], p, fp))
1729 goto bad;
1730 break;
1731 }
1732 }
1733 }
1734 }
1735
1736 rc = next_entry(buf, fp, sizeof(u32));
1737 if (rc < 0)
1738 goto bad;
1739 nel = le32_to_cpu(buf[0]);
1740 genfs_p = NULL;
1741 rc = -EINVAL;
1742 for (i = 0; i < nel; i++) {
1743 rc = next_entry(buf, fp, sizeof(u32));
1744 if (rc < 0)
1745 goto bad;
1746 len = le32_to_cpu(buf[0]);
James Morris89d155e2005-10-30 14:59:21 -08001747 newgenfs = kzalloc(sizeof(*newgenfs), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001748 if (!newgenfs) {
1749 rc = -ENOMEM;
1750 goto bad;
1751 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001752
1753 newgenfs->fstype = kmalloc(len + 1,GFP_KERNEL);
1754 if (!newgenfs->fstype) {
1755 rc = -ENOMEM;
1756 kfree(newgenfs);
1757 goto bad;
1758 }
1759 rc = next_entry(newgenfs->fstype, fp, len);
1760 if (rc < 0) {
1761 kfree(newgenfs->fstype);
1762 kfree(newgenfs);
1763 goto bad;
1764 }
1765 newgenfs->fstype[len] = 0;
1766 for (genfs_p = NULL, genfs = p->genfs; genfs;
1767 genfs_p = genfs, genfs = genfs->next) {
1768 if (strcmp(newgenfs->fstype, genfs->fstype) == 0) {
1769 printk(KERN_ERR "security: dup genfs "
1770 "fstype %s\n", newgenfs->fstype);
1771 kfree(newgenfs->fstype);
1772 kfree(newgenfs);
1773 goto bad;
1774 }
1775 if (strcmp(newgenfs->fstype, genfs->fstype) < 0)
1776 break;
1777 }
1778 newgenfs->next = genfs;
1779 if (genfs_p)
1780 genfs_p->next = newgenfs;
1781 else
1782 p->genfs = newgenfs;
1783 rc = next_entry(buf, fp, sizeof(u32));
1784 if (rc < 0)
1785 goto bad;
1786 nel2 = le32_to_cpu(buf[0]);
1787 for (j = 0; j < nel2; j++) {
1788 rc = next_entry(buf, fp, sizeof(u32));
1789 if (rc < 0)
1790 goto bad;
1791 len = le32_to_cpu(buf[0]);
1792
James Morris89d155e2005-10-30 14:59:21 -08001793 newc = kzalloc(sizeof(*newc), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001794 if (!newc) {
1795 rc = -ENOMEM;
1796 goto bad;
1797 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001798
1799 newc->u.name = kmalloc(len + 1,GFP_KERNEL);
1800 if (!newc->u.name) {
1801 rc = -ENOMEM;
1802 goto bad_newc;
1803 }
1804 rc = next_entry(newc->u.name, fp, len);
1805 if (rc < 0)
1806 goto bad_newc;
1807 newc->u.name[len] = 0;
1808 rc = next_entry(buf, fp, sizeof(u32));
1809 if (rc < 0)
1810 goto bad_newc;
1811 newc->v.sclass = le32_to_cpu(buf[0]);
1812 if (context_read_and_validate(&newc->context[0], p, fp))
1813 goto bad_newc;
1814 for (l = NULL, c = newgenfs->head; c;
1815 l = c, c = c->next) {
1816 if (!strcmp(newc->u.name, c->u.name) &&
1817 (!c->v.sclass || !newc->v.sclass ||
1818 newc->v.sclass == c->v.sclass)) {
1819 printk(KERN_ERR "security: dup genfs "
1820 "entry (%s,%s)\n",
1821 newgenfs->fstype, c->u.name);
1822 goto bad_newc;
1823 }
1824 len = strlen(newc->u.name);
1825 len2 = strlen(c->u.name);
1826 if (len > len2)
1827 break;
1828 }
1829
1830 newc->next = c;
1831 if (l)
1832 l->next = newc;
1833 else
1834 newgenfs->head = newc;
1835 }
1836 }
1837
1838 if (p->policyvers >= POLICYDB_VERSION_MLS) {
Darrel Goeddelf3f87712006-09-25 23:31:59 -07001839 int new_rangetr = p->policyvers >= POLICYDB_VERSION_RANGETRANS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001840 rc = next_entry(buf, fp, sizeof(u32));
1841 if (rc < 0)
1842 goto bad;
1843 nel = le32_to_cpu(buf[0]);
1844 lrt = NULL;
1845 for (i = 0; i < nel; i++) {
James Morris89d155e2005-10-30 14:59:21 -08001846 rt = kzalloc(sizeof(*rt), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001847 if (!rt) {
1848 rc = -ENOMEM;
1849 goto bad;
1850 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001851 if (lrt)
1852 lrt->next = rt;
1853 else
1854 p->range_tr = rt;
1855 rc = next_entry(buf, fp, (sizeof(u32) * 2));
1856 if (rc < 0)
1857 goto bad;
Darrel Goeddelf3f87712006-09-25 23:31:59 -07001858 rt->source_type = le32_to_cpu(buf[0]);
1859 rt->target_type = le32_to_cpu(buf[1]);
1860 if (new_rangetr) {
1861 rc = next_entry(buf, fp, sizeof(u32));
1862 if (rc < 0)
1863 goto bad;
1864 rt->target_class = le32_to_cpu(buf[0]);
1865 } else
1866 rt->target_class = SECCLASS_PROCESS;
1867 rc = mls_read_range_helper(&rt->target_range, fp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001868 if (rc)
1869 goto bad;
1870 lrt = rt;
1871 }
1872 }
1873
Stephen Smalley782ebb92005-09-03 15:55:16 -07001874 p->type_attr_map = kmalloc(p->p_types.nprim*sizeof(struct ebitmap), GFP_KERNEL);
1875 if (!p->type_attr_map)
1876 goto bad;
1877
1878 for (i = 0; i < p->p_types.nprim; i++) {
1879 ebitmap_init(&p->type_attr_map[i]);
1880 if (p->policyvers >= POLICYDB_VERSION_AVTAB) {
1881 if (ebitmap_read(&p->type_attr_map[i], fp))
1882 goto bad;
1883 }
1884 /* add the type itself as the degenerate case */
1885 if (ebitmap_set_bit(&p->type_attr_map[i], i, 1))
1886 goto bad;
1887 }
1888
Linus Torvalds1da177e2005-04-16 15:20:36 -07001889 rc = 0;
1890out:
1891 return rc;
1892bad_newc:
1893 ocontext_destroy(newc,OCON_FSUSE);
1894bad:
1895 if (!rc)
1896 rc = -EINVAL;
1897 policydb_destroy(p);
1898 goto out;
1899}