Home | History | Annotate | Download | only in src
      1 #include <sys/types.h>
      2 #include <unistd.h>
      3 #include <string.h>
      4 #include <stdio.h>
      5 #include <stdlib.h>
      6 #include <stdbool.h>
      7 #include <ctype.h>
      8 #include <errno.h>
      9 #include <pwd.h>
     10 #include <grp.h>
     11 #include <sys/mman.h>
     12 #include <sys/mount.h>
     13 #include <sys/types.h>
     14 #include <sys/stat.h>
     15 #include <sys/xattr.h>
     16 #include <fcntl.h>
     17 #include <fts.h>
     18 #include <selinux/selinux.h>
     19 #include <selinux/context.h>
     20 #include <selinux/android.h>
     21 #include <selinux/label.h>
     22 #include <selinux/avc.h>
     23 #include <mincrypt/sha.h>
     24 #include <private/android_filesystem_config.h>
     25 #include <log/log.h>
     26 #include "policy.h"
     27 #include "callbacks.h"
     28 #include "selinux_internal.h"
     29 #include "label_internal.h"
     30 
     31 /*
     32  * XXX Where should this configuration file be located?
     33  * Needs to be accessible by zygote and installd when
     34  * setting credentials for app processes and setting permissions
     35  * on app data directories.
     36  */
     37 static char const * const seapp_contexts_file[] = {
     38 	"/seapp_contexts",
     39 	"/data/security/current/seapp_contexts",
     40 	NULL };
     41 
     42 static const struct selinux_opt seopts[] = {
     43 	{ SELABEL_OPT_PATH, "/file_contexts" },
     44 	{ SELABEL_OPT_PATH, "/data/security/current/file_contexts" },
     45 	{ 0, NULL } };
     46 
     47 static const char *const sepolicy_file[] = {
     48 	"/sepolicy",
     49 	"/data/security/current/sepolicy",
     50 	NULL };
     51 
     52 static const struct selinux_opt seopts_service[] = {
     53     { SELABEL_OPT_PATH, "/service_contexts" },
     54     { SELABEL_OPT_PATH, "/data/security/current/service_contexts" },
     55     { 0, NULL }
     56 };
     57 
     58 enum levelFrom {
     59 	LEVELFROM_NONE,
     60 	LEVELFROM_APP,
     61 	LEVELFROM_USER,
     62 	LEVELFROM_ALL
     63 };
     64 
     65 #define POLICY_OVERRIDE_VERSION    "/data/security/current/selinux_version"
     66 #define POLICY_BASE_VERSION        "/selinux_version"
     67 static int policy_index = 0;
     68 
     69 static void set_policy_index(void)
     70 {
     71 	int fd_base = -1, fd_override = -1;
     72 	struct stat sb_base;
     73 	struct stat sb_override;
     74 	void *map_base, *map_override;
     75 
     76 	policy_index = 0;
     77 
     78 	fd_base = open(POLICY_BASE_VERSION, O_RDONLY | O_NOFOLLOW);
     79 	if (fd_base < 0)
     80 		return;
     81 
     82 	if (fstat(fd_base, &sb_base) < 0) {
     83 		close(fd_base);
     84 		return;
     85 	}
     86 
     87 	fd_override = open(POLICY_OVERRIDE_VERSION, O_RDONLY | O_NOFOLLOW);
     88 	if (fd_override < 0) {
     89 		close(fd_base);
     90 		return;
     91 	}
     92 
     93 	if (fstat(fd_override, &sb_override) < 0) {
     94 		close(fd_base);
     95 		close(fd_override);
     96 		return;
     97 	}
     98 
     99 	if (sb_base.st_size != sb_override.st_size) {
    100 		close(fd_base);
    101 		close(fd_override);
    102 		return;
    103 	}
    104 
    105 	map_base = mmap(NULL, sb_base.st_size, PROT_READ, MAP_PRIVATE, fd_base, 0);
    106 	if (map_base == MAP_FAILED) {
    107 		close(fd_base);
    108 		close(fd_override);
    109 		return;
    110 	}
    111 
    112 	map_override = mmap(NULL, sb_override.st_size, PROT_READ, MAP_PRIVATE, fd_override, 0);
    113 	if (map_override == MAP_FAILED) {
    114 		munmap(map_base, sb_base.st_size);
    115 		close(fd_base);
    116 		close(fd_override);
    117 		return;
    118 	}
    119 
    120 	if (memcmp(map_base, map_override, sb_base.st_size) == 0)
    121 		policy_index = 1;
    122 
    123 
    124 	close(fd_base);
    125 	close(fd_override);
    126 	munmap(map_base, sb_base.st_size);
    127 	munmap(map_override, sb_override.st_size);
    128 }
    129 
    130 bool selinux_android_use_data_policy(void)
    131 {
    132 	set_policy_index();
    133 	return (policy_index == 1);
    134 }
    135 
    136 #if DEBUG
    137 static char const * const levelFromName[] = {
    138 	"none",
    139 	"app",
    140 	"user",
    141 	"all"
    142 };
    143 #endif
    144 
    145 struct prefix_str {
    146 	size_t len;
    147 	char *str;
    148 	char is_prefix;
    149 };
    150 
    151 static void free_prefix_str(struct prefix_str *p)
    152 {
    153 	if (!p)
    154 		return;
    155 	free(p->str);
    156 }
    157 
    158 struct seapp_context {
    159 	/* input selectors */
    160 	char isSystemServer;
    161 	struct prefix_str user;
    162 	char *seinfo;
    163 	struct prefix_str name;
    164 	struct prefix_str path;
    165 	/* outputs */
    166 	char *domain;
    167 	char *type;
    168 	char *level;
    169 	char *sebool;
    170 	enum levelFrom levelFrom;
    171 };
    172 
    173 static void free_seapp_context(struct seapp_context *s)
    174 {
    175 	if (!s)
    176 		return;
    177 
    178 	free_prefix_str(&s->user);
    179 	free(s->seinfo);
    180 	free_prefix_str(&s->name);
    181 	free_prefix_str(&s->path);
    182 	free(s->domain);
    183 	free(s->type);
    184 	free(s->level);
    185 	free(s->sebool);
    186 }
    187 
    188 static int seapp_context_cmp(const void *A, const void *B)
    189 {
    190 	const struct seapp_context *const *sp1 = (const struct seapp_context *const *) A;
    191 	const struct seapp_context *const *sp2 = (const struct seapp_context *const *) B;
    192 	const struct seapp_context *s1 = *sp1, *s2 = *sp2;
    193 
    194 	/* Give precedence to isSystemServer=true. */
    195 	if (s1->isSystemServer != s2->isSystemServer)
    196 		return (s1->isSystemServer ? -1 : 1);
    197 
    198 	/* Give precedence to a specified user= over an unspecified user=. */
    199 	if (s1->user.str && !s2->user.str)
    200 		return -1;
    201 	if (!s1->user.str && s2->user.str)
    202 		return 1;
    203 
    204 	if (s1->user.str) {
    205 		/* Give precedence to a fixed user= string over a prefix. */
    206 		if (s1->user.is_prefix != s2->user.is_prefix)
    207 			return (s2->user.is_prefix ? -1 : 1);
    208 
    209 		/* Give precedence to a longer prefix over a shorter prefix. */
    210 		if (s1->user.is_prefix && s1->user.len != s2->user.len)
    211 			return (s1->user.len > s2->user.len) ? -1 : 1;
    212 	}
    213 
    214 	/* Give precedence to a specified seinfo= over an unspecified seinfo=. */
    215 	if (s1->seinfo && !s2->seinfo)
    216 		return -1;
    217 	if (!s1->seinfo && s2->seinfo)
    218 		return 1;
    219 
    220 	/* Give precedence to a specified name= over an unspecified name=. */
    221 	if (s1->name.str && !s2->name.str)
    222 		return -1;
    223 	if (!s1->name.str && s2->name.str)
    224 		return 1;
    225 
    226 	if (s1->name.str) {
    227 		/* Give precedence to a fixed name= string over a prefix. */
    228 		if (s1->name.is_prefix != s2->name.is_prefix)
    229 			return (s2->name.is_prefix ? -1 : 1);
    230 
    231 		/* Give precedence to a longer prefix over a shorter prefix. */
    232 		if (s1->name.is_prefix && s1->name.len != s2->name.len)
    233 			return (s1->name.len > s2->name.len) ? -1 : 1;
    234 	}
    235 
    236 	/* Give precedence to a specified path= over an unspecified path=. */
    237 	if (s1->path.str && !s2->path.str)
    238 		return -1;
    239 	if (!s1->path.str && s2->path.str)
    240 		return 1;
    241 
    242 	if (s1->path.str) {
    243 		/* Give precedence to a fixed path= string over a prefix. */
    244 		if (s1->path.is_prefix != s2->path.is_prefix)
    245 			return (s2->path.is_prefix ? -1 : 1);
    246 
    247 		/* Give precedence to a longer prefix over a shorter prefix. */
    248 		if (s1->path.is_prefix && s1->path.len != s2->path.len)
    249 			return (s1->path.len > s2->path.len) ? -1 : 1;
    250 	}
    251 
    252         /* Give precedence to a specified sebool= over an unspecified sebool=. */
    253         if (s1->sebool && !s2->sebool)
    254                 return -1;
    255         if (!s1->sebool && s2->sebool)
    256                 return 1;
    257 
    258 	/* Anything else has equal precedence. */
    259 	return 0;
    260 }
    261 
    262 static struct seapp_context **seapp_contexts = NULL;
    263 static int nspec = 0;
    264 
    265 static void free_seapp_contexts(void)
    266 {
    267 	int n;
    268 
    269 	if (!seapp_contexts)
    270 		return;
    271 
    272 	for (n = 0; n < nspec; n++)
    273 		free_seapp_context(seapp_contexts[n]);
    274 
    275 	free(seapp_contexts);
    276 	seapp_contexts = NULL;
    277 	nspec = 0;
    278 }
    279 
    280 int selinux_android_seapp_context_reload(void)
    281 {
    282 	FILE *fp = NULL;
    283 	char line_buf[BUFSIZ];
    284 	char *token;
    285 	unsigned lineno;
    286 	struct seapp_context *cur;
    287 	char *p, *name = NULL, *value = NULL, *saveptr;
    288 	size_t len;
    289 	int n, ret;
    290 
    291 	set_policy_index();
    292 
    293 	fp = fopen(seapp_contexts_file[policy_index], "r");
    294 	if (!fp) {
    295 		selinux_log(SELINUX_ERROR, "%s:  could not open any seapp_contexts file", __FUNCTION__);
    296 		return -1;
    297 	}
    298 
    299 	free_seapp_contexts();
    300 
    301 	nspec = 0;
    302 	while (fgets(line_buf, sizeof line_buf - 1, fp)) {
    303 		p = line_buf;
    304 		while (isspace(*p))
    305 			p++;
    306 		if (*p == '#' || *p == 0)
    307 			continue;
    308 		nspec++;
    309 	}
    310 
    311 	seapp_contexts = (struct seapp_context **) calloc(nspec, sizeof(struct seapp_context *));
    312 	if (!seapp_contexts)
    313 		goto oom;
    314 
    315 	rewind(fp);
    316 	nspec = 0;
    317 	lineno = 1;
    318 	while (fgets(line_buf, sizeof line_buf - 1, fp)) {
    319 		len = strlen(line_buf);
    320 		if (line_buf[len - 1] == '\n')
    321 			line_buf[len - 1] = 0;
    322 		p = line_buf;
    323 		while (isspace(*p))
    324 			p++;
    325 		if (*p == '#' || *p == 0)
    326 			continue;
    327 
    328 		cur = (struct seapp_context *) calloc(1, sizeof(struct seapp_context));
    329 		if (!cur)
    330 			goto oom;
    331 
    332 		token = strtok_r(p, " \t", &saveptr);
    333 		if (!token) {
    334 			free_seapp_context(cur);
    335 			goto err;
    336 		}
    337 
    338 		while (1) {
    339 			name = token;
    340 			value = strchr(name, '=');
    341 			if (!value) {
    342 				free_seapp_context(cur);
    343 				goto err;
    344 			}
    345 			*value++ = 0;
    346 
    347 			if (!strcasecmp(name, "isSystemServer")) {
    348 				if (!strcasecmp(value, "true"))
    349 					cur->isSystemServer = 1;
    350 				else if (!strcasecmp(value, "false"))
    351 					cur->isSystemServer = 0;
    352 				else {
    353 					free_seapp_context(cur);
    354 					goto err;
    355 				}
    356 			} else if (!strcasecmp(name, "user")) {
    357 				cur->user.str = strdup(value);
    358 				if (!cur->user.str) {
    359 					free_seapp_context(cur);
    360 					goto oom;
    361 				}
    362 				cur->user.len = strlen(cur->user.str);
    363 				if (cur->user.str[cur->user.len-1] == '*')
    364 					cur->user.is_prefix = 1;
    365 			} else if (!strcasecmp(name, "seinfo")) {
    366 				cur->seinfo = strdup(value);
    367 				if (!cur->seinfo) {
    368 					free_seapp_context(cur);
    369 					goto oom;
    370 				}
    371 			} else if (!strcasecmp(name, "name")) {
    372 				cur->name.str = strdup(value);
    373 				if (!cur->name.str) {
    374 					free_seapp_context(cur);
    375 					goto oom;
    376 				}
    377 				cur->name.len = strlen(cur->name.str);
    378 				if (cur->name.str[cur->name.len-1] == '*')
    379 					cur->name.is_prefix = 1;
    380 			} else if (!strcasecmp(name, "domain")) {
    381 				cur->domain = strdup(value);
    382 				if (!cur->domain) {
    383 					free_seapp_context(cur);
    384 					goto oom;
    385 				}
    386 			} else if (!strcasecmp(name, "type")) {
    387 				cur->type = strdup(value);
    388 				if (!cur->type) {
    389 					free_seapp_context(cur);
    390 					goto oom;
    391 				}
    392 			} else if (!strcasecmp(name, "levelFromUid")) {
    393 				if (!strcasecmp(value, "true"))
    394 					cur->levelFrom = LEVELFROM_APP;
    395 				else if (!strcasecmp(value, "false"))
    396 					cur->levelFrom = LEVELFROM_NONE;
    397 				else {
    398 					free_seapp_context(cur);
    399 					goto err;
    400 				}
    401 			} else if (!strcasecmp(name, "levelFrom")) {
    402 				if (!strcasecmp(value, "none"))
    403 					cur->levelFrom = LEVELFROM_NONE;
    404 				else if (!strcasecmp(value, "app"))
    405 					cur->levelFrom = LEVELFROM_APP;
    406 				else if (!strcasecmp(value, "user"))
    407 					cur->levelFrom = LEVELFROM_USER;
    408 				else if (!strcasecmp(value, "all"))
    409 					cur->levelFrom = LEVELFROM_ALL;
    410 				else {
    411 					free_seapp_context(cur);
    412 					goto err;
    413 				}
    414 			} else if (!strcasecmp(name, "level")) {
    415 				cur->level = strdup(value);
    416 				if (!cur->level) {
    417 					free_seapp_context(cur);
    418 					goto oom;
    419 				}
    420 			} else if (!strcasecmp(name, "path")) {
    421 				cur->path.str = strdup(value);
    422 				if (!cur->path.str) {
    423 					free_seapp_context(cur);
    424 					goto oom;
    425 				}
    426 				cur->path.len = strlen(cur->path.str);
    427 				if (cur->path.str[cur->path.len-1] == '*')
    428 					cur->path.is_prefix = 1;
    429 			} else if (!strcasecmp(name, "sebool")) {
    430 				cur->sebool = strdup(value);
    431 				if (!cur->sebool) {
    432 					free_seapp_context(cur);
    433 					goto oom;
    434 				}
    435 			} else {
    436 				free_seapp_context(cur);
    437 				goto err;
    438 			}
    439 
    440 			token = strtok_r(NULL, " \t", &saveptr);
    441 			if (!token)
    442 				break;
    443 		}
    444 
    445 		if (cur->name.str &&
    446 		    (!cur->seinfo || !strcmp(cur->seinfo, "default"))) {
    447 			selinux_log(SELINUX_ERROR, "%s:  No specific seinfo value specified with name=\"%s\", on line %u:  insecure configuration!\n",
    448 				    seapp_contexts_file[policy_index], cur->name.str, lineno);
    449 			free_seapp_context(cur);
    450 			goto err;
    451 		}
    452 
    453 		seapp_contexts[nspec] = cur;
    454 		nspec++;
    455 		lineno++;
    456 	}
    457 
    458 	qsort(seapp_contexts, nspec, sizeof(struct seapp_context *),
    459 	      seapp_context_cmp);
    460 
    461 #if DEBUG
    462 	{
    463 		int i;
    464 		for (i = 0; i < nspec; i++) {
    465 			cur = seapp_contexts[i];
    466 			selinux_log(SELINUX_INFO, "%s:  isSystemServer=%s user=%s seinfo=%s name=%s path=%s sebool=%s -> domain=%s type=%s level=%s levelFrom=%s",
    467 			__FUNCTION__,
    468 			cur->isSystemServer ? "true" : "false", cur->user.str,
    469 			cur->seinfo, cur->name.str, cur->path.str, cur->sebool, cur->domain,
    470 			cur->type, cur->level,
    471 			levelFromName[cur->levelFrom]);
    472 		}
    473 	}
    474 #endif
    475 
    476 	ret = 0;
    477 
    478 out:
    479 	fclose(fp);
    480 	return ret;
    481 
    482 err:
    483 	selinux_log(SELINUX_ERROR, "%s:  Invalid entry on line %u\n",
    484 		    seapp_contexts_file[policy_index], lineno);
    485 	free_seapp_contexts();
    486 	ret = -1;
    487 	goto out;
    488 oom:
    489 	selinux_log(SELINUX_ERROR,
    490 		    "%s:  Out of memory\n", __FUNCTION__);
    491 	free_seapp_contexts();
    492 	ret = -1;
    493 	goto out;
    494 }
    495 
    496 
    497 static void seapp_context_init(void)
    498 {
    499         selinux_android_seapp_context_reload();
    500 }
    501 
    502 static pthread_once_t once = PTHREAD_ONCE_INIT;
    503 
    504 /*
    505  * Max id that can be mapped to category set uniquely
    506  * using the current scheme.
    507  */
    508 #define CAT_MAPPING_MAX_ID (0x1<<16)
    509 
    510 enum seapp_kind {
    511 	SEAPP_TYPE,
    512 	SEAPP_DOMAIN
    513 };
    514 
    515 static int seapp_context_lookup(enum seapp_kind kind,
    516 				uid_t uid,
    517 				int isSystemServer,
    518 				const char *seinfo,
    519 				const char *pkgname,
    520 				const char *path,
    521 				context_t ctx)
    522 {
    523 	const char *username = NULL;
    524 	struct seapp_context *cur = NULL;
    525 	int i;
    526 	size_t n;
    527 	uid_t userid;
    528 	uid_t appid;
    529 
    530 	__selinux_once(once, seapp_context_init);
    531 
    532 	userid = uid / AID_USER;
    533 	appid = uid % AID_USER;
    534 	if (appid < AID_APP) {
    535 		for (n = 0; n < android_id_count; n++) {
    536 			if (android_ids[n].aid == appid) {
    537 				username = android_ids[n].name;
    538 				break;
    539 			}
    540 		}
    541 		if (!username)
    542 			goto err;
    543 	} else if (appid < AID_ISOLATED_START) {
    544 		username = "_app";
    545 		appid -= AID_APP;
    546 	} else {
    547 		username = "_isolated";
    548 		appid -= AID_ISOLATED_START;
    549 	}
    550 
    551 	if (appid >= CAT_MAPPING_MAX_ID || userid >= CAT_MAPPING_MAX_ID)
    552 		goto err;
    553 
    554 	for (i = 0; i < nspec; i++) {
    555 		cur = seapp_contexts[i];
    556 
    557 		if (cur->isSystemServer != isSystemServer)
    558 			continue;
    559 
    560 		if (cur->user.str) {
    561 			if (cur->user.is_prefix) {
    562 				if (strncasecmp(username, cur->user.str, cur->user.len-1))
    563 					continue;
    564 			} else {
    565 				if (strcasecmp(username, cur->user.str))
    566 					continue;
    567 			}
    568 		}
    569 
    570 		if (cur->seinfo) {
    571 			if (!seinfo || strcasecmp(seinfo, cur->seinfo))
    572 				continue;
    573 		}
    574 
    575 		if (cur->name.str) {
    576 			if(!pkgname)
    577 				continue;
    578 
    579 			if (cur->name.is_prefix) {
    580 				if (strncasecmp(pkgname, cur->name.str, cur->name.len-1))
    581 					continue;
    582 			} else {
    583 				if (strcasecmp(pkgname, cur->name.str))
    584 					continue;
    585 			}
    586 		}
    587 
    588 		if (cur->path.str) {
    589 			if (!path)
    590 				continue;
    591 
    592 			if (cur->path.is_prefix) {
    593 				if (strncmp(path, cur->path.str, cur->path.len-1))
    594 					continue;
    595 			} else {
    596 				if (strcmp(path, cur->path.str))
    597 					continue;
    598 			}
    599 		}
    600 
    601 		if (kind == SEAPP_TYPE && !cur->type)
    602 			continue;
    603 		else if (kind == SEAPP_DOMAIN && !cur->domain)
    604 			continue;
    605 
    606 		if (cur->sebool) {
    607 			int value = security_get_boolean_active(cur->sebool);
    608 			if (value == 0)
    609 				continue;
    610 			else if (value == -1) {
    611 				selinux_log(SELINUX_ERROR, \
    612 				"Could not find boolean: %s ", cur->sebool);
    613 				goto err;
    614 			}
    615 		}
    616 
    617 		if (kind == SEAPP_TYPE) {
    618 			if (context_type_set(ctx, cur->type))
    619 				goto oom;
    620 		} else if (kind == SEAPP_DOMAIN) {
    621 			if (context_type_set(ctx, cur->domain))
    622 				goto oom;
    623 		}
    624 
    625 		if (cur->levelFrom != LEVELFROM_NONE) {
    626 			char level[255];
    627 			switch (cur->levelFrom) {
    628 			case LEVELFROM_APP:
    629 				snprintf(level, sizeof level, "s0:c%u,c%u",
    630 					 appid & 0xff,
    631 					 256 + (appid>>8 & 0xff));
    632 				break;
    633 			case LEVELFROM_USER:
    634 				snprintf(level, sizeof level, "s0:c%u,c%u",
    635 					 512 + (userid & 0xff),
    636 					 768 + (userid>>8 & 0xff));
    637 				break;
    638 			case LEVELFROM_ALL:
    639 				snprintf(level, sizeof level, "s0:c%u,c%u,c%u,c%u",
    640 					 appid & 0xff,
    641 					 256 + (appid>>8 & 0xff),
    642 					 512 + (userid & 0xff),
    643 					 768 + (userid>>8 & 0xff));
    644 				break;
    645 			default:
    646 				goto err;
    647 			}
    648 			if (context_range_set(ctx, level))
    649 				goto oom;
    650 		} else if (cur->level) {
    651 			if (context_range_set(ctx, cur->level))
    652 				goto oom;
    653 		}
    654 
    655 		break;
    656 	}
    657 
    658 	if (kind == SEAPP_DOMAIN && i == nspec) {
    659 		/*
    660 		 * No match.
    661 		 * Fail to prevent staying in the zygote's context.
    662 		 */
    663 		selinux_log(SELINUX_ERROR,
    664 			    "%s:  No match for app with uid %d, seinfo %s, name %s\n",
    665 			    __FUNCTION__, uid, seinfo, pkgname);
    666 
    667 		if (security_getenforce() == 1)
    668 			goto err;
    669 	}
    670 
    671 	return 0;
    672 err:
    673 	return -1;
    674 oom:
    675 	return -2;
    676 }
    677 
    678 int selinux_android_setfilecon(const char *pkgdir,
    679 				const char *pkgname,
    680 				const char *seinfo,
    681 				uid_t uid)
    682 {
    683 	char *orig_ctx_str = NULL;
    684 	char *ctx_str = NULL;
    685 	context_t ctx = NULL;
    686 	int rc = -1;
    687 
    688 	if (is_selinux_enabled() <= 0)
    689 		return 0;
    690 
    691 	rc = getfilecon(pkgdir, &ctx_str);
    692 	if (rc < 0)
    693 		goto err;
    694 
    695 	ctx = context_new(ctx_str);
    696 	orig_ctx_str = ctx_str;
    697 	if (!ctx)
    698 		goto oom;
    699 
    700 	rc = seapp_context_lookup(SEAPP_TYPE, uid, 0, seinfo, pkgname, NULL, ctx);
    701 	if (rc == -1)
    702 		goto err;
    703 	else if (rc == -2)
    704 		goto oom;
    705 
    706 	ctx_str = context_str(ctx);
    707 	if (!ctx_str)
    708 		goto oom;
    709 
    710 	rc = security_check_context(ctx_str);
    711 	if (rc < 0)
    712 		goto err;
    713 
    714 	if (strcmp(ctx_str, orig_ctx_str)) {
    715 		rc = setfilecon(pkgdir, ctx_str);
    716 		if (rc < 0)
    717 			goto err;
    718 	}
    719 
    720 	rc = 0;
    721 out:
    722 	freecon(orig_ctx_str);
    723 	context_free(ctx);
    724 	return rc;
    725 err:
    726 	selinux_log(SELINUX_ERROR, "%s:  Error setting context for pkgdir %s, uid %d: %s\n",
    727 		    __FUNCTION__, pkgdir, uid, strerror(errno));
    728 	rc = -1;
    729 	goto out;
    730 oom:
    731 	selinux_log(SELINUX_ERROR, "%s:  Out of memory\n", __FUNCTION__);
    732 	rc = -1;
    733 	goto out;
    734 }
    735 
    736 int selinux_android_setcontext(uid_t uid,
    737 			       int isSystemServer,
    738 			       const char *seinfo,
    739 			       const char *pkgname)
    740 {
    741 	char *orig_ctx_str = NULL, *ctx_str;
    742 	context_t ctx = NULL;
    743 	int rc = -1;
    744 
    745 	if (is_selinux_enabled() <= 0)
    746 		return 0;
    747 
    748 	rc = getcon(&ctx_str);
    749 	if (rc)
    750 		goto err;
    751 
    752 	ctx = context_new(ctx_str);
    753 	orig_ctx_str = ctx_str;
    754 	if (!ctx)
    755 		goto oom;
    756 
    757 	rc = seapp_context_lookup(SEAPP_DOMAIN, uid, isSystemServer, seinfo, pkgname, NULL, ctx);
    758 	if (rc == -1)
    759 		goto err;
    760 	else if (rc == -2)
    761 		goto oom;
    762 
    763 	ctx_str = context_str(ctx);
    764 	if (!ctx_str)
    765 		goto oom;
    766 
    767 	rc = security_check_context(ctx_str);
    768 	if (rc < 0)
    769 		goto err;
    770 
    771 	if (strcmp(ctx_str, orig_ctx_str)) {
    772 		rc = setcon(ctx_str);
    773 		if (rc < 0)
    774 			goto err;
    775 	}
    776 
    777 	rc = 0;
    778 out:
    779 	freecon(orig_ctx_str);
    780 	context_free(ctx);
    781 	avc_netlink_close();
    782 	return rc;
    783 err:
    784 	if (isSystemServer)
    785 		selinux_log(SELINUX_ERROR,
    786 				"%s:  Error setting context for system server: %s\n",
    787 				__FUNCTION__, strerror(errno));
    788 	else
    789 		selinux_log(SELINUX_ERROR,
    790 				"%s:  Error setting context for app with uid %d, seinfo %s: %s\n",
    791 				__FUNCTION__, uid, seinfo, strerror(errno));
    792 
    793 	rc = -1;
    794 	goto out;
    795 oom:
    796 	selinux_log(SELINUX_ERROR, "%s:  Out of memory\n", __FUNCTION__);
    797 	rc = -1;
    798 	goto out;
    799 }
    800 
    801 static struct selabel_handle *sehandle = NULL;
    802 #define FC_DIGEST_SIZE SHA_DIGEST_SIZE
    803 static uint8_t fc_digest[FC_DIGEST_SIZE];
    804 
    805 static struct selabel_handle *get_selabel_handle(const struct selinux_opt opts[])
    806 {
    807     struct selabel_handle *h;
    808     int fd;
    809     struct stat sb;
    810     void *map;
    811 
    812     set_policy_index();
    813 
    814     h = selabel_open(SELABEL_CTX_FILE, &opts[policy_index], 1);
    815     if (!h)
    816         return NULL;
    817 
    818     fd = open(opts[policy_index].value, O_RDONLY | O_NOFOLLOW);
    819     if (fd < 0) {
    820         selinux_log(SELINUX_ERROR, "SELinux:  Could not open %s:  %s\n",
    821                     opts[policy_index].value, strerror(errno));
    822         goto err;
    823     }
    824     if (fstat(fd, &sb) < 0) {
    825         selinux_log(SELINUX_ERROR, "SELinux:  Could not stat %s:  %s\n",
    826                     opts[policy_index].value, strerror(errno));
    827         close(fd);
    828         goto err;
    829     }
    830     map = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
    831     if (map == MAP_FAILED) {
    832         selinux_log(SELINUX_ERROR, "SELinux:  Could not map %s:  %s\n",
    833                     opts[policy_index].value, strerror(errno));
    834         close(fd);
    835         goto err;
    836     }
    837     SHA_hash(map, sb.st_size, fc_digest);
    838     munmap(map, sb.st_size);
    839     close(fd);
    840 
    841     selinux_log(SELINUX_INFO, "SELinux: Loaded file_contexts from %s\n",
    842                 opts[policy_index].value);
    843 
    844     return h;
    845 
    846 err:
    847     selabel_close(h);
    848     return NULL;
    849 }
    850 
    851 static struct selabel_handle *file_context_open(void)
    852 {
    853 	struct selabel_handle *h;
    854 
    855 	h = get_selabel_handle(seopts);
    856 
    857 	if (!h)
    858 		selinux_log(SELINUX_ERROR, "%s: Error getting file context handle (%s)\n",
    859 				__FUNCTION__, strerror(errno));
    860 	return h;
    861 }
    862 
    863 static void file_context_init(void)
    864 {
    865     if (!sehandle)
    866         sehandle = file_context_open();
    867 }
    868 
    869 static struct selabel_handle *service_context_open(void)
    870 {
    871     struct selabel_handle *handle = NULL;
    872 
    873     set_policy_index();
    874     handle = selabel_open(SELABEL_CTX_ANDROID_PROP,
    875             &seopts_service[policy_index], 1);
    876 
    877     if (!handle) {
    878         selinux_log(SELINUX_ERROR, "%s: Error getting service context handle (%s)\n",
    879                 __FUNCTION__, strerror(errno));
    880     } else {
    881         selinux_log(SELINUX_INFO, "SELinux: Loaded service contexts from %s.\n",
    882                 seopts_service[policy_index].value);
    883     }
    884 
    885     return handle;
    886 }
    887 
    888 static pthread_once_t fc_once = PTHREAD_ONCE_INIT;
    889 
    890 struct pkgInfo {
    891     char *name;
    892     uid_t uid;
    893     bool debuggable;
    894     char *dataDir;
    895     char *seinfo;
    896     struct pkgInfo *next;
    897 };
    898 
    899 #define PKGTAB_SIZE 256
    900 static struct pkgInfo *pkgTab[PKGTAB_SIZE];
    901 
    902 static unsigned int pkghash(const char *pkgname)
    903 {
    904     unsigned int h = 7;
    905     for (; *pkgname; pkgname++) {
    906         h = h * 31 + *pkgname;
    907     }
    908     return h & (PKGTAB_SIZE - 1);
    909 }
    910 
    911 /* The file containing the list of installed packages on the system */
    912 #define PACKAGES_LIST_FILE  "/data/system/packages.list"
    913 
    914 static void package_info_init(void)
    915 {
    916     char *buf = NULL;
    917     size_t buflen = 0;
    918     ssize_t bytesread;
    919     FILE *fp;
    920     char *cur, *next;
    921     struct pkgInfo *pkgInfo = NULL;
    922     unsigned int hash;
    923     unsigned long lineno = 1;
    924 
    925     fp = fopen(PACKAGES_LIST_FILE, "r");
    926     if (!fp) {
    927         selinux_log(SELINUX_ERROR, "SELinux:  Could not open %s:  %s.\n",
    928                     PACKAGES_LIST_FILE, strerror(errno));
    929         return;
    930     }
    931     while ((bytesread = getline(&buf, &buflen, fp)) > 0) {
    932         pkgInfo = calloc(1, sizeof(*pkgInfo));
    933         if (!pkgInfo)
    934             goto err;
    935         next = buf;
    936         cur = strsep(&next, " \t\n");
    937         if (!cur)
    938             goto err;
    939         pkgInfo->name = strdup(cur);
    940         if (!pkgInfo->name)
    941             goto err;
    942         cur = strsep(&next, " \t\n");
    943         if (!cur)
    944             goto err;
    945         pkgInfo->uid = atoi(cur);
    946         if (!pkgInfo->uid)
    947             goto err;
    948         cur = strsep(&next, " \t\n");
    949         if (!cur)
    950             goto err;
    951         pkgInfo->debuggable = atoi(cur);
    952         cur = strsep(&next, " \t\n");
    953         if (!cur)
    954             goto err;
    955         pkgInfo->dataDir = strdup(cur);
    956         if (!pkgInfo->dataDir)
    957             goto err;
    958         cur = strsep(&next, " \t\n");
    959         if (!cur)
    960             goto err;
    961         pkgInfo->seinfo = strdup(cur);
    962         if (!pkgInfo->seinfo)
    963             goto err;
    964 
    965         hash = pkghash(pkgInfo->name);
    966         if (pkgTab[hash])
    967             pkgInfo->next = pkgTab[hash];
    968         pkgTab[hash] = pkgInfo;
    969 
    970         lineno++;
    971     }
    972 
    973 #if DEBUG
    974     {
    975         unsigned int buckets, entries, chainlen, longestchain;
    976 
    977         buckets = entries = longestchain = 0;
    978         for (hash = 0; hash < PKGTAB_SIZE; hash++) {
    979             if (pkgTab[hash]) {
    980                 buckets++;
    981                 chainlen = 0;
    982                 for (pkgInfo = pkgTab[hash]; pkgInfo; pkgInfo = pkgInfo->next) {
    983                     chainlen++;
    984                     selinux_log(SELINUX_INFO, "%s:  name=%s uid=%u debuggable=%s dataDir=%s seinfo=%s\n",
    985                                 __FUNCTION__,
    986                                 pkgInfo->name, pkgInfo->uid, pkgInfo->debuggable ? "true" : "false", pkgInfo->dataDir, pkgInfo->seinfo);
    987                 }
    988                 entries += chainlen;
    989                 if (longestchain < chainlen)
    990                     longestchain = chainlen;
    991             }
    992         }
    993         selinux_log(SELINUX_INFO, "SELinux:  %d pkg entries and %d/%d buckets used, longest chain %d\n", entries, buckets, PKGTAB_SIZE, longestchain);
    994     }
    995 #endif
    996 
    997 out:
    998     free(buf);
    999     fclose(fp);
   1000     return;
   1001 
   1002 err:
   1003     selinux_log(SELINUX_ERROR, "SELinux:  Error reading %s on line %lu.\n",
   1004                 PACKAGES_LIST_FILE, lineno);
   1005     if (pkgInfo) {
   1006         free(pkgInfo->name);
   1007         free(pkgInfo->dataDir);
   1008         free(pkgInfo->seinfo);
   1009         free(pkgInfo);
   1010     }
   1011     goto out;
   1012 }
   1013 
   1014 static pthread_once_t pkg_once = PTHREAD_ONCE_INIT;
   1015 
   1016 struct pkgInfo *package_info_lookup(const char *name)
   1017 {
   1018     struct pkgInfo *pkgInfo;
   1019     unsigned int hash;
   1020 
   1021     __selinux_once(pkg_once, package_info_init);
   1022 
   1023     hash = pkghash(name);
   1024     for (pkgInfo = pkgTab[hash]; pkgInfo; pkgInfo = pkgInfo->next) {
   1025         if (!strcmp(name, pkgInfo->name))
   1026             return pkgInfo;
   1027     }
   1028     return NULL;
   1029 }
   1030 
   1031 /* The path prefixes of package data directories. */
   1032 #define DATA_DATA_PATH "/data/data"
   1033 #define DATA_USER_PATH "/data/user"
   1034 #define DATA_DATA_PREFIX DATA_DATA_PATH "/"
   1035 #define DATA_USER_PREFIX DATA_USER_PATH "/"
   1036 
   1037 static int pkgdir_selabel_lookup(const char *pathname,
   1038                                  const char *seinfo,
   1039                                  uid_t uid,
   1040                                  char **secontextp)
   1041 {
   1042     char *pkgname = NULL, *end = NULL;
   1043     struct pkgInfo *pkgInfo = NULL;
   1044     char *secontext = *secontextp;
   1045     context_t ctx = NULL;
   1046     int rc = 0;
   1047 
   1048     /* Skip directory prefix before package name. */
   1049     if (!strncmp(pathname, DATA_DATA_PREFIX, sizeof(DATA_DATA_PREFIX)-1)) {
   1050         pathname += sizeof(DATA_DATA_PREFIX) - 1;
   1051     } else if (!strncmp(pathname, DATA_USER_PREFIX, sizeof(DATA_USER_PREFIX)-1)) {
   1052         pathname += sizeof(DATA_USER_PREFIX) - 1;
   1053         while (isdigit(*pathname))
   1054             pathname++;
   1055         if (*pathname == '/')
   1056             pathname++;
   1057         else
   1058             return 0;
   1059     } else
   1060         return 0;
   1061 
   1062     if (!(*pathname))
   1063         return 0;
   1064 
   1065     pkgname = strdup(pathname);
   1066     if (!pkgname)
   1067         return -1;
   1068 
   1069     for (end = pkgname; *end && *end != '/'; end++)
   1070         ;
   1071     pathname = end;
   1072     if (*end)
   1073         pathname++;
   1074     *end = '\0';
   1075 
   1076     if (!seinfo) {
   1077         pkgInfo = package_info_lookup(pkgname);
   1078         if (!pkgInfo) {
   1079             selinux_log(SELINUX_WARNING, "SELinux:  Could not look up information for package %s, cannot restorecon %s.\n",
   1080                         pkgname, pathname);
   1081             free(pkgname);
   1082             return -1;
   1083         }
   1084     }
   1085 
   1086     ctx = context_new(secontext);
   1087     if (!ctx)
   1088         goto err;
   1089 
   1090     rc = seapp_context_lookup(SEAPP_TYPE, pkgInfo ? pkgInfo->uid : uid, 0,
   1091                               pkgInfo ? pkgInfo->seinfo : seinfo, pkgInfo ? pkgInfo->name : pkgname, pathname, ctx);
   1092     if (rc < 0)
   1093         goto err;
   1094 
   1095     secontext = context_str(ctx);
   1096     if (!secontext)
   1097         goto err;
   1098 
   1099     if (!strcmp(secontext, *secontextp))
   1100         goto out;
   1101 
   1102     rc = security_check_context(secontext);
   1103     if (rc < 0)
   1104         goto err;
   1105 
   1106     freecon(*secontextp);
   1107     *secontextp = strdup(secontext);
   1108     if (!(*secontextp))
   1109         goto err;
   1110 
   1111     rc = 0;
   1112 
   1113 out:
   1114     free(pkgname);
   1115     context_free(ctx);
   1116     return rc;
   1117 err:
   1118     selinux_log(SELINUX_ERROR, "%s:  Error looking up context for path %s, pkgname %s, seinfo %s, uid %u: %s\n",
   1119                 __FUNCTION__, pathname, pkgname, pkgInfo->seinfo, pkgInfo->uid, strerror(errno));
   1120     rc = -1;
   1121     goto out;
   1122 }
   1123 
   1124 #define RESTORECON_LAST "security.restorecon_last"
   1125 
   1126 static int restorecon_sb(const char *pathname, const struct stat *sb,
   1127                          bool nochange, bool verbose,
   1128                          const char *seinfo, uid_t uid)
   1129 {
   1130     char *secontext = NULL;
   1131     char *oldsecontext = NULL;
   1132     int rc = 0;
   1133 
   1134     if (selabel_lookup(sehandle, &secontext, pathname, sb->st_mode) < 0)
   1135         return 0;  /* no match, but not an error */
   1136 
   1137     if (lgetfilecon(pathname, &oldsecontext) < 0)
   1138         goto err;
   1139 
   1140     /*
   1141      * For subdirectories of /data/data or /data/user, we ignore selabel_lookup()
   1142      * and use pkgdir_selabel_lookup() instead. Files within those directories
   1143      * have different labeling rules, based off of /seapp_contexts, and
   1144      * installd is responsible for managing these labels instead of init.
   1145      */
   1146     if (!strncmp(pathname, DATA_DATA_PREFIX, sizeof(DATA_DATA_PREFIX)-1) ||
   1147         !strncmp(pathname, DATA_USER_PREFIX, sizeof(DATA_USER_PREFIX)-1)) {
   1148         if (pkgdir_selabel_lookup(pathname, seinfo, uid, &secontext) < 0)
   1149             goto err;
   1150     }
   1151 
   1152     if (strcmp(oldsecontext, secontext) != 0) {
   1153         if (verbose)
   1154             selinux_log(SELINUX_INFO,
   1155                         "SELinux:  Relabeling %s from %s to %s.\n", pathname, oldsecontext, secontext);
   1156         if (!nochange) {
   1157             if (lsetfilecon(pathname, secontext) < 0)
   1158                 goto err;
   1159         }
   1160     }
   1161 
   1162     rc = 0;
   1163 
   1164 out:
   1165     freecon(oldsecontext);
   1166     freecon(secontext);
   1167     return rc;
   1168 
   1169 err:
   1170     selinux_log(SELINUX_ERROR,
   1171                 "SELinux: Could not set context for %s:  %s\n",
   1172                 pathname, strerror(errno));
   1173     rc = -1;
   1174     goto out;
   1175 }
   1176 
   1177 #define SYS_PATH "/sys"
   1178 #define SYS_PREFIX SYS_PATH "/"
   1179 
   1180 static int selinux_android_restorecon_common(const char* pathname,
   1181                                              const char *seinfo,
   1182                                              uid_t uid,
   1183                                              unsigned int flags)
   1184 {
   1185     bool nochange = (flags & SELINUX_ANDROID_RESTORECON_NOCHANGE) ? true : false;
   1186     bool verbose = (flags & SELINUX_ANDROID_RESTORECON_VERBOSE) ? true : false;
   1187     bool recurse = (flags & SELINUX_ANDROID_RESTORECON_RECURSE) ? true : false;
   1188     bool force = (flags & SELINUX_ANDROID_RESTORECON_FORCE) ? true : false;
   1189     bool datadata = (flags & SELINUX_ANDROID_RESTORECON_DATADATA) ? true : false;
   1190     bool issys = (!strcmp(pathname, SYS_PATH) || !strncmp(pathname, SYS_PREFIX, sizeof(SYS_PREFIX)-1)) ? true : false;
   1191     bool setrestoreconlast = true;
   1192     struct stat sb;
   1193     FTS *fts;
   1194     FTSENT *ftsent;
   1195     char *const paths[2] = { __UNCONST(pathname), NULL };
   1196     int ftsflags = FTS_COMFOLLOW | FTS_NOCHDIR | FTS_XDEV | FTS_PHYSICAL;
   1197     int error, sverrno;
   1198     char xattr_value[FC_DIGEST_SIZE];
   1199     ssize_t size;
   1200 
   1201     if (is_selinux_enabled() <= 0)
   1202         return 0;
   1203 
   1204     __selinux_once(fc_once, file_context_init);
   1205 
   1206     if (!sehandle)
   1207         return 0;
   1208 
   1209     if (!recurse) {
   1210         if (lstat(pathname, &sb) < 0)
   1211             return -1;
   1212 
   1213         return restorecon_sb(pathname, &sb, nochange, verbose, seinfo, uid);
   1214     }
   1215 
   1216     /*
   1217      * Ignore restorecon_last on /data/data or /data/user
   1218      * since their labeling is based on seapp_contexts and seinfo
   1219      * assignments rather than file_contexts and is managed by
   1220      * installd rather than init.
   1221      */
   1222     if (!strncmp(pathname, DATA_DATA_PREFIX, sizeof(DATA_DATA_PREFIX)-1) ||
   1223         !strncmp(pathname, DATA_USER_PREFIX, sizeof(DATA_USER_PREFIX)-1))
   1224         setrestoreconlast = false;
   1225 
   1226     /* Also ignore on /sys since it is regenerated on each boot regardless. */
   1227     if (issys)
   1228         setrestoreconlast = false;
   1229 
   1230     if (setrestoreconlast) {
   1231         size = getxattr(pathname, RESTORECON_LAST, xattr_value, sizeof fc_digest);
   1232         if (!force && size == sizeof fc_digest && memcmp(fc_digest, xattr_value, sizeof fc_digest) == 0) {
   1233             selinux_log(SELINUX_INFO,
   1234                         "SELinux: Skipping restorecon_recursive(%s)\n",
   1235                         pathname);
   1236             return 0;
   1237         }
   1238     }
   1239 
   1240     fts = fts_open(paths, ftsflags, NULL);
   1241     if (!fts)
   1242         return -1;
   1243 
   1244     error = 0;
   1245     while ((ftsent = fts_read(fts)) != NULL) {
   1246         switch (ftsent->fts_info) {
   1247         case FTS_DC:
   1248             selinux_log(SELINUX_ERROR,
   1249                         "SELinux:  Directory cycle on %s.\n", ftsent->fts_path);
   1250             errno = ELOOP;
   1251             error = -1;
   1252             goto out;
   1253         case FTS_DP:
   1254             continue;
   1255         case FTS_DNR:
   1256             selinux_log(SELINUX_ERROR,
   1257                         "SELinux:  Could not read %s: %s.\n", ftsent->fts_path, strerror(errno));
   1258             fts_set(fts, ftsent, FTS_SKIP);
   1259             continue;
   1260         case FTS_NS:
   1261             selinux_log(SELINUX_ERROR,
   1262                         "SELinux:  Could not stat %s: %s.\n", ftsent->fts_path, strerror(errno));
   1263             fts_set(fts, ftsent, FTS_SKIP);
   1264             continue;
   1265         case FTS_ERR:
   1266             selinux_log(SELINUX_ERROR,
   1267                         "SELinux:  Error on %s: %s.\n", ftsent->fts_path, strerror(errno));
   1268             fts_set(fts, ftsent, FTS_SKIP);
   1269             continue;
   1270         case FTS_D:
   1271             if (issys && !selabel_partial_match(sehandle, ftsent->fts_path)) {
   1272                 fts_set(fts, ftsent, FTS_SKIP);
   1273                 continue;
   1274             }
   1275             if (!datadata &&
   1276                 (!strcmp(ftsent->fts_path, DATA_DATA_PATH) ||
   1277                  !strncmp(ftsent->fts_path, DATA_USER_PREFIX, sizeof(DATA_USER_PREFIX)-1))) {
   1278                 // Don't label anything below this directory.
   1279                 fts_set(fts, ftsent, FTS_SKIP);
   1280                 // but fall through and make sure we label the directory itself
   1281             }
   1282             /* fall through */
   1283         default:
   1284             error |= restorecon_sb(ftsent->fts_path, ftsent->fts_statp, nochange, verbose, seinfo, uid);
   1285             break;
   1286         }
   1287     }
   1288 
   1289     // Labeling successful. Mark the top level directory as completed.
   1290     if (setrestoreconlast && !nochange && !error)
   1291         setxattr(pathname, RESTORECON_LAST, fc_digest, sizeof fc_digest, 0);
   1292 
   1293 out:
   1294     sverrno = errno;
   1295     (void) fts_close(fts);
   1296     errno = sverrno;
   1297     return error;
   1298 }
   1299 
   1300 int selinux_android_restorecon(const char *file, unsigned int flags)
   1301 {
   1302     return selinux_android_restorecon_common(file, NULL, -1, flags);
   1303 }
   1304 
   1305 int selinux_android_restorecon_pkgdir(const char *pkgdir,
   1306                                       const char *seinfo,
   1307                                       uid_t uid,
   1308                                       unsigned int flags)
   1309 {
   1310     return selinux_android_restorecon_common(pkgdir, seinfo, uid, flags | SELINUX_ANDROID_RESTORECON_DATADATA);
   1311 }
   1312 
   1313 struct selabel_handle* selinux_android_file_context_handle(void)
   1314 {
   1315     return file_context_open();
   1316 }
   1317 
   1318 struct selabel_handle* selinux_android_service_context_handle(void)
   1319 {
   1320     return service_context_open();
   1321 }
   1322 
   1323 void selinux_android_set_sehandle(const struct selabel_handle *hndl)
   1324 {
   1325     sehandle = (struct selabel_handle *) hndl;
   1326 }
   1327 
   1328 static int selinux_android_load_policy_helper(bool reload)
   1329 {
   1330 	int fd = -1, rc;
   1331 	struct stat sb;
   1332 	void *map = NULL;
   1333 
   1334 	/*
   1335 	 * If reloading policy and there is no /data policy or
   1336 	 * that /data policy has the wrong version or the /data
   1337 	 * policy is disabled via safe mode, then just return.
   1338 	 * There is no point in reloading policy from / a second time.
   1339 	 */
   1340 	if (reload && !selinux_android_use_data_policy())
   1341 		return 0;
   1342 
   1343 	fd = open(sepolicy_file[policy_index], O_RDONLY | O_NOFOLLOW);
   1344 	if (fd < 0) {
   1345 		selinux_log(SELINUX_ERROR, "SELinux:  Could not open sepolicy:  %s\n",
   1346 				strerror(errno));
   1347 		return -1;
   1348 	}
   1349 	if (fstat(fd, &sb) < 0) {
   1350 		selinux_log(SELINUX_ERROR, "SELinux:  Could not stat %s:  %s\n",
   1351 				sepolicy_file[policy_index], strerror(errno));
   1352 		close(fd);
   1353 		return -1;
   1354 	}
   1355 	map = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
   1356 	if (map == MAP_FAILED) {
   1357 		selinux_log(SELINUX_ERROR, "SELinux:  Could not map %s:  %s\n",
   1358 			sepolicy_file[policy_index], strerror(errno));
   1359 		close(fd);
   1360 		return -1;
   1361 	}
   1362 
   1363 	rc = security_load_policy(map, sb.st_size);
   1364 	if (rc < 0) {
   1365 		selinux_log(SELINUX_ERROR, "SELinux:  Could not load policy:  %s\n",
   1366 			strerror(errno));
   1367 		munmap(map, sb.st_size);
   1368 		close(fd);
   1369 		return -1;
   1370 	}
   1371 
   1372 	munmap(map, sb.st_size);
   1373 	close(fd);
   1374 	selinux_log(SELINUX_INFO, "SELinux: Loaded policy from %s\n", sepolicy_file[policy_index]);
   1375 
   1376 	return 0;
   1377 }
   1378 
   1379 int selinux_android_reload_policy(void)
   1380 {
   1381     return selinux_android_load_policy_helper(true);
   1382 }
   1383 
   1384 int selinux_android_load_policy(void)
   1385 {
   1386 	const char *mnt = SELINUXMNT;
   1387 	int rc;
   1388 	rc = mount(SELINUXFS, mnt, SELINUXFS, 0, NULL);
   1389 	if (rc < 0) {
   1390 		if (errno == ENODEV) {
   1391 			/* SELinux not enabled in kernel */
   1392 			return -1;
   1393 		}
   1394 		if (errno == ENOENT) {
   1395 			/* Fall back to legacy mountpoint. */
   1396 			mnt = OLDSELINUXMNT;
   1397 			rc = mkdir(mnt, 0755);
   1398 			if (rc == -1 && errno != EEXIST) {
   1399 				selinux_log(SELINUX_ERROR,"SELinux:  Could not mkdir:  %s\n",
   1400 					strerror(errno));
   1401 				return -1;
   1402 			}
   1403 			rc = mount(SELINUXFS, mnt, SELINUXFS, 0, NULL);
   1404 		}
   1405 	}
   1406 	if (rc < 0) {
   1407 		selinux_log(SELINUX_ERROR,"SELinux:  Could not mount selinuxfs:  %s\n",
   1408 				strerror(errno));
   1409 		return -1;
   1410 	}
   1411 	set_selinuxmnt(mnt);
   1412 
   1413     return selinux_android_load_policy_helper(false);
   1414 }
   1415 
   1416 int selinux_log_callback(int type, const char *fmt, ...)
   1417 {
   1418     va_list ap;
   1419     int priority;
   1420     char *strp;
   1421 
   1422     switch(type) {
   1423     case SELINUX_WARNING:
   1424         priority = ANDROID_LOG_WARN;
   1425         break;
   1426     case SELINUX_INFO:
   1427         priority = ANDROID_LOG_INFO;
   1428         break;
   1429     default:
   1430         priority = ANDROID_LOG_ERROR;
   1431         break;
   1432     }
   1433 
   1434     va_start(ap, fmt);
   1435     if (vasprintf(&strp, fmt, ap) != -1) {
   1436         LOG_PRI(priority, "SELinux", "%s", strp);
   1437         LOG_EVENT_STRING(AUDITD_LOG_TAG, strp);
   1438         free(strp);
   1439     }
   1440     va_end(ap);
   1441     return 0;
   1442 }
   1443