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