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