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