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