xref: /aosp_15_r20/external/selinux/libselinux/src/android/android_seapp.c (revision 2d543d20722ada2425b5bdab9d0d1d29470e7bba)
1*2d543d20SAndroid Build Coastguard Worker #include <ctype.h>
2*2d543d20SAndroid Build Coastguard Worker #include <limits.h>
3*2d543d20SAndroid Build Coastguard Worker #include <linux/magic.h>
4*2d543d20SAndroid Build Coastguard Worker #include <pwd.h>
5*2d543d20SAndroid Build Coastguard Worker #include <stdbool.h>
6*2d543d20SAndroid Build Coastguard Worker #include <stdio.h>
7*2d543d20SAndroid Build Coastguard Worker #include <stdlib.h>
8*2d543d20SAndroid Build Coastguard Worker #include <string.h>
9*2d543d20SAndroid Build Coastguard Worker #include <unistd.h>
10*2d543d20SAndroid Build Coastguard Worker 
11*2d543d20SAndroid Build Coastguard Worker #include <private/android_filesystem_config.h>
12*2d543d20SAndroid Build Coastguard Worker #include <selinux/android.h>
13*2d543d20SAndroid Build Coastguard Worker #include <selinux/context.h>
14*2d543d20SAndroid Build Coastguard Worker #include <selinux/selinux.h>
15*2d543d20SAndroid Build Coastguard Worker 
16*2d543d20SAndroid Build Coastguard Worker #include "android_internal.h"
17*2d543d20SAndroid Build Coastguard Worker #include "callbacks.h"
18*2d543d20SAndroid Build Coastguard Worker #include "selinux_internal.h"
19*2d543d20SAndroid Build Coastguard Worker 
20*2d543d20SAndroid Build Coastguard Worker /* Locations for the file_contexts files. For each partition, only the first
21*2d543d20SAndroid Build Coastguard Worker  * existing entry will be used (for example, if
22*2d543d20SAndroid Build Coastguard Worker  * /system/etc/selinux/plat_file_contexts exists, /plat_file_contexts will be
23*2d543d20SAndroid Build Coastguard Worker  * ignored).
24*2d543d20SAndroid Build Coastguard Worker  */
25*2d543d20SAndroid Build Coastguard Worker static const path_alts_t file_context_paths = { .paths = {
26*2d543d20SAndroid Build Coastguard Worker 	{
27*2d543d20SAndroid Build Coastguard Worker 		"/system/etc/selinux/plat_file_contexts",
28*2d543d20SAndroid Build Coastguard Worker 		"/plat_file_contexts"
29*2d543d20SAndroid Build Coastguard Worker 	},
30*2d543d20SAndroid Build Coastguard Worker 	{
31*2d543d20SAndroid Build Coastguard Worker 		"/system_ext/etc/selinux/system_ext_file_contexts",
32*2d543d20SAndroid Build Coastguard Worker 		"/system_ext_file_contexts"
33*2d543d20SAndroid Build Coastguard Worker 	},
34*2d543d20SAndroid Build Coastguard Worker 	{
35*2d543d20SAndroid Build Coastguard Worker 		"/product/etc/selinux/product_file_contexts",
36*2d543d20SAndroid Build Coastguard Worker 		"/product_file_contexts"
37*2d543d20SAndroid Build Coastguard Worker 	},
38*2d543d20SAndroid Build Coastguard Worker 	{
39*2d543d20SAndroid Build Coastguard Worker 		"/vendor/etc/selinux/vendor_file_contexts",
40*2d543d20SAndroid Build Coastguard Worker 		"/vendor_file_contexts"
41*2d543d20SAndroid Build Coastguard Worker 	},
42*2d543d20SAndroid Build Coastguard Worker 	{
43*2d543d20SAndroid Build Coastguard Worker 		"/odm/etc/selinux/odm_file_contexts",
44*2d543d20SAndroid Build Coastguard Worker 		"/odm_file_contexts"
45*2d543d20SAndroid Build Coastguard Worker 	}
46*2d543d20SAndroid Build Coastguard Worker }};
47*2d543d20SAndroid Build Coastguard Worker 
48*2d543d20SAndroid Build Coastguard Worker /* Locations for the seapp_contexts files, and corresponding partitions. For
49*2d543d20SAndroid Build Coastguard Worker  * each partition, only the first existing entry will be used (for example, if
50*2d543d20SAndroid Build Coastguard Worker  * /system/etc/selinux/plat_seapp_contexts exists, /plat_seapp_contexts will be
51*2d543d20SAndroid Build Coastguard Worker  * ignored).
52*2d543d20SAndroid Build Coastguard Worker  *
53*2d543d20SAndroid Build Coastguard Worker  * PLEASE KEEP IN SYNC WITH:
54*2d543d20SAndroid Build Coastguard Worker  * hostsidetests/security/src/android/security/cts/SELinuxHostTest.java
55*2d543d20SAndroid Build Coastguard Worker  */
56*2d543d20SAndroid Build Coastguard Worker static const path_alts_t seapp_context_paths = { .paths = {
57*2d543d20SAndroid Build Coastguard Worker 	{
58*2d543d20SAndroid Build Coastguard Worker 		"/system/etc/selinux/plat_seapp_contexts",
59*2d543d20SAndroid Build Coastguard Worker 		"/plat_seapp_contexts"
60*2d543d20SAndroid Build Coastguard Worker 	},
61*2d543d20SAndroid Build Coastguard Worker 	{
62*2d543d20SAndroid Build Coastguard Worker 		"/system_ext/etc/selinux/system_ext_seapp_contexts",
63*2d543d20SAndroid Build Coastguard Worker 		"/system_ext_seapp_contexts"
64*2d543d20SAndroid Build Coastguard Worker 	},
65*2d543d20SAndroid Build Coastguard Worker 	{
66*2d543d20SAndroid Build Coastguard Worker 		"/product/etc/selinux/product_seapp_contexts",
67*2d543d20SAndroid Build Coastguard Worker 		"/product_seapp_contexts"
68*2d543d20SAndroid Build Coastguard Worker 	},
69*2d543d20SAndroid Build Coastguard Worker 	{
70*2d543d20SAndroid Build Coastguard Worker 		"/vendor/etc/selinux/vendor_seapp_contexts",
71*2d543d20SAndroid Build Coastguard Worker 		"/vendor_seapp_contexts"
72*2d543d20SAndroid Build Coastguard Worker 	},
73*2d543d20SAndroid Build Coastguard Worker 	{
74*2d543d20SAndroid Build Coastguard Worker 		"/odm/etc/selinux/odm_seapp_contexts",
75*2d543d20SAndroid Build Coastguard Worker 		"/odm_seapp_contexts"
76*2d543d20SAndroid Build Coastguard Worker 	}
77*2d543d20SAndroid Build Coastguard Worker }, .partitions= {
78*2d543d20SAndroid Build Coastguard Worker 	"system",
79*2d543d20SAndroid Build Coastguard Worker 	"system_ext",
80*2d543d20SAndroid Build Coastguard Worker 	"product",
81*2d543d20SAndroid Build Coastguard Worker 	"vendor",
82*2d543d20SAndroid Build Coastguard Worker 	"odm"
83*2d543d20SAndroid Build Coastguard Worker }};
84*2d543d20SAndroid Build Coastguard Worker 
85*2d543d20SAndroid Build Coastguard Worker static pthread_once_t fc_once = PTHREAD_ONCE_INIT;
86*2d543d20SAndroid Build Coastguard Worker static struct selabel_handle* seapp_fc_sehandle = NULL;
87*2d543d20SAndroid Build Coastguard Worker 
selinux_android_file_context_handle_init(void)88*2d543d20SAndroid Build Coastguard Worker void selinux_android_file_context_handle_init(void)
89*2d543d20SAndroid Build Coastguard Worker {
90*2d543d20SAndroid Build Coastguard Worker 	const char* file_contexts[MAX_CONTEXT_PATHS];
91*2d543d20SAndroid Build Coastguard Worker 	struct selinux_opt opts[MAX_CONTEXT_PATHS + 1];
92*2d543d20SAndroid Build Coastguard Worker 	int npaths, nopts;
93*2d543d20SAndroid Build Coastguard Worker 
94*2d543d20SAndroid Build Coastguard Worker 	npaths = find_existing_files(&file_context_paths, file_contexts);
95*2d543d20SAndroid Build Coastguard Worker 	paths_to_opts(file_contexts, npaths, opts);
96*2d543d20SAndroid Build Coastguard Worker 
97*2d543d20SAndroid Build Coastguard Worker 	opts[npaths].type = SELABEL_OPT_BASEONLY;
98*2d543d20SAndroid Build Coastguard Worker 	opts[npaths].value = (char *) 1;
99*2d543d20SAndroid Build Coastguard Worker 	nopts = npaths + 1;
100*2d543d20SAndroid Build Coastguard Worker 
101*2d543d20SAndroid Build Coastguard Worker 	seapp_fc_sehandle = initialize_backend(SELABEL_CTX_FILE, "file", opts, nopts);
102*2d543d20SAndroid Build Coastguard Worker }
103*2d543d20SAndroid Build Coastguard Worker 
104*2d543d20SAndroid Build Coastguard Worker /* Returns a handle for the file contexts backend, initialized with the Android
105*2d543d20SAndroid Build Coastguard Worker  * configuration */
selinux_android_file_context_handle(void)106*2d543d20SAndroid Build Coastguard Worker struct selabel_handle* selinux_android_file_context_handle(void)
107*2d543d20SAndroid Build Coastguard Worker {
108*2d543d20SAndroid Build Coastguard Worker 	__selinux_once(fc_once, selinux_android_file_context_handle_init);
109*2d543d20SAndroid Build Coastguard Worker 	return seapp_fc_sehandle;
110*2d543d20SAndroid Build Coastguard Worker }
111*2d543d20SAndroid Build Coastguard Worker 
112*2d543d20SAndroid Build Coastguard Worker #if DEBUG
113*2d543d20SAndroid Build Coastguard Worker static char const * const levelFromName[] = {
114*2d543d20SAndroid Build Coastguard Worker 	"none",
115*2d543d20SAndroid Build Coastguard Worker 	"app",
116*2d543d20SAndroid Build Coastguard Worker 	"user",
117*2d543d20SAndroid Build Coastguard Worker 	"all"
118*2d543d20SAndroid Build Coastguard Worker };
119*2d543d20SAndroid Build Coastguard Worker #endif
120*2d543d20SAndroid Build Coastguard Worker 
121*2d543d20SAndroid Build Coastguard Worker struct prefix_str {
122*2d543d20SAndroid Build Coastguard Worker 	size_t len;
123*2d543d20SAndroid Build Coastguard Worker 	char *str;
124*2d543d20SAndroid Build Coastguard Worker 	char is_prefix;
125*2d543d20SAndroid Build Coastguard Worker };
126*2d543d20SAndroid Build Coastguard Worker 
free_prefix_str(struct prefix_str * p)127*2d543d20SAndroid Build Coastguard Worker static void free_prefix_str(struct prefix_str *p)
128*2d543d20SAndroid Build Coastguard Worker {
129*2d543d20SAndroid Build Coastguard Worker 	if (!p)
130*2d543d20SAndroid Build Coastguard Worker 		return;
131*2d543d20SAndroid Build Coastguard Worker 	free(p->str);
132*2d543d20SAndroid Build Coastguard Worker }
133*2d543d20SAndroid Build Coastguard Worker 
134*2d543d20SAndroid Build Coastguard Worker /* For a set of selectors, represents the contexts that should be applied to an
135*2d543d20SAndroid Build Coastguard Worker  * app and its data. Each instance is based on a line in a seapp_contexts file.
136*2d543d20SAndroid Build Coastguard Worker  * */
137*2d543d20SAndroid Build Coastguard Worker struct seapp_context {
138*2d543d20SAndroid Build Coastguard Worker 	/* input selectors */
139*2d543d20SAndroid Build Coastguard Worker 	bool isSystemServer;
140*2d543d20SAndroid Build Coastguard Worker 	bool isEphemeralAppSet;
141*2d543d20SAndroid Build Coastguard Worker 	bool isEphemeralApp;
142*2d543d20SAndroid Build Coastguard Worker 	struct prefix_str user;
143*2d543d20SAndroid Build Coastguard Worker 	char *seinfo;
144*2d543d20SAndroid Build Coastguard Worker 	struct prefix_str name;
145*2d543d20SAndroid Build Coastguard Worker 	bool isPrivAppSet;
146*2d543d20SAndroid Build Coastguard Worker 	bool isPrivApp;
147*2d543d20SAndroid Build Coastguard Worker 	int32_t minTargetSdkVersion;
148*2d543d20SAndroid Build Coastguard Worker 	bool fromRunAs;
149*2d543d20SAndroid Build Coastguard Worker 	bool isIsolatedComputeApp;
150*2d543d20SAndroid Build Coastguard Worker 	bool isSdkSandboxAudit;
151*2d543d20SAndroid Build Coastguard Worker 	bool isSdkSandboxNext;
152*2d543d20SAndroid Build Coastguard Worker 	/* outputs */
153*2d543d20SAndroid Build Coastguard Worker 	char *domain;
154*2d543d20SAndroid Build Coastguard Worker 	char *type;
155*2d543d20SAndroid Build Coastguard Worker 	char *level;
156*2d543d20SAndroid Build Coastguard Worker 	enum levelFrom levelFrom;
157*2d543d20SAndroid Build Coastguard Worker 	const char* partition;
158*2d543d20SAndroid Build Coastguard Worker };
159*2d543d20SAndroid Build Coastguard Worker 
free_seapp_context(struct seapp_context * s)160*2d543d20SAndroid Build Coastguard Worker static void free_seapp_context(struct seapp_context *s)
161*2d543d20SAndroid Build Coastguard Worker {
162*2d543d20SAndroid Build Coastguard Worker 	if (!s)
163*2d543d20SAndroid Build Coastguard Worker 		return;
164*2d543d20SAndroid Build Coastguard Worker 
165*2d543d20SAndroid Build Coastguard Worker 	free_prefix_str(&s->user);
166*2d543d20SAndroid Build Coastguard Worker 	free(s->seinfo);
167*2d543d20SAndroid Build Coastguard Worker 	free_prefix_str(&s->name);
168*2d543d20SAndroid Build Coastguard Worker 	free(s->domain);
169*2d543d20SAndroid Build Coastguard Worker 	free(s->type);
170*2d543d20SAndroid Build Coastguard Worker 	free(s->level);
171*2d543d20SAndroid Build Coastguard Worker }
172*2d543d20SAndroid Build Coastguard Worker 
is_platform(const char * partition)173*2d543d20SAndroid Build Coastguard Worker static bool is_platform(const char *partition) {
174*2d543d20SAndroid Build Coastguard Worker 	// system, system_ext, product are regarded as "platform", whereas vendor
175*2d543d20SAndroid Build Coastguard Worker 	// and odm are regarded as vendor.
176*2d543d20SAndroid Build Coastguard Worker 	if (strcmp(partition, "system") == 0) return true;
177*2d543d20SAndroid Build Coastguard Worker 	if (strcmp(partition, "system_ext") == 0) return true;
178*2d543d20SAndroid Build Coastguard Worker 	if (strcmp(partition, "product") == 0) return true;
179*2d543d20SAndroid Build Coastguard Worker 	return false;
180*2d543d20SAndroid Build Coastguard Worker }
181*2d543d20SAndroid Build Coastguard Worker 
182*2d543d20SAndroid Build Coastguard Worker /* Compare two seapp_context. Used to sort all the entries found. */
seapp_context_cmp(const void * A,const void * B)183*2d543d20SAndroid Build Coastguard Worker static int seapp_context_cmp(const void *A, const void *B)
184*2d543d20SAndroid Build Coastguard Worker {
185*2d543d20SAndroid Build Coastguard Worker 	const struct seapp_context *const *sp1 = (const struct seapp_context *const *) A;
186*2d543d20SAndroid Build Coastguard Worker 	const struct seapp_context *const *sp2 = (const struct seapp_context *const *) B;
187*2d543d20SAndroid Build Coastguard Worker 	const struct seapp_context *s1 = *sp1, *s2 = *sp2;
188*2d543d20SAndroid Build Coastguard Worker 
189*2d543d20SAndroid Build Coastguard Worker 	/* Give precedence to isSystemServer=true. */
190*2d543d20SAndroid Build Coastguard Worker 	if (s1->isSystemServer != s2->isSystemServer)
191*2d543d20SAndroid Build Coastguard Worker 		return (s1->isSystemServer ? -1 : 1);
192*2d543d20SAndroid Build Coastguard Worker 
193*2d543d20SAndroid Build Coastguard Worker 	/* Give precedence to a specified isEphemeral= over an
194*2d543d20SAndroid Build Coastguard Worker 	 * unspecified isEphemeral=. */
195*2d543d20SAndroid Build Coastguard Worker 	if (s1->isEphemeralAppSet != s2->isEphemeralAppSet)
196*2d543d20SAndroid Build Coastguard Worker 		return (s1->isEphemeralAppSet ? -1 : 1);
197*2d543d20SAndroid Build Coastguard Worker 
198*2d543d20SAndroid Build Coastguard Worker 	/* Give precedence to a specified user= over an unspecified user=. */
199*2d543d20SAndroid Build Coastguard Worker 	if (s1->user.str && !s2->user.str)
200*2d543d20SAndroid Build Coastguard Worker 		return -1;
201*2d543d20SAndroid Build Coastguard Worker 	if (!s1->user.str && s2->user.str)
202*2d543d20SAndroid Build Coastguard Worker 		return 1;
203*2d543d20SAndroid Build Coastguard Worker 
204*2d543d20SAndroid Build Coastguard Worker 	if (s1->user.str) {
205*2d543d20SAndroid Build Coastguard Worker 		/* Give precedence to a fixed user= string over a prefix. */
206*2d543d20SAndroid Build Coastguard Worker 		if (s1->user.is_prefix != s2->user.is_prefix)
207*2d543d20SAndroid Build Coastguard Worker 			return (s2->user.is_prefix ? -1 : 1);
208*2d543d20SAndroid Build Coastguard Worker 
209*2d543d20SAndroid Build Coastguard Worker 		/* Give precedence to a longer prefix over a shorter prefix. */
210*2d543d20SAndroid Build Coastguard Worker 		if (s1->user.is_prefix && s1->user.len != s2->user.len)
211*2d543d20SAndroid Build Coastguard Worker 			return (s1->user.len > s2->user.len) ? -1 : 1;
212*2d543d20SAndroid Build Coastguard Worker 	}
213*2d543d20SAndroid Build Coastguard Worker 
214*2d543d20SAndroid Build Coastguard Worker 	/* Give precedence to a specified seinfo= over an unspecified seinfo=. */
215*2d543d20SAndroid Build Coastguard Worker 	if (s1->seinfo && !s2->seinfo)
216*2d543d20SAndroid Build Coastguard Worker 		return -1;
217*2d543d20SAndroid Build Coastguard Worker 	if (!s1->seinfo && s2->seinfo)
218*2d543d20SAndroid Build Coastguard Worker 		return 1;
219*2d543d20SAndroid Build Coastguard Worker 
220*2d543d20SAndroid Build Coastguard Worker 	/* Give precedence to a specified name= over an unspecified name=. */
221*2d543d20SAndroid Build Coastguard Worker 	if (s1->name.str && !s2->name.str)
222*2d543d20SAndroid Build Coastguard Worker 		return -1;
223*2d543d20SAndroid Build Coastguard Worker 	if (!s1->name.str && s2->name.str)
224*2d543d20SAndroid Build Coastguard Worker 		return 1;
225*2d543d20SAndroid Build Coastguard Worker 
226*2d543d20SAndroid Build Coastguard Worker 	if (s1->name.str) {
227*2d543d20SAndroid Build Coastguard Worker 		/* Give precedence to a fixed name= string over a prefix. */
228*2d543d20SAndroid Build Coastguard Worker 		if (s1->name.is_prefix != s2->name.is_prefix)
229*2d543d20SAndroid Build Coastguard Worker 			return (s2->name.is_prefix ? -1 : 1);
230*2d543d20SAndroid Build Coastguard Worker 
231*2d543d20SAndroid Build Coastguard Worker 		/* Give precedence to a longer prefix over a shorter prefix. */
232*2d543d20SAndroid Build Coastguard Worker 		if (s1->name.is_prefix && s1->name.len != s2->name.len)
233*2d543d20SAndroid Build Coastguard Worker 			return (s1->name.len > s2->name.len) ? -1 : 1;
234*2d543d20SAndroid Build Coastguard Worker 	}
235*2d543d20SAndroid Build Coastguard Worker 
236*2d543d20SAndroid Build Coastguard Worker 	/* Give precedence to a specified isPrivApp= over an unspecified isPrivApp=. */
237*2d543d20SAndroid Build Coastguard Worker 	if (s1->isPrivAppSet != s2->isPrivAppSet)
238*2d543d20SAndroid Build Coastguard Worker 		return (s1->isPrivAppSet ? -1 : 1);
239*2d543d20SAndroid Build Coastguard Worker 
240*2d543d20SAndroid Build Coastguard Worker 	/* Give precedence to a higher minTargetSdkVersion= over a lower minTargetSdkVersion=.
241*2d543d20SAndroid Build Coastguard Worker 	 * If unspecified, minTargetSdkVersion has a default value of 0.
242*2d543d20SAndroid Build Coastguard Worker 	 */
243*2d543d20SAndroid Build Coastguard Worker 	if (s1->minTargetSdkVersion > s2->minTargetSdkVersion)
244*2d543d20SAndroid Build Coastguard Worker 		return -1;
245*2d543d20SAndroid Build Coastguard Worker 	else if (s1->minTargetSdkVersion < s2->minTargetSdkVersion)
246*2d543d20SAndroid Build Coastguard Worker 		return 1;
247*2d543d20SAndroid Build Coastguard Worker 
248*2d543d20SAndroid Build Coastguard Worker 	/* Give precedence to fromRunAs=true. */
249*2d543d20SAndroid Build Coastguard Worker 	if (s1->fromRunAs != s2->fromRunAs)
250*2d543d20SAndroid Build Coastguard Worker 		return (s1->fromRunAs ? -1 : 1);
251*2d543d20SAndroid Build Coastguard Worker 
252*2d543d20SAndroid Build Coastguard Worker 	/* Give precedence to platform side contexts */
253*2d543d20SAndroid Build Coastguard Worker 	bool isS1Platform = is_platform(s1->partition);
254*2d543d20SAndroid Build Coastguard Worker 	bool isS2Platform = is_platform(s2->partition);
255*2d543d20SAndroid Build Coastguard Worker 	if (isS1Platform != isS2Platform)
256*2d543d20SAndroid Build Coastguard Worker 		return (isS1Platform ? -1 : 1);
257*2d543d20SAndroid Build Coastguard Worker 
258*2d543d20SAndroid Build Coastguard Worker 	/* Anything else has equal precedence. */
259*2d543d20SAndroid Build Coastguard Worker 	return 0;
260*2d543d20SAndroid Build Coastguard Worker }
261*2d543d20SAndroid Build Coastguard Worker 
262*2d543d20SAndroid Build Coastguard Worker /* Array of all the seapp_context entries configured. */
263*2d543d20SAndroid Build Coastguard Worker static struct seapp_context **seapp_contexts = NULL;
264*2d543d20SAndroid Build Coastguard Worker /* Size of seapp_contexts */
265*2d543d20SAndroid Build Coastguard Worker static int nspec = 0;
266*2d543d20SAndroid Build Coastguard Worker 
free_seapp_contexts(void)267*2d543d20SAndroid Build Coastguard Worker static void free_seapp_contexts(void)
268*2d543d20SAndroid Build Coastguard Worker {
269*2d543d20SAndroid Build Coastguard Worker 	int n;
270*2d543d20SAndroid Build Coastguard Worker 
271*2d543d20SAndroid Build Coastguard Worker 	if (!seapp_contexts)
272*2d543d20SAndroid Build Coastguard Worker 		return;
273*2d543d20SAndroid Build Coastguard Worker 
274*2d543d20SAndroid Build Coastguard Worker 	for (n = 0; n < nspec; n++)
275*2d543d20SAndroid Build Coastguard Worker 		free_seapp_context(seapp_contexts[n]);
276*2d543d20SAndroid Build Coastguard Worker 
277*2d543d20SAndroid Build Coastguard Worker 	free(seapp_contexts);
278*2d543d20SAndroid Build Coastguard Worker 	seapp_contexts = NULL;
279*2d543d20SAndroid Build Coastguard Worker 	nspec = 0;
280*2d543d20SAndroid Build Coastguard Worker }
281*2d543d20SAndroid Build Coastguard Worker 
get_minTargetSdkVersion(const char * value)282*2d543d20SAndroid Build Coastguard Worker static int32_t get_minTargetSdkVersion(const char *value)
283*2d543d20SAndroid Build Coastguard Worker {
284*2d543d20SAndroid Build Coastguard Worker 	char *endptr;
285*2d543d20SAndroid Build Coastguard Worker 	long minTargetSdkVersion;
286*2d543d20SAndroid Build Coastguard Worker 	minTargetSdkVersion = strtol(value, &endptr, 10);
287*2d543d20SAndroid Build Coastguard Worker 	if (('\0' != *endptr) || (minTargetSdkVersion < 0) || (minTargetSdkVersion > INT32_MAX)) {
288*2d543d20SAndroid Build Coastguard Worker 		return -1; /* error parsing minTargetSdkVersion */
289*2d543d20SAndroid Build Coastguard Worker 	} else {
290*2d543d20SAndroid Build Coastguard Worker 		return (int32_t) minTargetSdkVersion;
291*2d543d20SAndroid Build Coastguard Worker 	}
292*2d543d20SAndroid Build Coastguard Worker }
293*2d543d20SAndroid Build Coastguard Worker 
seapp_context_reload_internal(const path_alts_t * context_paths)294*2d543d20SAndroid Build Coastguard Worker int seapp_context_reload_internal(const path_alts_t *context_paths)
295*2d543d20SAndroid Build Coastguard Worker {
296*2d543d20SAndroid Build Coastguard Worker 	FILE *fp = NULL;
297*2d543d20SAndroid Build Coastguard Worker 	char line_buf[BUFSIZ];
298*2d543d20SAndroid Build Coastguard Worker 	char *token;
299*2d543d20SAndroid Build Coastguard Worker 	unsigned lineno;
300*2d543d20SAndroid Build Coastguard Worker 	struct seapp_context *cur;
301*2d543d20SAndroid Build Coastguard Worker 	char *p, *name = NULL, *value = NULL, *saveptr;
302*2d543d20SAndroid Build Coastguard Worker 	size_t i, len, files_len = 0;
303*2d543d20SAndroid Build Coastguard Worker 	int ret;
304*2d543d20SAndroid Build Coastguard Worker 	const char* seapp_contexts_files[MAX_CONTEXT_PATHS];
305*2d543d20SAndroid Build Coastguard Worker 	const char* seapp_contexts_partitions[MAX_CONTEXT_PATHS];
306*2d543d20SAndroid Build Coastguard Worker 
307*2d543d20SAndroid Build Coastguard Worker 	files_len = find_existing_files_with_partitions(context_paths, seapp_contexts_files, seapp_contexts_partitions);
308*2d543d20SAndroid Build Coastguard Worker 
309*2d543d20SAndroid Build Coastguard Worker 	/* Reset the current entries */
310*2d543d20SAndroid Build Coastguard Worker 	free_seapp_contexts();
311*2d543d20SAndroid Build Coastguard Worker 
312*2d543d20SAndroid Build Coastguard Worker 	nspec = 0;
313*2d543d20SAndroid Build Coastguard Worker 	for (i = 0; i < files_len; i++) {
314*2d543d20SAndroid Build Coastguard Worker 		fp = fopen(seapp_contexts_files[i], "re");
315*2d543d20SAndroid Build Coastguard Worker 		if (!fp) {
316*2d543d20SAndroid Build Coastguard Worker 			selinux_log(SELINUX_ERROR, "%s:  could not open seapp_contexts file: %s",
317*2d543d20SAndroid Build Coastguard Worker 				    __FUNCTION__, seapp_contexts_files[i]);
318*2d543d20SAndroid Build Coastguard Worker 			return -1;
319*2d543d20SAndroid Build Coastguard Worker 		}
320*2d543d20SAndroid Build Coastguard Worker 		while (fgets(line_buf, sizeof line_buf - 1, fp)) {
321*2d543d20SAndroid Build Coastguard Worker 			p = line_buf;
322*2d543d20SAndroid Build Coastguard Worker 			while (isspace(*p))
323*2d543d20SAndroid Build Coastguard Worker 				p++;
324*2d543d20SAndroid Build Coastguard Worker 			if (*p == '#' || *p == 0)
325*2d543d20SAndroid Build Coastguard Worker 				continue;
326*2d543d20SAndroid Build Coastguard Worker 			nspec++;
327*2d543d20SAndroid Build Coastguard Worker 		}
328*2d543d20SAndroid Build Coastguard Worker 		fclose(fp);
329*2d543d20SAndroid Build Coastguard Worker 	}
330*2d543d20SAndroid Build Coastguard Worker 
331*2d543d20SAndroid Build Coastguard Worker 	seapp_contexts = (struct seapp_context **) calloc(nspec, sizeof(struct seapp_context *));
332*2d543d20SAndroid Build Coastguard Worker 	if (!seapp_contexts)
333*2d543d20SAndroid Build Coastguard Worker 		goto oom;
334*2d543d20SAndroid Build Coastguard Worker 
335*2d543d20SAndroid Build Coastguard Worker 	nspec = 0;
336*2d543d20SAndroid Build Coastguard Worker 	for (i = 0; i < files_len; i++) {
337*2d543d20SAndroid Build Coastguard Worker 		lineno = 1;
338*2d543d20SAndroid Build Coastguard Worker 		fp = fopen(seapp_contexts_files[i], "re");
339*2d543d20SAndroid Build Coastguard Worker 		if (!fp) {
340*2d543d20SAndroid Build Coastguard Worker 			selinux_log(SELINUX_ERROR, "%s:  could not open seapp_contexts file: %s",
341*2d543d20SAndroid Build Coastguard Worker 				    __FUNCTION__, seapp_contexts_files[i]);
342*2d543d20SAndroid Build Coastguard Worker 			free_seapp_contexts();
343*2d543d20SAndroid Build Coastguard Worker 			return -1;
344*2d543d20SAndroid Build Coastguard Worker 		}
345*2d543d20SAndroid Build Coastguard Worker 		while (fgets(line_buf, sizeof line_buf - 1, fp)) {
346*2d543d20SAndroid Build Coastguard Worker 			len = strlen(line_buf);
347*2d543d20SAndroid Build Coastguard Worker 			if (len == 0) {
348*2d543d20SAndroid Build Coastguard Worker 				// line contains a NUL byte as its first entry
349*2d543d20SAndroid Build Coastguard Worker 				goto err;
350*2d543d20SAndroid Build Coastguard Worker 			}
351*2d543d20SAndroid Build Coastguard Worker 			if (line_buf[len - 1] == '\n')
352*2d543d20SAndroid Build Coastguard Worker 				line_buf[len - 1] = 0;
353*2d543d20SAndroid Build Coastguard Worker 			p = line_buf;
354*2d543d20SAndroid Build Coastguard Worker 			while (isspace(*p))
355*2d543d20SAndroid Build Coastguard Worker 				p++;
356*2d543d20SAndroid Build Coastguard Worker 			if (*p == '#' || *p == 0)
357*2d543d20SAndroid Build Coastguard Worker 				continue;
358*2d543d20SAndroid Build Coastguard Worker 
359*2d543d20SAndroid Build Coastguard Worker 			cur = (struct seapp_context *) calloc(1, sizeof(struct seapp_context));
360*2d543d20SAndroid Build Coastguard Worker 			if (!cur)
361*2d543d20SAndroid Build Coastguard Worker 				goto oom;
362*2d543d20SAndroid Build Coastguard Worker 
363*2d543d20SAndroid Build Coastguard Worker 			token = strtok_r(p, " \t", &saveptr);
364*2d543d20SAndroid Build Coastguard Worker 			if (!token) {
365*2d543d20SAndroid Build Coastguard Worker 				free_seapp_context(cur);
366*2d543d20SAndroid Build Coastguard Worker 				goto err;
367*2d543d20SAndroid Build Coastguard Worker 			}
368*2d543d20SAndroid Build Coastguard Worker 
369*2d543d20SAndroid Build Coastguard Worker 			while (1) {
370*2d543d20SAndroid Build Coastguard Worker 				name = token;
371*2d543d20SAndroid Build Coastguard Worker 				value = strchr(name, '=');
372*2d543d20SAndroid Build Coastguard Worker 				if (!value) {
373*2d543d20SAndroid Build Coastguard Worker 					free_seapp_context(cur);
374*2d543d20SAndroid Build Coastguard Worker 					goto err;
375*2d543d20SAndroid Build Coastguard Worker 				}
376*2d543d20SAndroid Build Coastguard Worker 				*value++ = 0;
377*2d543d20SAndroid Build Coastguard Worker 
378*2d543d20SAndroid Build Coastguard Worker 				if (!strcasecmp(name, "isSystemServer")) {
379*2d543d20SAndroid Build Coastguard Worker 					if (!strcasecmp(value, "true"))
380*2d543d20SAndroid Build Coastguard Worker 						cur->isSystemServer = true;
381*2d543d20SAndroid Build Coastguard Worker 					else if (!strcasecmp(value, "false"))
382*2d543d20SAndroid Build Coastguard Worker 						cur->isSystemServer = false;
383*2d543d20SAndroid Build Coastguard Worker 					else {
384*2d543d20SAndroid Build Coastguard Worker 						free_seapp_context(cur);
385*2d543d20SAndroid Build Coastguard Worker 						goto err;
386*2d543d20SAndroid Build Coastguard Worker 					}
387*2d543d20SAndroid Build Coastguard Worker 				} else if (!strcasecmp(name, "isEphemeralApp")) {
388*2d543d20SAndroid Build Coastguard Worker 					cur->isEphemeralAppSet = true;
389*2d543d20SAndroid Build Coastguard Worker 					if (!strcasecmp(value, "true"))
390*2d543d20SAndroid Build Coastguard Worker 						cur->isEphemeralApp = true;
391*2d543d20SAndroid Build Coastguard Worker 					else if (!strcasecmp(value, "false"))
392*2d543d20SAndroid Build Coastguard Worker 						cur->isEphemeralApp = false;
393*2d543d20SAndroid Build Coastguard Worker 					else {
394*2d543d20SAndroid Build Coastguard Worker 						free_seapp_context(cur);
395*2d543d20SAndroid Build Coastguard Worker 						goto err;
396*2d543d20SAndroid Build Coastguard Worker 					}
397*2d543d20SAndroid Build Coastguard Worker 				} else if (!strcasecmp(name, "user")) {
398*2d543d20SAndroid Build Coastguard Worker 					if (cur->user.str) {
399*2d543d20SAndroid Build Coastguard Worker 						free_seapp_context(cur);
400*2d543d20SAndroid Build Coastguard Worker 						goto err;
401*2d543d20SAndroid Build Coastguard Worker 					}
402*2d543d20SAndroid Build Coastguard Worker 					cur->user.str = strdup(value);
403*2d543d20SAndroid Build Coastguard Worker 					if (!cur->user.str) {
404*2d543d20SAndroid Build Coastguard Worker 						free_seapp_context(cur);
405*2d543d20SAndroid Build Coastguard Worker 						goto oom;
406*2d543d20SAndroid Build Coastguard Worker 					}
407*2d543d20SAndroid Build Coastguard Worker 					cur->user.len = strlen(cur->user.str);
408*2d543d20SAndroid Build Coastguard Worker 					if (cur->user.str[cur->user.len-1] == '*')
409*2d543d20SAndroid Build Coastguard Worker 						cur->user.is_prefix = 1;
410*2d543d20SAndroid Build Coastguard Worker 				} else if (!strcasecmp(name, "seinfo")) {
411*2d543d20SAndroid Build Coastguard Worker 					if (cur->seinfo) {
412*2d543d20SAndroid Build Coastguard Worker 						free_seapp_context(cur);
413*2d543d20SAndroid Build Coastguard Worker 						goto err;
414*2d543d20SAndroid Build Coastguard Worker 					}
415*2d543d20SAndroid Build Coastguard Worker 					cur->seinfo = strdup(value);
416*2d543d20SAndroid Build Coastguard Worker 					if (!cur->seinfo) {
417*2d543d20SAndroid Build Coastguard Worker 						free_seapp_context(cur);
418*2d543d20SAndroid Build Coastguard Worker 						goto oom;
419*2d543d20SAndroid Build Coastguard Worker 					}
420*2d543d20SAndroid Build Coastguard Worker 					if (strstr(value, ":")) {
421*2d543d20SAndroid Build Coastguard Worker 						free_seapp_context(cur);
422*2d543d20SAndroid Build Coastguard Worker 						goto err;
423*2d543d20SAndroid Build Coastguard Worker 					}
424*2d543d20SAndroid Build Coastguard Worker 				} else if (!strcasecmp(name, "name")) {
425*2d543d20SAndroid Build Coastguard Worker 					if (cur->name.str) {
426*2d543d20SAndroid Build Coastguard Worker 						free_seapp_context(cur);
427*2d543d20SAndroid Build Coastguard Worker 						goto err;
428*2d543d20SAndroid Build Coastguard Worker 					}
429*2d543d20SAndroid Build Coastguard Worker 					cur->name.str = strdup(value);
430*2d543d20SAndroid Build Coastguard Worker 					if (!cur->name.str) {
431*2d543d20SAndroid Build Coastguard Worker 						free_seapp_context(cur);
432*2d543d20SAndroid Build Coastguard Worker 						goto oom;
433*2d543d20SAndroid Build Coastguard Worker 					}
434*2d543d20SAndroid Build Coastguard Worker 					cur->name.len = strlen(cur->name.str);
435*2d543d20SAndroid Build Coastguard Worker 					if (cur->name.str[cur->name.len-1] == '*')
436*2d543d20SAndroid Build Coastguard Worker 						cur->name.is_prefix = 1;
437*2d543d20SAndroid Build Coastguard Worker 				} else if (!strcasecmp(name, "domain")) {
438*2d543d20SAndroid Build Coastguard Worker 					if (cur->domain) {
439*2d543d20SAndroid Build Coastguard Worker 						free_seapp_context(cur);
440*2d543d20SAndroid Build Coastguard Worker 						goto err;
441*2d543d20SAndroid Build Coastguard Worker 					}
442*2d543d20SAndroid Build Coastguard Worker 					cur->domain = strdup(value);
443*2d543d20SAndroid Build Coastguard Worker 					if (!cur->domain) {
444*2d543d20SAndroid Build Coastguard Worker 						free_seapp_context(cur);
445*2d543d20SAndroid Build Coastguard Worker 						goto oom;
446*2d543d20SAndroid Build Coastguard Worker 					}
447*2d543d20SAndroid Build Coastguard Worker 				} else if (!strcasecmp(name, "type")) {
448*2d543d20SAndroid Build Coastguard Worker 					if (cur->type) {
449*2d543d20SAndroid Build Coastguard Worker 						free_seapp_context(cur);
450*2d543d20SAndroid Build Coastguard Worker 						goto err;
451*2d543d20SAndroid Build Coastguard Worker 					}
452*2d543d20SAndroid Build Coastguard Worker 					cur->type = strdup(value);
453*2d543d20SAndroid Build Coastguard Worker 					if (!cur->type) {
454*2d543d20SAndroid Build Coastguard Worker 						free_seapp_context(cur);
455*2d543d20SAndroid Build Coastguard Worker 						goto oom;
456*2d543d20SAndroid Build Coastguard Worker 					}
457*2d543d20SAndroid Build Coastguard Worker 				} else if (!strcasecmp(name, "levelFrom")) {
458*2d543d20SAndroid Build Coastguard Worker 					if (cur->levelFrom) {
459*2d543d20SAndroid Build Coastguard Worker 						free_seapp_context(cur);
460*2d543d20SAndroid Build Coastguard Worker 						goto err;
461*2d543d20SAndroid Build Coastguard Worker 					}
462*2d543d20SAndroid Build Coastguard Worker 					if (!strcasecmp(value, "none"))
463*2d543d20SAndroid Build Coastguard Worker 						cur->levelFrom = LEVELFROM_NONE;
464*2d543d20SAndroid Build Coastguard Worker 					else if (!strcasecmp(value, "app"))
465*2d543d20SAndroid Build Coastguard Worker 						cur->levelFrom = LEVELFROM_APP;
466*2d543d20SAndroid Build Coastguard Worker 					else if (!strcasecmp(value, "user"))
467*2d543d20SAndroid Build Coastguard Worker 						cur->levelFrom = LEVELFROM_USER;
468*2d543d20SAndroid Build Coastguard Worker 					else if (!strcasecmp(value, "all"))
469*2d543d20SAndroid Build Coastguard Worker 						cur->levelFrom = LEVELFROM_ALL;
470*2d543d20SAndroid Build Coastguard Worker 					else {
471*2d543d20SAndroid Build Coastguard Worker 						free_seapp_context(cur);
472*2d543d20SAndroid Build Coastguard Worker 						goto err;
473*2d543d20SAndroid Build Coastguard Worker 					}
474*2d543d20SAndroid Build Coastguard Worker 				} else if (!strcasecmp(name, "level")) {
475*2d543d20SAndroid Build Coastguard Worker 					if (cur->level) {
476*2d543d20SAndroid Build Coastguard Worker 						free_seapp_context(cur);
477*2d543d20SAndroid Build Coastguard Worker 						goto err;
478*2d543d20SAndroid Build Coastguard Worker 					}
479*2d543d20SAndroid Build Coastguard Worker 					cur->level = strdup(value);
480*2d543d20SAndroid Build Coastguard Worker 					if (!cur->level) {
481*2d543d20SAndroid Build Coastguard Worker 						free_seapp_context(cur);
482*2d543d20SAndroid Build Coastguard Worker 						goto oom;
483*2d543d20SAndroid Build Coastguard Worker 					}
484*2d543d20SAndroid Build Coastguard Worker 				} else if (!strcasecmp(name, "isPrivApp")) {
485*2d543d20SAndroid Build Coastguard Worker 					cur->isPrivAppSet = true;
486*2d543d20SAndroid Build Coastguard Worker 					if (!strcasecmp(value, "true"))
487*2d543d20SAndroid Build Coastguard Worker 						cur->isPrivApp = true;
488*2d543d20SAndroid Build Coastguard Worker 					else if (!strcasecmp(value, "false"))
489*2d543d20SAndroid Build Coastguard Worker 						cur->isPrivApp = false;
490*2d543d20SAndroid Build Coastguard Worker 					else {
491*2d543d20SAndroid Build Coastguard Worker 						free_seapp_context(cur);
492*2d543d20SAndroid Build Coastguard Worker 						goto err;
493*2d543d20SAndroid Build Coastguard Worker 					}
494*2d543d20SAndroid Build Coastguard Worker 				} else if (!strcasecmp(name, "minTargetSdkVersion")) {
495*2d543d20SAndroid Build Coastguard Worker 					cur->minTargetSdkVersion = get_minTargetSdkVersion(value);
496*2d543d20SAndroid Build Coastguard Worker 					if (cur->minTargetSdkVersion < 0) {
497*2d543d20SAndroid Build Coastguard Worker 						free_seapp_context(cur);
498*2d543d20SAndroid Build Coastguard Worker 						goto err;
499*2d543d20SAndroid Build Coastguard Worker 					}
500*2d543d20SAndroid Build Coastguard Worker 				} else if (!strcasecmp(name, "fromRunAs")) {
501*2d543d20SAndroid Build Coastguard Worker 					if (!strcasecmp(value, "true"))
502*2d543d20SAndroid Build Coastguard Worker 						cur->fromRunAs = true;
503*2d543d20SAndroid Build Coastguard Worker 					else if (!strcasecmp(value, "false"))
504*2d543d20SAndroid Build Coastguard Worker 						cur->fromRunAs = false;
505*2d543d20SAndroid Build Coastguard Worker 					else {
506*2d543d20SAndroid Build Coastguard Worker 						free_seapp_context(cur);
507*2d543d20SAndroid Build Coastguard Worker 						goto err;
508*2d543d20SAndroid Build Coastguard Worker 					}
509*2d543d20SAndroid Build Coastguard Worker 				} else if (!strcasecmp(name, "isIsolatedComputeApp")) {
510*2d543d20SAndroid Build Coastguard Worker 					if (!strcasecmp(value, "true"))
511*2d543d20SAndroid Build Coastguard Worker 						cur->isIsolatedComputeApp = true;
512*2d543d20SAndroid Build Coastguard Worker 					else if (!strcasecmp(value, "false"))
513*2d543d20SAndroid Build Coastguard Worker 						cur->isIsolatedComputeApp = false;
514*2d543d20SAndroid Build Coastguard Worker 					else {
515*2d543d20SAndroid Build Coastguard Worker 						free_seapp_context(cur);
516*2d543d20SAndroid Build Coastguard Worker 						goto err;
517*2d543d20SAndroid Build Coastguard Worker 					}
518*2d543d20SAndroid Build Coastguard Worker 				} else if (!strcasecmp(name, "isSdkSandboxAudit")) {
519*2d543d20SAndroid Build Coastguard Worker 					if (!strcasecmp(value, "true"))
520*2d543d20SAndroid Build Coastguard Worker 						cur->isSdkSandboxAudit = true;
521*2d543d20SAndroid Build Coastguard Worker 					else if (!strcasecmp(value, "false"))
522*2d543d20SAndroid Build Coastguard Worker 						cur->isSdkSandboxAudit = false;
523*2d543d20SAndroid Build Coastguard Worker 					else {
524*2d543d20SAndroid Build Coastguard Worker 						free_seapp_context(cur);
525*2d543d20SAndroid Build Coastguard Worker 						goto err;
526*2d543d20SAndroid Build Coastguard Worker 					}
527*2d543d20SAndroid Build Coastguard Worker 				} else if (!strcasecmp(name, "isSdkSandboxNext")) {
528*2d543d20SAndroid Build Coastguard Worker 					if (!strcasecmp(value, "true"))
529*2d543d20SAndroid Build Coastguard Worker 						cur->isSdkSandboxNext = true;
530*2d543d20SAndroid Build Coastguard Worker 					else if (!strcasecmp(value, "false"))
531*2d543d20SAndroid Build Coastguard Worker 						cur->isSdkSandboxNext = false;
532*2d543d20SAndroid Build Coastguard Worker 					else {
533*2d543d20SAndroid Build Coastguard Worker 						free_seapp_context(cur);
534*2d543d20SAndroid Build Coastguard Worker 						goto err;
535*2d543d20SAndroid Build Coastguard Worker 					}
536*2d543d20SAndroid Build Coastguard Worker 				} else {
537*2d543d20SAndroid Build Coastguard Worker 					free_seapp_context(cur);
538*2d543d20SAndroid Build Coastguard Worker 					goto err;
539*2d543d20SAndroid Build Coastguard Worker 				}
540*2d543d20SAndroid Build Coastguard Worker 
541*2d543d20SAndroid Build Coastguard Worker 				token = strtok_r(NULL, " \t", &saveptr);
542*2d543d20SAndroid Build Coastguard Worker 				if (!token)
543*2d543d20SAndroid Build Coastguard Worker 					break;
544*2d543d20SAndroid Build Coastguard Worker 			}
545*2d543d20SAndroid Build Coastguard Worker 
546*2d543d20SAndroid Build Coastguard Worker 			if (!cur->isPrivApp && cur->name.str &&
547*2d543d20SAndroid Build Coastguard Worker 			    (!cur->seinfo || !strcmp(cur->seinfo, "default"))) {
548*2d543d20SAndroid Build Coastguard Worker 				selinux_log(SELINUX_ERROR, "%s:  No specific seinfo value specified with name=\"%s\", on line %u:  insecure configuration!\n",
549*2d543d20SAndroid Build Coastguard Worker 					    seapp_contexts_files[i], cur->name.str, lineno);
550*2d543d20SAndroid Build Coastguard Worker 				free_seapp_context(cur);
551*2d543d20SAndroid Build Coastguard Worker 				goto err;
552*2d543d20SAndroid Build Coastguard Worker 			}
553*2d543d20SAndroid Build Coastguard Worker 
554*2d543d20SAndroid Build Coastguard Worker 			cur->partition = seapp_contexts_partitions[i];
555*2d543d20SAndroid Build Coastguard Worker 			seapp_contexts[nspec] = cur;
556*2d543d20SAndroid Build Coastguard Worker 			nspec++;
557*2d543d20SAndroid Build Coastguard Worker 			lineno++;
558*2d543d20SAndroid Build Coastguard Worker 		}
559*2d543d20SAndroid Build Coastguard Worker 		fclose(fp);
560*2d543d20SAndroid Build Coastguard Worker 		fp = NULL;
561*2d543d20SAndroid Build Coastguard Worker 	}
562*2d543d20SAndroid Build Coastguard Worker 
563*2d543d20SAndroid Build Coastguard Worker 	qsort(seapp_contexts, nspec, sizeof(struct seapp_context *),
564*2d543d20SAndroid Build Coastguard Worker 	      seapp_context_cmp);
565*2d543d20SAndroid Build Coastguard Worker 
566*2d543d20SAndroid Build Coastguard Worker 	for (int i = 0; i < nspec; i++) {
567*2d543d20SAndroid Build Coastguard Worker 		const struct seapp_context *s1 = seapp_contexts[i];
568*2d543d20SAndroid Build Coastguard Worker 		for (int j = i + 1; j < nspec; j++) {
569*2d543d20SAndroid Build Coastguard Worker 			const struct seapp_context *s2 = seapp_contexts[j];
570*2d543d20SAndroid Build Coastguard Worker 			if (seapp_context_cmp(&s1, &s2) != 0)
571*2d543d20SAndroid Build Coastguard Worker 				break;
572*2d543d20SAndroid Build Coastguard Worker 			/*
573*2d543d20SAndroid Build Coastguard Worker 			* Check for a duplicated entry on the input selectors.
574*2d543d20SAndroid Build Coastguard Worker 			* We already compared isSystemServer with seapp_context_cmp.
575*2d543d20SAndroid Build Coastguard Worker 			* We also have already checked that both entries specify the same
576*2d543d20SAndroid Build Coastguard Worker 			* string fields, so if s1 has a non-NULL string, then so does s2.
577*2d543d20SAndroid Build Coastguard Worker 			*/
578*2d543d20SAndroid Build Coastguard Worker 			bool dup = (!s1->user.str || !strcmp(s1->user.str, s2->user.str)) &&
579*2d543d20SAndroid Build Coastguard Worker 				(!s1->seinfo || !strcmp(s1->seinfo, s2->seinfo)) &&
580*2d543d20SAndroid Build Coastguard Worker 				(!s1->name.str || !strcmp(s1->name.str, s2->name.str)) &&
581*2d543d20SAndroid Build Coastguard Worker 				(!s1->isPrivAppSet || s1->isPrivApp == s2->isPrivApp) &&
582*2d543d20SAndroid Build Coastguard Worker 				(!s1->isEphemeralAppSet || s1->isEphemeralApp == s2->isEphemeralApp) &&
583*2d543d20SAndroid Build Coastguard Worker 				(s1->isIsolatedComputeApp == s2->isIsolatedComputeApp) &&
584*2d543d20SAndroid Build Coastguard Worker 				(s1->isSdkSandboxAudit == s2->isSdkSandboxAudit) &&
585*2d543d20SAndroid Build Coastguard Worker 				(s1->isSdkSandboxNext == s2->isSdkSandboxNext);
586*2d543d20SAndroid Build Coastguard Worker 
587*2d543d20SAndroid Build Coastguard Worker 			if (dup) {
588*2d543d20SAndroid Build Coastguard Worker 				selinux_log(SELINUX_ERROR, "seapp_contexts:  Duplicated entry\n");
589*2d543d20SAndroid Build Coastguard Worker 				if (s1->user.str)
590*2d543d20SAndroid Build Coastguard Worker 					selinux_log(SELINUX_ERROR, " user=%s\n", s1->user.str);
591*2d543d20SAndroid Build Coastguard Worker 				if (s1->seinfo)
592*2d543d20SAndroid Build Coastguard Worker 					selinux_log(SELINUX_ERROR, " seinfo=%s\n", s1->seinfo);
593*2d543d20SAndroid Build Coastguard Worker 				if (s1->name.str)
594*2d543d20SAndroid Build Coastguard Worker 					selinux_log(SELINUX_ERROR, " name=%s\n", s1->name.str);
595*2d543d20SAndroid Build Coastguard Worker 				if (s1->partition)
596*2d543d20SAndroid Build Coastguard Worker 					selinux_log(SELINUX_ERROR, " partition=%s\n", s1->partition);
597*2d543d20SAndroid Build Coastguard Worker 				goto err_no_log;
598*2d543d20SAndroid Build Coastguard Worker 			}
599*2d543d20SAndroid Build Coastguard Worker 		}
600*2d543d20SAndroid Build Coastguard Worker 	}
601*2d543d20SAndroid Build Coastguard Worker 
602*2d543d20SAndroid Build Coastguard Worker #if DEBUG
603*2d543d20SAndroid Build Coastguard Worker 	{
604*2d543d20SAndroid Build Coastguard Worker 		int i;
605*2d543d20SAndroid Build Coastguard Worker 		for (i = 0; i < nspec; i++) {
606*2d543d20SAndroid Build Coastguard Worker 			cur = seapp_contexts[i];
607*2d543d20SAndroid Build Coastguard Worker 			selinux_log(SELINUX_INFO, "%s:  isSystemServer=%s isEphemeralApp=%s "
608*2d543d20SAndroid Build Coastguard Worker 				"isIsolatedComputeApp=%s isSdkSandboxAudit=%s isSdkSandboxNext=%s "
609*2d543d20SAndroid Build Coastguard Worker 				"user=%s seinfo=%s name=%s isPrivApp=%s minTargetSdkVersion=%d "
610*2d543d20SAndroid Build Coastguard Worker 				"fromRunAs=%s -> domain=%s type=%s level=%s levelFrom=%s",
611*2d543d20SAndroid Build Coastguard Worker 				__FUNCTION__,
612*2d543d20SAndroid Build Coastguard Worker 				cur->isSystemServer ? "true" : "false",
613*2d543d20SAndroid Build Coastguard Worker 				cur->isEphemeralAppSet ? (cur->isEphemeralApp ? "true" : "false") : "null",
614*2d543d20SAndroid Build Coastguard Worker 				cur->isIsolatedComputeApp ? "true" : "false",
615*2d543d20SAndroid Build Coastguard Worker 				cur->isSdkSandboxAudit ? "true" : "false",
616*2d543d20SAndroid Build Coastguard Worker 				cur->isSdkSandboxNext ? "true" : "false",
617*2d543d20SAndroid Build Coastguard Worker 				cur->user.str,
618*2d543d20SAndroid Build Coastguard Worker 				cur->seinfo, cur->name.str,
619*2d543d20SAndroid Build Coastguard Worker 				cur->isPrivAppSet ? (cur->isPrivApp ? "true" : "false") : "null",
620*2d543d20SAndroid Build Coastguard Worker 				cur->minTargetSdkVersion,
621*2d543d20SAndroid Build Coastguard Worker 				cur->fromRunAs ? "true" : "false",
622*2d543d20SAndroid Build Coastguard Worker 				cur->domain, cur->type, cur->level,
623*2d543d20SAndroid Build Coastguard Worker 				levelFromName[cur->levelFrom]);
624*2d543d20SAndroid Build Coastguard Worker 		}
625*2d543d20SAndroid Build Coastguard Worker 	}
626*2d543d20SAndroid Build Coastguard Worker #endif
627*2d543d20SAndroid Build Coastguard Worker 
628*2d543d20SAndroid Build Coastguard Worker 	ret = 0;
629*2d543d20SAndroid Build Coastguard Worker 
630*2d543d20SAndroid Build Coastguard Worker out:
631*2d543d20SAndroid Build Coastguard Worker 	if (fp) {
632*2d543d20SAndroid Build Coastguard Worker 		fclose(fp);
633*2d543d20SAndroid Build Coastguard Worker 	}
634*2d543d20SAndroid Build Coastguard Worker 	return ret;
635*2d543d20SAndroid Build Coastguard Worker 
636*2d543d20SAndroid Build Coastguard Worker err:
637*2d543d20SAndroid Build Coastguard Worker 	selinux_log(SELINUX_ERROR, "%s:  Invalid entry on line %u\n",
638*2d543d20SAndroid Build Coastguard Worker 		    seapp_contexts_files[i], lineno);
639*2d543d20SAndroid Build Coastguard Worker err_no_log:
640*2d543d20SAndroid Build Coastguard Worker 	free_seapp_contexts();
641*2d543d20SAndroid Build Coastguard Worker 	ret = -1;
642*2d543d20SAndroid Build Coastguard Worker 	goto out;
643*2d543d20SAndroid Build Coastguard Worker oom:
644*2d543d20SAndroid Build Coastguard Worker 	selinux_log(SELINUX_ERROR,
645*2d543d20SAndroid Build Coastguard Worker 		    "%s:  Out of memory\n", __FUNCTION__);
646*2d543d20SAndroid Build Coastguard Worker 	free_seapp_contexts();
647*2d543d20SAndroid Build Coastguard Worker 	ret = -1;
648*2d543d20SAndroid Build Coastguard Worker 	goto out;
649*2d543d20SAndroid Build Coastguard Worker }
650*2d543d20SAndroid Build Coastguard Worker 
selinux_android_seapp_context_reload(void)651*2d543d20SAndroid Build Coastguard Worker int selinux_android_seapp_context_reload(void)
652*2d543d20SAndroid Build Coastguard Worker {
653*2d543d20SAndroid Build Coastguard Worker 	return seapp_context_reload_internal(&seapp_context_paths);
654*2d543d20SAndroid Build Coastguard Worker }
655*2d543d20SAndroid Build Coastguard Worker 
656*2d543d20SAndroid Build Coastguard Worker /* indirection to support pthread_once */
seapp_context_init(void)657*2d543d20SAndroid Build Coastguard Worker static void seapp_context_init(void)
658*2d543d20SAndroid Build Coastguard Worker {
659*2d543d20SAndroid Build Coastguard Worker 	selinux_android_seapp_context_reload();
660*2d543d20SAndroid Build Coastguard Worker }
661*2d543d20SAndroid Build Coastguard Worker 
662*2d543d20SAndroid Build Coastguard Worker static pthread_once_t seapp_once = PTHREAD_ONCE_INIT;
663*2d543d20SAndroid Build Coastguard Worker 
selinux_android_seapp_context_init(void)664*2d543d20SAndroid Build Coastguard Worker void selinux_android_seapp_context_init(void) {
665*2d543d20SAndroid Build Coastguard Worker 	__selinux_once(seapp_once, seapp_context_init);
666*2d543d20SAndroid Build Coastguard Worker }
667*2d543d20SAndroid Build Coastguard Worker 
668*2d543d20SAndroid Build Coastguard Worker /*
669*2d543d20SAndroid Build Coastguard Worker  * Max id that can be mapped to category set uniquely
670*2d543d20SAndroid Build Coastguard Worker  * using the current scheme.
671*2d543d20SAndroid Build Coastguard Worker  */
672*2d543d20SAndroid Build Coastguard Worker #define CAT_MAPPING_MAX_ID (0x1<<16)
673*2d543d20SAndroid Build Coastguard Worker 
674*2d543d20SAndroid Build Coastguard Worker #define PRIVILEGED_APP_STR "privapp"
675*2d543d20SAndroid Build Coastguard Worker #define ISOLATED_COMPUTE_APP_STR "isolatedComputeApp"
676*2d543d20SAndroid Build Coastguard Worker #define APPLY_SDK_SANDBOX_AUDIT_RESTRICTIONS_STR "isSdkSandboxAudit"
677*2d543d20SAndroid Build Coastguard Worker #define APPLY_SDK_SANDBOX_NEXT_RESTRICTIONS_STR "isSdkSandboxNext"
678*2d543d20SAndroid Build Coastguard Worker #define EPHEMERAL_APP_STR "ephemeralapp"
679*2d543d20SAndroid Build Coastguard Worker #define TARGETSDKVERSION_STR "targetSdkVersion"
680*2d543d20SAndroid Build Coastguard Worker #define PARTITION_STR "partition"
681*2d543d20SAndroid Build Coastguard Worker #define FROM_RUNAS_STR "fromRunAs"
682*2d543d20SAndroid Build Coastguard Worker #define COMPLETE_STR "complete"
683*2d543d20SAndroid Build Coastguard Worker 
is_preinstalled_app_partition_valid(const char * app_policy,const char * app_partition)684*2d543d20SAndroid Build Coastguard Worker static bool is_preinstalled_app_partition_valid(const char *app_policy, const char *app_partition) {
685*2d543d20SAndroid Build Coastguard Worker 	// We forbid system/system_ext/product installed apps from being labeled with vendor sepolicy.
686*2d543d20SAndroid Build Coastguard Worker 	// So, either the app shouldn't be platform, or the spec should be platform.
687*2d543d20SAndroid Build Coastguard Worker 	return !(is_platform(app_partition) && !is_platform(app_policy));
688*2d543d20SAndroid Build Coastguard Worker }
689*2d543d20SAndroid Build Coastguard Worker 
690*2d543d20SAndroid Build Coastguard Worker /* Sets the categories of ctx based on the level request */
set_range_from_level(context_t ctx,enum levelFrom levelFrom,uid_t userid,uid_t appid)691*2d543d20SAndroid Build Coastguard Worker int set_range_from_level(context_t ctx, enum levelFrom levelFrom, uid_t userid, uid_t appid)
692*2d543d20SAndroid Build Coastguard Worker {
693*2d543d20SAndroid Build Coastguard Worker 	char level[255];
694*2d543d20SAndroid Build Coastguard Worker 	switch (levelFrom) {
695*2d543d20SAndroid Build Coastguard Worker 	case LEVELFROM_NONE:
696*2d543d20SAndroid Build Coastguard Worker 		strncpy(level, "s0", sizeof level);
697*2d543d20SAndroid Build Coastguard Worker 		break;
698*2d543d20SAndroid Build Coastguard Worker 	case LEVELFROM_APP:
699*2d543d20SAndroid Build Coastguard Worker 		snprintf(level, sizeof level, "s0:c%u,c%u",
700*2d543d20SAndroid Build Coastguard Worker 			 appid & 0xff,
701*2d543d20SAndroid Build Coastguard Worker 			 256 + (appid>>8 & 0xff));
702*2d543d20SAndroid Build Coastguard Worker 		break;
703*2d543d20SAndroid Build Coastguard Worker 	case LEVELFROM_USER:
704*2d543d20SAndroid Build Coastguard Worker 		snprintf(level, sizeof level, "s0:c%u,c%u",
705*2d543d20SAndroid Build Coastguard Worker 			 512 + (userid & 0xff),
706*2d543d20SAndroid Build Coastguard Worker 			 768 + (userid>>8 & 0xff));
707*2d543d20SAndroid Build Coastguard Worker 		break;
708*2d543d20SAndroid Build Coastguard Worker 	case LEVELFROM_ALL:
709*2d543d20SAndroid Build Coastguard Worker 		snprintf(level, sizeof level, "s0:c%u,c%u,c%u,c%u",
710*2d543d20SAndroid Build Coastguard Worker 			 appid & 0xff,
711*2d543d20SAndroid Build Coastguard Worker 			 256 + (appid>>8 & 0xff),
712*2d543d20SAndroid Build Coastguard Worker 			 512 + (userid & 0xff),
713*2d543d20SAndroid Build Coastguard Worker 			 768 + (userid>>8 & 0xff));
714*2d543d20SAndroid Build Coastguard Worker 		break;
715*2d543d20SAndroid Build Coastguard Worker 	default:
716*2d543d20SAndroid Build Coastguard Worker 		return -1;
717*2d543d20SAndroid Build Coastguard Worker 	}
718*2d543d20SAndroid Build Coastguard Worker 	if (context_range_set(ctx, level)) {
719*2d543d20SAndroid Build Coastguard Worker 		return -2;
720*2d543d20SAndroid Build Coastguard Worker 	}
721*2d543d20SAndroid Build Coastguard Worker 	return 0;
722*2d543d20SAndroid Build Coastguard Worker }
723*2d543d20SAndroid Build Coastguard Worker 
parse_seinfo(const char * seinfo,struct parsed_seinfo * info)724*2d543d20SAndroid Build Coastguard Worker int parse_seinfo(const char* seinfo, struct parsed_seinfo* info) {
725*2d543d20SAndroid Build Coastguard Worker 	char local_seinfo[SEINFO_BUFSIZ];
726*2d543d20SAndroid Build Coastguard Worker 
727*2d543d20SAndroid Build Coastguard Worker 	memset(info, 0, sizeof(*info));
728*2d543d20SAndroid Build Coastguard Worker 
729*2d543d20SAndroid Build Coastguard Worker 	if (strlen(seinfo) >= SEINFO_BUFSIZ) {
730*2d543d20SAndroid Build Coastguard Worker 		selinux_log(SELINUX_ERROR, "%s:  seinfo is too large to be parsed: %zu\n",
731*2d543d20SAndroid Build Coastguard Worker 				__FUNCTION__, strlen(seinfo));
732*2d543d20SAndroid Build Coastguard Worker 		return -1;
733*2d543d20SAndroid Build Coastguard Worker 	}
734*2d543d20SAndroid Build Coastguard Worker 	strncpy(local_seinfo, seinfo, SEINFO_BUFSIZ);
735*2d543d20SAndroid Build Coastguard Worker 
736*2d543d20SAndroid Build Coastguard Worker 	char *token;
737*2d543d20SAndroid Build Coastguard Worker 	char *saved_colon_ptr = NULL;
738*2d543d20SAndroid Build Coastguard Worker 	char *saved_equal_ptr;
739*2d543d20SAndroid Build Coastguard Worker 	bool first = true;
740*2d543d20SAndroid Build Coastguard Worker 	for (token = strtok_r(local_seinfo, ":", &saved_colon_ptr); token; token = strtok_r(NULL, ":", &saved_colon_ptr)) {
741*2d543d20SAndroid Build Coastguard Worker 		if (first) {
742*2d543d20SAndroid Build Coastguard Worker 			strncpy(info->base, token, SEINFO_BUFSIZ);
743*2d543d20SAndroid Build Coastguard Worker 			first = false;
744*2d543d20SAndroid Build Coastguard Worker 			continue;
745*2d543d20SAndroid Build Coastguard Worker 		}
746*2d543d20SAndroid Build Coastguard Worker 		if (!strcmp(token, PRIVILEGED_APP_STR)) {
747*2d543d20SAndroid Build Coastguard Worker 			info->is |= IS_PRIV_APP;
748*2d543d20SAndroid Build Coastguard Worker 			continue;
749*2d543d20SAndroid Build Coastguard Worker 		}
750*2d543d20SAndroid Build Coastguard Worker 		if (!strcmp(token, EPHEMERAL_APP_STR)) {
751*2d543d20SAndroid Build Coastguard Worker 			info->is |= IS_EPHEMERAL_APP;
752*2d543d20SAndroid Build Coastguard Worker 			continue;
753*2d543d20SAndroid Build Coastguard Worker 		}
754*2d543d20SAndroid Build Coastguard Worker 		if (!strcmp(token, ISOLATED_COMPUTE_APP_STR)) {
755*2d543d20SAndroid Build Coastguard Worker 			info->is |= IS_ISOLATED_COMPUTE_APP;
756*2d543d20SAndroid Build Coastguard Worker 			continue;
757*2d543d20SAndroid Build Coastguard Worker 		}
758*2d543d20SAndroid Build Coastguard Worker 		if (!strcmp(token, APPLY_SDK_SANDBOX_AUDIT_RESTRICTIONS_STR)) {
759*2d543d20SAndroid Build Coastguard Worker 			info->is |= IS_SDK_SANDBOX_AUDIT;
760*2d543d20SAndroid Build Coastguard Worker 			continue;
761*2d543d20SAndroid Build Coastguard Worker 		}
762*2d543d20SAndroid Build Coastguard Worker 		if (!strcmp(token, APPLY_SDK_SANDBOX_NEXT_RESTRICTIONS_STR)) {
763*2d543d20SAndroid Build Coastguard Worker 			info->is |= IS_SDK_SANDBOX_NEXT;
764*2d543d20SAndroid Build Coastguard Worker 			continue;
765*2d543d20SAndroid Build Coastguard Worker 		}
766*2d543d20SAndroid Build Coastguard Worker 		if (!strcmp(token, FROM_RUNAS_STR)) {
767*2d543d20SAndroid Build Coastguard Worker 			info->is |= IS_FROM_RUN_AS;
768*2d543d20SAndroid Build Coastguard Worker 			continue;
769*2d543d20SAndroid Build Coastguard Worker 		}
770*2d543d20SAndroid Build Coastguard Worker 		if (!strncmp(token, TARGETSDKVERSION_STR, strlen(TARGETSDKVERSION_STR))) {
771*2d543d20SAndroid Build Coastguard Worker 			saved_equal_ptr = NULL;
772*2d543d20SAndroid Build Coastguard Worker 			char *subtoken = strtok_r(token, "=", &saved_equal_ptr);
773*2d543d20SAndroid Build Coastguard Worker 			subtoken = strtok_r(NULL, "=", &saved_equal_ptr);
774*2d543d20SAndroid Build Coastguard Worker 			if (!subtoken) {
775*2d543d20SAndroid Build Coastguard Worker 				selinux_log(SELINUX_ERROR, "%s:  Invalid targetSdkVersion: %s in %s\n",
776*2d543d20SAndroid Build Coastguard Worker 						__FUNCTION__, token, seinfo);
777*2d543d20SAndroid Build Coastguard Worker 				return -1;
778*2d543d20SAndroid Build Coastguard Worker 			}
779*2d543d20SAndroid Build Coastguard Worker 			info->targetSdkVersion = strtol(subtoken, NULL, 10);
780*2d543d20SAndroid Build Coastguard Worker 			continue;
781*2d543d20SAndroid Build Coastguard Worker 		}
782*2d543d20SAndroid Build Coastguard Worker 		if (!strncmp(token, PARTITION_STR, strlen(PARTITION_STR))) {
783*2d543d20SAndroid Build Coastguard Worker 			saved_equal_ptr = NULL;
784*2d543d20SAndroid Build Coastguard Worker 			char *subtoken = strtok_r(token, "=", &saved_equal_ptr);
785*2d543d20SAndroid Build Coastguard Worker 			subtoken = strtok_r(NULL, "=", &saved_equal_ptr);
786*2d543d20SAndroid Build Coastguard Worker 			if (!subtoken) {
787*2d543d20SAndroid Build Coastguard Worker 				selinux_log(SELINUX_ERROR, "%s:  Invalid partition: %s in %s\n",
788*2d543d20SAndroid Build Coastguard Worker 						__FUNCTION__, token, seinfo);
789*2d543d20SAndroid Build Coastguard Worker 				return -1;
790*2d543d20SAndroid Build Coastguard Worker 			}
791*2d543d20SAndroid Build Coastguard Worker 			info->isPreinstalledApp = true;
792*2d543d20SAndroid Build Coastguard Worker 			strncpy(info->partition, subtoken, strlen(subtoken));
793*2d543d20SAndroid Build Coastguard Worker 			continue;
794*2d543d20SAndroid Build Coastguard Worker 		}
795*2d543d20SAndroid Build Coastguard Worker 		if (!strcmp(token, COMPLETE_STR)) {
796*2d543d20SAndroid Build Coastguard Worker 			break;
797*2d543d20SAndroid Build Coastguard Worker 		}
798*2d543d20SAndroid Build Coastguard Worker 		selinux_log(SELINUX_WARNING, "%s:  Ignoring unknown seinfo field: %s in %s\n",
799*2d543d20SAndroid Build Coastguard Worker 				__FUNCTION__, token, seinfo);
800*2d543d20SAndroid Build Coastguard Worker 	}
801*2d543d20SAndroid Build Coastguard Worker 	return 0;
802*2d543d20SAndroid Build Coastguard Worker }
803*2d543d20SAndroid Build Coastguard Worker 
804*2d543d20SAndroid Build Coastguard Worker /*
805*2d543d20SAndroid Build Coastguard Worker  * This code is Android specific, bionic guarantees that
806*2d543d20SAndroid Build Coastguard Worker  * calls to non-reentrant getpwuid() are thread safe.
807*2d543d20SAndroid Build Coastguard Worker  */
808*2d543d20SAndroid Build Coastguard Worker struct passwd *(*seapp_getpwuid)(uid_t uid) = getpwuid;
809*2d543d20SAndroid Build Coastguard Worker 
seapp_context_lookup_internal(enum seapp_kind kind,uid_t uid,bool isSystemServer,const char * seinfo,const char * pkgname,context_t ctx)810*2d543d20SAndroid Build Coastguard Worker int seapp_context_lookup_internal(enum seapp_kind kind,
811*2d543d20SAndroid Build Coastguard Worker 				uid_t uid,
812*2d543d20SAndroid Build Coastguard Worker 				bool isSystemServer,
813*2d543d20SAndroid Build Coastguard Worker 				const char *seinfo,
814*2d543d20SAndroid Build Coastguard Worker 				const char *pkgname,
815*2d543d20SAndroid Build Coastguard Worker 				context_t ctx)
816*2d543d20SAndroid Build Coastguard Worker {
817*2d543d20SAndroid Build Coastguard Worker 	struct passwd *pwd;
818*2d543d20SAndroid Build Coastguard Worker 	const char *username = NULL;
819*2d543d20SAndroid Build Coastguard Worker 	struct seapp_context *cur = NULL;
820*2d543d20SAndroid Build Coastguard Worker 	int i;
821*2d543d20SAndroid Build Coastguard Worker 	uid_t userid;
822*2d543d20SAndroid Build Coastguard Worker 	uid_t appid;
823*2d543d20SAndroid Build Coastguard Worker 	struct parsed_seinfo info;
824*2d543d20SAndroid Build Coastguard Worker 	memset(&info, 0, sizeof(info));
825*2d543d20SAndroid Build Coastguard Worker 
826*2d543d20SAndroid Build Coastguard Worker 	if (seinfo) {
827*2d543d20SAndroid Build Coastguard Worker 		int ret = parse_seinfo(seinfo, &info);
828*2d543d20SAndroid Build Coastguard Worker 		if (ret) {
829*2d543d20SAndroid Build Coastguard Worker 			selinux_log(SELINUX_ERROR, "%s:  Invalid seinfo: %s\n", __FUNCTION__, seinfo);
830*2d543d20SAndroid Build Coastguard Worker 			goto err;
831*2d543d20SAndroid Build Coastguard Worker 		}
832*2d543d20SAndroid Build Coastguard Worker 		if (info.targetSdkVersion < 0) {
833*2d543d20SAndroid Build Coastguard Worker 			selinux_log(SELINUX_ERROR,
834*2d543d20SAndroid Build Coastguard Worker 					"%s:  Invalid targetSdkVersion passed for app with uid %d, seinfo %s, name %s\n",
835*2d543d20SAndroid Build Coastguard Worker 					__FUNCTION__, uid, seinfo, pkgname);
836*2d543d20SAndroid Build Coastguard Worker 			goto err;
837*2d543d20SAndroid Build Coastguard Worker 		}
838*2d543d20SAndroid Build Coastguard Worker 	}
839*2d543d20SAndroid Build Coastguard Worker 
840*2d543d20SAndroid Build Coastguard Worker 	userid = uid / AID_USER_OFFSET;
841*2d543d20SAndroid Build Coastguard Worker 	appid = uid % AID_USER_OFFSET;
842*2d543d20SAndroid Build Coastguard Worker 	if (appid < AID_APP_START) {
843*2d543d20SAndroid Build Coastguard Worker 		pwd = seapp_getpwuid(appid);
844*2d543d20SAndroid Build Coastguard Worker 		if (!pwd)
845*2d543d20SAndroid Build Coastguard Worker 			goto err;
846*2d543d20SAndroid Build Coastguard Worker 		username = pwd->pw_name;
847*2d543d20SAndroid Build Coastguard Worker 	} else if (appid < AID_SDK_SANDBOX_PROCESS_START) {
848*2d543d20SAndroid Build Coastguard Worker 		username = "_app";
849*2d543d20SAndroid Build Coastguard Worker 		appid -= AID_APP_START;
850*2d543d20SAndroid Build Coastguard Worker 	} else if (appid < AID_ISOLATED_START) {
851*2d543d20SAndroid Build Coastguard Worker 		username = "_sdksandbox";
852*2d543d20SAndroid Build Coastguard Worker 		appid -= AID_SDK_SANDBOX_PROCESS_START;
853*2d543d20SAndroid Build Coastguard Worker 	} else {
854*2d543d20SAndroid Build Coastguard Worker 		username = "_isolated";
855*2d543d20SAndroid Build Coastguard Worker 		appid -= AID_ISOLATED_START;
856*2d543d20SAndroid Build Coastguard Worker 	}
857*2d543d20SAndroid Build Coastguard Worker 
858*2d543d20SAndroid Build Coastguard Worker 	if (appid >= CAT_MAPPING_MAX_ID || userid >= CAT_MAPPING_MAX_ID)
859*2d543d20SAndroid Build Coastguard Worker 		goto err;
860*2d543d20SAndroid Build Coastguard Worker 
861*2d543d20SAndroid Build Coastguard Worker 	for (i = 0; i < nspec; i++) {
862*2d543d20SAndroid Build Coastguard Worker 		cur = seapp_contexts[i];
863*2d543d20SAndroid Build Coastguard Worker 
864*2d543d20SAndroid Build Coastguard Worker 		if (cur->isSystemServer != isSystemServer)
865*2d543d20SAndroid Build Coastguard Worker 			continue;
866*2d543d20SAndroid Build Coastguard Worker 
867*2d543d20SAndroid Build Coastguard Worker 		if (cur->isEphemeralAppSet && cur->isEphemeralApp != ((info.is & IS_EPHEMERAL_APP) != 0))
868*2d543d20SAndroid Build Coastguard Worker 			continue;
869*2d543d20SAndroid Build Coastguard Worker 
870*2d543d20SAndroid Build Coastguard Worker 		if (cur->user.str) {
871*2d543d20SAndroid Build Coastguard Worker 			if (cur->user.is_prefix) {
872*2d543d20SAndroid Build Coastguard Worker 				if (strncasecmp(username, cur->user.str, cur->user.len-1))
873*2d543d20SAndroid Build Coastguard Worker 					continue;
874*2d543d20SAndroid Build Coastguard Worker 			} else {
875*2d543d20SAndroid Build Coastguard Worker 				if (strcasecmp(username, cur->user.str))
876*2d543d20SAndroid Build Coastguard Worker 					continue;
877*2d543d20SAndroid Build Coastguard Worker 			}
878*2d543d20SAndroid Build Coastguard Worker 		}
879*2d543d20SAndroid Build Coastguard Worker 
880*2d543d20SAndroid Build Coastguard Worker 		if (cur->seinfo) {
881*2d543d20SAndroid Build Coastguard Worker 			if (!seinfo || strcasecmp(info.base, cur->seinfo))
882*2d543d20SAndroid Build Coastguard Worker 				continue;
883*2d543d20SAndroid Build Coastguard Worker 		}
884*2d543d20SAndroid Build Coastguard Worker 
885*2d543d20SAndroid Build Coastguard Worker 		if (cur->name.str) {
886*2d543d20SAndroid Build Coastguard Worker 			if(!pkgname)
887*2d543d20SAndroid Build Coastguard Worker 				continue;
888*2d543d20SAndroid Build Coastguard Worker 
889*2d543d20SAndroid Build Coastguard Worker 			if (cur->name.is_prefix) {
890*2d543d20SAndroid Build Coastguard Worker 				if (strncasecmp(pkgname, cur->name.str, cur->name.len-1))
891*2d543d20SAndroid Build Coastguard Worker 					continue;
892*2d543d20SAndroid Build Coastguard Worker 			} else {
893*2d543d20SAndroid Build Coastguard Worker 				if (strcasecmp(pkgname, cur->name.str))
894*2d543d20SAndroid Build Coastguard Worker 					continue;
895*2d543d20SAndroid Build Coastguard Worker 			}
896*2d543d20SAndroid Build Coastguard Worker 		}
897*2d543d20SAndroid Build Coastguard Worker 
898*2d543d20SAndroid Build Coastguard Worker 		if (cur->isPrivAppSet && cur->isPrivApp != ((info.is & IS_PRIV_APP) != 0))
899*2d543d20SAndroid Build Coastguard Worker 			continue;
900*2d543d20SAndroid Build Coastguard Worker 
901*2d543d20SAndroid Build Coastguard Worker 		if (cur->minTargetSdkVersion > info.targetSdkVersion)
902*2d543d20SAndroid Build Coastguard Worker 			continue;
903*2d543d20SAndroid Build Coastguard Worker 
904*2d543d20SAndroid Build Coastguard Worker 		if (cur->fromRunAs != ((info.is & IS_FROM_RUN_AS) != 0))
905*2d543d20SAndroid Build Coastguard Worker 			continue;
906*2d543d20SAndroid Build Coastguard Worker 
907*2d543d20SAndroid Build Coastguard Worker 		if (cur->isIsolatedComputeApp != ((info.is & IS_ISOLATED_COMPUTE_APP) != 0))
908*2d543d20SAndroid Build Coastguard Worker 			continue;
909*2d543d20SAndroid Build Coastguard Worker 
910*2d543d20SAndroid Build Coastguard Worker 		if (cur->isSdkSandboxAudit != ((info.is & IS_SDK_SANDBOX_AUDIT) != 0))
911*2d543d20SAndroid Build Coastguard Worker 			continue;
912*2d543d20SAndroid Build Coastguard Worker 
913*2d543d20SAndroid Build Coastguard Worker 		if (cur->isSdkSandboxNext != ((info.is & IS_SDK_SANDBOX_NEXT) != 0))
914*2d543d20SAndroid Build Coastguard Worker 			continue;
915*2d543d20SAndroid Build Coastguard Worker 
916*2d543d20SAndroid Build Coastguard Worker 		if (kind == SEAPP_TYPE && !cur->type)
917*2d543d20SAndroid Build Coastguard Worker 			continue;
918*2d543d20SAndroid Build Coastguard Worker 		else if (kind == SEAPP_DOMAIN && !cur->domain)
919*2d543d20SAndroid Build Coastguard Worker 			continue;
920*2d543d20SAndroid Build Coastguard Worker 
921*2d543d20SAndroid Build Coastguard Worker 		if (kind == SEAPP_TYPE) {
922*2d543d20SAndroid Build Coastguard Worker 			if (context_type_set(ctx, cur->type))
923*2d543d20SAndroid Build Coastguard Worker 				goto oom;
924*2d543d20SAndroid Build Coastguard Worker 		} else if (kind == SEAPP_DOMAIN) {
925*2d543d20SAndroid Build Coastguard Worker 			if (context_type_set(ctx, cur->domain))
926*2d543d20SAndroid Build Coastguard Worker 				goto oom;
927*2d543d20SAndroid Build Coastguard Worker 		}
928*2d543d20SAndroid Build Coastguard Worker 
929*2d543d20SAndroid Build Coastguard Worker 		if (cur->levelFrom != LEVELFROM_NONE) {
930*2d543d20SAndroid Build Coastguard Worker 			int res = set_range_from_level(ctx, cur->levelFrom, userid, appid);
931*2d543d20SAndroid Build Coastguard Worker 			if (res != 0) {
932*2d543d20SAndroid Build Coastguard Worker 				return res;
933*2d543d20SAndroid Build Coastguard Worker 			}
934*2d543d20SAndroid Build Coastguard Worker 		} else if (cur->level) {
935*2d543d20SAndroid Build Coastguard Worker 			if (context_range_set(ctx, cur->level))
936*2d543d20SAndroid Build Coastguard Worker 				goto oom;
937*2d543d20SAndroid Build Coastguard Worker 		}
938*2d543d20SAndroid Build Coastguard Worker 
939*2d543d20SAndroid Build Coastguard Worker 		if (info.isPreinstalledApp
940*2d543d20SAndroid Build Coastguard Worker 				&& !is_preinstalled_app_partition_valid(cur->partition, info.partition)) {
941*2d543d20SAndroid Build Coastguard Worker 			// TODO(b/280547417): make this an error after fixing violations
942*2d543d20SAndroid Build Coastguard Worker 			selinux_log(SELINUX_WARNING,
943*2d543d20SAndroid Build Coastguard Worker 				"%s:  App %s preinstalled to %s can't be labeled with %s sepolicy",
944*2d543d20SAndroid Build Coastguard Worker 				__FUNCTION__, pkgname, info.partition, cur->partition);
945*2d543d20SAndroid Build Coastguard Worker 		}
946*2d543d20SAndroid Build Coastguard Worker 
947*2d543d20SAndroid Build Coastguard Worker 		break;
948*2d543d20SAndroid Build Coastguard Worker 	}
949*2d543d20SAndroid Build Coastguard Worker 
950*2d543d20SAndroid Build Coastguard Worker 	if (kind == SEAPP_DOMAIN && i == nspec) {
951*2d543d20SAndroid Build Coastguard Worker 		/*
952*2d543d20SAndroid Build Coastguard Worker 		 * No match.
953*2d543d20SAndroid Build Coastguard Worker 		 * Fail to prevent staying in the zygote's context.
954*2d543d20SAndroid Build Coastguard Worker 		 */
955*2d543d20SAndroid Build Coastguard Worker 		selinux_log(SELINUX_ERROR,
956*2d543d20SAndroid Build Coastguard Worker 			    "%s:  No match for app with uid %d, seinfo %s, name %s\n",
957*2d543d20SAndroid Build Coastguard Worker 			    __FUNCTION__, uid, seinfo, pkgname);
958*2d543d20SAndroid Build Coastguard Worker 
959*2d543d20SAndroid Build Coastguard Worker 		if (security_getenforce() == 1)
960*2d543d20SAndroid Build Coastguard Worker 			goto err;
961*2d543d20SAndroid Build Coastguard Worker 	}
962*2d543d20SAndroid Build Coastguard Worker 
963*2d543d20SAndroid Build Coastguard Worker 	return 0;
964*2d543d20SAndroid Build Coastguard Worker err:
965*2d543d20SAndroid Build Coastguard Worker 	return -1;
966*2d543d20SAndroid Build Coastguard Worker oom:
967*2d543d20SAndroid Build Coastguard Worker 	return -2;
968*2d543d20SAndroid Build Coastguard Worker }
969*2d543d20SAndroid Build Coastguard Worker 
seapp_context_lookup(enum seapp_kind kind,uid_t uid,bool isSystemServer,const char * seinfo,const char * pkgname,context_t ctx)970*2d543d20SAndroid Build Coastguard Worker int seapp_context_lookup(enum seapp_kind kind,
971*2d543d20SAndroid Build Coastguard Worker 				uid_t uid,
972*2d543d20SAndroid Build Coastguard Worker 				bool isSystemServer,
973*2d543d20SAndroid Build Coastguard Worker 				const char *seinfo,
974*2d543d20SAndroid Build Coastguard Worker 				const char *pkgname,
975*2d543d20SAndroid Build Coastguard Worker 				context_t ctx)
976*2d543d20SAndroid Build Coastguard Worker {
977*2d543d20SAndroid Build Coastguard Worker 	// Ensure the default context files are loaded.
978*2d543d20SAndroid Build Coastguard Worker 	selinux_android_seapp_context_init();
979*2d543d20SAndroid Build Coastguard Worker 	return seapp_context_lookup_internal(kind, uid, isSystemServer, seinfo, pkgname, ctx);
980*2d543d20SAndroid Build Coastguard Worker }
981