1 #include <cil/android.h>
2 #include <sepol/policydb/hashtab.h>
3 #include <stdlib.h>
4 #include <string.h>
5
6 #include "cil_binary.h"
7 #include "cil_build_ast.h"
8 #include "cil_internal.h"
9 #include "cil_strpool.h"
10 #include "cil_symtab.h"
11 #include "cil_tree.h"
12
13 #define VER_MAP_SZ (1 << 12)
14
15 /* added to hashmap - currently unused as hashmap is used as a set */
16 struct version_datum {
17 struct cil_db *db;
18 struct cil_tree_node *ast_node;
19 char *orig_name;
20 };
21
22 struct version_args {
23 struct cil_db *db;
24 hashtab_t vers_map;
25 const char *num;
26 };
27
28 struct policydb_amend_args {
29 const struct cil_db *db;
30 policydb_t *pdb;
31 void **type_value_to_cil;
32 };
33
34 enum plat_flavor {
35 PLAT_NONE = 0,
36 PLAT_TYPE,
37 PLAT_ATTRIB
38 };
39
ver_map_hash_val(hashtab_t h,const_hashtab_key_t key)40 static unsigned int ver_map_hash_val(hashtab_t h, const_hashtab_key_t key)
41 {
42 /* from cil_stpool.c */
43 char *p, *keyp;
44 size_t size;
45 unsigned int val;
46
47 val = 0;
48 keyp = (char*)key;
49 size = strlen(keyp);
50 for (p = keyp; ((size_t) (p - keyp)) < size; p++)
51 val =
52 (val << 4 | (val >> (8 * sizeof(unsigned int) - 4))) ^ (*p);
53 return val & (h->size - 1);
54 }
55
56
ver_map_key_cmp(hashtab_t h,const_hashtab_key_t key1,const_hashtab_key_t key2)57 static int ver_map_key_cmp(hashtab_t h __attribute__ ((unused)),
58 const_hashtab_key_t key1, const_hashtab_key_t key2)
59 {
60 /* hashtab_key_t is just a const char* underneath */
61 return strcmp(key1, key2);
62 }
63
64 /*
65 * version_datum pointers all refer to memory owned elsewhere, so just free the
66 * datum itself.
67 */
ver_map_entry_destroy(hashtab_key_t k,hashtab_datum_t d,void * args)68 static int ver_map_entry_destroy(__attribute__ ((unused))hashtab_key_t k,
69 hashtab_datum_t d, __attribute__ ((unused))void *args)
70 {
71 free(d);
72 return 0;
73 }
74
ver_map_destroy(hashtab_t h)75 static void ver_map_destroy(hashtab_t h)
76 {
77 hashtab_map(h, ver_map_entry_destroy, NULL);
78 hashtab_destroy(h);
79 }
80
__extract_attributees_helper(struct cil_tree_node * node,uint32_t * finished,void * extra_args)81 static int __extract_attributees_helper(struct cil_tree_node *node, uint32_t *finished, void *extra_args)
82 {
83 int rc = SEPOL_ERR;
84 struct version_args *args = (struct version_args *) extra_args;
85 char *key;
86 struct version_datum *datum;
87
88 if (node == NULL || finished == NULL || extra_args == NULL) {
89 goto exit;
90 }
91
92 switch (node->flavor) {
93 case CIL_ROLE:
94 cil_log(CIL_ERR, "%s unsupported statement in attributee policy (line %d)\n",
95 CIL_KEY_ROLE, node->line);
96 rc = SEPOL_ERR;
97 break;
98 case CIL_TYPE:
99 case CIL_TYPEATTRIBUTE:
100 datum = cil_malloc(sizeof(*datum));
101 datum->db = args->db;
102 datum->ast_node = node;
103 datum->orig_name = DATUM(node->data)->name;
104 key = datum->orig_name;
105 if (!strncmp(key, "base_typeattr_", 14)) {
106 /* checkpolicy creates base attributes which are just typeattributesets,
107 of the existing types and attributes. These may be differnt in
108 every checkpolicy output, ignore them here, they'll be dealt with
109 as a special case when attributizing. */
110 free(datum);
111 } else {
112 rc = hashtab_insert(args->vers_map, (hashtab_key_t) key, (hashtab_datum_t) datum);
113 if (rc != SEPOL_OK) {
114 goto exit;
115 }
116 }
117 break;
118 case CIL_TYPEALIAS:
119 cil_log(CIL_ERR, "%s unsupported statement in attributee policy (line %d)\n",
120 CIL_KEY_TYPEALIAS, node->line);
121 goto exit;
122 break;
123 case CIL_TYPEPERMISSIVE:
124 cil_log(CIL_ERR, "%s unsupported statement in attributee policy (line %d)\n",
125 CIL_KEY_TYPEPERMISSIVE, node->line);
126 goto exit;
127 break;
128 case CIL_NAMETYPETRANSITION:
129 case CIL_TYPE_RULE:
130 cil_log(CIL_ERR, "%s unsupported statement in attributee policy (line %d)\n",
131 CIL_KEY_TYPETRANSITION, node->line);
132 goto exit;
133 break;
134 default:
135 break;
136 }
137 return SEPOL_OK;
138 exit:
139 return rc;
140 }
141
142 /*
143 * For the given db, with an already-built AST, fill the vers_map hash table
144 * with every encountered type and attribute. This could eventually be expanded
145 * to include other language constructs, such as users and roles, in which case
146 * multiple hash tables would be needed. These tables can then be used by
147 * attributize() to change all references to these types.
148 */
cil_extract_attributees(struct cil_db * db,hashtab_t vers_map)149 int cil_extract_attributees(struct cil_db *db, hashtab_t vers_map)
150 {
151 /* walk ast. */
152 int rc = SEPOL_ERR;
153 struct version_args extra_args;
154 extra_args.db = db;
155 extra_args.vers_map = vers_map;
156 extra_args.num = NULL;
157 rc = cil_tree_walk(db->ast->root, __extract_attributees_helper, NULL, NULL, &extra_args);
158 if (rc != SEPOL_OK) {
159 goto exit;
160 }
161
162 return SEPOL_OK;
163 exit:
164 return rc;
165 }
166
__cil_get_plat_flavor(hashtab_t vers_map,hashtab_key_t key)167 static enum plat_flavor __cil_get_plat_flavor(hashtab_t vers_map, hashtab_key_t key)
168 {
169 enum plat_flavor rc;
170 struct version_datum *vers_datum;
171
172 vers_datum = (struct version_datum *)hashtab_search(vers_map, key);
173 if (vers_datum == NULL) {
174 return PLAT_NONE;
175 }
176 switch (vers_datum->ast_node->flavor) {
177 case CIL_TYPE:
178 rc = PLAT_TYPE;
179 break;
180 case CIL_TYPEATTRIBUTE:
181 rc = PLAT_ATTRIB;
182 break;
183 default:
184 rc = PLAT_NONE;
185 break;
186 }
187 return rc;
188 }
189
190 /*
191 * Takes the old name and version string and creates a new strpool entry by
192 * combining them.
193 */
__cil_attrib_get_versname(char * old,const char * vers)194 static char *__cil_attrib_get_versname(char *old, const char *vers)
195 {
196 size_t len = 0;
197 char *tmp_new = NULL;
198 char *final;
199
200 len += strlen(old) + strlen(vers) + 2;
201 tmp_new = cil_malloc(len);
202 snprintf(tmp_new, len, "%s_%s", old, vers);
203 final = cil_strpool_add(tmp_new);
204 free(tmp_new);
205 return final;
206 }
207
208 /*
209 * Change type to attribute - create new versioned name based on old, create
210 * typeattribute node add to the existing type node.
211 */
__cil_attrib_convert_type(struct cil_tree_node * node,struct version_args * args)212 static int __cil_attrib_convert_type(struct cil_tree_node *node, struct version_args *args)
213 {
214 int rc = SEPOL_ERR;
215 struct cil_type *type = (struct cil_type *)node->data;
216 struct cil_typeattribute *typeattr = NULL;
217 struct cil_tree_node *new_ast_node = NULL;
218 char *new_key;
219
220 cil_typeattribute_init(&typeattr);
221
222 new_key = __cil_attrib_get_versname(type->datum.name, args->num);
223
224 /* create new tree node to contain typeattribute and add to tree */
225 cil_tree_node_init(&new_ast_node);
226 new_ast_node->parent = node->parent;
227 new_ast_node->next = node->next;
228 node->next = new_ast_node;
229
230 rc = cil_gen_node(args->db, new_ast_node, (struct cil_symtab_datum *) typeattr,
231 new_key, CIL_SYM_TYPES, CIL_TYPEATTRIBUTE);
232 if (rc != SEPOL_OK) {
233 goto exit;
234 }
235
236 return SEPOL_OK;
237 exit:
238 return rc;
239 }
240
241 /*
242 * Update datum - create new key, remove entry under old key,
243 * update entry, and insert under new key
244 */
__cil_attrib_swap_symtab_key(struct cil_tree_node * node,char * old_key,const char * num)245 static int __cil_attrib_swap_symtab_key(struct cil_tree_node *node, char *old_key,
246 const char *num)
247 {
248 int rc = SEPOL_ERR;
249 char *new_key;
250 symtab_t *symtab;
251 struct cil_symtab_datum *datum = (struct cil_symtab_datum *) node->data;
252
253 new_key = __cil_attrib_get_versname(old_key, num);
254
255 symtab = datum->symtab;
256
257 /* TODO: remove, but what happens to other nodes on this datum ?*/
258 cil_list_remove(datum->nodes, CIL_NODE, node, 0);
259 cil_symtab_remove_datum(datum);
260
261 rc = cil_symtab_insert(symtab, new_key, datum, node);
262
263 if (rc != SEPOL_OK) {
264 goto exit;
265 }
266
267 return SEPOL_OK;
268 exit:
269 return rc;
270 }
271
272 /*
273 * expressions may contains strings which are not in the type-attribute
274 * namespace, so this is not a general cil_expr attributizer.
275 * TODO: add support for other types of expressions which may contain types.
276 */
cil_attrib_type_expr(struct cil_list * expr_str,struct version_args * args)277 static int cil_attrib_type_expr(struct cil_list *expr_str, struct version_args *args)
278 {
279 int rc = SEPOL_ERR;
280 struct cil_list_item *curr = NULL;
281 char *new;
282 hashtab_key_t key;
283
284 /* iterate through cil_list, replacing types */
285 cil_list_for_each(curr, expr_str) {
286 switch(curr->flavor) {
287 case CIL_LIST:
288 rc = cil_attrib_type_expr((struct cil_list *)curr->data, args);
289 if (rc != SEPOL_OK)
290 goto exit;
291 break;
292 case CIL_STRING:
293 key = (hashtab_key_t) curr->data;
294 enum plat_flavor pf = __cil_get_plat_flavor(args->vers_map, key);
295 if (!strncmp(curr->data, "base_typeattr_", 14) || pf == PLAT_TYPE) {
296 new = __cil_attrib_get_versname((char *) curr->data, args->num);
297 curr->data = (void *) new;
298 }
299 break;
300 case CIL_DATUM:
301 cil_log(CIL_ERR, "AST already resolved. Not yet supported.\n");
302 rc = SEPOL_ERR;
303 goto exit;
304 break;
305 default:
306 break;
307 }
308 }
309
310 return SEPOL_OK;
311 exit:
312 return rc;
313 }
314
cil_attrib_check_context(struct cil_context * ctxt,struct version_args * args)315 static int cil_attrib_check_context(struct cil_context *ctxt, struct version_args *args)
316 {
317 int rc = SEPOL_ERR;
318 hashtab_key_t key;
319
320 if (ctxt->type != NULL) {
321 cil_log(CIL_ERR, "AST already resolved. Not yet supported.\n");
322 goto exit;
323 }
324
325 key = (hashtab_key_t) ctxt->type_str;
326 if (__cil_get_plat_flavor(args->vers_map, key) != PLAT_NONE) {
327 /* TODO: reinstate check, but leave out for now
328 cil_log(CIL_ERR, "AST contains context with platform public type: %s\n",
329 ctxt->type_str);
330 rc = SEPOL_ERR;
331 goto exit; */
332 }
333
334 return SEPOL_OK;
335 exit:
336 return rc;
337 }
338
cil_attrib_sidcontext(struct cil_tree_node * node,struct version_args * args)339 static int cil_attrib_sidcontext(struct cil_tree_node *node, struct version_args *args)
340 {
341 int rc = SEPOL_ERR;
342 struct cil_sidcontext *sidcon = (struct cil_sidcontext *)node->data;
343
344 if (sidcon->context_str == NULL) {
345 /* sidcon contains an anon context, which needs to have type checked */
346 rc = cil_attrib_check_context(sidcon->context, args);
347 if (rc != SEPOL_OK) {
348 goto exit;
349 }
350 }
351
352 return SEPOL_OK;
353 exit:
354 return rc;
355 }
356
cil_attrib_context(struct cil_tree_node * node,struct version_args * args)357 static int cil_attrib_context(struct cil_tree_node *node, struct version_args *args)
358 {
359 struct cil_context *ctxt = (struct cil_context *)node->data;
360
361 return cil_attrib_check_context(ctxt, args);
362 }
363
cil_attrib_roletype(struct cil_tree_node * node,struct version_args * args)364 static int cil_attrib_roletype(struct cil_tree_node *node,
365 __attribute__((unused)) struct version_args *args)
366 {
367 int rc = SEPOL_ERR;
368 char *key;
369 struct cil_roletype *roletype = (struct cil_roletype *)node->data;
370
371 if (roletype->role) {
372 cil_log(CIL_ERR, "AST already resolved. !!! Not yet supported.\n");
373 goto exit;
374 }
375 key = roletype->type_str;
376 if (__cil_get_plat_flavor(args->vers_map, (hashtab_key_t) key) == PLAT_TYPE) {
377 roletype->type_str = __cil_attrib_get_versname(key, args->num);
378 }
379
380 return SEPOL_OK;
381 exit:
382 return rc;
383 }
384
cil_attrib_type(struct cil_tree_node * node,struct version_args * args)385 static int cil_attrib_type(struct cil_tree_node *node, struct version_args *args)
386 {
387 int rc = SEPOL_ERR;
388 struct cil_type *type = (struct cil_type *)node->data;
389 char *key = type->datum.name;
390
391 if (type->value) {
392 cil_log(CIL_ERR, "AST already resolved. !!! Not yet supported.\n");
393 goto exit;
394 }
395 if (__cil_get_plat_flavor(args->vers_map, (hashtab_key_t) key) == PLAT_TYPE) {
396 rc = __cil_attrib_convert_type(node, args);
397 if (rc != SEPOL_OK) {
398 goto exit;
399 }
400 }
401
402 return SEPOL_OK;
403 exit:
404 return rc;
405 }
406
cil_attrib_typepermissive(struct cil_tree_node * node,struct version_args * args)407 static int cil_attrib_typepermissive(struct cil_tree_node *node,
408 struct version_args *args __attribute__ ((unused)))
409 {
410 struct cil_typepermissive *typeperm = (struct cil_typepermissive *)node->data;
411
412 if (typeperm->type != NULL) {
413 cil_log(CIL_ERR, "AST already resolved. ### Not yet supported.\n");
414 return SEPOL_ERR;
415 }
416
417 return SEPOL_OK;
418 }
419
cil_attrib_typeattribute(struct cil_tree_node * node,struct version_args * args)420 static int cil_attrib_typeattribute(struct cil_tree_node *node, struct version_args *args)
421 {
422 int rc = SEPOL_ERR;
423 struct cil_typeattribute *typeattr = (struct cil_typeattribute *)node->data;
424 char *key = typeattr->datum.name;
425
426 if (typeattr->types) {
427 cil_log(CIL_ERR, "AST already resolved. Not yet supported (line %d).\n",
428 node->line);
429 goto exit;
430 }
431 if (!strncmp(key, "base_typeattr_", 14)) {
432 rc = __cil_attrib_swap_symtab_key(node, key, args->num);
433 if (rc != SEPOL_OK) {
434 goto exit;
435 }
436 }
437
438 return SEPOL_OK;
439 exit:
440 return rc;
441 }
442
cil_attrib_typeattributeset(struct cil_tree_node * node,struct version_args * args)443 static int cil_attrib_typeattributeset(struct cil_tree_node *node, struct version_args *args)
444 {
445 int rc = SEPOL_ERR;
446 char *key;
447 struct cil_typeattributeset *typeattrset = (struct cil_typeattributeset *) node->data;
448
449 if (typeattrset->datum_expr != NULL) {
450 cil_log(CIL_ERR, "AST already resolved. Not yet supported (line %d).\n",
451 node->line);
452 goto exit;
453 }
454
455 key = typeattrset->attr_str;
456 /* first check to see if the attribute to which this set belongs is versioned */
457 if (!strncmp(key, "base_typeattr_", 14)) {
458 typeattrset->attr_str = __cil_attrib_get_versname(key, args->num);
459 }
460
461 rc = cil_attrib_type_expr(typeattrset->str_expr, args);
462 if (rc != SEPOL_OK) {
463 goto exit;
464 }
465
466 return SEPOL_OK;
467 exit:
468 return rc;
469 }
470
cil_attrib_typealiasactual(struct cil_tree_node * node,struct version_args * args)471 static int cil_attrib_typealiasactual(struct cil_tree_node *node, struct version_args *args)
472 {
473 int rc = SEPOL_ERR;
474 char *key;
475 struct cil_aliasactual *aliasact = (struct cil_aliasactual *)node->data;
476
477 key = aliasact->actual_str;
478 if (__cil_get_plat_flavor(args->vers_map, (hashtab_key_t) key) != PLAT_NONE) {
479 cil_log(CIL_ERR, "%s with platform public type not allowed (line %d)\n",
480 CIL_KEY_TYPEALIASACTUAL, node->line);
481 goto exit;
482 }
483
484 return SEPOL_OK;
485 exit:
486 return rc;
487 }
488
cil_attrib_nametypetransition(struct cil_tree_node * node,struct version_args * args)489 static int cil_attrib_nametypetransition(struct cil_tree_node *node, struct version_args *args)
490 {
491 int rc = SEPOL_ERR;
492 char *key;
493 struct cil_nametypetransition *namettrans = (struct cil_nametypetransition *)node->data;
494
495 if (namettrans->src != NULL) {
496 cil_log(CIL_ERR, "AST already resolved. Not yet supported (line %d).\n",
497 node->line);
498 goto exit;
499 }
500 key = namettrans->src_str;
501 if (__cil_get_plat_flavor(args->vers_map, (hashtab_key_t) key) == PLAT_TYPE) {
502 namettrans->src_str = __cil_attrib_get_versname(key, args->num);
503 }
504
505 key = namettrans->tgt_str;
506 if (__cil_get_plat_flavor(args->vers_map, (hashtab_key_t) key) == PLAT_TYPE) {
507 namettrans->tgt_str = __cil_attrib_get_versname(key, args->num);
508 }
509
510 return SEPOL_OK;
511 exit:
512 return rc;
513 }
514
515 /*
516 * This is exactly the same as cil_attrib_nametypetransition, but the struct
517 * layouts differ, so we can't reuse it.
518 */
cil_attrib_type_rule(struct cil_tree_node * node,struct version_args * args)519 static int cil_attrib_type_rule(struct cil_tree_node *node, struct version_args *args)
520 {
521 int rc = SEPOL_ERR;
522 char *key;
523 struct cil_type_rule *type_rule = (struct cil_type_rule *)node->data;
524
525 if (type_rule->src != NULL) {
526 cil_log(CIL_ERR, "AST already resolved. Not yet supported (line %d).\n",
527 node->line);
528 goto exit;
529 }
530 key = type_rule->src_str;
531 if (__cil_get_plat_flavor(args->vers_map, (hashtab_key_t) key) == PLAT_TYPE) {
532 type_rule->src_str = __cil_attrib_get_versname(key, args->num);
533 }
534
535 key = type_rule->tgt_str;
536 if (__cil_get_plat_flavor(args->vers_map, (hashtab_key_t) key) == PLAT_TYPE) {
537 type_rule->tgt_str = __cil_attrib_get_versname(key, args->num);
538 }
539
540 return SEPOL_OK;
541 exit:
542 return rc;
543 }
544
cil_attrib_avrule(struct cil_tree_node * node,struct version_args * args)545 static int cil_attrib_avrule(struct cil_tree_node *node, struct version_args *args)
546 {
547 int rc = SEPOL_ERR;
548 char *key;
549 struct cil_avrule *avrule = (struct cil_avrule *)node->data;
550
551 if (avrule->src != NULL) {
552 cil_log(CIL_ERR, "AST already resolved. Not yet supported (line %d).\n",
553 node->line);
554 goto exit;
555 }
556
557 key = avrule->src_str;
558 if (!strncmp(key, "base_typeattr_", 14) ||
559 __cil_get_plat_flavor(args->vers_map, (hashtab_key_t) key) == PLAT_TYPE) {
560 avrule->src_str = __cil_attrib_get_versname(key, args->num);
561 }
562
563 key = avrule->tgt_str;
564 if (!strncmp(key, "base_typeattr_", 14) ||
565 __cil_get_plat_flavor(args->vers_map, (hashtab_key_t) key) == PLAT_TYPE) {
566 avrule->tgt_str = __cil_attrib_get_versname(key, args->num);
567 }
568
569 return SEPOL_OK;
570 exit:
571 return rc;
572 }
573
cil_attrib_genfscon(struct cil_tree_node * node,struct version_args * args)574 static int cil_attrib_genfscon(struct cil_tree_node *node, struct version_args *args)
575 {
576 int rc = SEPOL_ERR;
577
578 struct cil_genfscon *genfscon = (struct cil_genfscon *)node->data;
579
580 if (genfscon->context_str == NULL) {
581 /* genfscon contains an anon context, which needs to have type checked */
582 rc = cil_attrib_check_context(genfscon->context, args);
583 if (rc != SEPOL_OK) {
584 goto exit;
585 }
586 }
587
588 return SEPOL_OK;
589 exit:
590 return rc;
591 }
592
cil_attrib_fsuse(struct cil_tree_node * node,struct version_args * args)593 static int cil_attrib_fsuse(struct cil_tree_node *node, struct version_args *args)
594 {
595 int rc = SEPOL_ERR;
596 struct cil_fsuse *fsuse = (struct cil_fsuse *)node->data;
597
598 if (fsuse->context_str == NULL) {
599 /* fsuse contains an anon context, which needs to have type checked */
600 rc = cil_attrib_check_context(fsuse->context, args);
601 if (rc != SEPOL_OK) {
602 goto exit;
603 }
604 }
605
606 return SEPOL_OK;
607 exit:
608 return rc;
609 }
610
__attributize_helper(struct cil_tree_node * node,uint32_t * finished,void * extra_args)611 static int __attributize_helper(struct cil_tree_node *node, uint32_t *finished, void *extra_args)
612 {
613 int rc = SEPOL_ERR;
614 struct version_args *args = (struct version_args *) extra_args;
615
616 if (node == NULL || finished == NULL || extra_args == NULL) {
617 goto exit;
618 }
619
620 switch (node->flavor) {
621 case CIL_SIDCONTEXT:
622 /* contains type, but shouldn't involve an attributized type, maybe add
623 a check on type and error if it conflicts */
624 rc = cil_attrib_sidcontext(node, args);
625 if (rc != SEPOL_OK) {
626 goto exit;
627 }
628 break;
629 case CIL_ROLE:
630 cil_log(CIL_ERR, "%s declaration illegal non-platform policy (line %d)\n",
631 CIL_KEY_ROLE, node->line);
632 rc = SEPOL_ERR;
633 break;
634 case CIL_ROLETYPE:
635 /* Yes, this is needed if we support roletype in non-platform policy.
636 type_id can be type, typealias or typeattr */
637 rc = cil_attrib_roletype(node, args);
638 if (rc != SEPOL_OK) {
639 goto exit;
640 }
641 break;
642 case CIL_ROLEATTRIBUTE:
643 /* don't think this is needed, only used for cil_gen_req, and we aren't
644 yet supporting roles in non-platform policy. */
645 break;
646 case CIL_TYPE:
647 /* conver to attribute if in policy */
648 rc = cil_attrib_type(node, args);
649 if (rc != SEPOL_OK) {
650 goto exit;
651 }
652 break;
653 case CIL_TYPEPERMISSIVE:
654 rc = cil_attrib_typepermissive(node, args);
655 if (rc != SEPOL_OK) {
656 goto exit;
657 }
658 break;
659 case CIL_TYPEATTRIBUTE:
660 rc = cil_attrib_typeattribute(node, args);
661 if (rc != SEPOL_OK) {
662 goto exit;
663 }
664 break;
665 case CIL_TYPEATTRIBUTESET:
666 rc = cil_attrib_typeattributeset(node, args);
667 if (rc != SEPOL_OK) {
668 goto exit;
669 }
670 break;
671 case CIL_TYPEALIASACTUAL:
672 /* this will break on an attributized type - identify it and throw error */
673 rc = cil_attrib_typealiasactual(node, args);
674 if (rc != SEPOL_OK) {
675 goto exit;
676 }
677 break;
678 case CIL_NAMETYPETRANSITION:
679 /* not allowed in plat-policy. Types present, throw error if attributee */
680 rc = cil_attrib_nametypetransition(node, args);
681 if (rc != SEPOL_OK) {
682 goto exit;
683 }
684 break;
685 case CIL_TYPE_RULE:
686 /* not allowed in plat-policy. Types present, throw error if attributee */
687 rc = cil_attrib_type_rule(node, args);
688 if (rc != SEPOL_OK) {
689 goto exit;
690 }
691 break;
692 case CIL_AVRULE:
693 case CIL_AVRULEX:
694 rc = cil_attrib_avrule(node, args);
695 if (rc != SEPOL_OK) {
696 goto exit;
697 }
698 break;
699 case CIL_CONTEXT:
700 /* not currently found in AOSP policy, but if found would need to be
701 checked to not be attributee */
702 rc = cil_attrib_context(node, args);
703 if (rc != SEPOL_OK) {
704 goto exit;
705 }
706 break;
707 case CIL_GENFSCON:
708 /* not allowed in plat-policy, but types present, throw error if attributee */
709 rc = cil_attrib_genfscon(node, args);
710 if (rc != SEPOL_OK) {
711 goto exit;
712 }
713 break;
714 case CIL_FILECON:
715 case CIL_NODECON:
716 case CIL_PORTCON:
717 case CIL_PIRQCON:
718 case CIL_IOMEMCON:
719 case CIL_IOPORTCON:
720 case CIL_PCIDEVICECON:
721 case CIL_DEVICETREECON:
722 case CIL_VALIDATETRANS:
723 case CIL_MLSVALIDATETRANS:
724 case CIL_CALL:
725 case CIL_MACRO:
726 case CIL_OPTIONAL:
727 /* Not currently found in AOSP and not yet properly handled. Return err until support added. */
728 cil_log(CIL_ERR, "unsupported policy statement (line %d)\n", node->line);
729 rc = SEPOL_ERR;
730 goto exit;
731 case CIL_FSUSE:
732 /* not allowed in plat-policy, but types present, throw error if attributee */
733 cil_attrib_fsuse(node, args);
734 if (rc != SEPOL_OK) {
735 goto exit;
736 }
737 break;
738 case CIL_CONSTRAIN:
739 case CIL_MLSCONSTRAIN:
740 /* there is type info here, but not sure if we'll allow non-platform code
741 to have this, or whether or not it's in platform policy. Currently
742 assuming that mlsconstrain is private-platform only, and that normal
743 constrain is verboten. */
744 cil_log(CIL_ERR, "unsupported policy statement (line %d)\n", node->line);
745 rc = SEPOL_ERR;
746 goto exit;
747 default:
748 break;
749 }
750
751 return SEPOL_OK;
752 exit:
753 return rc;
754 }
755
756 /*
757 * walk ast, replacing previously identified types and attributes with the
758 * attributized version. Also replace previous references to the attributees
759 * with the versioned type.
760 */
cil_attributize(struct cil_db * db,hashtab_t vers_map,const char * num)761 static int cil_attributize(struct cil_db *db, hashtab_t vers_map, const char *num)
762 {
763 int rc = SEPOL_ERR;
764 struct version_args extra_args;
765 extra_args.db = db;
766 extra_args.vers_map = vers_map;
767 extra_args.num = num;
768
769 rc = cil_tree_walk(db->ast->root, __attributize_helper, NULL, NULL, &extra_args);
770 if (rc != SEPOL_OK) {
771 goto exit;
772 }
773
774 return SEPOL_OK;
775 exit:
776 return rc;
777 }
778
779 /*
780 * Create typeattributeset mappings from the attributes generated from the
781 * original types/attributes to the original values. This mapping will provide
782 * the basis for the platform policy's mapping to this public version.
783 *
784 * Add these new typeattributeset nodes to the given cil_db.
785 */
cil_build_mappings_tree(hashtab_key_t k,hashtab_datum_t d,void * args)786 static int cil_build_mappings_tree(hashtab_key_t k, hashtab_datum_t d, void *args)
787 {
788 struct cil_typeattributeset *attrset = NULL;
789 struct cil_typeattribute *typeattr = NULL;
790 struct cil_expandtypeattribute *expandattr = NULL;
791 struct cil_tree_node *ast_node = NULL;
792 struct version_args *verargs = (struct version_args *)args;
793 struct cil_tree_node *ast_parent = verargs->db->ast->root;
794 char *orig_type = (char *) k;
795 struct version_datum *vers_datum = (struct version_datum *) d;
796 char *new_key = __cil_attrib_get_versname(orig_type, verargs->num);
797
798 if (vers_datum->ast_node->flavor == CIL_TYPEATTRIBUTE) {
799 // platform attributes are not versioned
800 return SEPOL_OK;
801 }
802 /* create typeattributeset datum */
803 cil_typeattributeset_init(&attrset);
804 cil_list_init(&attrset->str_expr, CIL_TYPE);
805 attrset->attr_str = new_key;
806 cil_list_append(attrset->str_expr, CIL_STRING, orig_type);
807
808 /* create containing tree node */
809 cil_tree_node_init(&ast_node);
810 ast_node->data = attrset;
811 ast_node->flavor = CIL_TYPEATTRIBUTESET;
812
813 /* add to tree */
814 ast_node->parent = ast_parent;
815 if (ast_parent->cl_head == NULL)
816 ast_parent->cl_head = ast_node;
817 else
818 ast_parent->cl_tail->next = ast_node;
819 ast_parent->cl_tail = ast_node;
820
821 /* create expandtypeattribute datum */
822 cil_expandtypeattribute_init(&expandattr);
823 cil_list_init(&expandattr->attr_strs, CIL_TYPE);
824 cil_list_append(expandattr->attr_strs, CIL_STRING, new_key);
825 expandattr->expand = CIL_TRUE;
826
827 /* create containing tree node */
828 cil_tree_node_init(&ast_node);
829 ast_node->data = expandattr;
830 ast_node->flavor = CIL_EXPANDTYPEATTRIBUTE;
831 /* add to tree */
832 ast_node->parent = ast_parent;
833 ast_parent->cl_tail->next = ast_node;
834 ast_parent->cl_tail = ast_node;
835
836 /* re)declare typeattribute. */
837 cil_typeattribute_init(&typeattr);
838 typeattr->datum.name = new_key;
839 typeattr->datum.fqn = new_key;
840 cil_tree_node_init(&ast_node);
841 ast_node->data = typeattr;
842 ast_node->flavor = CIL_TYPEATTRIBUTE;
843 ast_node->parent = ast_parent;
844 ast_parent->cl_tail->next = ast_node;
845 ast_parent->cl_tail = ast_node;
846
847 return SEPOL_OK;
848 }
849
850 /*
851 * Initializes the given db and uses the version mapping generated by
852 * cil_extract_attributees() to fill it with the glue policy required to
853 * connect the attributized policy created by cil_attributize() to the policy
854 * declaring the concrete types.
855 */
cil_attrib_mapping(struct cil_db ** db,hashtab_t vers_map,const char * num)856 static int cil_attrib_mapping(struct cil_db **db, hashtab_t vers_map, const char *num)
857 {
858 int rc = SEPOL_ERR;
859 struct version_args extra_args;
860
861 cil_db_init(db);
862
863 /* foreach entry in vers_map, create typeattributeset node and attach to tree */
864 extra_args.db = *db;
865 extra_args.vers_map = NULL;
866 extra_args.num = num;
867 rc = hashtab_map(vers_map, cil_build_mappings_tree, &extra_args);
868 if (rc != SEPOL_OK) {
869 goto exit;
870 }
871
872 return SEPOL_OK;
873 exit:
874 return rc;
875 }
876
cil_android_attrib_mapping(struct cil_db ** mdb,struct cil_db * srcdb,const char * num)877 int cil_android_attrib_mapping(struct cil_db **mdb, struct cil_db *srcdb, const char *num)
878 {
879 int rc = SEPOL_ERR;
880 hashtab_t ver_map_tab = NULL;
881
882 ver_map_tab = hashtab_create(ver_map_hash_val, ver_map_key_cmp, VER_MAP_SZ);
883 if (!ver_map_tab) {
884 cil_log(CIL_ERR, "Unable to create version mapping table.\n");
885 goto exit;
886 }
887 rc = cil_build_ast(srcdb, srcdb->parse->root, srcdb->ast->root);
888 if (rc != SEPOL_OK) {
889 cil_log(CIL_ERR, "Unable to build source db AST.\n");
890 goto exit;
891 }
892 rc = cil_extract_attributees(srcdb, ver_map_tab);
893 if (rc != SEPOL_OK) {
894 cil_log(CIL_ERR, "Unable to extract attributizable elements from source db.\n");
895 goto exit;
896 }
897 rc = cil_attrib_mapping(mdb, ver_map_tab, num);
898 if (rc != SEPOL_OK) {
899 cil_log(CIL_ERR, "Unable to create mapping db from source db.\n");
900 goto exit;
901 }
902 exit:
903 ver_map_destroy(ver_map_tab);
904 return rc;
905 }
906
cil_android_attributize(struct cil_db * tgtdb,struct cil_db * srcdb,const char * num)907 int cil_android_attributize(struct cil_db *tgtdb, struct cil_db *srcdb, const char *num)
908 {
909 int rc = SEPOL_ERR;
910 hashtab_t ver_map_tab = NULL;
911
912 ver_map_tab = hashtab_create(ver_map_hash_val, ver_map_key_cmp, VER_MAP_SZ);
913 if (!ver_map_tab) {
914 cil_log(CIL_ERR, "Unable to create version mapping table.\n");
915 goto exit;
916 }
917 rc = cil_build_ast(srcdb, srcdb->parse->root, srcdb->ast->root);
918 if (rc != SEPOL_OK) {
919 cil_log(CIL_ERR, "Unable to build source db AST.\n");
920 goto exit;
921 }
922 rc = cil_extract_attributees(srcdb, ver_map_tab);
923 if (rc != SEPOL_OK) {
924 cil_log(CIL_ERR, "Unable to extract attributizable elements from source db.\n");
925 goto exit;
926 }
927 rc = cil_build_ast(tgtdb, tgtdb->parse->root, tgtdb->ast->root);
928 if (rc != SEPOL_OK) {
929 cil_log(CIL_ERR, "Unable to build target db AST.\n");
930 goto exit;
931 }
932 rc = cil_attributize(tgtdb, ver_map_tab, num);
933 if (rc != SEPOL_OK) {
934 cil_log(CIL_ERR, "Unable to attributize target db.\n");
935 goto exit;
936 }
937 exit:
938 ver_map_destroy(ver_map_tab);
939 return rc;
940 }
941
define_symbols(struct cil_tree_node * node,uint32_t * finished,void * extra_args)942 static int define_symbols(struct cil_tree_node *node, uint32_t *finished __attribute__((unused)), void *extra_args)
943 {
944 int rc = SEPOL_OK;
945 struct cil_type *type = NULL;
946 struct cil_typeattribute *typeattribute = NULL;
947 struct policydb_amend_args *args = extra_args;
948 policydb_t *pdb = args->pdb;
949 void **type_value_to_cil = args->type_value_to_cil;
950
951 switch (node->flavor) {
952 case CIL_TYPE:
953 rc = cil_type_to_policydb(pdb, node->data, type_value_to_cil);
954 // symtab_insert returns 1 when the symbol already exists
955 if (rc == 1) {
956 type = node->data;
957 cil_log(CIL_WARN, "Type with symbol \"%s\" already exists.\n", type->datum.fqn);
958 rc = SEPOL_OK;
959 }
960 break;
961 case CIL_TYPEATTRIBUTE:
962 rc = cil_typeattribute_to_policydb(pdb, node->data, type_value_to_cil);
963 // symtab_insert returns 1 when the symbol already exists
964 if (rc == 1) {
965 typeattribute = node->data;
966 cil_log(CIL_WARN, "Typeattribute with symbol \"%s\" already exists.\n", typeattribute->datum.fqn);
967 rc = SEPOL_OK;
968 }
969 break;
970 case CIL_ROLE:
971 case CIL_POLICYCAP:
972 case CIL_USER:
973 case CIL_BOOL:
974 case CIL_CATALIAS:
975 case CIL_SENS: // Unsupported symbol statements.
976 default:
977 break;
978 }
979
980 return rc;
981 }
982
expand_symbols(struct cil_tree_node * node,uint32_t * finished,void * extra_args)983 static int expand_symbols(struct cil_tree_node *node, uint32_t *finished __attribute__((unused)), void *extra_args)
984 {
985 int rc = SEPOL_OK;
986 struct policydb_amend_args *args = extra_args;
987 const struct cil_db *db = args->db;
988 policydb_t *pdb = args->pdb;
989
990 switch (node->flavor) {
991 case CIL_TYPEATTRIBUTE:
992 rc = cil_typeattribute_to_bitmap(pdb, db, node->data);
993 break;
994 case CIL_ROLE:
995 case CIL_AVRULE:
996 case CIL_AVRULEX:
997 case CIL_TYPE:
998 case CIL_TYPEALIAS:
999 case CIL_TYPEPERMISSIVE:
1000 case CIL_SENSALIAS:
1001 case CIL_USER:
1002 case CIL_TYPE_RULE:
1003 case CIL_ROLETRANSITION:
1004 case CIL_ROLEATTRIBUTESET:
1005 case CIL_NAMETYPETRANSITION:
1006 case CIL_CONSTRAIN:
1007 case CIL_MLSCONSTRAIN:
1008 case CIL_VALIDATETRANS:
1009 case CIL_MLSVALIDATETRANS:
1010 case CIL_RANGETRANSITION:
1011 case CIL_DEFAULTUSER:
1012 case CIL_DEFAULTROLE:
1013 case CIL_DEFAULTTYPE:
1014 case CIL_DEFAULTRANGE: // Unsupported symbol statements.
1015 default:
1016 break;
1017 }
1018
1019 return rc;
1020 }
1021
apply_rules(struct cil_tree_node * node,uint32_t * finished,void * extra_args)1022 static int apply_rules(struct cil_tree_node *node, uint32_t *finished __attribute__((unused)), void *extra_args)
1023 {
1024 int rc = SEPOL_OK;
1025 struct cil_avrule *rule = NULL;
1026 struct policydb_amend_args *args = extra_args;
1027 const struct cil_db *db = args->db;
1028 policydb_t *pdb = args->pdb;
1029
1030 switch (node->flavor) {
1031 case CIL_AVRULE:
1032 rule = node->data;
1033 if (rule->rule_kind != CIL_AVRULE_NEVERALLOW) {
1034 rc = cil_avrule_to_policydb(pdb, db, node->data);
1035 }
1036 else {
1037 cil_log(CIL_WARN, "Found a neverallow rule.\n");
1038 }
1039 break;
1040 case CIL_BOOLEANIF:
1041 case CIL_AVRULEX:
1042 case CIL_ROLEALLOW: // Unsupported rule statement.
1043 default:
1044 break;
1045 }
1046
1047 return rc;
1048 }
1049
cil_amend_policydb(struct cil_db * db,sepol_policydb_t * policydb)1050 int cil_amend_policydb(struct cil_db *db, sepol_policydb_t *policydb)
1051 {
1052 int rc = SEPOL_ERR;
1053 policydb_t *pdb = &policydb->p;
1054
1055 if (db == NULL || policydb == NULL) {
1056 if (db == NULL) {
1057 cil_log(CIL_ERR, "db == NULL\n");
1058 }
1059 else if (policydb == NULL) {
1060 cil_log(CIL_ERR, "policydb == NULL\n");
1061 }
1062 return rc;
1063 }
1064
1065 // type_value_to_cil should be able to map the new types in the cil_db, the
1066 // existing types in the pdb, and the redefinitions from the cil_db.
1067 // Since libsepol values start at 1, we allocate extra memory instead of shifting every value.
1068 void **type_value_to_cil = calloc(db->num_types_and_attrs + pdb->p_types.nprim + 1,
1069 sizeof(*type_value_to_cil));
1070 if (!type_value_to_cil)
1071 goto exit;
1072
1073 struct policydb_amend_args extra_args;
1074 extra_args.db = db;
1075 extra_args.pdb = pdb;
1076 extra_args.type_value_to_cil = type_value_to_cil;
1077
1078 // 1) Add types and attributes symbols to policy_db.
1079 unsigned int types_size = pdb->p_types.nprim;
1080 rc = cil_tree_walk(db->ast->root, define_symbols, NULL, NULL, &extra_args);
1081 if(rc != SEPOL_OK) {
1082 cil_log(CIL_ERR, "Error adding symbols to policydb.\n");
1083 goto exit;
1084 }
1085 if (pdb->p_types.nprim > types_size) {
1086 // We introduced new types, we need to expand the type<->attr maps.
1087 pdb->type_attr_map = cil_realloc(pdb->type_attr_map, pdb->p_types.nprim * sizeof(ebitmap_t));
1088 pdb->attr_type_map = cil_realloc(pdb->attr_type_map, pdb->p_types.nprim * sizeof(ebitmap_t));
1089 for (unsigned int i = types_size; i < pdb->p_types.nprim; i++) {
1090 ebitmap_init(&pdb->type_attr_map[i]);
1091 ebitmap_init(&pdb->attr_type_map[i]);
1092 }
1093 }
1094
1095 // 2) Expand typeattribute symbols.
1096 rc = cil_tree_walk(db->ast->root, expand_symbols, NULL, NULL, &extra_args);
1097 if(rc != SEPOL_OK) {
1098 cil_log(CIL_ERR, "Error expanding symbols.\n");
1099 goto exit;
1100 }
1101
1102 // 3) Apply rule statements.
1103 rc = cil_tree_walk(db->ast->root, apply_rules, NULL, NULL, &extra_args);
1104 if(rc != SEPOL_OK) {
1105 cil_log(CIL_ERR, "Error applying rules.\n");
1106 goto exit;
1107 }
1108
1109 exit:
1110 free(type_value_to_cil);
1111 return rc;
1112 }
1113