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 } else {
104 rc = hashtab_insert(args->vers_map, (hashtab_key_t) key, (hashtab_datum_t) datum);
105 if (rc != SEPOL_OK) {
106 goto exit;
107 }
108 }
109 break;
110 case CIL_TYPEALIAS:
111 cil_log(CIL_ERR, "%s unsupported statement in attributee policy (line %d)\n",
112 CIL_KEY_TYPEALIAS, node->line);
113 goto exit;
114 break;
115 case CIL_TYPEPERMISSIVE:
116 cil_log(CIL_ERR, "%s unsupported statement in attributee policy (line %d)\n",
117 CIL_KEY_TYPEPERMISSIVE, node->line);
118 goto exit;
119 break;
120 case CIL_NAMETYPETRANSITION:
121 case CIL_TYPE_RULE:
122 cil_log(CIL_ERR, "%s unsupported statement in attributee policy (line %d)\n",
123 CIL_KEY_TYPETRANSITION, node->line);
124 goto exit;
125 break;
126 default:
127 break;
128 }
129 return SEPOL_OK;
130 exit:
131 return rc;
132 }
133
134 /*
135 * For the given db, with an already-built AST, fill the vers_map hash table
136 * with every encountered type and attribute. This could eventually be expanded
137 * to include other language constructs, such as users and roles, in which case
138 * multiple hash tables would be needed. These tables can then be used by
139 * attributize() to change all references to these types.
140 */
cil_extract_attributees(struct cil_db * db,hashtab_t vers_map)141 int cil_extract_attributees(struct cil_db *db, hashtab_t vers_map)
142 {
143 /* walk ast. */
144 int rc = SEPOL_ERR;
145 struct version_args extra_args;
146 extra_args.db = db;
147 extra_args.vers_map = vers_map;
148 extra_args.num = NULL;
149 rc = cil_tree_walk(db->ast->root, __extract_attributees_helper, NULL, NULL, &extra_args);
150 if (rc != SEPOL_OK) {
151 goto exit;
152 }
153
154 return SEPOL_OK;
155 exit:
156 return rc;
157 }
158
__cil_get_plat_flavor(hashtab_t vers_map,hashtab_key_t key)159 static enum plat_flavor __cil_get_plat_flavor(hashtab_t vers_map, hashtab_key_t key)
160 {
161 enum plat_flavor rc;
162 struct version_datum *vers_datum;
163
164 vers_datum = (struct version_datum *)hashtab_search(vers_map, key);
165 if (vers_datum == NULL) {
166 return PLAT_NONE;
167 }
168 switch (vers_datum->ast_node->flavor) {
169 case CIL_TYPE:
170 rc = PLAT_TYPE;
171 break;
172 case CIL_TYPEATTRIBUTE:
173 rc = PLAT_ATTRIB;
174 break;
175 default:
176 rc = PLAT_NONE;
177 break;
178 }
179 return rc;
180 }
181
182 /*
183 * Takes the old name and version string and creates a new strpool entry by
184 * combining them.
185 */
__cil_attrib_get_versname(char * old,const char * vers)186 static char *__cil_attrib_get_versname(char *old, const char *vers)
187 {
188 size_t len = 0;
189 char *tmp_new = NULL;
190 char *final;
191
192 len += strlen(old) + strlen(vers) + 2;
193 tmp_new = cil_malloc(len);
194 snprintf(tmp_new, len, "%s_%s", old, vers);
195 final = cil_strpool_add(tmp_new);
196 free(tmp_new);
197 return final;
198 }
199
200 /*
201 * Change type to attribute - create new versioned name based on old, create
202 * typeattribute node and replace existing type node.
203 */
__cil_attrib_convert_type(struct cil_tree_node * node,struct version_args * args)204 static int __cil_attrib_convert_type(struct cil_tree_node *node, struct version_args *args)
205 {
206 int rc = SEPOL_ERR;
207 struct cil_type *type = (struct cil_type *)node->data;
208 struct cil_typeattribute *typeattr = NULL;
209 char *new_key;
210
211 cil_typeattribute_init(&typeattr);
212
213 new_key = __cil_attrib_get_versname(type->datum.name, args->num);
214
215 cil_symtab_datum_remove_node(&type->datum, node);
216 cil_destroy_type(type);
217
218 rc = cil_gen_node(args->db, node, (struct cil_symtab_datum *) typeattr,
219 new_key, CIL_SYM_TYPES, CIL_TYPEATTRIBUTE);
220 if (rc != SEPOL_OK) {
221 goto exit;
222 }
223
224 return SEPOL_OK;
225 exit:
226 return rc;
227 }
228
229 /*
230 * Update datum - create new key, remove entry under old key,
231 * update entry, and insert under new key
232 */
__cil_attrib_swap_symtab_key(struct cil_tree_node * node,char * old_key,const char * num)233 static int __cil_attrib_swap_symtab_key(struct cil_tree_node *node, char *old_key,
234 const char *num)
235 {
236 int rc = SEPOL_ERR;
237 char *new_key;
238 symtab_t *symtab;
239 struct cil_symtab_datum *datum = (struct cil_symtab_datum *) node->data;
240
241 new_key = __cil_attrib_get_versname(old_key, num);
242
243 symtab = datum->symtab;
244
245 /* TODO: remove, but what happens to other nodes on this datum ?*/
246 cil_list_remove(datum->nodes, CIL_NODE, node, 0);
247 cil_symtab_remove_datum(datum);
248
249 rc = cil_symtab_insert(symtab, new_key, datum, node);
250
251 if (rc != SEPOL_OK) {
252 goto exit;
253 }
254
255 return SEPOL_OK;
256 exit:
257 return rc;
258 }
259
260 /*
261 * expressions may contains strings which are not in the type-attribute
262 * namespace, so this is not a general cil_expr attributizer.
263 * TODO: add support for other types of expressions which may contain types.
264 */
cil_attrib_type_expr(struct cil_list * expr_str,struct version_args * args)265 static int cil_attrib_type_expr(struct cil_list *expr_str, struct version_args *args)
266 {
267 int rc = SEPOL_ERR;
268 struct cil_list_item *curr = NULL;
269 char *new;
270 hashtab_key_t key;
271
272 /* iterate through cil_list, replacing types */
273 cil_list_for_each(curr, expr_str) {
274 switch(curr->flavor) {
275 case CIL_LIST:
276 rc = cil_attrib_type_expr((struct cil_list *)curr->data, args);
277 if (rc != SEPOL_OK)
278 goto exit;
279 break;
280 case CIL_STRING:
281 key = (hashtab_key_t) curr->data;
282 enum plat_flavor pf = __cil_get_plat_flavor(args->vers_map, key);
283 if (!strncmp(curr->data, "base_typeattr_", 14) || pf == PLAT_TYPE) {
284 new = __cil_attrib_get_versname((char *) curr->data, args->num);
285 curr->data = (void *) new;
286 }
287 break;
288 case CIL_DATUM:
289 cil_log(CIL_ERR, "AST already resolved. Not yet supported.\n");
290 rc = SEPOL_ERR;
291 goto exit;
292 break;
293 default:
294 break;
295 }
296 }
297
298 return SEPOL_OK;
299 exit:
300 return rc;
301 }
302
cil_attrib_check_context(struct cil_context * ctxt,struct version_args * args)303 static int cil_attrib_check_context(struct cil_context *ctxt, struct version_args *args)
304 {
305 int rc = SEPOL_ERR;
306 hashtab_key_t key;
307
308 if (ctxt->type != NULL) {
309 cil_log(CIL_ERR, "AST already resolved. Not yet supported.\n");
310 goto exit;
311 }
312
313 key = (hashtab_key_t) ctxt->type_str;
314 if (__cil_get_plat_flavor(args->vers_map, key) != PLAT_NONE) {
315 /* TODO: reinstate check, but leave out for now
316 cil_log(CIL_ERR, "AST contains context with platform public type: %s\n",
317 ctxt->type_str);
318 rc = SEPOL_ERR;
319 goto exit; */
320 }
321
322 return SEPOL_OK;
323 exit:
324 return rc;
325 }
326
cil_attrib_sidcontext(struct cil_tree_node * node,struct version_args * args)327 static int cil_attrib_sidcontext(struct cil_tree_node *node, struct version_args *args)
328 {
329 int rc = SEPOL_ERR;
330 struct cil_sidcontext *sidcon = (struct cil_sidcontext *)node->data;
331
332 if (sidcon->context_str == NULL) {
333 /* sidcon contains an anon context, which needs to have type checked */
334 rc = cil_attrib_check_context(sidcon->context, args);
335 if (rc != SEPOL_OK) {
336 goto exit;
337 }
338 }
339
340 return SEPOL_OK;
341 exit:
342 return rc;
343 }
344
cil_attrib_context(struct cil_tree_node * node,struct version_args * args)345 static int cil_attrib_context(struct cil_tree_node *node, struct version_args *args)
346 {
347 struct cil_context *ctxt = (struct cil_context *)node->data;
348
349 return cil_attrib_check_context(ctxt, args);
350 }
351
cil_attrib_roletype(struct cil_tree_node * node,struct version_args * args)352 static int cil_attrib_roletype(struct cil_tree_node *node,
353 __attribute__((unused)) struct version_args *args)
354 {
355 int rc = SEPOL_ERR;
356 char *key;
357 struct cil_roletype *roletype = (struct cil_roletype *)node->data;
358
359 if (roletype->role) {
360 cil_log(CIL_ERR, "AST already resolved. !!! Not yet supported.\n");
361 goto exit;
362 }
363 key = roletype->type_str;
364 if (__cil_get_plat_flavor(args->vers_map, (hashtab_key_t) key) == PLAT_TYPE) {
365 roletype->type_str = __cil_attrib_get_versname(key, args->num);
366 }
367
368 return SEPOL_OK;
369 exit:
370 return rc;
371 }
372
cil_attrib_type(struct cil_tree_node * node,struct version_args * args)373 static int cil_attrib_type(struct cil_tree_node *node, struct version_args *args)
374 {
375 int rc = SEPOL_ERR;
376 struct cil_type *type = (struct cil_type *)node->data;
377 char *key = type->datum.name;
378
379 if (type->value) {
380 cil_log(CIL_ERR, "AST already resolved. !!! Not yet supported.\n");
381 goto exit;
382 }
383 if (__cil_get_plat_flavor(args->vers_map, (hashtab_key_t) key) == PLAT_TYPE) {
384 rc = __cil_attrib_convert_type(node, args);
385 if (rc != SEPOL_OK) {
386 goto exit;
387 }
388 }
389
390 return SEPOL_OK;
391 exit:
392 return rc;
393 }
394
cil_attrib_typepermissive(struct cil_tree_node * node,struct version_args * args)395 static int cil_attrib_typepermissive(struct cil_tree_node *node,
396 struct version_args *args __attribute__ ((unused)))
397 {
398 struct cil_typepermissive *typeperm = (struct cil_typepermissive *)node->data;
399
400 if (typeperm->type != NULL) {
401 cil_log(CIL_ERR, "AST already resolved. ### Not yet supported.\n");
402 return SEPOL_ERR;
403 }
404
405 return SEPOL_OK;
406 }
407
cil_attrib_typeattribute(struct cil_tree_node * node,struct version_args * args)408 static int cil_attrib_typeattribute(struct cil_tree_node *node, struct version_args *args)
409 {
410 int rc = SEPOL_ERR;
411 struct cil_typeattribute *typeattr = (struct cil_typeattribute *)node->data;
412 char *key = typeattr->datum.name;
413
414 if (typeattr->types) {
415 cil_log(CIL_ERR, "AST already resolved. Not yet supported (line %d).\n",
416 node->line);
417 goto exit;
418 }
419 if (!strncmp(key, "base_typeattr_", 14)) {
420 rc = __cil_attrib_swap_symtab_key(node, key, args->num);
421 if (rc != SEPOL_OK) {
422 goto exit;
423 }
424 } else if (__cil_get_plat_flavor(args->vers_map, key) == PLAT_ATTRIB) {
425 // platform attribute declaration to be provided by platform policy
426 cil_symtab_datum_remove_node(&typeattr->datum, node);
427 cil_destroy_typeattribute(typeattr);
428 node->flavor = CIL_NONE; // traversal relies on this node sticking around, empty it.
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_tree_node *ast_node = NULL;
783 struct version_args *verargs = (struct version_args *)args;
784 struct cil_tree_node *ast_parent = verargs->db->ast->root;
785 char *orig_type = (char *) k;
786 struct version_datum *vers_datum = (struct version_datum *) d;
787
788 if (vers_datum->ast_node->flavor == CIL_TYPEATTRIBUTE) {
789 // platform attributes are not versioned
790 return SEPOL_OK;
791 }
792 /* create typeattributeset datum */
793 cil_typeattributeset_init(&attrset);
794 cil_list_init(&attrset->str_expr, CIL_TYPE);
795 attrset->attr_str = __cil_attrib_get_versname(orig_type, verargs->num);
796 cil_list_append(attrset->str_expr, CIL_STRING, orig_type);
797
798 /* create containing tree node */
799 cil_tree_node_init(&ast_node);
800 ast_node->data = attrset;
801 ast_node->flavor = CIL_TYPEATTRIBUTESET;
802
803 /* add to tree */
804 ast_node->parent = ast_parent;
805 if (ast_parent->cl_head == NULL)
806 ast_parent->cl_head = ast_node;
807 else
808 ast_parent->cl_tail->next = ast_node;
809 ast_parent->cl_tail = ast_node;
810 return SEPOL_OK;
811 }
812
813 /*
814 * Initializes the given db and uses the version mapping generated by
815 * cil_extract_attributees() to fill it with the glue policy required to
816 * connect the attributized policy created by cil_attributize() to the policy
817 * declaring the concrete types.
818 */
cil_attrib_mapping(struct cil_db ** db,hashtab_t vers_map,const char * num)819 static int cil_attrib_mapping(struct cil_db **db, hashtab_t vers_map, const char *num)
820 {
821 int rc = SEPOL_ERR;
822 struct version_args extra_args;
823
824 cil_db_init(db);
825
826 /* foreach entry in vers_map, create typeattributeset node and attach to tree */
827 extra_args.db = *db;
828 extra_args.vers_map = NULL;
829 extra_args.num = num;
830 rc = hashtab_map(vers_map, cil_build_mappings_tree, &extra_args);
831 if (rc != SEPOL_OK) {
832 goto exit;
833 }
834
835 return SEPOL_OK;
836 exit:
837 return rc;
838 }
839
cil_android_attrib_mapping(struct cil_db ** mdb,struct cil_db * srcdb,const char * num)840 int cil_android_attrib_mapping(struct cil_db **mdb, struct cil_db *srcdb, const char *num)
841 {
842 int rc = SEPOL_ERR;
843 hashtab_t ver_map_tab = NULL;
844
845 ver_map_tab = hashtab_create(ver_map_hash_val, ver_map_key_cmp, VER_MAP_SZ);
846 if (!ver_map_tab) {
847 cil_log(CIL_ERR, "Unable to create version mapping table.\n");
848 goto exit;
849 }
850 rc = cil_build_ast(srcdb, srcdb->parse->root, srcdb->ast->root);
851 if (rc != SEPOL_OK) {
852 cil_log(CIL_ERR, "Unable to build source db AST.\n");
853 goto exit;
854 }
855 rc = cil_extract_attributees(srcdb, ver_map_tab);
856 if (rc != SEPOL_OK) {
857 cil_log(CIL_ERR, "Unable to extract attributizable elements from source db.\n");
858 goto exit;
859 }
860 rc = cil_attrib_mapping(mdb, ver_map_tab, num);
861 if (rc != SEPOL_OK) {
862 cil_log(CIL_ERR, "Unable to create mapping db from source db.\n");
863 goto exit;
864 }
865 exit:
866 ver_map_destroy(ver_map_tab);
867 return rc;
868 }
869
cil_android_attributize(struct cil_db * tgtdb,struct cil_db * srcdb,const char * num)870 int cil_android_attributize(struct cil_db *tgtdb, struct cil_db *srcdb, const char *num)
871 {
872 int rc = SEPOL_ERR;
873 hashtab_t ver_map_tab = NULL;
874
875 ver_map_tab = hashtab_create(ver_map_hash_val, ver_map_key_cmp, VER_MAP_SZ);
876 if (!ver_map_tab) {
877 cil_log(CIL_ERR, "Unable to create version mapping table.\n");
878 goto exit;
879 }
880 rc = cil_build_ast(srcdb, srcdb->parse->root, srcdb->ast->root);
881 if (rc != SEPOL_OK) {
882 cil_log(CIL_ERR, "Unable to build source db AST.\n");
883 goto exit;
884 }
885 rc = cil_extract_attributees(srcdb, ver_map_tab);
886 if (rc != SEPOL_OK) {
887 cil_log(CIL_ERR, "Unable to extract attributizable elements from source db.\n");
888 goto exit;
889 }
890 rc = cil_build_ast(tgtdb, tgtdb->parse->root, tgtdb->ast->root);
891 if (rc != SEPOL_OK) {
892 cil_log(CIL_ERR, "Unable to build target db AST.\n");
893 goto exit;
894 }
895 rc = cil_attributize(tgtdb, ver_map_tab, num);
896 if (rc != SEPOL_OK) {
897 cil_log(CIL_ERR, "Unable to attributize target db.\n");
898 goto exit;
899 }
900 exit:
901 ver_map_destroy(ver_map_tab);
902 return rc;
903 }
904