Home | History | Annotate | Download | only in android
      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 <openssl/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 #include <fnmatch.h>
     31 #include <limits.h>
     32 #include <sys/vfs.h>
     33 #include <linux/magic.h>
     34 #include <libgen.h>
     35 #include <packagelistparser/packagelistparser.h>
     36 
     37 #define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
     38 #include <sys/_system_properties.h>
     39 
     40 #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
     41 
     42 /*
     43  * XXX Where should this configuration file be located?
     44  * Needs to be accessible by zygote and installd when
     45  * setting credentials for app processes and setting permissions
     46  * on app data directories.
     47  */
     48 static char const * const seapp_contexts_split[] = {
     49 	"/system/etc/selinux/plat_seapp_contexts",
     50 	"/vendor/etc/selinux/nonplat_seapp_contexts"
     51 };
     52 
     53 static char const * const seapp_contexts_rootfs[] = {
     54 	"/plat_seapp_contexts",
     55 	"/nonplat_seapp_contexts"
     56 };
     57 
     58 static const struct selinux_opt seopts_file_split[] = {
     59     { SELABEL_OPT_PATH, "/system/etc/selinux/plat_file_contexts" },
     60     { SELABEL_OPT_PATH, "/vendor/etc/selinux/nonplat_file_contexts" }
     61 };
     62 
     63 static const struct selinux_opt seopts_file_rootfs[] = {
     64     { SELABEL_OPT_PATH, "/plat_file_contexts" },
     65     { SELABEL_OPT_PATH, "/nonplat_file_contexts" }
     66 };
     67 
     68 static const char *const sepolicy_file = "/sepolicy";
     69 
     70 static const struct selinux_opt seopts_prop_split[] = {
     71     { SELABEL_OPT_PATH, "/system/etc/selinux/plat_property_contexts" },
     72     { SELABEL_OPT_PATH, "/vendor/etc/selinux/nonplat_property_contexts"}
     73 };
     74 
     75 static const struct selinux_opt seopts_prop_rootfs[] = {
     76     { SELABEL_OPT_PATH, "/plat_property_contexts" },
     77     { SELABEL_OPT_PATH, "/nonplat_property_contexts"}
     78 };
     79 
     80 static const struct selinux_opt seopts_service_split[] = {
     81     { SELABEL_OPT_PATH, "/system/etc/selinux/plat_service_contexts" },
     82     { SELABEL_OPT_PATH, "/vendor/etc/selinux/nonplat_service_contexts" }
     83 };
     84 
     85 static const struct selinux_opt seopts_service_rootfs[] = {
     86     { SELABEL_OPT_PATH, "/plat_service_contexts" },
     87     { SELABEL_OPT_PATH, "/nonplat_service_contexts" }
     88 };
     89 
     90 static const struct selinux_opt seopts_hwservice_split[] = {
     91     { SELABEL_OPT_PATH, "/system/etc/selinux/plat_hwservice_contexts" },
     92     { SELABEL_OPT_PATH, "/vendor/etc/selinux/nonplat_hwservice_contexts" }
     93 };
     94 
     95 static const struct selinux_opt seopts_hwservice_rootfs[] = {
     96     { SELABEL_OPT_PATH, "/plat_hwservice_contexts" },
     97     { SELABEL_OPT_PATH, "/nonplat_hwservice_contexts" }
     98 };
     99 
    100 
    101 static const struct selinux_opt seopts_vndservice =
    102     { SELABEL_OPT_PATH, "/vendor/etc/selinux/vndservice_contexts" };
    103 
    104 static const struct selinux_opt seopts_vndservice_rootfs =
    105     { SELABEL_OPT_PATH, "/vndservice_contexts" };
    106 
    107 
    108 enum levelFrom {
    109 	LEVELFROM_NONE,
    110 	LEVELFROM_APP,
    111 	LEVELFROM_USER,
    112 	LEVELFROM_ALL
    113 };
    114 
    115 #if DEBUG
    116 static char const * const levelFromName[] = {
    117 	"none",
    118 	"app",
    119 	"user",
    120 	"all"
    121 };
    122 #endif
    123 
    124 struct prefix_str {
    125 	size_t len;
    126 	char *str;
    127 	char is_prefix;
    128 };
    129 
    130 static void free_prefix_str(struct prefix_str *p)
    131 {
    132 	if (!p)
    133 		return;
    134 	free(p->str);
    135 }
    136 
    137 struct seapp_context {
    138 	/* input selectors */
    139 	bool isSystemServer;
    140 	bool isEphemeralAppSet;
    141 	bool isEphemeralApp;
    142 	bool isV2AppSet;
    143 	bool isV2App;
    144 	bool isOwnerSet;
    145 	bool isOwner;
    146 	struct prefix_str user;
    147 	char *seinfo;
    148 	struct prefix_str name;
    149 	struct prefix_str path;
    150 	bool isPrivAppSet;
    151 	bool isPrivApp;
    152 	int32_t minTargetSdkVersion;
    153 	/* outputs */
    154 	char *domain;
    155 	char *type;
    156 	char *level;
    157 	enum levelFrom levelFrom;
    158 };
    159 
    160 static void free_seapp_context(struct seapp_context *s)
    161 {
    162 	if (!s)
    163 		return;
    164 
    165 	free_prefix_str(&s->user);
    166 	free(s->seinfo);
    167 	free_prefix_str(&s->name);
    168 	free_prefix_str(&s->path);
    169 	free(s->domain);
    170 	free(s->type);
    171 	free(s->level);
    172 }
    173 
    174 static bool seapp_contexts_dup = false;
    175 
    176 static int seapp_context_cmp(const void *A, const void *B)
    177 {
    178 	const struct seapp_context *const *sp1 = (const struct seapp_context *const *) A;
    179 	const struct seapp_context *const *sp2 = (const struct seapp_context *const *) B;
    180 	const struct seapp_context *s1 = *sp1, *s2 = *sp2;
    181 	bool dup;
    182 
    183 	/* Give precedence to isSystemServer=true. */
    184 	if (s1->isSystemServer != s2->isSystemServer)
    185 		return (s1->isSystemServer ? -1 : 1);
    186 
    187 	/* Give precedence to a specified isEphemeral= over an
    188 	 * unspecified isEphemeral=. */
    189 	if (s1->isEphemeralAppSet != s2->isEphemeralAppSet)
    190 		return (s1->isEphemeralAppSet ? -1 : 1);
    191 
    192 	/* Give precedence to a specified isV2= over an
    193 	 * unspecified isV2=. */
    194 	if (s1->isV2AppSet != s2->isV2AppSet)
    195 		return (s1->isV2AppSet ? -1 : 1);
    196 
    197 
    198 	/* Give precedence to a specified isOwner= over an unspecified isOwner=. */
    199 	if (s1->isOwnerSet != s2->isOwnerSet)
    200 		return (s1->isOwnerSet ? -1 : 1);
    201 
    202 	/* Give precedence to a specified user= over an unspecified user=. */
    203 	if (s1->user.str && !s2->user.str)
    204 		return -1;
    205 	if (!s1->user.str && s2->user.str)
    206 		return 1;
    207 
    208 	if (s1->user.str) {
    209 		/* Give precedence to a fixed user= string over a prefix. */
    210 		if (s1->user.is_prefix != s2->user.is_prefix)
    211 			return (s2->user.is_prefix ? -1 : 1);
    212 
    213 		/* Give precedence to a longer prefix over a shorter prefix. */
    214 		if (s1->user.is_prefix && s1->user.len != s2->user.len)
    215 			return (s1->user.len > s2->user.len) ? -1 : 1;
    216 	}
    217 
    218 	/* Give precedence to a specified seinfo= over an unspecified seinfo=. */
    219 	if (s1->seinfo && !s2->seinfo)
    220 		return -1;
    221 	if (!s1->seinfo && s2->seinfo)
    222 		return 1;
    223 
    224 	/* Give precedence to a specified name= over an unspecified name=. */
    225 	if (s1->name.str && !s2->name.str)
    226 		return -1;
    227 	if (!s1->name.str && s2->name.str)
    228 		return 1;
    229 
    230 	if (s1->name.str) {
    231 		/* Give precedence to a fixed name= string over a prefix. */
    232 		if (s1->name.is_prefix != s2->name.is_prefix)
    233 			return (s2->name.is_prefix ? -1 : 1);
    234 
    235 		/* Give precedence to a longer prefix over a shorter prefix. */
    236 		if (s1->name.is_prefix && s1->name.len != s2->name.len)
    237 			return (s1->name.len > s2->name.len) ? -1 : 1;
    238 	}
    239 
    240 	/* Give precedence to a specified path= over an unspecified path=. */
    241 	if (s1->path.str && !s2->path.str)
    242 		return -1;
    243 	if (!s1->path.str && s2->path.str)
    244 		return 1;
    245 
    246 	if (s1->path.str) {
    247 		/* Give precedence to a fixed path= string over a prefix. */
    248 		if (s1->path.is_prefix != s2->path.is_prefix)
    249 			return (s2->path.is_prefix ? -1 : 1);
    250 
    251 		/* Give precedence to a longer prefix over a shorter prefix. */
    252 		if (s1->path.is_prefix && s1->path.len != s2->path.len)
    253 			return (s1->path.len > s2->path.len) ? -1 : 1;
    254 	}
    255 
    256 	/* Give precedence to a specified isPrivApp= over an unspecified isPrivApp=. */
    257 	if (s1->isPrivAppSet != s2->isPrivAppSet)
    258 		return (s1->isPrivAppSet ? -1 : 1);
    259 
    260 	/* Give precedence to a higher minTargetSdkVersion= over a lower minTargetSdkVersion=.
    261 	 * If unspecified, minTargetSdkVersion has a default value of 0.
    262 	 */
    263 	if (s1->minTargetSdkVersion > s2->minTargetSdkVersion)
    264 		return -1;
    265 	else if (s1->minTargetSdkVersion < s2->minTargetSdkVersion)
    266 		return 1;
    267 
    268 	/*
    269 	 * Check for a duplicated entry on the input selectors.
    270 	 * We already compared isSystemServer, isOwnerSet, and isOwner above.
    271 	 * We also have already checked that both entries specify the same
    272 	 * string fields, so if s1 has a non-NULL string, then so does s2.
    273 	 */
    274 	dup = (!s1->user.str || !strcmp(s1->user.str, s2->user.str)) &&
    275 		(!s1->seinfo || !strcmp(s1->seinfo, s2->seinfo)) &&
    276 		(!s1->name.str || !strcmp(s1->name.str, s2->name.str)) &&
    277 		(!s1->path.str || !strcmp(s1->path.str, s2->path.str)) &&
    278 		(s1->isPrivAppSet && s1->isPrivApp == s2->isPrivApp) &&
    279 		(s1->isOwnerSet && s1->isOwner == s2->isOwner) &&
    280 		(s1->isSystemServer && s1->isSystemServer == s2->isSystemServer) &&
    281 		(s1->isV2AppSet && s1->isV2App == s2->isV2App) &&
    282 		(s1->isEphemeralAppSet && s1->isEphemeralApp == s2->isEphemeralApp);
    283 
    284 	if (dup) {
    285 		seapp_contexts_dup = true;
    286 		selinux_log(SELINUX_ERROR, "seapp_contexts:  Duplicated entry\n");
    287 		if (s1->user.str)
    288 			selinux_log(SELINUX_ERROR, " user=%s\n", s1->user.str);
    289 		if (s1->seinfo)
    290 			selinux_log(SELINUX_ERROR, " seinfo=%s\n", s1->seinfo);
    291 		if (s1->name.str)
    292 			selinux_log(SELINUX_ERROR, " name=%s\n", s1->name.str);
    293 		if (s1->path.str)
    294 			selinux_log(SELINUX_ERROR, " path=%s\n", s1->path.str);
    295 	}
    296 
    297 	/* Anything else has equal precedence. */
    298 	return 0;
    299 }
    300 
    301 static struct seapp_context **seapp_contexts = NULL;
    302 static int nspec = 0;
    303 
    304 static void free_seapp_contexts(void)
    305 {
    306 	int n;
    307 
    308 	if (!seapp_contexts)
    309 		return;
    310 
    311 	for (n = 0; n < nspec; n++)
    312 		free_seapp_context(seapp_contexts[n]);
    313 
    314 	free(seapp_contexts);
    315 	seapp_contexts = NULL;
    316 	nspec = 0;
    317 }
    318 
    319 static int32_t get_minTargetSdkVersion(const char *value)
    320 {
    321 	char *endptr;
    322 	long minTargetSdkVersion;
    323 	minTargetSdkVersion = strtol(value, &endptr, 10);
    324 	if (('\0' != *endptr) || (minTargetSdkVersion < 0) || (minTargetSdkVersion > INT32_MAX)) {
    325 		return -1; /* error parsing minTargetSdkVersion */
    326 	} else {
    327 		return (int32_t) minTargetSdkVersion;
    328 	}
    329 }
    330 
    331 int selinux_android_seapp_context_reload(void)
    332 {
    333 	FILE *fp = NULL;
    334 	char line_buf[BUFSIZ];
    335 	char *token;
    336 	unsigned lineno;
    337 	struct seapp_context *cur;
    338 	char *p, *name = NULL, *value = NULL, *saveptr;
    339 	size_t i, len, files_len;
    340 	int n, ret;
    341 	const char *const *seapp_contexts_files;
    342 
    343 	// Prefer files from /system & /vendor, fall back to files from /
    344 	if (access(seapp_contexts_split[0], R_OK) != -1) {
    345 		seapp_contexts_files = seapp_contexts_split;
    346 		files_len = sizeof(seapp_contexts_split)/sizeof(seapp_contexts_split[0]);
    347 	} else {
    348 		seapp_contexts_files = seapp_contexts_rootfs;
    349 		files_len = sizeof(seapp_contexts_rootfs)/sizeof(seapp_contexts_rootfs[0]);
    350 	}
    351 
    352 	free_seapp_contexts();
    353 
    354 	nspec = 0;
    355 	for (i = 0; i < files_len; i++) {
    356 		fp = fopen(seapp_contexts_files[i], "re");
    357 		if (!fp) {
    358 			selinux_log(SELINUX_ERROR, "%s:  could not open seapp_contexts file: %s",
    359 				    __FUNCTION__, seapp_contexts_files[i]);
    360 			return -1;
    361 		}
    362 		while (fgets(line_buf, sizeof line_buf - 1, fp)) {
    363 			p = line_buf;
    364 			while (isspace(*p))
    365 				p++;
    366 			if (*p == '#' || *p == 0)
    367 				continue;
    368 			nspec++;
    369 		}
    370 		fclose(fp);
    371 	}
    372 
    373 	seapp_contexts = (struct seapp_context **) calloc(nspec, sizeof(struct seapp_context *));
    374 	if (!seapp_contexts)
    375 		goto oom;
    376 
    377 	nspec = 0;
    378 	for (i = 0; i < files_len; i++) {
    379 		lineno = 1;
    380 		fp = fopen(seapp_contexts_files[i], "re");
    381 		if (!fp) {
    382 			selinux_log(SELINUX_ERROR, "%s:  could not open seapp_contexts file: %s",
    383 				    __FUNCTION__, seapp_contexts_files[i]);
    384 			free_seapp_contexts();
    385 			return -1;
    386 		}
    387 		while (fgets(line_buf, sizeof line_buf - 1, fp)) {
    388 			len = strlen(line_buf);
    389 			if (line_buf[len - 1] == '\n')
    390 				line_buf[len - 1] = 0;
    391 			p = line_buf;
    392 			while (isspace(*p))
    393 				p++;
    394 			if (*p == '#' || *p == 0)
    395 				continue;
    396 
    397 			cur = (struct seapp_context *) calloc(1, sizeof(struct seapp_context));
    398 			if (!cur)
    399 				goto oom;
    400 
    401 			token = strtok_r(p, " \t", &saveptr);
    402 			if (!token) {
    403 				free_seapp_context(cur);
    404 				goto err;
    405 			}
    406 
    407 			while (1) {
    408 				name = token;
    409 				value = strchr(name, '=');
    410 				if (!value) {
    411 					free_seapp_context(cur);
    412 					goto err;
    413 				}
    414 				*value++ = 0;
    415 
    416 				if (!strcasecmp(name, "isSystemServer")) {
    417 					if (!strcasecmp(value, "true"))
    418 						cur->isSystemServer = true;
    419 					else if (!strcasecmp(value, "false"))
    420 						cur->isSystemServer = false;
    421 					else {
    422 						free_seapp_context(cur);
    423 						goto err;
    424 					}
    425 				} else if (!strcasecmp(name, "isEphemeralApp")) {
    426 					cur->isEphemeralAppSet = true;
    427 					if (!strcasecmp(value, "true"))
    428 						cur->isEphemeralApp = true;
    429 					else if (!strcasecmp(value, "false"))
    430 						cur->isEphemeralApp = false;
    431 					else {
    432 						free_seapp_context(cur);
    433 						goto err;
    434 					}
    435 				} else if (!strcasecmp(name, "isV2App")) {
    436 					cur->isV2AppSet = true;
    437 					if (!strcasecmp(value, "true"))
    438 						cur->isV2App = true;
    439 					else if (!strcasecmp(value, "false"))
    440 						cur->isV2App = false;
    441 					else {
    442 						free_seapp_context(cur);
    443 						goto err;
    444 					}
    445 				} else if (!strcasecmp(name, "isOwner")) {
    446 					cur->isOwnerSet = true;
    447 					if (!strcasecmp(value, "true"))
    448 						cur->isOwner = true;
    449 					else if (!strcasecmp(value, "false"))
    450 						cur->isOwner = false;
    451 					else {
    452 						free_seapp_context(cur);
    453 						goto err;
    454 					}
    455 				} else if (!strcasecmp(name, "user")) {
    456 					if (cur->user.str) {
    457 						free_seapp_context(cur);
    458 						goto err;
    459 					}
    460 					cur->user.str = strdup(value);
    461 					if (!cur->user.str) {
    462 						free_seapp_context(cur);
    463 						goto oom;
    464 					}
    465 					cur->user.len = strlen(cur->user.str);
    466 					if (cur->user.str[cur->user.len-1] == '*')
    467 						cur->user.is_prefix = 1;
    468 				} else if (!strcasecmp(name, "seinfo")) {
    469 					if (cur->seinfo) {
    470 						free_seapp_context(cur);
    471 						goto err;
    472 					}
    473 					cur->seinfo = strdup(value);
    474 					if (!cur->seinfo) {
    475 						free_seapp_context(cur);
    476 						goto oom;
    477 					}
    478 					if (strstr(value, ":")) {
    479 						free_seapp_context(cur);
    480 						goto err;
    481 					}
    482 				} else if (!strcasecmp(name, "name")) {
    483 					if (cur->name.str) {
    484 						free_seapp_context(cur);
    485 						goto err;
    486 					}
    487 					cur->name.str = strdup(value);
    488 					if (!cur->name.str) {
    489 						free_seapp_context(cur);
    490 						goto oom;
    491 					}
    492 					cur->name.len = strlen(cur->name.str);
    493 					if (cur->name.str[cur->name.len-1] == '*')
    494 						cur->name.is_prefix = 1;
    495 				} else if (!strcasecmp(name, "domain")) {
    496 					if (cur->domain) {
    497 						free_seapp_context(cur);
    498 						goto err;
    499 					}
    500 					cur->domain = strdup(value);
    501 					if (!cur->domain) {
    502 						free_seapp_context(cur);
    503 						goto oom;
    504 					}
    505 				} else if (!strcasecmp(name, "type")) {
    506 					if (cur->type) {
    507 						free_seapp_context(cur);
    508 						goto err;
    509 					}
    510 					cur->type = strdup(value);
    511 					if (!cur->type) {
    512 						free_seapp_context(cur);
    513 						goto oom;
    514 					}
    515 				} else if (!strcasecmp(name, "levelFromUid")) {
    516 					if (cur->levelFrom) {
    517 						free_seapp_context(cur);
    518 						goto err;
    519 					}
    520 					if (!strcasecmp(value, "true"))
    521 						cur->levelFrom = LEVELFROM_APP;
    522 					else if (!strcasecmp(value, "false"))
    523 						cur->levelFrom = LEVELFROM_NONE;
    524 					else {
    525 						free_seapp_context(cur);
    526 						goto err;
    527 					}
    528 				} else if (!strcasecmp(name, "levelFrom")) {
    529 					if (cur->levelFrom) {
    530 						free_seapp_context(cur);
    531 						goto err;
    532 					}
    533 					if (!strcasecmp(value, "none"))
    534 						cur->levelFrom = LEVELFROM_NONE;
    535 					else if (!strcasecmp(value, "app"))
    536 						cur->levelFrom = LEVELFROM_APP;
    537 					else if (!strcasecmp(value, "user"))
    538 						cur->levelFrom = LEVELFROM_USER;
    539 					else if (!strcasecmp(value, "all"))
    540 						cur->levelFrom = LEVELFROM_ALL;
    541 					else {
    542 						free_seapp_context(cur);
    543 						goto err;
    544 					}
    545 				} else if (!strcasecmp(name, "level")) {
    546 					if (cur->level) {
    547 						free_seapp_context(cur);
    548 						goto err;
    549 					}
    550 					cur->level = strdup(value);
    551 					if (!cur->level) {
    552 						free_seapp_context(cur);
    553 						goto oom;
    554 					}
    555 				} else if (!strcasecmp(name, "path")) {
    556 					if (cur->path.str) {
    557 						free_seapp_context(cur);
    558 						goto err;
    559 					}
    560 					cur->path.str = strdup(value);
    561 					if (!cur->path.str) {
    562 						free_seapp_context(cur);
    563 					goto oom;
    564 					}
    565 					cur->path.len = strlen(cur->path.str);
    566 					if (cur->path.str[cur->path.len-1] == '*')
    567 						cur->path.is_prefix = 1;
    568 				} else if (!strcasecmp(name, "isPrivApp")) {
    569 					cur->isPrivAppSet = true;
    570 					if (!strcasecmp(value, "true"))
    571 						cur->isPrivApp = true;
    572 					else if (!strcasecmp(value, "false"))
    573 						cur->isPrivApp = false;
    574 					else {
    575 						free_seapp_context(cur);
    576 						goto err;
    577 					}
    578 				} else if (!strcasecmp(name, "minTargetSdkVersion")) {
    579 					cur->minTargetSdkVersion = get_minTargetSdkVersion(value);
    580 					if (cur->minTargetSdkVersion < 0) {
    581 						free_seapp_context(cur);
    582 						goto err;
    583 					}
    584 				} else {
    585 					free_seapp_context(cur);
    586 					goto err;
    587 				}
    588 
    589 				token = strtok_r(NULL, " \t", &saveptr);
    590 				if (!token)
    591 					break;
    592 			}
    593 
    594 			if (cur->name.str &&
    595 			    (!cur->seinfo || !strcmp(cur->seinfo, "default"))) {
    596 				selinux_log(SELINUX_ERROR, "%s:  No specific seinfo value specified with name=\"%s\", on line %u:  insecure configuration!\n",
    597 					    seapp_contexts_files[i], cur->name.str, lineno);
    598 				free_seapp_context(cur);
    599 				goto err;
    600 			}
    601 
    602 			seapp_contexts[nspec] = cur;
    603 			nspec++;
    604 			lineno++;
    605 		}
    606 		fclose(fp);
    607 		fp = NULL;
    608 	}
    609 
    610 	qsort(seapp_contexts, nspec, sizeof(struct seapp_context *),
    611 	      seapp_context_cmp);
    612 
    613 	if (seapp_contexts_dup)
    614 		goto err_no_log;
    615 
    616 #if DEBUG
    617 	{
    618 		int i;
    619 		for (i = 0; i < nspec; i++) {
    620 			cur = seapp_contexts[i];
    621 			selinux_log(SELINUX_INFO, "%s:  isSystemServer=%s  isEphemeralApp=%s isV2App=%s isOwner=%s user=%s seinfo=%s "
    622 					"name=%s path=%s isPrivApp=%s minTargetSdkVersion=%d -> domain=%s type=%s level=%s levelFrom=%s",
    623 				__FUNCTION__,
    624 				cur->isSystemServer ? "true" : "false",
    625 				cur->isEphemeralAppSet ? (cur->isEphemeralApp ? "true" : "false") : "null",
    626 				cur->isV2AppSet ? (cur->isV2App ? "true" : "false") : "null",
    627 				cur->isOwnerSet ? (cur->isOwner ? "true" : "false") : "null",
    628 				cur->user.str,
    629 				cur->seinfo, cur->name.str, cur->path.str,
    630 				cur->isPrivAppSet ? (cur->isPrivApp ? "true" : "false") : "null",
    631 				cur->minTargetSdkVersion,
    632 				cur->domain, cur->type, cur->level,
    633 				levelFromName[cur->levelFrom]);
    634 		}
    635 	}
    636 #endif
    637 
    638 	ret = 0;
    639 
    640 out:
    641 	if (fp) {
    642 		fclose(fp);
    643 	}
    644 	return ret;
    645 
    646 err:
    647 	selinux_log(SELINUX_ERROR, "%s:  Invalid entry on line %u\n",
    648 		    seapp_contexts_files[i], lineno);
    649 err_no_log:
    650 	free_seapp_contexts();
    651 	ret = -1;
    652 	goto out;
    653 oom:
    654 	selinux_log(SELINUX_ERROR,
    655 		    "%s:  Out of memory\n", __FUNCTION__);
    656 	free_seapp_contexts();
    657 	ret = -1;
    658 	goto out;
    659 }
    660 
    661 
    662 static void seapp_context_init(void)
    663 {
    664         selinux_android_seapp_context_reload();
    665 }
    666 
    667 static pthread_once_t once = PTHREAD_ONCE_INIT;
    668 
    669 /*
    670  * Max id that can be mapped to category set uniquely
    671  * using the current scheme.
    672  */
    673 #define CAT_MAPPING_MAX_ID (0x1<<16)
    674 
    675 enum seapp_kind {
    676 	SEAPP_TYPE,
    677 	SEAPP_DOMAIN
    678 };
    679 
    680 #define PRIVILEGED_APP_STR ":privapp"
    681 #define EPHEMERAL_APP_STR ":ephemeralapp"
    682 #define V2_APP_STR ":v2"
    683 #define TARGETSDKVERSION_STR ":targetSdkVersion="
    684 static int32_t get_app_targetSdkVersion(const char *seinfo)
    685 {
    686 	char *substr = strstr(seinfo, TARGETSDKVERSION_STR);
    687 	long targetSdkVersion;
    688 	char *endptr;
    689 	if (substr != NULL) {
    690 		substr = substr + strlen(TARGETSDKVERSION_STR);
    691 		if (substr != NULL) {
    692 			targetSdkVersion = strtol(substr, &endptr, 10);
    693 			if (('\0' != *endptr && ':' != *endptr)
    694 					|| (targetSdkVersion < 0) || (targetSdkVersion > INT32_MAX)) {
    695 				return -1; /* malformed targetSdkVersion value in seinfo */
    696 			} else {
    697 				return (int32_t) targetSdkVersion;
    698 			}
    699 		}
    700 	}
    701 	return 0; /* default to 0 when targetSdkVersion= is not present in seinfo */
    702 }
    703 
    704 static int seinfo_parse(char *dest, const char *src, size_t size)
    705 {
    706 	size_t len;
    707 	char *p;
    708 
    709 	if ((p = strchr(src, ':')) != NULL)
    710 		len = p - src;
    711 	else
    712 		len = strlen(src);
    713 
    714 	if (len > size - 1)
    715 		return -1;
    716 
    717 	strncpy(dest, src, len);
    718 	dest[len] = '\0';
    719 
    720 	return 0;
    721 }
    722 
    723 static int seapp_context_lookup(enum seapp_kind kind,
    724 				uid_t uid,
    725 				bool isSystemServer,
    726 				const char *seinfo,
    727 				const char *pkgname,
    728 				const char *path,
    729 				context_t ctx)
    730 {
    731 	struct passwd *pwd;
    732 	bool isOwner;
    733 	const char *username = NULL;
    734 	struct seapp_context *cur = NULL;
    735 	int i;
    736 	size_t n;
    737 	uid_t userid;
    738 	uid_t appid;
    739 	bool isPrivApp = false;
    740 	bool isEphemeralApp = false;
    741 	int32_t targetSdkVersion = 0;
    742 	bool isV2App = false;
    743 	char parsedseinfo[BUFSIZ];
    744 
    745 	__selinux_once(once, seapp_context_init);
    746 
    747 	if (seinfo) {
    748 		if (seinfo_parse(parsedseinfo, seinfo, BUFSIZ))
    749 			goto err;
    750 		isPrivApp = strstr(seinfo, PRIVILEGED_APP_STR) ? true : false;
    751 		isEphemeralApp = strstr(seinfo, EPHEMERAL_APP_STR) ? true : false;
    752 		isV2App = strstr(seinfo, V2_APP_STR) ? true : false;
    753 		targetSdkVersion = get_app_targetSdkVersion(seinfo);
    754 		if (targetSdkVersion < 0) {
    755 			selinux_log(SELINUX_ERROR,
    756 					"%s:  Invalid targetSdkVersion passed for app with uid %d, seinfo %s, name %s\n",
    757 					__FUNCTION__, uid, seinfo, pkgname);
    758 			goto err;
    759 		}
    760 		seinfo = parsedseinfo;
    761 	}
    762 
    763 	userid = uid / AID_USER;
    764 	isOwner = (userid == 0);
    765 	appid = uid % AID_USER;
    766 	if (appid < AID_APP) {
    767             /*
    768              * This code is Android specific, bionic guarantees that
    769              * calls to non-reentrant getpwuid() are thread safe.
    770              */
    771 #ifndef __BIONIC__
    772 #warning "This code assumes that getpwuid is thread safe, only true with Bionic!"
    773 #endif
    774 		pwd = getpwuid(appid);
    775 		if (!pwd)
    776 			goto err;
    777 
    778 		username = pwd->pw_name;
    779 
    780 	} else if (appid < AID_ISOLATED_START) {
    781 		username = "_app";
    782 		appid -= AID_APP;
    783 	} else {
    784 		username = "_isolated";
    785 		appid -= AID_ISOLATED_START;
    786 	}
    787 
    788 	if (appid >= CAT_MAPPING_MAX_ID || userid >= CAT_MAPPING_MAX_ID)
    789 		goto err;
    790 
    791 	for (i = 0; i < nspec; i++) {
    792 		cur = seapp_contexts[i];
    793 
    794 		if (cur->isSystemServer != isSystemServer)
    795 			continue;
    796 
    797 		if (cur->isEphemeralAppSet && cur->isEphemeralApp != isEphemeralApp)
    798 			continue;
    799 
    800 		if (cur->isV2AppSet && cur->isV2App != isV2App)
    801 			continue;
    802 
    803 		if (cur->isOwnerSet && cur->isOwner != isOwner)
    804 			continue;
    805 
    806 		if (cur->user.str) {
    807 			if (cur->user.is_prefix) {
    808 				if (strncasecmp(username, cur->user.str, cur->user.len-1))
    809 					continue;
    810 			} else {
    811 				if (strcasecmp(username, cur->user.str))
    812 					continue;
    813 			}
    814 		}
    815 
    816 		if (cur->seinfo) {
    817 			if (!seinfo || strcasecmp(seinfo, cur->seinfo))
    818 				continue;
    819 		}
    820 
    821 		if (cur->name.str) {
    822 			if(!pkgname)
    823 				continue;
    824 
    825 			if (cur->name.is_prefix) {
    826 				if (strncasecmp(pkgname, cur->name.str, cur->name.len-1))
    827 					continue;
    828 			} else {
    829 				if (strcasecmp(pkgname, cur->name.str))
    830 					continue;
    831 			}
    832 		}
    833 
    834 		if (cur->isPrivAppSet && cur->isPrivApp != isPrivApp)
    835 			continue;
    836 
    837 		if (cur->minTargetSdkVersion > targetSdkVersion)
    838 			continue;
    839 
    840 		if (cur->path.str) {
    841 			if (!path)
    842 				continue;
    843 
    844 			if (cur->path.is_prefix) {
    845 				if (strncmp(path, cur->path.str, cur->path.len-1))
    846 					continue;
    847 			} else {
    848 				if (strcmp(path, cur->path.str))
    849 					continue;
    850 			}
    851 		}
    852 
    853 		if (kind == SEAPP_TYPE && !cur->type)
    854 			continue;
    855 		else if (kind == SEAPP_DOMAIN && !cur->domain)
    856 			continue;
    857 
    858 		if (kind == SEAPP_TYPE) {
    859 			if (context_type_set(ctx, cur->type))
    860 				goto oom;
    861 		} else if (kind == SEAPP_DOMAIN) {
    862 			if (context_type_set(ctx, cur->domain))
    863 				goto oom;
    864 		}
    865 
    866 		if (cur->levelFrom != LEVELFROM_NONE) {
    867 			char level[255];
    868 			switch (cur->levelFrom) {
    869 			case LEVELFROM_APP:
    870 				snprintf(level, sizeof level, "s0:c%u,c%u",
    871 					 appid & 0xff,
    872 					 256 + (appid>>8 & 0xff));
    873 				break;
    874 			case LEVELFROM_USER:
    875 				snprintf(level, sizeof level, "s0:c%u,c%u",
    876 					 512 + (userid & 0xff),
    877 					 768 + (userid>>8 & 0xff));
    878 				break;
    879 			case LEVELFROM_ALL:
    880 				snprintf(level, sizeof level, "s0:c%u,c%u,c%u,c%u",
    881 					 appid & 0xff,
    882 					 256 + (appid>>8 & 0xff),
    883 					 512 + (userid & 0xff),
    884 					 768 + (userid>>8 & 0xff));
    885 				break;
    886 			default:
    887 				goto err;
    888 			}
    889 			if (context_range_set(ctx, level))
    890 				goto oom;
    891 		} else if (cur->level) {
    892 			if (context_range_set(ctx, cur->level))
    893 				goto oom;
    894 		}
    895 
    896 		break;
    897 	}
    898 
    899 	if (kind == SEAPP_DOMAIN && i == nspec) {
    900 		/*
    901 		 * No match.
    902 		 * Fail to prevent staying in the zygote's context.
    903 		 */
    904 		selinux_log(SELINUX_ERROR,
    905 			    "%s:  No match for app with uid %d, seinfo %s, name %s\n",
    906 			    __FUNCTION__, uid, seinfo, pkgname);
    907 
    908 		if (security_getenforce() == 1)
    909 			goto err;
    910 	}
    911 
    912 	return 0;
    913 err:
    914 	return -1;
    915 oom:
    916 	return -2;
    917 }
    918 
    919 int selinux_android_setfilecon(const char *pkgdir,
    920 				const char *pkgname,
    921 				const char *seinfo,
    922 				uid_t uid)
    923 {
    924 	char *orig_ctx_str = NULL;
    925 	char *ctx_str = NULL;
    926 	context_t ctx = NULL;
    927 	int rc = -1;
    928 
    929 	if (is_selinux_enabled() <= 0)
    930 		return 0;
    931 
    932 	rc = getfilecon(pkgdir, &ctx_str);
    933 	if (rc < 0)
    934 		goto err;
    935 
    936 	ctx = context_new(ctx_str);
    937 	orig_ctx_str = ctx_str;
    938 	if (!ctx)
    939 		goto oom;
    940 
    941 	rc = seapp_context_lookup(SEAPP_TYPE, uid, 0, seinfo, pkgname, NULL, ctx);
    942 	if (rc == -1)
    943 		goto err;
    944 	else if (rc == -2)
    945 		goto oom;
    946 
    947 	ctx_str = context_str(ctx);
    948 	if (!ctx_str)
    949 		goto oom;
    950 
    951 	rc = security_check_context(ctx_str);
    952 	if (rc < 0)
    953 		goto err;
    954 
    955 	if (strcmp(ctx_str, orig_ctx_str)) {
    956 		rc = setfilecon(pkgdir, ctx_str);
    957 		if (rc < 0)
    958 			goto err;
    959 	}
    960 
    961 	rc = 0;
    962 out:
    963 	freecon(orig_ctx_str);
    964 	context_free(ctx);
    965 	return rc;
    966 err:
    967 	selinux_log(SELINUX_ERROR, "%s:  Error setting context for pkgdir %s, uid %d: %s\n",
    968 		    __FUNCTION__, pkgdir, uid, strerror(errno));
    969 	rc = -1;
    970 	goto out;
    971 oom:
    972 	selinux_log(SELINUX_ERROR, "%s:  Out of memory\n", __FUNCTION__);
    973 	rc = -1;
    974 	goto out;
    975 }
    976 
    977 int selinux_android_setcon(const char *con)
    978 {
    979 	int ret = setcon(con);
    980 	if (ret)
    981 		return ret;
    982 	/*
    983 	  System properties must be reinitialized after setcon() otherwise the
    984 	  previous property files will be leaked since mmap()'ed regions are not
    985 	  closed as a result of setcon().
    986 	*/
    987 	return __system_properties_init();
    988 }
    989 
    990 int selinux_android_setcontext(uid_t uid,
    991 			       bool isSystemServer,
    992 			       const char *seinfo,
    993 			       const char *pkgname)
    994 {
    995 	char *orig_ctx_str = NULL, *ctx_str;
    996 	context_t ctx = NULL;
    997 	int rc = -1;
    998 
    999 	if (is_selinux_enabled() <= 0)
   1000 		return 0;
   1001 
   1002 	rc = getcon(&ctx_str);
   1003 	if (rc)
   1004 		goto err;
   1005 
   1006 	ctx = context_new(ctx_str);
   1007 	orig_ctx_str = ctx_str;
   1008 	if (!ctx)
   1009 		goto oom;
   1010 
   1011 	rc = seapp_context_lookup(SEAPP_DOMAIN, uid, isSystemServer, seinfo, pkgname, NULL, ctx);
   1012 	if (rc == -1)
   1013 		goto err;
   1014 	else if (rc == -2)
   1015 		goto oom;
   1016 
   1017 	ctx_str = context_str(ctx);
   1018 	if (!ctx_str)
   1019 		goto oom;
   1020 
   1021 	rc = security_check_context(ctx_str);
   1022 	if (rc < 0)
   1023 		goto err;
   1024 
   1025 	if (strcmp(ctx_str, orig_ctx_str)) {
   1026 		rc = selinux_android_setcon(ctx_str);
   1027 		if (rc < 0)
   1028 			goto err;
   1029 	}
   1030 
   1031 	rc = 0;
   1032 out:
   1033 	freecon(orig_ctx_str);
   1034 	context_free(ctx);
   1035 	avc_netlink_close();
   1036 	return rc;
   1037 err:
   1038 	if (isSystemServer)
   1039 		selinux_log(SELINUX_ERROR,
   1040 				"%s:  Error setting context for system server: %s\n",
   1041 				__FUNCTION__, strerror(errno));
   1042 	else
   1043 		selinux_log(SELINUX_ERROR,
   1044 				"%s:  Error setting context for app with uid %d, seinfo %s: %s\n",
   1045 				__FUNCTION__, uid, seinfo, strerror(errno));
   1046 
   1047 	rc = -1;
   1048 	goto out;
   1049 oom:
   1050 	selinux_log(SELINUX_ERROR, "%s:  Out of memory\n", __FUNCTION__);
   1051 	rc = -1;
   1052 	goto out;
   1053 }
   1054 
   1055 static struct selabel_handle *fc_sehandle = NULL;
   1056 #define FC_DIGEST_SIZE SHA_DIGEST_LENGTH
   1057 static uint8_t fc_digest[FC_DIGEST_SIZE];
   1058 
   1059 static bool compute_file_contexts_hash(uint8_t c_digest[], const struct selinux_opt *opts, unsigned nopts)
   1060 {
   1061     int fd = -1;
   1062     void *map = MAP_FAILED;
   1063     bool ret = false;
   1064     uint8_t *fc_data = NULL;
   1065     size_t total_size = 0;
   1066     struct stat sb;
   1067     size_t i;
   1068 
   1069     for (i = 0; i < nopts; i++) {
   1070         fd = open(opts[i].value, O_CLOEXEC | O_RDONLY);
   1071         if (fd < 0) {
   1072             selinux_log(SELINUX_ERROR, "SELinux:  Could not open %s:  %s\n",
   1073                     opts[i].value, strerror(errno));
   1074             goto cleanup;
   1075         }
   1076 
   1077         if (fstat(fd, &sb) < 0) {
   1078             selinux_log(SELINUX_ERROR, "SELinux:  Could not stat %s:  %s\n",
   1079                     opts[i].value, strerror(errno));
   1080             goto cleanup;
   1081         }
   1082 
   1083         map = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
   1084         if (map == MAP_FAILED) {
   1085             selinux_log(SELINUX_ERROR, "SELinux:  Could not map %s:  %s\n",
   1086                     opts[i].value, strerror(errno));
   1087             goto cleanup;
   1088         }
   1089 
   1090         fc_data = realloc(fc_data, total_size + sb.st_size);
   1091         if (!fc_data) {
   1092             selinux_log(SELINUX_ERROR, "SELinux: Count not re-alloc for %s:  %s\n",
   1093                      opts[i].value, strerror(errno));
   1094             goto cleanup;
   1095         }
   1096 
   1097         memcpy(fc_data + total_size, map, sb.st_size);
   1098         total_size += sb.st_size;
   1099 
   1100         /* reset everything for next file */
   1101         munmap(map, sb.st_size);
   1102         close(fd);
   1103         map = MAP_FAILED;
   1104         fd = -1;
   1105     }
   1106 
   1107     SHA1(fc_data, total_size, c_digest);
   1108     ret = true;
   1109 
   1110 cleanup:
   1111     if (map != MAP_FAILED)
   1112         munmap(map, sb.st_size);
   1113     if (fd >= 0)
   1114         close(fd);
   1115     free(fc_data);
   1116 
   1117     return ret;
   1118 }
   1119 
   1120 static void file_context_init(void)
   1121 {
   1122     if (!fc_sehandle)
   1123         fc_sehandle = selinux_android_file_context_handle();
   1124 }
   1125 
   1126 
   1127 
   1128 static pthread_once_t fc_once = PTHREAD_ONCE_INIT;
   1129 
   1130 #define PKGTAB_SIZE 256
   1131 static struct pkg_info *pkgTab[PKGTAB_SIZE];
   1132 
   1133 static unsigned int pkghash(const char *pkgname)
   1134 {
   1135     unsigned int h = 7;
   1136     for (; *pkgname; pkgname++) {
   1137         h = h * 31 + *pkgname;
   1138     }
   1139     return h & (PKGTAB_SIZE - 1);
   1140 }
   1141 
   1142 static bool pkg_parse_callback(pkg_info *info, void *userdata) {
   1143 
   1144     (void) userdata;
   1145 
   1146     unsigned int hash = pkghash(info->name);
   1147     if (pkgTab[hash])
   1148         info->private_data = pkgTab[hash];
   1149     pkgTab[hash] = info;
   1150     return true;
   1151 }
   1152 
   1153 static void package_info_init(void)
   1154 {
   1155 
   1156     bool rc = packagelist_parse(pkg_parse_callback, NULL);
   1157     if (!rc) {
   1158         selinux_log(SELINUX_ERROR, "SELinux: Could NOT parse package list\n");
   1159         return;
   1160     }
   1161 
   1162 #if DEBUG
   1163     {
   1164         unsigned int hash, buckets, entries, chainlen, longestchain;
   1165         struct pkg_info *info = NULL;
   1166 
   1167         buckets = entries = longestchain = 0;
   1168         for (hash = 0; hash < PKGTAB_SIZE; hash++) {
   1169             if (pkgTab[hash]) {
   1170                 buckets++;
   1171                 chainlen = 0;
   1172                 for (info = pkgTab[hash]; info; info = (pkg_info *)info->private_data) {
   1173                     chainlen++;
   1174                     selinux_log(SELINUX_INFO, "%s:  name=%s uid=%u debuggable=%s dataDir=%s seinfo=%s\n",
   1175                                 __FUNCTION__,
   1176                                 info->name, info->uid, info->debuggable ? "true" : "false", info->data_dir, info->seinfo);
   1177                 }
   1178                 entries += chainlen;
   1179                 if (longestchain < chainlen)
   1180                     longestchain = chainlen;
   1181             }
   1182         }
   1183         selinux_log(SELINUX_INFO, "SELinux:  %d pkg entries and %d/%d buckets used, longest chain %d\n", entries, buckets, PKGTAB_SIZE, longestchain);
   1184     }
   1185 #endif
   1186 
   1187 }
   1188 
   1189 static pthread_once_t pkg_once = PTHREAD_ONCE_INIT;
   1190 
   1191 struct pkg_info *package_info_lookup(const char *name)
   1192 {
   1193     struct pkg_info *info;
   1194     unsigned int hash;
   1195 
   1196     __selinux_once(pkg_once, package_info_init);
   1197 
   1198     hash = pkghash(name);
   1199     for (info = pkgTab[hash]; info; info = (pkg_info *)info->private_data) {
   1200         if (!strcmp(name, info->name))
   1201             return info;
   1202     }
   1203     return NULL;
   1204 }
   1205 
   1206 /* The contents of these paths are encrypted on FBE devices until user
   1207  * credentials are presented (filenames inside are mangled), so we need
   1208  * to delay restorecon of those until vold explicitly requests it. */
   1209 // NOTE: these paths need to be kept in sync with vold
   1210 #define DATA_SYSTEM_CE_PREFIX "/data/system_ce/"
   1211 #define DATA_MISC_CE_PREFIX "/data/misc_ce/"
   1212 
   1213 /* The path prefixes of package data directories. */
   1214 #define DATA_DATA_PATH "/data/data"
   1215 #define DATA_USER_PATH "/data/user"
   1216 #define DATA_USER_DE_PATH "/data/user_de"
   1217 #define EXPAND_USER_PATH "/mnt/expand/\?\?\?\?\?\?\?\?-\?\?\?\?-\?\?\?\?-\?\?\?\?-\?\?\?\?\?\?\?\?\?\?\?\?/user"
   1218 #define EXPAND_USER_DE_PATH "/mnt/expand/\?\?\?\?\?\?\?\?-\?\?\?\?-\?\?\?\?-\?\?\?\?-\?\?\?\?\?\?\?\?\?\?\?\?/user_de"
   1219 #define DATA_DATA_PREFIX DATA_DATA_PATH "/"
   1220 #define DATA_USER_PREFIX DATA_USER_PATH "/"
   1221 #define DATA_USER_DE_PREFIX DATA_USER_DE_PATH "/"
   1222 
   1223 static int pkgdir_selabel_lookup(const char *pathname,
   1224                                  const char *seinfo,
   1225                                  uid_t uid,
   1226                                  char **secontextp)
   1227 {
   1228     char *pkgname = NULL, *end = NULL;
   1229     struct pkg_info *info = NULL;
   1230     char *secontext = *secontextp;
   1231     context_t ctx = NULL;
   1232     int rc = 0;
   1233 
   1234     /* Skip directory prefix before package name. */
   1235     if (!strncmp(pathname, DATA_DATA_PREFIX, sizeof(DATA_DATA_PREFIX)-1)) {
   1236         pathname += sizeof(DATA_DATA_PREFIX) - 1;
   1237     } else if (!strncmp(pathname, DATA_USER_PREFIX, sizeof(DATA_USER_PREFIX)-1)) {
   1238         pathname += sizeof(DATA_USER_PREFIX) - 1;
   1239         while (isdigit(*pathname))
   1240             pathname++;
   1241         if (*pathname == '/')
   1242             pathname++;
   1243         else
   1244             return 0;
   1245     } else if (!strncmp(pathname, DATA_USER_DE_PREFIX, sizeof(DATA_USER_DE_PREFIX)-1)) {
   1246         pathname += sizeof(DATA_USER_DE_PREFIX) - 1;
   1247         while (isdigit(*pathname))
   1248             pathname++;
   1249         if (*pathname == '/')
   1250             pathname++;
   1251         else
   1252             return 0;
   1253     } else if (!fnmatch(EXPAND_USER_PATH, pathname, FNM_LEADING_DIR|FNM_PATHNAME)) {
   1254         pathname += sizeof(EXPAND_USER_PATH);
   1255         while (isdigit(*pathname))
   1256             pathname++;
   1257         if (*pathname == '/')
   1258             pathname++;
   1259         else
   1260             return 0;
   1261     } else if (!fnmatch(EXPAND_USER_DE_PATH, pathname, FNM_LEADING_DIR|FNM_PATHNAME)) {
   1262         pathname += sizeof(EXPAND_USER_DE_PATH);
   1263         while (isdigit(*pathname))
   1264             pathname++;
   1265         if (*pathname == '/')
   1266             pathname++;
   1267         else
   1268             return 0;
   1269     } else
   1270         return 0;
   1271 
   1272     if (!(*pathname))
   1273         return 0;
   1274 
   1275     pkgname = strdup(pathname);
   1276     if (!pkgname)
   1277         return -1;
   1278 
   1279     for (end = pkgname; *end && *end != '/'; end++)
   1280         ;
   1281     pathname = end;
   1282     if (*end)
   1283         pathname++;
   1284     *end = '\0';
   1285 
   1286     if (!seinfo) {
   1287         info = package_info_lookup(pkgname);
   1288         if (!info) {
   1289             selinux_log(SELINUX_WARNING, "SELinux:  Could not look up information for package %s, cannot restorecon %s.\n",
   1290                         pkgname, pathname);
   1291             free(pkgname);
   1292             return -1;
   1293         }
   1294     }
   1295 
   1296     ctx = context_new(secontext);
   1297     if (!ctx)
   1298         goto err;
   1299 
   1300     rc = seapp_context_lookup(SEAPP_TYPE, info ? info->uid : uid, 0,
   1301                               info ? info->seinfo : seinfo, info ? info->name : pkgname, pathname, ctx);
   1302     if (rc < 0)
   1303         goto err;
   1304 
   1305     secontext = context_str(ctx);
   1306     if (!secontext)
   1307         goto err;
   1308 
   1309     if (!strcmp(secontext, *secontextp))
   1310         goto out;
   1311 
   1312     rc = security_check_context(secontext);
   1313     if (rc < 0)
   1314         goto err;
   1315 
   1316     freecon(*secontextp);
   1317     *secontextp = strdup(secontext);
   1318     if (!(*secontextp))
   1319         goto err;
   1320 
   1321     rc = 0;
   1322 
   1323 out:
   1324     free(pkgname);
   1325     context_free(ctx);
   1326     return rc;
   1327 err:
   1328     selinux_log(SELINUX_ERROR, "%s:  Error looking up context for path %s, pkgname %s, seinfo %s, uid %u: %s\n",
   1329                 __FUNCTION__, pathname, pkgname, info->seinfo, info->uid, strerror(errno));
   1330     rc = -1;
   1331     goto out;
   1332 }
   1333 
   1334 #define RESTORECON_LAST "security.restorecon_last"
   1335 
   1336 static int restorecon_sb(const char *pathname, const struct stat *sb,
   1337                          bool nochange, bool verbose,
   1338                          const char *seinfo, uid_t uid)
   1339 {
   1340     char *secontext = NULL;
   1341     char *oldsecontext = NULL;
   1342     int rc = 0;
   1343 
   1344     if (selabel_lookup(fc_sehandle, &secontext, pathname, sb->st_mode) < 0)
   1345         return 0;  /* no match, but not an error */
   1346 
   1347     if (lgetfilecon(pathname, &oldsecontext) < 0)
   1348         goto err;
   1349 
   1350     /*
   1351      * For subdirectories of /data/data or /data/user, we ignore selabel_lookup()
   1352      * and use pkgdir_selabel_lookup() instead. Files within those directories
   1353      * have different labeling rules, based off of /seapp_contexts, and
   1354      * installd is responsible for managing these labels instead of init.
   1355      */
   1356     if (!strncmp(pathname, DATA_DATA_PREFIX, sizeof(DATA_DATA_PREFIX)-1) ||
   1357         !strncmp(pathname, DATA_USER_PREFIX, sizeof(DATA_USER_PREFIX)-1) ||
   1358         !strncmp(pathname, DATA_USER_DE_PREFIX, sizeof(DATA_USER_DE_PREFIX)-1) ||
   1359         !fnmatch(EXPAND_USER_PATH, pathname, FNM_LEADING_DIR|FNM_PATHNAME) ||
   1360         !fnmatch(EXPAND_USER_DE_PATH, pathname, FNM_LEADING_DIR|FNM_PATHNAME)) {
   1361         if (pkgdir_selabel_lookup(pathname, seinfo, uid, &secontext) < 0)
   1362             goto err;
   1363     }
   1364 
   1365     if (strcmp(oldsecontext, secontext) != 0) {
   1366         if (verbose)
   1367             selinux_log(SELINUX_INFO,
   1368                         "SELinux:  Relabeling %s from %s to %s.\n", pathname, oldsecontext, secontext);
   1369         if (!nochange) {
   1370             if (lsetfilecon(pathname, secontext) < 0)
   1371                 goto err;
   1372         }
   1373     }
   1374 
   1375     rc = 0;
   1376 
   1377 out:
   1378     freecon(oldsecontext);
   1379     freecon(secontext);
   1380     return rc;
   1381 
   1382 err:
   1383     selinux_log(SELINUX_ERROR,
   1384                 "SELinux: Could not set context for %s:  %s\n",
   1385                 pathname, strerror(errno));
   1386     rc = -1;
   1387     goto out;
   1388 }
   1389 
   1390 #define SYS_PATH "/sys"
   1391 #define SYS_PREFIX SYS_PATH "/"
   1392 
   1393 static int selinux_android_restorecon_common(const char* pathname_orig,
   1394                                              const char *seinfo,
   1395                                              uid_t uid,
   1396                                              unsigned int flags)
   1397 {
   1398     bool nochange = (flags & SELINUX_ANDROID_RESTORECON_NOCHANGE) ? true : false;
   1399     bool verbose = (flags & SELINUX_ANDROID_RESTORECON_VERBOSE) ? true : false;
   1400     bool recurse = (flags & SELINUX_ANDROID_RESTORECON_RECURSE) ? true : false;
   1401     bool force = (flags & SELINUX_ANDROID_RESTORECON_FORCE) ? true : false;
   1402     bool datadata = (flags & SELINUX_ANDROID_RESTORECON_DATADATA) ? true : false;
   1403     bool skipce = (flags & SELINUX_ANDROID_RESTORECON_SKIPCE) ? true : false;
   1404     bool cross_filesystems = (flags & SELINUX_ANDROID_RESTORECON_CROSS_FILESYSTEMS) ? true : false;
   1405     bool issys;
   1406     bool setrestoreconlast = true;
   1407     struct stat sb;
   1408     struct statfs sfsb;
   1409     FTS *fts;
   1410     FTSENT *ftsent;
   1411     char *pathname = NULL, *pathdnamer = NULL, *pathdname, *pathbname;
   1412     char * paths[2] = { NULL , NULL };
   1413     int ftsflags = FTS_NOCHDIR | FTS_PHYSICAL;
   1414     int error, sverrno;
   1415     char xattr_value[FC_DIGEST_SIZE];
   1416     ssize_t size;
   1417 
   1418     if (!cross_filesystems) {
   1419         ftsflags |= FTS_XDEV;
   1420     }
   1421 
   1422     if (is_selinux_enabled() <= 0)
   1423         return 0;
   1424 
   1425     __selinux_once(fc_once, file_context_init);
   1426 
   1427     if (!fc_sehandle)
   1428         return 0;
   1429 
   1430     /*
   1431      * Convert passed-in pathname to canonical pathname by resolving realpath of
   1432      * containing dir, then appending last component name.
   1433      */
   1434     pathbname = basename(pathname_orig);
   1435     if (!strcmp(pathbname, "/") || !strcmp(pathbname, ".") || !strcmp(pathbname, "..")) {
   1436         pathname = realpath(pathname_orig, NULL);
   1437         if (!pathname)
   1438             goto realpatherr;
   1439     } else {
   1440         pathdname = dirname(pathname_orig);
   1441         pathdnamer = realpath(pathdname, NULL);
   1442         if (!pathdnamer)
   1443             goto realpatherr;
   1444         if (!strcmp(pathdnamer, "/"))
   1445             error = asprintf(&pathname, "/%s", pathbname);
   1446         else
   1447             error = asprintf(&pathname, "%s/%s", pathdnamer, pathbname);
   1448         if (error < 0)
   1449             goto oom;
   1450     }
   1451 
   1452     paths[0] = pathname;
   1453     issys = (!strcmp(pathname, SYS_PATH)
   1454             || !strncmp(pathname, SYS_PREFIX, sizeof(SYS_PREFIX)-1)) ? true : false;
   1455 
   1456     if (!recurse) {
   1457         if (lstat(pathname, &sb) < 0) {
   1458             error = -1;
   1459             goto cleanup;
   1460         }
   1461 
   1462         error = restorecon_sb(pathname, &sb, nochange, verbose, seinfo, uid);
   1463         goto cleanup;
   1464     }
   1465 
   1466     /*
   1467      * Ignore restorecon_last on /data/data or /data/user
   1468      * since their labeling is based on seapp_contexts and seinfo
   1469      * assignments rather than file_contexts and is managed by
   1470      * installd rather than init.
   1471      */
   1472     if (!strncmp(pathname, DATA_DATA_PREFIX, sizeof(DATA_DATA_PREFIX)-1) ||
   1473         !strncmp(pathname, DATA_USER_PREFIX, sizeof(DATA_USER_PREFIX)-1) ||
   1474         !strncmp(pathname, DATA_USER_DE_PREFIX, sizeof(DATA_USER_DE_PREFIX)-1) ||
   1475         !fnmatch(EXPAND_USER_PATH, pathname, FNM_LEADING_DIR|FNM_PATHNAME) ||
   1476         !fnmatch(EXPAND_USER_DE_PATH, pathname, FNM_LEADING_DIR|FNM_PATHNAME))
   1477         setrestoreconlast = false;
   1478 
   1479     /* Also ignore on /sys since it is regenerated on each boot regardless. */
   1480     if (issys)
   1481         setrestoreconlast = false;
   1482 
   1483     /* Ignore files on in-memory filesystems */
   1484     if (statfs(pathname, &sfsb) == 0) {
   1485         if (sfsb.f_type == RAMFS_MAGIC || sfsb.f_type == TMPFS_MAGIC)
   1486             setrestoreconlast = false;
   1487     }
   1488 
   1489     if (setrestoreconlast) {
   1490         size = getxattr(pathname, RESTORECON_LAST, xattr_value, sizeof fc_digest);
   1491         if (!force && size == sizeof fc_digest && memcmp(fc_digest, xattr_value, sizeof fc_digest) == 0) {
   1492             selinux_log(SELINUX_INFO,
   1493                         "SELinux: Skipping restorecon_recursive(%s)\n",
   1494                         pathname);
   1495             error = 0;
   1496             goto cleanup;
   1497         }
   1498     }
   1499 
   1500     fts = fts_open(paths, ftsflags, NULL);
   1501     if (!fts) {
   1502         error = -1;
   1503         goto cleanup;
   1504     }
   1505 
   1506     error = 0;
   1507     while ((ftsent = fts_read(fts)) != NULL) {
   1508         switch (ftsent->fts_info) {
   1509         case FTS_DC:
   1510             selinux_log(SELINUX_ERROR,
   1511                         "SELinux:  Directory cycle on %s.\n", ftsent->fts_path);
   1512             errno = ELOOP;
   1513             error = -1;
   1514             goto out;
   1515         case FTS_DP:
   1516             continue;
   1517         case FTS_DNR:
   1518             selinux_log(SELINUX_ERROR,
   1519                         "SELinux:  Could not read %s: %s.\n", ftsent->fts_path, strerror(errno));
   1520             fts_set(fts, ftsent, FTS_SKIP);
   1521             continue;
   1522         case FTS_NS:
   1523             selinux_log(SELINUX_ERROR,
   1524                         "SELinux:  Could not stat %s: %s.\n", ftsent->fts_path, strerror(errno));
   1525             fts_set(fts, ftsent, FTS_SKIP);
   1526             continue;
   1527         case FTS_ERR:
   1528             selinux_log(SELINUX_ERROR,
   1529                         "SELinux:  Error on %s: %s.\n", ftsent->fts_path, strerror(errno));
   1530             fts_set(fts, ftsent, FTS_SKIP);
   1531             continue;
   1532         case FTS_D:
   1533             if (issys && !selabel_partial_match(fc_sehandle, ftsent->fts_path)) {
   1534                 fts_set(fts, ftsent, FTS_SKIP);
   1535                 continue;
   1536             }
   1537 
   1538             if (skipce &&
   1539                 (!strncmp(ftsent->fts_path, DATA_SYSTEM_CE_PREFIX, sizeof(DATA_SYSTEM_CE_PREFIX)-1) ||
   1540                  !strncmp(ftsent->fts_path, DATA_MISC_CE_PREFIX, sizeof(DATA_MISC_CE_PREFIX)-1))) {
   1541                 // Don't label anything below this directory.
   1542                 fts_set(fts, ftsent, FTS_SKIP);
   1543                 // but fall through and make sure we label the directory itself
   1544             }
   1545 
   1546             if (!datadata &&
   1547                 (!strcmp(ftsent->fts_path, DATA_DATA_PATH) ||
   1548                  !strncmp(ftsent->fts_path, DATA_USER_PREFIX, sizeof(DATA_USER_PREFIX)-1) ||
   1549                  !strncmp(ftsent->fts_path, DATA_USER_DE_PREFIX, sizeof(DATA_USER_DE_PREFIX)-1) ||
   1550                  !fnmatch(EXPAND_USER_PATH, ftsent->fts_path, FNM_LEADING_DIR|FNM_PATHNAME) ||
   1551                  !fnmatch(EXPAND_USER_DE_PATH, ftsent->fts_path, FNM_LEADING_DIR|FNM_PATHNAME))) {
   1552                 // Don't label anything below this directory.
   1553                 fts_set(fts, ftsent, FTS_SKIP);
   1554                 // but fall through and make sure we label the directory itself
   1555             }
   1556             /* fall through */
   1557         default:
   1558             error |= restorecon_sb(ftsent->fts_path, ftsent->fts_statp, nochange, verbose, seinfo, uid);
   1559             break;
   1560         }
   1561     }
   1562 
   1563     // Labeling successful. Mark the top level directory as completed.
   1564     if (setrestoreconlast && !nochange && !error)
   1565         setxattr(pathname, RESTORECON_LAST, fc_digest, sizeof fc_digest, 0);
   1566 
   1567 out:
   1568     sverrno = errno;
   1569     (void) fts_close(fts);
   1570     errno = sverrno;
   1571 cleanup:
   1572     free(pathdnamer);
   1573     free(pathname);
   1574     return error;
   1575 oom:
   1576     sverrno = errno;
   1577     selinux_log(SELINUX_ERROR, "%s:  Out of memory\n", __FUNCTION__);
   1578     errno = sverrno;
   1579     error = -1;
   1580     goto cleanup;
   1581 realpatherr:
   1582     sverrno = errno;
   1583     selinux_log(SELINUX_ERROR, "SELinux: Could not get canonical path for %s restorecon: %s.\n",
   1584             pathname_orig, strerror(errno));
   1585     errno = sverrno;
   1586     error = -1;
   1587     goto cleanup;
   1588 }
   1589 
   1590 int selinux_android_restorecon(const char *file, unsigned int flags)
   1591 {
   1592     return selinux_android_restorecon_common(file, NULL, -1, flags);
   1593 }
   1594 
   1595 int selinux_android_restorecon_pkgdir(const char *pkgdir,
   1596                                       const char *seinfo,
   1597                                       uid_t uid,
   1598                                       unsigned int flags)
   1599 {
   1600     return selinux_android_restorecon_common(pkgdir, seinfo, uid, flags | SELINUX_ANDROID_RESTORECON_DATADATA);
   1601 }
   1602 
   1603 static struct selabel_handle* selinux_android_file_context(const struct selinux_opt *opts,
   1604                                                     unsigned nopts)
   1605 {
   1606     struct selabel_handle *sehandle;
   1607     struct selinux_opt fc_opts[nopts + 1];
   1608 
   1609     memcpy(fc_opts, opts, nopts*sizeof(struct selinux_opt));
   1610     fc_opts[nopts].type = SELABEL_OPT_BASEONLY;
   1611     fc_opts[nopts].value = (char *)1;
   1612 
   1613     sehandle = selabel_open(SELABEL_CTX_FILE, fc_opts, ARRAY_SIZE(fc_opts));
   1614     if (!sehandle) {
   1615         selinux_log(SELINUX_ERROR, "%s: Error getting file context handle (%s)\n",
   1616                 __FUNCTION__, strerror(errno));
   1617         return NULL;
   1618     }
   1619     if (!compute_file_contexts_hash(fc_digest, opts, nopts)) {
   1620         selabel_close(sehandle);
   1621         return NULL;
   1622     }
   1623 
   1624     selinux_log(SELINUX_INFO, "SELinux: Loaded file_contexts\n");
   1625 
   1626     return sehandle;
   1627 }
   1628 
   1629 static bool selinux_android_opts_file_exists(const struct selinux_opt *opt)
   1630 {
   1631     return (access(opt[0].value, R_OK) != -1);
   1632 }
   1633 
   1634 struct selabel_handle* selinux_android_file_context_handle(void)
   1635 {
   1636     if (selinux_android_opts_file_exists(seopts_file_split)) {
   1637         return selinux_android_file_context(seopts_file_split,
   1638                                             ARRAY_SIZE(seopts_file_split));
   1639     } else {
   1640         return selinux_android_file_context(seopts_file_rootfs,
   1641                                             ARRAY_SIZE(seopts_file_rootfs));
   1642     }
   1643 }
   1644 struct selabel_handle* selinux_android_prop_context_handle(void)
   1645 {
   1646     struct selabel_handle* sehandle;
   1647     const struct selinux_opt* seopts_prop;
   1648 
   1649     // Prefer files from /system & /vendor, fall back to files from /
   1650     if (access(seopts_prop_split[0].value, R_OK) != -1) {
   1651         seopts_prop = seopts_prop_split;
   1652     } else {
   1653         seopts_prop = seopts_prop_rootfs;
   1654     }
   1655 
   1656     sehandle = selabel_open(SELABEL_CTX_ANDROID_PROP,
   1657             seopts_prop, 2);
   1658     if (!sehandle) {
   1659         selinux_log(SELINUX_ERROR, "%s: Error getting property context handle (%s)\n",
   1660                 __FUNCTION__, strerror(errno));
   1661         return NULL;
   1662     }
   1663     selinux_log(SELINUX_INFO, "SELinux: Loaded property_contexts from %s & %s.\n",
   1664             seopts_prop[0].value, seopts_prop[1].value);
   1665 
   1666     return sehandle;
   1667 }
   1668 
   1669 struct selabel_handle* selinux_android_service_open_context_handle(const struct selinux_opt* seopts_service,
   1670                                                                    unsigned nopts)
   1671 {
   1672     struct selabel_handle* sehandle;
   1673 
   1674     sehandle = selabel_open(SELABEL_CTX_ANDROID_SERVICE,
   1675             seopts_service, nopts);
   1676 
   1677     if (!sehandle) {
   1678         selinux_log(SELINUX_ERROR, "%s: Error getting service context handle (%s)\n",
   1679                 __FUNCTION__, strerror(errno));
   1680         return NULL;
   1681     }
   1682     selinux_log(SELINUX_INFO, "SELinux: Loaded service_contexts from:\n");
   1683     for (unsigned i = 0; i < nopts; i++) {
   1684         selinux_log(SELINUX_INFO, "    %s\n", seopts_service[i].value);
   1685     }
   1686     return sehandle;
   1687 }
   1688 
   1689 struct selabel_handle* selinux_android_service_context_handle(void)
   1690 {
   1691     const struct selinux_opt* seopts_service;
   1692 
   1693     // Prefer files from /system & /vendor, fall back to files from /
   1694     if (access(seopts_service_split[0].value, R_OK) != -1) {
   1695         seopts_service = seopts_service_split;
   1696     } else {
   1697         seopts_service = seopts_service_rootfs;
   1698     }
   1699 
   1700     // TODO(b/36866029) full treble devices can't load non-plat
   1701     return selinux_android_service_open_context_handle(seopts_service, 2);
   1702 }
   1703 
   1704 struct selabel_handle* selinux_android_hw_service_context_handle(void)
   1705 {
   1706     const struct selinux_opt* seopts_service;
   1707     if (access(seopts_hwservice_split[0].value, R_OK) != -1) {
   1708         seopts_service = seopts_hwservice_split;
   1709     } else {
   1710         seopts_service = seopts_hwservice_rootfs;
   1711     }
   1712 
   1713     return selinux_android_service_open_context_handle(seopts_service, 2);
   1714 }
   1715 
   1716 struct selabel_handle* selinux_android_vendor_service_context_handle(void)
   1717 {
   1718     const struct selinux_opt* seopts_service;
   1719     if (access(seopts_vndservice.value, R_OK) != -1) {
   1720         seopts_service = &seopts_vndservice;
   1721     } else {
   1722         seopts_service = &seopts_vndservice_rootfs;
   1723     }
   1724 
   1725     return selinux_android_service_open_context_handle(seopts_service, 1);
   1726 }
   1727 
   1728 void selinux_android_set_sehandle(const struct selabel_handle *hndl)
   1729 {
   1730     fc_sehandle = (struct selabel_handle *) hndl;
   1731 }
   1732 
   1733 int selinux_android_load_policy()
   1734 {
   1735 	int fd = -1;
   1736 
   1737 	fd = open(sepolicy_file, O_RDONLY | O_NOFOLLOW | O_CLOEXEC);
   1738 	if (fd < 0) {
   1739 		selinux_log(SELINUX_ERROR, "SELinux:  Could not open %s:  %s\n",
   1740 				sepolicy_file, strerror(errno));
   1741 		return -1;
   1742 	}
   1743 	int ret = selinux_android_load_policy_from_fd(fd, sepolicy_file);
   1744 	close(fd);
   1745 	return ret;
   1746 }
   1747 
   1748 int selinux_android_load_policy_from_fd(int fd, const char *description)
   1749 {
   1750 	int rc;
   1751 	struct stat sb;
   1752 	void *map = NULL;
   1753 	static int load_successful = 0;
   1754 
   1755 	/*
   1756 	 * Since updating policy at runtime has been abolished
   1757 	 * we just check whether a policy has been loaded before
   1758 	 * and return if this is the case.
   1759 	 * There is no point in reloading policy.
   1760 	 */
   1761 	if (load_successful){
   1762 	  selinux_log(SELINUX_WARNING, "SELinux: Attempted reload of SELinux policy!/n");
   1763 	  return 0;
   1764 	}
   1765 
   1766 	set_selinuxmnt(SELINUXMNT);
   1767 	if (fstat(fd, &sb) < 0) {
   1768 		selinux_log(SELINUX_ERROR, "SELinux:  Could not stat %s:  %s\n",
   1769 				description, strerror(errno));
   1770 		return -1;
   1771 	}
   1772 	map = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
   1773 	if (map == MAP_FAILED) {
   1774 		selinux_log(SELINUX_ERROR, "SELinux:  Could not map %s:  %s\n",
   1775 				description, strerror(errno));
   1776 		return -1;
   1777 	}
   1778 
   1779 	rc = security_load_policy(map, sb.st_size);
   1780 	if (rc < 0) {
   1781 		selinux_log(SELINUX_ERROR, "SELinux:  Could not load policy:  %s\n",
   1782 				strerror(errno));
   1783 		munmap(map, sb.st_size);
   1784 		return -1;
   1785 	}
   1786 
   1787 	munmap(map, sb.st_size);
   1788 	selinux_log(SELINUX_INFO, "SELinux: Loaded policy from %s\n", description);
   1789 	load_successful = 1;
   1790 	return 0;
   1791 }
   1792 
   1793 int selinux_log_callback(int type, const char *fmt, ...)
   1794 {
   1795     va_list ap;
   1796     int priority;
   1797     char *strp;
   1798 
   1799     switch(type) {
   1800     case SELINUX_WARNING:
   1801         priority = ANDROID_LOG_WARN;
   1802         break;
   1803     case SELINUX_INFO:
   1804         priority = ANDROID_LOG_INFO;
   1805         break;
   1806     default:
   1807         priority = ANDROID_LOG_ERROR;
   1808         break;
   1809     }
   1810 
   1811     va_start(ap, fmt);
   1812     if (vasprintf(&strp, fmt, ap) != -1) {
   1813         LOG_PRI(priority, "SELinux", "%s", strp);
   1814         LOG_EVENT_STRING(AUDITD_LOG_TAG, strp);
   1815         free(strp);
   1816     }
   1817     va_end(ap);
   1818     return 0;
   1819 }
   1820