blob: 6e5483c17540b4003fad5062cda39dcfb0aefea5 [file] [log] [blame]
Joshua Brindle13cd4c82008-08-19 15:30:36 -04001/* Author : Joshua Brindle <jbrindle@tresys.com>
2 * Karl MacMillan <kmacmillan@tresys.com>
3 * Jason Tang <jtang@tresys.com>
4 * Added support for binary policy modules
5 *
6 * Copyright (C) 2004 - 2005 Tresys Technology, LLC
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, version 2.
10 */
11
12#include <assert.h>
13#include <stdarg.h>
14#include <stdlib.h>
15#include <string.h>
16
17#include <sepol/policydb/policydb.h>
18#include <sepol/policydb/avrule_block.h>
19#include <sepol/policydb/conditional.h>
20
21#include "queue.h"
22#include "module_compiler.h"
23
24union stack_item_u {
25 avrule_block_t *avrule;
26 cond_list_t *cond_list;
27};
28
29typedef struct scope_stack {
30 union stack_item_u u;
31 int type; /* for above union: 1 = avrule block, 2 = conditional */
32 avrule_decl_t *decl; /* if in an avrule block, which
33 * declaration is current */
34 avrule_t *last_avrule;
35 int in_else; /* if in an avrule block, within ELSE branch */
36 int require_given; /* 1 if this block had at least one require */
37 struct scope_stack *parent, *child;
38} scope_stack_t;
39
40extern policydb_t *policydbp;
41extern queue_t id_queue;
Nicolas Iooss832e7012014-09-14 23:41:39 +020042extern int yyerror(const char *msg);
Nicolas Iooss8db96d02014-09-14 23:41:38 +020043__attribute__ ((format(printf, 1, 2)))
Nicolas Iooss832e7012014-09-14 23:41:39 +020044extern void yyerror2(const char *fmt, ...);
Joshua Brindle13cd4c82008-08-19 15:30:36 -040045
46static int push_stack(int stack_type, ...);
47static void pop_stack(void);
48
49/* keep track of the last item added to the stack */
50static scope_stack_t *stack_top = NULL;
51static avrule_block_t *last_block;
52static uint32_t next_decl_id = 1;
53
54int define_policy(int pass, int module_header_given)
55{
56 char *id;
57
58 if (module_header_given) {
59 if (policydbp->policy_type != POLICY_MOD) {
60 yyerror
61 ("Module specification found while not building a policy module.\n");
62 return -1;
63 }
64
65 if (pass == 2) {
66 while ((id = queue_remove(id_queue)) != NULL)
67 free(id);
68 } else {
69 id = (char *)queue_remove(id_queue);
70 if (!id) {
71 yyerror("no module name");
72 return -1;
73 }
74 policydbp->name = id;
75 if ((policydbp->version =
76 queue_remove(id_queue)) == NULL) {
77 yyerror
78 ("Expected a module version but none was found.");
79 return -1;
80 }
81 }
82 } else {
83 if (policydbp->policy_type == POLICY_MOD) {
84 yyerror
85 ("Building a policy module, but no module specification found.\n");
86 return -1;
87 }
88 }
89 /* the first declaration within the global avrule
90 block will always have an id of 1 */
91 next_decl_id = 2;
92
93 /* reset the scoping stack */
94 while (stack_top != NULL) {
95 pop_stack();
96 }
97 if (push_stack(1, policydbp->global, policydbp->global->branch_list) ==
98 -1) {
99 return -1;
100 }
101 last_block = policydbp->global;
102 return 0;
103}
104
105/* Given the current parse stack, returns 1 if a declaration would be
106 * allowed here or 0 if not. For example, declarations are not
107 * allowed in conditionals, so if there are any conditionals in the
108 * current scope stack then this would return a 0.
109 */
110static int is_declaration_allowed(void)
111{
112 if (stack_top->type != 1 || stack_top->in_else) {
113 return 0;
114 }
115 return 1;
116}
117
118/* Attempt to declare a symbol within the current declaration. If
119 * currently within a non-conditional and in a non-else branch then
120 * insert the symbol, return 0 on success if symbol was undeclared.
121 * For roles and users, it is legal to have multiple declarations; as
122 * such return 1 to indicate that caller must free() the datum because
123 * it was not added. If symbols may not be declared here return -1.
124 * For duplicate declarations return -2. For all else, including out
125 * of memory, return -3. Note that dest_value and datum_value might
126 * not be restricted pointers. */
127int declare_symbol(uint32_t symbol_type,
128 hashtab_key_t key, hashtab_datum_t datum,
129 uint32_t * dest_value, uint32_t * datum_value)
130{
131 avrule_decl_t *decl = stack_top->decl;
132 int retval;
133
134 /* first check that symbols may be declared here */
135 if (!is_declaration_allowed()) {
136 return -1;
137 }
138 retval = symtab_insert(policydbp, symbol_type, key, datum,
139 SCOPE_DECL, decl->decl_id, dest_value);
Caleb Casef7917ea2009-02-10 15:38:41 -0500140 if (retval == 1 && dest_value) {
Joshua Brindle13cd4c82008-08-19 15:30:36 -0400141 symtab_datum_t *s =
142 (symtab_datum_t *) hashtab_search(policydbp->
143 symtab[symbol_type].table,
144 key);
145 assert(s != NULL);
146
147 if (symbol_type == SYM_LEVELS) {
148 *dest_value = ((level_datum_t *)s)->level->sens;
149 } else {
150 *dest_value = s->value;
151 }
152 } else if (retval == -2) {
153 return -2;
154 } else if (retval < 0) {
155 return -3;
156 } else { /* fall through possible if retval is 0 */
157 }
158 if (datum_value != NULL) {
159 if (ebitmap_set_bit(decl->declared.scope + symbol_type,
160 *datum_value - 1, 1)) {
161 return -3;
162 }
163 }
164 return retval;
165}
166
Joshua Brindle45728402008-10-08 06:56:51 -0400167static int role_implicit_bounds(hashtab_t roles_tab,
168 char *role_id, role_datum_t *role)
169{
170 role_datum_t *bounds;
171 char *bounds_id, *delim;
172
173 delim = strrchr(role_id, '.');
174 if (!delim)
175 return 0; /* no implicit boundary */
176
177 bounds_id = strdup(role_id);
178 if (!bounds_id) {
179 yyerror("out of memory");
180 return -1;
181 }
182 bounds_id[(size_t)(delim - role_id)] = '\0';
183
184 bounds = hashtab_search(roles_tab, bounds_id);
185 if (!bounds) {
186 yyerror2("role %s doesn't exist, is implicit bounds of %s",
187 bounds_id, role_id);
188 return -1;
189 }
190
191 if (!role->bounds)
192 role->bounds = bounds->s.value;
193 else if (role->bounds != bounds->s.value) {
194 yyerror2("role %s has inconsistent bounds %s/%s",
195 role_id, bounds_id,
196 policydbp->p_role_val_to_name[role->bounds - 1]);
197 return -1;
198 }
199 free(bounds_id);
200
201 return 0;
202}
203
Harry Ciao16675b72011-07-25 09:23:54 +0800204role_datum_t *declare_role(unsigned char isattr)
Joshua Brindle13cd4c82008-08-19 15:30:36 -0400205{
206 char *id = queue_remove(id_queue), *dest_id = NULL;
207 role_datum_t *role = NULL, *dest_role = NULL;
208 int retval;
209 uint32_t value;
210
211 if (id == NULL) {
212 yyerror("no role name");
213 return NULL;
214 }
215 if ((role = (role_datum_t *) malloc(sizeof(*role))) == NULL) {
216 yyerror("Out of memory!");
217 free(id);
218 return NULL;
219 }
220 role_datum_init(role);
Harry Ciao16675b72011-07-25 09:23:54 +0800221 role->flavor = isattr ? ROLE_ATTRIB : ROLE_ROLE;
Joshua Brindle13cd4c82008-08-19 15:30:36 -0400222 retval =
223 declare_symbol(SYM_ROLES, id, (hashtab_datum_t *) role, &value,
224 &value);
225 if (retval == 0) {
226 role->s.value = value;
227 if ((dest_id = strdup(id)) == NULL) {
228 yyerror("Out of memory!");
229 return NULL;
230 }
231 } else {
232 /* this role was already declared in this module, or error */
233 dest_id = id;
234 role_datum_destroy(role);
235 free(role);
236 }
237 if (retval == 0 || retval == 1) {
238 /* create a new role_datum_t for this decl, if necessary */
239 hashtab_t roles_tab;
240 assert(stack_top->type == 1);
241 if (stack_top->parent == NULL) {
242 /* in parent, so use global symbol table */
243 roles_tab = policydbp->p_roles.table;
244 } else {
245 roles_tab = stack_top->decl->p_roles.table;
246 }
247 dest_role = (role_datum_t *) hashtab_search(roles_tab, dest_id);
248 if (dest_role == NULL) {
249 if ((dest_role =
250 (role_datum_t *) malloc(sizeof(*dest_role))) ==
251 NULL) {
252 yyerror("Out of memory!");
253 free(dest_id);
254 return NULL;
255 }
256 role_datum_init(dest_role);
257 dest_role->s.value = value;
Harry Ciao16675b72011-07-25 09:23:54 +0800258 dest_role->flavor = isattr ? ROLE_ATTRIB : ROLE_ROLE;
Joshua Brindle45728402008-10-08 06:56:51 -0400259 if (role_implicit_bounds(roles_tab, dest_id, dest_role)) {
260 free(dest_id);
261 role_datum_destroy(dest_role);
262 free(dest_role);
263 return NULL;
264 }
Joshua Brindle13cd4c82008-08-19 15:30:36 -0400265 if (hashtab_insert(roles_tab, dest_id, dest_role)) {
266 yyerror("Out of memory!");
267 free(dest_id);
268 role_datum_destroy(dest_role);
269 free(dest_role);
270 return NULL;
271 }
272 } else {
273 free(dest_id);
274 }
275 } else {
276 free(dest_id);
277 }
278 switch (retval) {
279 case -3:{
280 yyerror("Out of memory!");
281 return NULL;
282 }
283 case -2:{
284 yyerror("duplicate declaration of role");
285 return NULL;
286 }
287 case -1:{
288 yyerror("could not declare role here");
289 return NULL;
290 }
291 case 0:{
292 if (ebitmap_set_bit
293 (&dest_role->dominates, role->s.value - 1, 1)) {
294 yyerror("out of memory");
295 return NULL;
296 }
297 return dest_role;
298 }
299 case 1:{
300 return dest_role; /* role already declared for this block */
301 }
302 default:{
Dan Albert099223b2015-06-11 16:47:16 -0700303 abort(); /* should never get here */
Joshua Brindle13cd4c82008-08-19 15:30:36 -0400304 }
305 }
306}
307
308type_datum_t *declare_type(unsigned char primary, unsigned char isattr)
309{
310 char *id;
311 type_datum_t *typdatum;
312 int retval;
313 uint32_t value = 0;
314
315 id = (char *)queue_remove(id_queue);
316 if (!id) {
317 yyerror("no type/attribute name?");
318 return NULL;
319 }
320 if (strcmp(id, "self") == 0) {
321 yyerror
322 ("'self' is a reserved type name and may not be declared.");
323 free(id);
324 return NULL;
325 }
326
327 typdatum = (type_datum_t *) malloc(sizeof(type_datum_t));
328 if (!typdatum) {
329 yyerror("Out of memory!");
330 free(id);
331 return NULL;
332 }
333 type_datum_init(typdatum);
334 typdatum->primary = primary;
335 typdatum->flavor = isattr ? TYPE_ATTRIB : TYPE_TYPE;
336
337 retval = declare_symbol(SYM_TYPES, id, typdatum, &value, &value);
338 if (retval == 0 || retval == 1) {
339 if (typdatum->primary) {
340 typdatum->s.value = value;
341 }
342 } else {
343 /* error occurred (can't have duplicate type declarations) */
344 free(id);
345 type_datum_destroy(typdatum);
346 free(typdatum);
347 }
348 switch (retval) {
349 case -3:{
350 yyerror("Out of memory!");
351 return NULL;
352 }
353 case -2:{
354 yyerror2("duplicate declaration of type/attribute");
355 return NULL;
356 }
357 case -1:{
358 yyerror("could not declare type/attribute here");
359 return NULL;
360 }
361 case 0:
362 case 1:{
363 return typdatum;
364 }
365 default:{
Dan Albert099223b2015-06-11 16:47:16 -0700366 abort(); /* should never get here */
Joshua Brindle13cd4c82008-08-19 15:30:36 -0400367 }
368 }
369}
370
Joshua Brindle45728402008-10-08 06:56:51 -0400371static int user_implicit_bounds(hashtab_t users_tab,
372 char *user_id, user_datum_t *user)
373{
374 user_datum_t *bounds;
375 char *bounds_id, *delim;
376
377 delim = strrchr(user_id, '.');
378 if (!delim)
379 return 0; /* no implicit boundary */
380
381 bounds_id = strdup(user_id);
382 if (!bounds_id) {
383 yyerror("out of memory");
384 return -1;
385 }
386 bounds_id[(size_t)(delim - user_id)] = '\0';
387
388 bounds = hashtab_search(users_tab, bounds_id);
389 if (!bounds) {
390 yyerror2("user %s doesn't exist, is implicit bounds of %s",
391 bounds_id, user_id);
392 return -1;
393 }
394
395 if (!user->bounds)
396 user->bounds = bounds->s.value;
397 else if (user->bounds != bounds->s.value) {
398 yyerror2("user %s has inconsistent bounds %s/%s",
399 user_id, bounds_id,
400 policydbp->p_role_val_to_name[user->bounds - 1]);
401 return -1;
402 }
403 free(bounds_id);
404
405 return 0;
406}
407
Joshua Brindle13cd4c82008-08-19 15:30:36 -0400408user_datum_t *declare_user(void)
409{
410 char *id = queue_remove(id_queue), *dest_id = NULL;
411 user_datum_t *user = NULL, *dest_user = NULL;
412 int retval;
413 uint32_t value = 0;
414
415 if (id == NULL) {
416 yyerror("no user name");
417 return NULL;
418 }
419 if ((user = (user_datum_t *) malloc(sizeof(*user))) == NULL) {
420 yyerror("Out of memory!");
421 free(id);
422 return NULL;
423 }
424 user_datum_init(user);
425
426 retval =
427 declare_symbol(SYM_USERS, id, (hashtab_datum_t *) user, &value,
428 &value);
429
430 if (retval == 0) {
431 user->s.value = value;
432 if ((dest_id = strdup(id)) == NULL) {
433 yyerror("Out of memory!");
434 return NULL;
435 }
436 } else {
437 /* this user was already declared in this module, or error */
438 dest_id = id;
439 user_datum_destroy(user);
440 free(user);
441 }
442 if (retval == 0 || retval == 1) {
443 /* create a new user_datum_t for this decl, if necessary */
444 hashtab_t users_tab;
445 assert(stack_top->type == 1);
446 if (stack_top->parent == NULL) {
447 /* in parent, so use global symbol table */
448 users_tab = policydbp->p_users.table;
449 } else {
450 users_tab = stack_top->decl->p_users.table;
451 }
452 dest_user = (user_datum_t *) hashtab_search(users_tab, dest_id);
453 if (dest_user == NULL) {
454 if ((dest_user =
455 (user_datum_t *) malloc(sizeof(*dest_user))) ==
456 NULL) {
457 yyerror("Out of memory!");
458 free(dest_id);
459 return NULL;
460 }
461 user_datum_init(dest_user);
462 dest_user->s.value = value;
Joshua Brindle45728402008-10-08 06:56:51 -0400463 if (user_implicit_bounds(users_tab, dest_id, dest_user)) {
464 free(dest_id);
465 user_datum_destroy(dest_user);
466 free(dest_user);
467 return NULL;
468 }
Joshua Brindle13cd4c82008-08-19 15:30:36 -0400469 if (hashtab_insert(users_tab, dest_id, dest_user)) {
470 yyerror("Out of memory!");
471 free(dest_id);
472 user_datum_destroy(dest_user);
473 free(dest_user);
474 return NULL;
475 }
476 } else {
477 free(dest_id);
478 }
479 } else {
480 free(dest_id);
481 }
482 switch (retval) {
483 case -3:{
484 yyerror("Out of memory!");
485 return NULL;
486 }
487 case -2:{
488 yyerror("duplicate declaration of user");
489 return NULL;
490 }
491 case -1:{
492 yyerror("could not declare user here");
493 return NULL;
494 }
495 case 0:{
496 return dest_user;
497 }
498 case 1:{
499 return dest_user; /* user already declared for this block */
500 }
501 default:{
Dan Albert099223b2015-06-11 16:47:16 -0700502 abort(); /* should never get here */
Joshua Brindle13cd4c82008-08-19 15:30:36 -0400503 }
504 }
505}
506
507/* Return a type_datum_t for the local avrule_decl with the given ID.
508 * If it does not exist, create one with the same value as 'value'.
509 * This function assumes that the ID is within scope. c.f.,
510 * is_id_in_scope().
511 *
512 * NOTE: this function usurps ownership of id afterwards. The caller
513 * shall not reference it nor free() it afterwards.
514 */
515type_datum_t *get_local_type(char *id, uint32_t value, unsigned char isattr)
516{
517 type_datum_t *dest_typdatum;
518 hashtab_t types_tab;
519 assert(stack_top->type == 1);
520 if (stack_top->parent == NULL) {
521 /* in global, so use global symbol table */
522 types_tab = policydbp->p_types.table;
523 } else {
524 types_tab = stack_top->decl->p_types.table;
525 }
526 dest_typdatum = hashtab_search(types_tab, id);
527 if (!dest_typdatum) {
528 dest_typdatum = (type_datum_t *) malloc(sizeof(type_datum_t));
529 if (dest_typdatum == NULL) {
530 free(id);
531 return NULL;
532 }
533 type_datum_init(dest_typdatum);
534 dest_typdatum->s.value = value;
535 dest_typdatum->flavor = isattr ? TYPE_ATTRIB : TYPE_TYPE;
536 dest_typdatum->primary = 1;
537 if (hashtab_insert(types_tab, id, dest_typdatum)) {
538 free(id);
539 type_datum_destroy(dest_typdatum);
540 free(dest_typdatum);
541 return NULL;
542 }
543
544 } else {
545 free(id);
546 if (dest_typdatum->flavor != isattr ? TYPE_ATTRIB : TYPE_TYPE) {
547 return NULL;
548 }
549 }
550 return dest_typdatum;
551}
552
Harry Ciao16675b72011-07-25 09:23:54 +0800553/* Return a role_datum_t for the local avrule_decl with the given ID.
554 * If it does not exist, create one with the same value as 'value'.
555 * This function assumes that the ID is within scope. c.f.,
556 * is_id_in_scope().
557 *
558 * NOTE: this function usurps ownership of id afterwards. The caller
559 * shall not reference it nor free() it afterwards.
560 */
561role_datum_t *get_local_role(char *id, uint32_t value, unsigned char isattr)
562{
563 role_datum_t *dest_roledatum;
564 hashtab_t roles_tab;
565
566 assert(stack_top->type == 1);
567
568 if (stack_top->parent == NULL) {
569 /* in global, so use global symbol table */
570 roles_tab = policydbp->p_roles.table;
571 } else {
572 roles_tab = stack_top->decl->p_roles.table;
573 }
574
575 dest_roledatum = hashtab_search(roles_tab, id);
576 if (!dest_roledatum) {
577 dest_roledatum = (role_datum_t *)malloc(sizeof(role_datum_t));
578 if (dest_roledatum == NULL) {
579 free(id);
580 return NULL;
581 }
582
583 role_datum_init(dest_roledatum);
584 dest_roledatum->s.value = value;
585 dest_roledatum->flavor = isattr ? ROLE_ATTRIB : ROLE_ROLE;
586
587 if (hashtab_insert(roles_tab, id, dest_roledatum)) {
588 free(id);
589 role_datum_destroy(dest_roledatum);
590 free(dest_roledatum);
591 return NULL;
592 }
593 } else {
594 free(id);
595 if (dest_roledatum->flavor != isattr ? ROLE_ATTRIB : ROLE_ROLE)
596 return NULL;
597 }
598
599 return dest_roledatum;
600}
601
Joshua Brindle13cd4c82008-08-19 15:30:36 -0400602/* Given the current parse stack, returns 1 if a requirement would be
603 * allowed here or 0 if not. For example, the ELSE branch may never
604 * have its own requirements.
605 */
606static int is_require_allowed(void)
607{
608 if (stack_top->type == 1 && !stack_top->in_else) {
609 return 1;
610 }
611 return 0;
612}
613
614/* Attempt to require a symbol within the current scope. If currently
615 * within an optional (and not its else branch), add the symbol to the
616 * required list. Return 0 on success, 1 if caller needs to free()
617 * datum. If symbols may not be declared here return -1. For duplicate
618 * declarations return -2. For all else, including out of memory,
619 * return -3.. Note that dest_value and datum_value might not be
620 * restricted pointers.
621 */
622int require_symbol(uint32_t symbol_type,
623 hashtab_key_t key, hashtab_datum_t datum,
624 uint32_t * dest_value, uint32_t * datum_value)
625{
626 avrule_decl_t *decl = stack_top->decl;
627 int retval;
628
629 /* first check that symbols may be required here */
630 if (!is_require_allowed()) {
631 return -1;
632 }
633 retval = symtab_insert(policydbp, symbol_type, key, datum,
634 SCOPE_REQ, decl->decl_id, dest_value);
635 if (retval == 1) {
636 symtab_datum_t *s =
637 (symtab_datum_t *) hashtab_search(policydbp->
638 symtab[symbol_type].table,
639 key);
640 assert(s != NULL);
641
642 if (symbol_type == SYM_LEVELS) {
643 *dest_value = ((level_datum_t *)s)->level->sens;
644 } else {
645 *dest_value = s->value;
646 }
647 } else if (retval == -2) {
648 /* ignore require statements if that symbol was
649 * previously declared and is in current scope */
650 int prev_declaration_ok = 0;
651 if (is_id_in_scope(symbol_type, key)) {
652 if (symbol_type == SYM_TYPES) {
653 /* check that previous symbol has same
654 * type/attribute-ness */
655 unsigned char new_isattr =
656 ((type_datum_t *) datum)->flavor;
657 type_datum_t *old_datum =
658 (type_datum_t *) hashtab_search(policydbp->
659 symtab
660 [SYM_TYPES].
661 table, key);
662 assert(old_datum != NULL);
663 unsigned char old_isattr = old_datum->flavor;
664 prev_declaration_ok =
665 (old_isattr == new_isattr ? 1 : 0);
666 } else {
667 prev_declaration_ok = 1;
668 }
669 }
670 if (prev_declaration_ok) {
671 /* ignore this require statement because it
672 * was already declared within my scope */
673 stack_top->require_given = 1;
674 return 1;
675 } else {
676 /* previous declaration was not in scope or
677 * had a mismatched type/attribute, so
678 * generate an error */
679 return -2;
680 }
681 } else if (retval < 0) {
682 return -3;
683 } else { /* fall through possible if retval is 0 or 1 */
684 }
685 if (datum_value != NULL) {
686 if (ebitmap_set_bit(decl->required.scope + symbol_type,
687 *datum_value - 1, 1)) {
688 return -3;
689 }
690 }
691 stack_top->require_given = 1;
692 return retval;
693}
694
695int add_perm_to_class(uint32_t perm_value, uint32_t class_value)
696{
697 avrule_decl_t *decl = stack_top->decl;
698 scope_index_t *scope;
699
700 assert(perm_value >= 1);
701 assert(class_value >= 1);
702 scope = &decl->required;
703 if (class_value > scope->class_perms_len) {
Nicolas Iooss581d3eb2014-09-14 23:41:41 +0200704 uint32_t i;
Joshua Brindle13cd4c82008-08-19 15:30:36 -0400705 ebitmap_t *new_map = realloc(scope->class_perms_map,
706 class_value * sizeof(*new_map));
707 if (new_map == NULL) {
708 return -1;
709 }
710 scope->class_perms_map = new_map;
711 for (i = scope->class_perms_len; i < class_value; i++) {
712 ebitmap_init(scope->class_perms_map + i);
713 }
714 scope->class_perms_len = class_value;
715 }
716 if (ebitmap_set_bit(scope->class_perms_map + class_value - 1,
717 perm_value - 1, 1)) {
718 return -1;
719 }
720 return 0;
721}
722
723static int perm_destroy(hashtab_key_t key, hashtab_datum_t datum, void *p
724 __attribute__ ((unused)))
725{
726 if (key)
727 free(key);
728 free(datum);
729 return 0;
730}
731
732static void class_datum_destroy(class_datum_t * cladatum)
733{
734 if (cladatum != NULL) {
735 hashtab_map(cladatum->permissions.table, perm_destroy, NULL);
736 hashtab_destroy(cladatum->permissions.table);
737 free(cladatum);
738 }
739}
740
741int require_class(int pass)
742{
743 char *class_id = queue_remove(id_queue);
744 char *perm_id = NULL;
745 class_datum_t *datum = NULL;
746 perm_datum_t *perm = NULL;
747 int ret;
748
749 if (pass == 2) {
750 free(class_id);
751 while ((perm_id = queue_remove(id_queue)) != NULL)
752 free(perm_id);
753 return 0;
754 }
755
756 /* first add the class if it is not already there */
757 if (class_id == NULL) {
758 yyerror("no class name for class definition?");
759 return -1;
760 }
761
762 if ((datum = calloc(1, sizeof(*datum))) == NULL ||
763 symtab_init(&datum->permissions, PERM_SYMTAB_SIZE)) {
764 yyerror("Out of memory!");
765 goto cleanup;
766 }
767 ret =
768 require_symbol(SYM_CLASSES, class_id, datum, &datum->s.value,
769 &datum->s.value);
770 switch (ret) {
771 case -3:{
772 yyerror("Out of memory!");
773 free(class_id);
774 class_datum_destroy(datum);
775 goto cleanup;
776 }
777 case -2:{
778 yyerror("duplicate declaration of class");
779 free(class_id);
780 class_datum_destroy(datum);
781 goto cleanup;
782 }
783 case -1:{
784 yyerror("could not require class here");
785 free(class_id);
786 class_datum_destroy(datum);
787 goto cleanup;
788 }
789 case 0:{
790 /* a new class was added; reindex everything */
791 if (policydb_index_classes(policydbp)) {
792 yyerror("Out of memory!");
793 goto cleanup;
794 }
795 break;
796 }
797 case 1:{
798 class_datum_destroy(datum);
799 datum =
800 hashtab_search(policydbp->p_classes.table,
801 class_id);
802 assert(datum); /* the class datum should have existed */
803 free(class_id);
804 break;
805 }
806 default:{
Dan Albert099223b2015-06-11 16:47:16 -0700807 abort(); /* should never get here */
Joshua Brindle13cd4c82008-08-19 15:30:36 -0400808 }
809 }
810
811 /* now add each of the permissions to this class's requirements */
812 while ((perm_id = queue_remove(id_queue)) != NULL) {
813 int allocated = 0;
814
815 /* Is the permission already in the table? */
816 perm = hashtab_search(datum->permissions.table, perm_id);
817 if (!perm && datum->comdatum)
818 perm =
819 hashtab_search(datum->comdatum->permissions.table,
820 perm_id);
821 if (perm) {
822 /* Yes, drop the name. */
823 free(perm_id);
824 } else {
825 /* No - allocate and insert an entry for it. */
826 if (policydbp->policy_type == POLICY_BASE) {
827 yyerror2
828 ("Base policy - require of permission %s without prior declaration.",
829 perm_id);
830 free(perm_id);
831 goto cleanup;
832 }
833 allocated = 1;
834 if ((perm = malloc(sizeof(*perm))) == NULL) {
835 yyerror("Out of memory!");
836 free(perm_id);
837 goto cleanup;
838 }
839 memset(perm, 0, sizeof(*perm));
840 ret =
841 hashtab_insert(datum->permissions.table, perm_id,
842 perm);
843 if (ret) {
844 yyerror("Out of memory!");
845 free(perm_id);
846 free(perm);
847 goto cleanup;
848 }
849 perm->s.value = datum->permissions.nprim + 1;
850 }
851
852 if (add_perm_to_class(perm->s.value, datum->s.value) == -1) {
853 yyerror("Out of memory!");
854 goto cleanup;
855 }
856
857 /* Update number of primitives if we allocated one. */
858 if (allocated)
859 datum->permissions.nprim++;
860 }
861 return 0;
862 cleanup:
863 return -1;
864}
865
Harry Ciao16675b72011-07-25 09:23:54 +0800866static int require_role_or_attribute(int pass, unsigned char isattr)
Joshua Brindle13cd4c82008-08-19 15:30:36 -0400867{
868 char *id = queue_remove(id_queue);
869 role_datum_t *role = NULL;
870 int retval;
871 if (pass == 2) {
872 free(id);
873 return 0;
874 }
875 if (id == NULL) {
876 yyerror("no role name");
877 return -1;
878 }
879 if ((role = malloc(sizeof(*role))) == NULL) {
880 free(id);
881 yyerror("Out of memory!");
882 return -1;
883 }
884 role_datum_init(role);
Harry Ciao16675b72011-07-25 09:23:54 +0800885 role->flavor = isattr ? ROLE_ATTRIB : ROLE_ROLE;
Joshua Brindle13cd4c82008-08-19 15:30:36 -0400886 retval =
887 require_symbol(SYM_ROLES, id, (hashtab_datum_t *) role,
888 &role->s.value, &role->s.value);
889 if (retval != 0) {
890 free(id);
891 role_datum_destroy(role);
892 free(role);
893 }
894 switch (retval) {
895 case -3:{
896 yyerror("Out of memory!");
897 return -1;
898 }
899 case -2:{
900 yyerror("duplicate declaration of role");
901 return -1;
902 }
903 case -1:{
904 yyerror("could not require role here");
905 return -1;
906 }
907 case 0:{
908 /* all roles dominate themselves */
909 if (ebitmap_set_bit
910 (&role->dominates, role->s.value - 1, 1)) {
911 yyerror("Out of memory");
912 return -1;
913 }
914 return 0;
915 }
916 case 1:{
917 return 0; /* role already required */
918 }
919 default:{
Dan Albert099223b2015-06-11 16:47:16 -0700920 abort(); /* should never get here */
Joshua Brindle13cd4c82008-08-19 15:30:36 -0400921 }
922 }
923}
924
Harry Ciao16675b72011-07-25 09:23:54 +0800925int require_role(int pass)
926{
927 return require_role_or_attribute(pass, 0);
928}
929
930int require_attribute_role(int pass)
931{
932 return require_role_or_attribute(pass, 1);
933}
934
Joshua Brindle13cd4c82008-08-19 15:30:36 -0400935static int require_type_or_attribute(int pass, unsigned char isattr)
936{
937 char *id = queue_remove(id_queue);
938 type_datum_t *type = NULL;
939 int retval;
940 if (pass == 2) {
941 free(id);
942 return 0;
943 }
944 if (id == NULL) {
945 yyerror("no type name");
946 return -1;
947 }
948 if ((type = malloc(sizeof(*type))) == NULL) {
949 free(id);
950 yyerror("Out of memory!");
951 return -1;
952 }
953 type_datum_init(type);
954 type->primary = 1;
955 type->flavor = isattr ? TYPE_ATTRIB : TYPE_TYPE;
956 retval =
957 require_symbol(SYM_TYPES, id, (hashtab_datum_t *) type,
958 &type->s.value, &type->s.value);
959 if (retval != 0) {
960 free(id);
961 free(type);
962 }
963 switch (retval) {
964 case -3:{
965 yyerror("Out of memory!");
966 return -1;
967 }
968 case -2:{
969 yyerror("duplicate declaration of type/attribute");
970 return -1;
971 }
972 case -1:{
973 yyerror("could not require type/attribute here");
974 return -1;
975 }
976 case 0:{
977 return 0;
978 }
979 case 1:{
980 return 0; /* type already required */
981 }
982 default:{
Dan Albert099223b2015-06-11 16:47:16 -0700983 abort(); /* should never get here */
Joshua Brindle13cd4c82008-08-19 15:30:36 -0400984 }
985 }
986}
987
988int require_type(int pass)
989{
990 return require_type_or_attribute(pass, 0);
991}
992
993int require_attribute(int pass)
994{
995 return require_type_or_attribute(pass, 1);
996}
997
998int require_user(int pass)
999{
1000 char *id = queue_remove(id_queue);
1001 user_datum_t *user = NULL;
1002 int retval;
1003 if (pass == 1) {
1004 free(id);
1005 return 0;
1006 }
1007 if (id == NULL) {
1008 yyerror("no user name");
1009 return -1;
1010 }
1011 if ((user = malloc(sizeof(*user))) == NULL) {
1012 free(id);
1013 yyerror("Out of memory!");
1014 return -1;
1015 }
1016 user_datum_init(user);
1017 retval =
1018 require_symbol(SYM_USERS, id, (hashtab_datum_t *) user,
1019 &user->s.value, &user->s.value);
1020 if (retval != 0) {
1021 free(id);
1022 user_datum_destroy(user);
1023 }
1024 switch (retval) {
1025 case -3:{
1026 yyerror("Out of memory!");
1027 return -1;
1028 }
1029 case -2:{
1030 yyerror("duplicate declaration of user");
1031 return -1;
1032 }
1033 case -1:{
1034 yyerror("could not require user here");
1035 return -1;
1036 }
1037 case 0:{
1038 return 0;
1039 }
1040 case 1:{
1041 return 0; /* user already required */
1042 }
1043 default:{
Dan Albert099223b2015-06-11 16:47:16 -07001044 abort(); /* should never get here */
Joshua Brindle13cd4c82008-08-19 15:30:36 -04001045 }
1046 }
1047}
1048
Harry Ciao80f26c52011-09-01 11:29:41 +08001049static int require_bool_tunable(int pass, int is_tunable)
Joshua Brindle13cd4c82008-08-19 15:30:36 -04001050{
1051 char *id = queue_remove(id_queue);
1052 cond_bool_datum_t *booldatum = NULL;
1053 int retval;
1054 if (pass == 2) {
1055 free(id);
1056 return 0;
1057 }
1058 if (id == NULL) {
1059 yyerror("no boolean name");
1060 return -1;
1061 }
1062 if ((booldatum = calloc(1, sizeof(*booldatum))) == NULL) {
1063 cond_destroy_bool(id, booldatum, NULL);
1064 yyerror("Out of memory!");
1065 return -1;
1066 }
Harry Ciao80f26c52011-09-01 11:29:41 +08001067 if (is_tunable)
1068 booldatum->flags |= COND_BOOL_FLAGS_TUNABLE;
Joshua Brindle13cd4c82008-08-19 15:30:36 -04001069 retval =
1070 require_symbol(SYM_BOOLS, id, (hashtab_datum_t *) booldatum,
1071 &booldatum->s.value, &booldatum->s.value);
1072 if (retval != 0) {
1073 cond_destroy_bool(id, booldatum, NULL);
1074 }
1075 switch (retval) {
1076 case -3:{
1077 yyerror("Out of memory!");
1078 return -1;
1079 }
1080 case -2:{
1081 yyerror("duplicate declaration of boolean");
1082 return -1;
1083 }
1084 case -1:{
1085 yyerror("could not require boolean here");
1086 return -1;
1087 }
1088 case 0:{
1089 return 0;
1090 }
1091 case 1:{
1092 return 0; /* boolean already required */
1093 }
1094 default:{
Dan Albert099223b2015-06-11 16:47:16 -07001095 abort(); /* should never get here */
Joshua Brindle13cd4c82008-08-19 15:30:36 -04001096 }
1097 }
1098}
1099
Harry Ciao80f26c52011-09-01 11:29:41 +08001100int require_bool(int pass)
1101{
1102 return require_bool_tunable(pass, 0);
1103}
1104
1105int require_tunable(int pass)
1106{
1107 return require_bool_tunable(pass, 1);
1108}
1109
Joshua Brindle13cd4c82008-08-19 15:30:36 -04001110int require_sens(int pass)
1111{
1112 char *id = queue_remove(id_queue);
1113 level_datum_t *level = NULL;
1114 int retval;
1115 if (pass == 2) {
1116 free(id);
1117 return 0;
1118 }
1119 if (!id) {
1120 yyerror("no sensitivity name");
1121 return -1;
1122 }
1123 level = malloc(sizeof(level_datum_t));
1124 if (!level) {
1125 free(id);
1126 yyerror("Out of memory!");
1127 return -1;
1128 }
1129 level_datum_init(level);
1130 level->level = malloc(sizeof(mls_level_t));
1131 if (!level->level) {
1132 free(id);
1133 level_datum_destroy(level);
1134 free(level);
1135 yyerror("Out of memory!");
1136 return -1;
1137 }
1138 mls_level_init(level->level);
1139 retval = require_symbol(SYM_LEVELS, id, (hashtab_datum_t *) level,
1140 &level->level->sens, &level->level->sens);
1141 if (retval != 0) {
1142 free(id);
1143 mls_level_destroy(level->level);
1144 free(level->level);
1145 level_datum_destroy(level);
1146 free(level);
1147 }
1148 switch (retval) {
1149 case -3:{
1150 yyerror("Out of memory!");
1151 return -1;
1152 }
1153 case -2:{
1154 yyerror("duplicate declaration of sensitivity");
1155 return -1;
1156 }
1157 case -1:{
1158 yyerror("could not require sensitivity here");
1159 return -1;
1160 }
1161 case 0:{
1162 return 0;
1163 }
1164 case 1:{
1165 return 0; /* sensitivity already required */
1166 }
1167 default:{
Dan Albert099223b2015-06-11 16:47:16 -07001168 abort(); /* should never get here */
Joshua Brindle13cd4c82008-08-19 15:30:36 -04001169 }
1170 }
1171}
1172
1173int require_cat(int pass)
1174{
1175 char *id = queue_remove(id_queue);
1176 cat_datum_t *cat = NULL;
1177 int retval;
1178 if (pass == 2) {
1179 free(id);
1180 return 0;
1181 }
1182 if (!id) {
1183 yyerror("no category name");
1184 return -1;
1185 }
1186 cat = malloc(sizeof(cat_datum_t));
1187 if (!cat) {
1188 free(id);
1189 yyerror("Out of memory!");
1190 return -1;
1191 }
1192 cat_datum_init(cat);
1193
1194 retval = require_symbol(SYM_CATS, id, (hashtab_datum_t *) cat,
1195 &cat->s.value, &cat->s.value);
1196 if (retval != 0) {
1197 free(id);
1198 cat_datum_destroy(cat);
1199 free(cat);
1200 }
1201 switch (retval) {
1202 case -3:{
1203 yyerror("Out of memory!");
1204 return -1;
1205 }
1206 case -2:{
1207 yyerror("duplicate declaration of category");
1208 return -1;
1209 }
1210 case -1:{
1211 yyerror("could not require category here");
1212 return -1;
1213 }
1214 case 0:{
1215 return 0;
1216 }
1217 case 1:{
1218 return 0; /* category already required */
1219 }
1220 default:{
Dan Albert099223b2015-06-11 16:47:16 -07001221 abort(); /* should never get here */
Joshua Brindle13cd4c82008-08-19 15:30:36 -04001222 }
1223 }
1224}
1225
1226static int is_scope_in_stack(scope_datum_t * scope, scope_stack_t * stack)
1227{
Nicolas Iooss581d3eb2014-09-14 23:41:41 +02001228 uint32_t i;
Joshua Brindle13cd4c82008-08-19 15:30:36 -04001229 if (stack == NULL) {
1230 return 0; /* no matching scope found */
1231 }
1232 if (stack->type == 1) {
1233 avrule_decl_t *decl = stack->decl;
1234 for (i = 0; i < scope->decl_ids_len; i++) {
1235 if (scope->decl_ids[i] == decl->decl_id) {
1236 return 1;
1237 }
1238 }
1239 } else {
1240 /* note that conditionals can't declare or require
1241 * symbols, so skip this level */
1242 }
1243
1244 /* not within scope of this stack, so try its parent */
1245 return is_scope_in_stack(scope, stack->parent);
1246}
1247
1248int is_id_in_scope(uint32_t symbol_type, hashtab_key_t id)
1249{
1250 scope_datum_t *scope =
1251 (scope_datum_t *) hashtab_search(policydbp->scope[symbol_type].
1252 table, id);
1253 if (scope == NULL) {
1254 return 1; /* id is not known, so return success */
1255 }
1256 return is_scope_in_stack(scope, stack_top);
1257}
1258
1259static int is_perm_in_scope_index(uint32_t perm_value, uint32_t class_value,
1260 scope_index_t * scope)
1261{
1262 if (class_value > scope->class_perms_len) {
1263 return 1;
1264 }
1265 if (ebitmap_get_bit(scope->class_perms_map + class_value - 1,
1266 perm_value - 1)) {
1267 return 1;
1268 }
1269 return 0;
1270}
1271
1272static int is_perm_in_stack(uint32_t perm_value, uint32_t class_value,
1273 scope_stack_t * stack)
1274{
1275 if (stack == NULL) {
1276 return 0; /* no matching scope found */
1277 }
1278 if (stack->type == 1) {
1279 avrule_decl_t *decl = stack->decl;
1280 if (is_perm_in_scope_index
1281 (perm_value, class_value, &decl->required)
1282 || is_perm_in_scope_index(perm_value, class_value,
1283 &decl->declared)) {
1284 return 1;
1285 }
1286 } else {
1287 /* note that conditionals can't declare or require
1288 * symbols, so skip this level */
1289 }
1290
1291 /* not within scope of this stack, so try its parent */
1292 return is_perm_in_stack(perm_value, class_value, stack->parent);
1293}
1294
1295int is_perm_in_scope(hashtab_key_t perm_id, hashtab_key_t class_id)
1296{
1297 class_datum_t *cladatum =
1298 (class_datum_t *) hashtab_search(policydbp->p_classes.table,
1299 class_id);
1300 perm_datum_t *perdatum;
1301 if (cladatum == NULL) {
1302 return 1;
1303 }
1304 perdatum = (perm_datum_t *) hashtab_search(cladatum->permissions.table,
1305 perm_id);
1306 if (perdatum == NULL) {
1307 return 1;
1308 }
1309 return is_perm_in_stack(perdatum->s.value, cladatum->s.value,
1310 stack_top);
1311}
1312
1313cond_list_t *get_current_cond_list(cond_list_t * cond)
1314{
1315 /* FIX ME: do something different here if in a nested
1316 * conditional? */
1317 avrule_decl_t *decl = stack_top->decl;
1318 return get_decl_cond_list(policydbp, decl, cond);
1319}
1320
1321/* Append the new conditional node to the existing ones. During
1322 * expansion the list will be reversed -- i.e., the last AV rule will
1323 * be the first one listed in the policy. This matches the behavior
1324 * of the upstream compiler. */
1325void append_cond_list(cond_list_t * cond)
1326{
1327 cond_list_t *old_cond = get_current_cond_list(cond);
1328 avrule_t *tmp;
1329 assert(old_cond != NULL); /* probably out of memory */
1330 if (old_cond->avtrue_list == NULL) {
1331 old_cond->avtrue_list = cond->avtrue_list;
1332 } else {
1333 for (tmp = old_cond->avtrue_list; tmp->next != NULL;
1334 tmp = tmp->next) ;
1335 tmp->next = cond->avtrue_list;
1336 }
1337 if (old_cond->avfalse_list == NULL) {
1338 old_cond->avfalse_list = cond->avfalse_list;
1339 } else {
1340 for (tmp = old_cond->avfalse_list; tmp->next != NULL;
1341 tmp = tmp->next) ;
1342 tmp->next = cond->avfalse_list;
1343 }
Harry Ciao80f26c52011-09-01 11:29:41 +08001344
1345 old_cond->flags |= cond->flags;
Joshua Brindle13cd4c82008-08-19 15:30:36 -04001346}
1347
1348void append_avrule(avrule_t * avrule)
1349{
1350 avrule_decl_t *decl = stack_top->decl;
1351
1352 /* currently avrules follow a completely different code path
1353 * for handling avrules and compute types
1354 * (define_cond_avrule_te_avtab, define_cond_compute_type);
1355 * therefore there ought never be a conditional on top of the
1356 * scope stack */
1357 assert(stack_top->type == 1);
1358
1359 if (stack_top->last_avrule == NULL) {
1360 decl->avrules = avrule;
1361 } else {
1362 stack_top->last_avrule->next = avrule;
1363 }
1364 stack_top->last_avrule = avrule;
1365}
1366
1367/* this doesn't actually append, but really prepends it */
1368void append_role_trans(role_trans_rule_t * role_tr_rules)
1369{
1370 avrule_decl_t *decl = stack_top->decl;
1371
1372 /* role transitions are not allowed within conditionals */
1373 assert(stack_top->type == 1);
1374
1375 role_tr_rules->next = decl->role_tr_rules;
1376 decl->role_tr_rules = role_tr_rules;
1377}
1378
1379/* this doesn't actually append, but really prepends it */
1380void append_role_allow(role_allow_rule_t * role_allow_rules)
1381{
1382 avrule_decl_t *decl = stack_top->decl;
1383
1384 /* role allows are not allowed within conditionals */
1385 assert(stack_top->type == 1);
1386
1387 role_allow_rules->next = decl->role_allow_rules;
1388 decl->role_allow_rules = role_allow_rules;
1389}
1390
1391/* this doesn't actually append, but really prepends it */
Eric Paris516cb2a2011-03-28 14:00:19 -04001392void append_filename_trans(filename_trans_rule_t * filename_trans_rules)
1393{
1394 avrule_decl_t *decl = stack_top->decl;
1395
1396 /* filename transitions are not allowed within conditionals */
1397 assert(stack_top->type == 1);
1398
1399 filename_trans_rules->next = decl->filename_trans_rules;
1400 decl->filename_trans_rules = filename_trans_rules;
1401}
1402
1403/* this doesn't actually append, but really prepends it */
Joshua Brindle13cd4c82008-08-19 15:30:36 -04001404void append_range_trans(range_trans_rule_t * range_tr_rules)
1405{
1406 avrule_decl_t *decl = stack_top->decl;
1407
1408 /* range transitions are not allowed within conditionals */
1409 assert(stack_top->type == 1);
1410
1411 range_tr_rules->next = decl->range_tr_rules;
1412 decl->range_tr_rules = range_tr_rules;
1413}
1414
1415int begin_optional(int pass)
1416{
1417 avrule_block_t *block = NULL;
1418 avrule_decl_t *decl;
1419 if (pass == 1) {
1420 /* allocate a new avrule block for this optional block */
1421 if ((block = avrule_block_create()) == NULL ||
1422 (decl = avrule_decl_create(next_decl_id)) == NULL) {
1423 goto cleanup;
1424 }
1425 block->flags |= AVRULE_OPTIONAL;
1426 block->branch_list = decl;
1427 last_block->next = block;
1428 } else {
1429 /* select the next block from the chain built during pass 1 */
1430 block = last_block->next;
1431 assert(block != NULL &&
1432 block->branch_list != NULL &&
1433 block->branch_list->decl_id == next_decl_id);
1434 decl = block->branch_list;
1435 }
1436 if (push_stack(1, block, decl) == -1) {
1437 goto cleanup;
1438 }
1439 stack_top->last_avrule = NULL;
1440 last_block = block;
1441 next_decl_id++;
1442 return 0;
1443 cleanup:
1444 yyerror("Out of memory!");
1445 avrule_block_destroy(block);
1446 return -1;
1447}
1448
Nicolas Iooss5af8c5a2014-09-14 23:41:50 +02001449int end_optional(int pass __attribute__ ((unused)))
Joshua Brindle13cd4c82008-08-19 15:30:36 -04001450{
1451 /* once nested conditionals are allowed, do the stack unfolding here */
1452 pop_stack();
1453 return 0;
1454}
1455
1456int begin_optional_else(int pass)
1457{
1458 avrule_decl_t *decl;
1459 assert(stack_top->type == 1 && stack_top->in_else == 0);
1460 if (pass == 1) {
1461 /* allocate a new declaration and add it to the
1462 * current chain */
1463 if ((decl = avrule_decl_create(next_decl_id)) == NULL) {
1464 yyerror("Out of memory!");
1465 return -1;
1466 }
1467 stack_top->decl->next = decl;
1468 } else {
1469 /* pick the (hopefully last) declaration of this
1470 avrule block, built from pass 1 */
1471 decl = stack_top->decl->next;
1472 assert(decl != NULL &&
1473 decl->next == NULL && decl->decl_id == next_decl_id);
1474 }
1475 stack_top->in_else = 1;
1476 stack_top->decl = decl;
1477 stack_top->last_avrule = NULL;
1478 stack_top->require_given = 0;
1479 next_decl_id++;
1480 return 0;
1481}
1482
1483static int copy_requirements(avrule_decl_t * dest, scope_stack_t * stack)
1484{
Nicolas Iooss581d3eb2014-09-14 23:41:41 +02001485 uint32_t i;
Joshua Brindle13cd4c82008-08-19 15:30:36 -04001486 if (stack == NULL) {
1487 return 0;
1488 }
1489 if (stack->type == 1) {
1490 scope_index_t *src_scope = &stack->decl->required;
1491 scope_index_t *dest_scope = &dest->required;
1492 for (i = 0; i < SYM_NUM; i++) {
1493 ebitmap_t *src_bitmap = &src_scope->scope[i];
1494 ebitmap_t *dest_bitmap = &dest_scope->scope[i];
1495 if (ebitmap_union(dest_bitmap, src_bitmap)) {
1496 yyerror("Out of memory!");
1497 return -1;
1498 }
1499 }
1500 /* now copy class permissions */
1501 if (src_scope->class_perms_len > dest_scope->class_perms_len) {
1502 ebitmap_t *new_map =
1503 realloc(dest_scope->class_perms_map,
1504 src_scope->class_perms_len *
1505 sizeof(*new_map));
1506 if (new_map == NULL) {
1507 yyerror("Out of memory!");
1508 return -1;
1509 }
1510 dest_scope->class_perms_map = new_map;
1511 for (i = dest_scope->class_perms_len;
1512 i < src_scope->class_perms_len; i++) {
1513 ebitmap_init(dest_scope->class_perms_map + i);
1514 }
1515 dest_scope->class_perms_len =
1516 src_scope->class_perms_len;
1517 }
1518 for (i = 0; i < src_scope->class_perms_len; i++) {
1519 ebitmap_t *src_bitmap = &src_scope->class_perms_map[i];
1520 ebitmap_t *dest_bitmap =
1521 &dest_scope->class_perms_map[i];
1522 if (ebitmap_union(dest_bitmap, src_bitmap)) {
1523 yyerror("Out of memory!");
1524 return -1;
1525 }
1526 }
1527 }
1528 return copy_requirements(dest, stack->parent);
1529}
1530
1531/* During pass 1, check that at least one thing was required within
1532 * this block, for those places where a REQUIRED is necessary. During
1533 * pass 2, have this block inherit its parents' requirements. Return
1534 * 0 on success, -1 on failure. */
1535int end_avrule_block(int pass)
1536{
1537 avrule_decl_t *decl = stack_top->decl;
1538 assert(stack_top->type == 1);
1539 if (pass == 2) {
1540 /* this avrule_decl inherits all of its parents'
1541 * requirements */
1542 if (copy_requirements(decl, stack_top->parent) == -1) {
1543 return -1;
1544 }
1545 return 0;
1546 }
1547 if (!stack_top->in_else && !stack_top->require_given) {
1548 if (policydbp->policy_type == POLICY_BASE
1549 && stack_top->parent != NULL) {
1550 /* if this is base no require should be in the global block */
1551 return 0;
1552 } else {
1553 /* non-ELSE branches must have at least one thing required */
1554 yyerror("This block has no require section.");
1555 return -1;
1556 }
1557 }
1558 return 0;
1559}
1560
1561/* Push a new scope on to the stack and update the 'last' pointer.
1562 * Return 0 on success, -1 if out * of memory. */
1563static int push_stack(int stack_type, ...)
1564{
1565 scope_stack_t *s = calloc(1, sizeof(*s));
1566 va_list ap;
1567 if (s == NULL) {
1568 return -1;
1569 }
1570 va_start(ap, stack_type);
1571 switch (s->type = stack_type) {
1572 case 1:{
1573 s->u.avrule = va_arg(ap, avrule_block_t *);
1574 s->decl = va_arg(ap, avrule_decl_t *);
1575 break;
1576 }
1577 case 2:{
1578 s->u.cond_list = va_arg(ap, cond_list_t *);
1579 break;
1580 }
1581 default:
1582 /* invalid stack type given */
1583 assert(0);
1584 }
1585 va_end(ap);
1586 s->parent = stack_top;
1587 s->child = NULL;
1588 stack_top = s;
1589 return 0;
1590}
1591
1592/* Pop off the most recently added from the stack. Update the 'last'
1593 * pointer. */
1594static void pop_stack(void)
1595{
1596 scope_stack_t *parent;
1597 assert(stack_top != NULL);
1598 parent = stack_top->parent;
1599 if (parent != NULL) {
1600 parent->child = NULL;
1601 }
1602 free(stack_top);
1603 stack_top = parent;
1604}