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