xref: /aosp_15_r20/external/selinux/libsepol/cil/src/android.c (revision 2d543d20722ada2425b5bdab9d0d1d29470e7bba)
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