1 #include <errno.h>
2 #include <fnmatch.h>
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <unistd.h>
6
7 #include <log/log.h>
8 #include <selinux/android.h>
9 #include <selinux/label.h>
10
11 #include "android_internal.h"
12 #include "callbacks.h"
13
14 #ifdef __ANDROID_VNDK__
15 #ifndef LOG_EVENT_STRING
16 #define LOG_EVENT_STRING(...)
17 #endif // LOG_EVENT_STRING
18 #endif // __ANDROID_VNDK__
19
20 static const path_alts_t service_context_paths = { .paths = {
21 {
22 "/system/etc/selinux/plat_service_contexts",
23 "/plat_service_contexts"
24 },
25 {
26 "/system_ext/etc/selinux/system_ext_service_contexts",
27 "/system_ext_service_contexts"
28 },
29 {
30 "/product/etc/selinux/product_service_contexts",
31 "/product_service_contexts"
32 },
33 {
34 "/vendor/etc/selinux/vendor_service_contexts",
35 "/vendor_service_contexts"
36 },
37 {
38 "/odm/etc/selinux/odm_service_contexts",
39 }
40 }};
41
42 static const path_alts_t hwservice_context_paths = { .paths = {
43 {
44 "/system/etc/selinux/plat_hwservice_contexts",
45 "/plat_hwservice_contexts"
46 },
47 {
48 "/system_ext/etc/selinux/system_ext_hwservice_contexts",
49 "/system_ext_hwservice_contexts"
50 },
51 {
52 "/product/etc/selinux/product_hwservice_contexts",
53 "/product_hwservice_contexts"
54 },
55 {
56 "/vendor/etc/selinux/vendor_hwservice_contexts",
57 "/vendor_hwservice_contexts"
58 },
59 {
60 "/odm/etc/selinux/odm_hwservice_contexts",
61 "/odm_hwservice_contexts"
62 },
63 }};
64
65 static const path_alts_t vndservice_context_paths = { .paths = {
66 {
67 "/vendor/etc/selinux/vndservice_contexts",
68 "/vndservice_contexts"
69 }
70 }};
71
72 static const path_alts_t keystore2_context_paths = { .paths = {
73 {
74 "/system/etc/selinux/plat_keystore2_key_contexts",
75 "/plat_keystore2_key_contexts"
76 },
77 {
78 "/system_ext/etc/selinux/system_ext_keystore2_key_contexts",
79 "/system_ext_keystore2_key_contexts"
80 },
81 {
82 "/product/etc/selinux/product_keystore2_key_contexts",
83 "/product_keystore2_key_contexts"
84 },
85 {
86 "/vendor/etc/selinux/vendor_keystore2_key_contexts",
87 "/vendor_keystore2_key_contexts"
88 }
89 }};
90
91 static const path_alts_t tee_service_context_paths = { .paths = {
92 {
93 "/system/etc/selinux/plat_tee_service_contexts",
94 "/plat_tee_service_contexts"
95 },
96 {
97 "/system_ext/etc/selinux/system_ext_tee_service_contexts",
98 "/system_ext_tee_service_contexts"
99 },
100 {
101 "/product/etc/selinux/product_tee_service_contexts",
102 "/product_tee_service_contexts"
103 },
104 {
105 "/vendor/etc/selinux/vendor_tee_service_contexts",
106 "/vendor_tee_service_contexts"
107 }
108 }};
109
find_existing_files(const path_alts_t * path_sets,const char * paths[MAX_CONTEXT_PATHS])110 size_t find_existing_files(
111 const path_alts_t *path_sets,
112 const char* paths[MAX_CONTEXT_PATHS])
113 {
114 return find_existing_files_with_partitions(
115 path_sets,
116 paths,
117 NULL
118 );
119 }
120
find_existing_files_with_partitions(const path_alts_t * path_sets,const char * paths[MAX_CONTEXT_PATHS],const char * partitions[MAX_CONTEXT_PATHS])121 size_t find_existing_files_with_partitions(
122 const path_alts_t *path_sets,
123 const char* paths[MAX_CONTEXT_PATHS],
124 const char* partitions[MAX_CONTEXT_PATHS])
125 {
126 size_t i, j, len = 0;
127 for (i = 0; i < MAX_CONTEXT_PATHS; i++) {
128 for (j = 0; j < MAX_ALT_CONTEXT_PATHS; j++) {
129 const char* file = path_sets->paths[i][j];
130 if (file && access(file, R_OK) != -1) {
131 if (partitions) {
132 partitions[len] = path_sets->partitions[i];
133 }
134 paths[len++] = file;
135 /* Within each set, only the first valid entry is used */
136 break;
137 }
138 }
139 }
140 return len;
141 }
142
paths_to_opts(const char * paths[MAX_CONTEXT_PATHS],size_t npaths,struct selinux_opt * const opts)143 void paths_to_opts(const char* paths[MAX_CONTEXT_PATHS],
144 size_t npaths,
145 struct selinux_opt* const opts)
146 {
147 for (size_t i = 0; i < npaths; i++) {
148 opts[i].type = SELABEL_OPT_PATH;
149 opts[i].value = paths[i];
150 }
151 }
152
initialize_backend(unsigned int backend,const char * name,const struct selinux_opt * opts,size_t nopts)153 struct selabel_handle* initialize_backend(
154 unsigned int backend,
155 const char* name,
156 const struct selinux_opt* opts,
157 size_t nopts)
158 {
159 struct selabel_handle* sehandle;
160
161 sehandle = selabel_open(backend, opts, nopts);
162
163 if (!sehandle) {
164 selinux_log(SELINUX_ERROR, "%s: Error getting %s handle (%s)\n",
165 __FUNCTION__, name, strerror(errno));
166 return NULL;
167 }
168 selinux_log(SELINUX_INFO, "SELinux: Loaded %s context from:\n", name);
169 for (unsigned i = 0; i < nopts; i++) {
170 if (opts[i].type == SELABEL_OPT_PATH)
171 selinux_log(SELINUX_INFO, " %s\n", opts[i].value);
172 }
173 return sehandle;
174 }
175
context_handle(unsigned int backend,const path_alts_t * context_paths,const char * name)176 struct selabel_handle* context_handle(
177 unsigned int backend,
178 const path_alts_t *context_paths,
179 const char *name)
180 {
181 const char* existing_paths[MAX_CONTEXT_PATHS];
182 struct selinux_opt opts[MAX_CONTEXT_PATHS];
183 int size = 0;
184
185 size = find_existing_files(context_paths, existing_paths);
186 paths_to_opts(existing_paths, size, opts);
187
188 return initialize_backend(backend, name, opts, size);
189 }
190
selinux_android_service_context_handle(void)191 struct selabel_handle* selinux_android_service_context_handle(void)
192 {
193 return context_handle(SELABEL_CTX_ANDROID_SERVICE, &service_context_paths, "service");
194 }
195
selinux_android_hw_service_context_handle(void)196 struct selabel_handle* selinux_android_hw_service_context_handle(void)
197 {
198 return context_handle(SELABEL_CTX_ANDROID_SERVICE, &hwservice_context_paths, "hwservice");
199 }
200
selinux_android_vendor_service_context_handle(void)201 struct selabel_handle* selinux_android_vendor_service_context_handle(void)
202 {
203 return context_handle(SELABEL_CTX_ANDROID_SERVICE, &vndservice_context_paths, "vndservice");
204 }
205
selinux_android_keystore2_key_context_handle(void)206 struct selabel_handle* selinux_android_keystore2_key_context_handle(void)
207 {
208 return context_handle(SELABEL_CTX_ANDROID_KEYSTORE2_KEY, &keystore2_context_paths, "keystore2");
209 }
210
selinux_android_tee_service_context_handle(void)211 struct selabel_handle* selinux_android_tee_service_context_handle(void)
212 {
213 return context_handle(SELABEL_CTX_ANDROID_SERVICE, &tee_service_context_paths, "tee_service");
214 }
215
216 /* The contents of these paths are encrypted on FBE devices until user
217 * credentials are presented (filenames inside are mangled), so we need
218 * to delay restorecon of those until vold explicitly requests it. */
219 // NOTE: these paths need to be kept in sync with vold
220 #define DATA_SYSTEM_CE_PATH "/data/system_ce"
221 #define DATA_VENDOR_CE_PATH "/data/vendor_ce"
222 #define DATA_MISC_CE_PATH "/data/misc_ce"
223
224 /* The path prefixes of package data directories. */
225 #define DATA_DATA_PATH "/data/data"
226 #define DATA_USER_PATH "/data/user"
227 #define DATA_USER_DE_PATH "/data/user_de"
228 #define DATA_MISC_DE_PATH "/data/misc_de"
229 #define DATA_STORAGE_AREA_PATH "/data/storage_area"
230 #define SDK_SANDBOX_DATA_CE_PATH "/data/misc_ce/*/sdksandbox"
231 #define SDK_SANDBOX_DATA_DE_PATH "/data/misc_de/*/sdksandbox"
232
233 #define EXPAND_MNT_PATH "/mnt/expand/\?\?\?\?\?\?\?\?-\?\?\?\?-\?\?\?\?-\?\?\?\?-\?\?\?\?\?\?\?\?\?\?\?\?"
234 #define EXPAND_USER_PATH EXPAND_MNT_PATH "/user"
235 #define EXPAND_USER_DE_PATH EXPAND_MNT_PATH "/user_de"
236 #define EXPAND_SDK_CE_PATH EXPAND_MNT_PATH "/misc_ce/*/sdksandbox"
237 #define EXPAND_SDK_DE_PATH EXPAND_MNT_PATH "/misc_de/*/sdksandbox"
238
239 #define DATA_DATA_PREFIX DATA_DATA_PATH "/"
240 #define DATA_USER_PREFIX DATA_USER_PATH "/"
241 #define DATA_USER_DE_PREFIX DATA_USER_DE_PATH "/"
242 #define DATA_STORAGE_AREA_PREFIX DATA_STORAGE_AREA_PATH "/"
243 #define DATA_MISC_CE_PREFIX DATA_MISC_CE_PATH "/"
244 #define DATA_MISC_DE_PREFIX DATA_MISC_DE_PATH "/"
245 #define EXPAND_MNT_PATH_PREFIX EXPAND_MNT_PATH "/"
246
is_app_data_path(const char * pathname)247 bool is_app_data_path(const char *pathname) {
248 int flags = FNM_LEADING_DIR|FNM_PATHNAME;
249 #ifdef SELINUX_FLAGS_DATA_DATA_IGNORE
250 if (!strcmp(pathname, DATA_DATA_PATH)) {
251 return true;
252 }
253 #endif
254 return (!strncmp(pathname, DATA_DATA_PREFIX, sizeof(DATA_DATA_PREFIX)-1) ||
255 !strncmp(pathname, DATA_USER_PREFIX, sizeof(DATA_USER_PREFIX)-1) ||
256 !strncmp(pathname, DATA_USER_DE_PREFIX, sizeof(DATA_USER_DE_PREFIX)-1) ||
257 !strncmp(pathname, DATA_STORAGE_AREA_PREFIX, sizeof(DATA_STORAGE_AREA_PREFIX)-1) ||
258 !fnmatch(EXPAND_USER_PATH, pathname, flags) ||
259 !fnmatch(EXPAND_USER_DE_PATH, pathname, flags) ||
260 !fnmatch(SDK_SANDBOX_DATA_CE_PATH, pathname, flags) ||
261 !fnmatch(SDK_SANDBOX_DATA_DE_PATH, pathname, flags) ||
262 !fnmatch(EXPAND_SDK_CE_PATH, pathname, flags) ||
263 !fnmatch(EXPAND_SDK_DE_PATH, pathname, flags));
264 }
265
is_credential_encrypted_path(const char * pathname)266 bool is_credential_encrypted_path(const char *pathname) {
267 return !strncmp(pathname, DATA_SYSTEM_CE_PATH, sizeof(DATA_SYSTEM_CE_PATH)-1) ||
268 !strncmp(pathname, DATA_MISC_CE_PATH, sizeof(DATA_MISC_CE_PATH)-1) ||
269 !strncmp(pathname, DATA_VENDOR_CE_PATH, sizeof(DATA_VENDOR_CE_PATH)-1);
270 }
271
272 /*
273 * Extract the userid from a path.
274 * On success, pathname is updated past the userid.
275 * Returns 0 on success, -1 on error
276 */
extract_userid(const char ** pathname,unsigned int * userid)277 static int extract_userid(const char **pathname, unsigned int *userid)
278 {
279 char *end = NULL;
280
281 errno = 0;
282 *userid = strtoul(*pathname, &end, 10);
283 if (errno) {
284 selinux_log(SELINUX_ERROR, "SELinux: Could not parse userid %s: %s.\n",
285 *pathname, strerror(errno));
286 return -1;
287 }
288 if (*pathname == end) {
289 return -1;
290 }
291 if (*userid > 1000) {
292 return -1;
293 }
294 *pathname = end;
295 return 0;
296 }
297
extract_pkgname_and_userid(const char * pathname,char ** pkgname,unsigned int * userid)298 int extract_pkgname_and_userid(const char *pathname, char **pkgname, unsigned int *userid)
299 {
300 char *end = NULL;
301
302 if (pkgname == NULL || *pkgname != NULL || userid == NULL) {
303 errno = EINVAL;
304 return -2;
305 }
306
307 /* Skip directory prefix before package name. */
308 if (!strncmp(pathname, DATA_DATA_PREFIX, sizeof(DATA_DATA_PREFIX)-1)) {
309 pathname += sizeof(DATA_DATA_PREFIX) - 1;
310 } else if (!strncmp(pathname, DATA_USER_PREFIX, sizeof(DATA_USER_PREFIX)-1)) {
311 pathname += sizeof(DATA_USER_PREFIX) - 1;
312 int rc = extract_userid(&pathname, userid);
313 if (rc)
314 return -1;
315 if (*pathname == '/')
316 pathname++;
317 else
318 return -1;
319 } else if (!strncmp(pathname, DATA_USER_DE_PREFIX, sizeof(DATA_USER_DE_PREFIX)-1)) {
320 pathname += sizeof(DATA_USER_DE_PREFIX) - 1;
321 int rc = extract_userid(&pathname, userid);
322 if (rc)
323 return -1;
324 if (*pathname == '/')
325 pathname++;
326 else
327 return -1;
328 } else if (!strncmp(pathname, DATA_STORAGE_AREA_PREFIX, sizeof(DATA_STORAGE_AREA_PREFIX)-1)) {
329 pathname += sizeof(DATA_STORAGE_AREA_PREFIX) - 1;
330 int rc = extract_userid(&pathname, userid);
331 if (rc)
332 return -1;
333 if (*pathname == '/')
334 pathname++;
335 else
336 return -1;
337 } else if (!fnmatch(EXPAND_USER_PATH, pathname, FNM_LEADING_DIR|FNM_PATHNAME)) {
338 pathname += sizeof(EXPAND_USER_PATH);
339 int rc = extract_userid(&pathname, userid);
340 if (rc)
341 return -1;
342 if (*pathname == '/')
343 pathname++;
344 else
345 return -1;
346 } else if (!fnmatch(EXPAND_USER_DE_PATH, pathname, FNM_LEADING_DIR|FNM_PATHNAME)) {
347 pathname += sizeof(EXPAND_USER_DE_PATH);
348 int rc = extract_userid(&pathname, userid);
349 if (rc)
350 return -1;
351 if (*pathname == '/')
352 pathname++;
353 else
354 return -1;
355 } else if (!strncmp(pathname, DATA_MISC_CE_PREFIX, sizeof(DATA_MISC_CE_PREFIX)-1)) {
356 pathname += sizeof(DATA_MISC_CE_PREFIX) - 1;
357 int rc = extract_userid(&pathname, userid);
358 if (rc)
359 return -1;
360 if (!strncmp(pathname, "/sdksandbox/", sizeof("/sdksandbox/")-1))
361 pathname += sizeof("/sdksandbox/") - 1;
362 else
363 return -1;
364 } else if (!strncmp(pathname, DATA_MISC_DE_PREFIX, sizeof(DATA_MISC_DE_PREFIX)-1)) {
365 pathname += sizeof(DATA_MISC_DE_PREFIX) - 1;
366 int rc = extract_userid(&pathname, userid);
367 if (rc)
368 return -1;
369 if (!strncmp(pathname, "/sdksandbox/", sizeof("/sdksandbox/")-1))
370 pathname += sizeof("/sdksandbox/") - 1;
371 else
372 return -1;
373 } else if (!fnmatch(EXPAND_SDK_CE_PATH, pathname, FNM_LEADING_DIR|FNM_PATHNAME)) {
374 pathname += sizeof(EXPAND_MNT_PATH_PREFIX) - 1;
375 pathname += sizeof("misc_ce/") - 1;
376 int rc = extract_userid(&pathname, userid);
377 if (rc)
378 return -1;
379 if (!strncmp(pathname, "/sdksandbox/", sizeof("/sdksandbox/")-1))
380 pathname += sizeof("/sdksandbox/") - 1;
381 else
382 return -1;
383 } else if (!fnmatch(EXPAND_SDK_DE_PATH, pathname, FNM_LEADING_DIR|FNM_PATHNAME)) {
384 pathname += sizeof(EXPAND_MNT_PATH_PREFIX) - 1;
385 pathname += sizeof("misc_de/") - 1;
386 int rc = extract_userid(&pathname, userid);
387 if (rc)
388 return -1;
389 if (!strncmp(pathname, "/sdksandbox/", sizeof("/sdksandbox/")-1))
390 pathname += sizeof("/sdksandbox/") - 1;
391 else
392 return -1;
393 } else
394 return -1;
395
396 if (!(*pathname))
397 return -1;
398
399 *pkgname = strdup(pathname);
400 if (!(*pkgname))
401 return -2;
402
403 // Trim pkgname.
404 for (end = *pkgname; *end && *end != '/'; end++);
405 *end = '\0';
406
407 return 0;
408 }
409
__selinux_log_callback(bool add_to_event_log,int type,const char * fmt,va_list ap)410 static void __selinux_log_callback(bool add_to_event_log, int type, const char *fmt, va_list ap) {
411 int priority;
412 char *strp;
413
414 switch(type) {
415 case SELINUX_WARNING:
416 priority = ANDROID_LOG_WARN;
417 break;
418 case SELINUX_INFO:
419 priority = ANDROID_LOG_INFO;
420 break;
421 default:
422 priority = ANDROID_LOG_ERROR;
423 break;
424 }
425
426 int len = vasprintf(&strp, fmt, ap);
427 if (len < 0) {
428 return;
429 }
430
431 /* libselinux log messages usually contain a new line character, while
432 * Android LOG() does not expect it. Remove it to avoid empty lines in
433 * the log buffers.
434 */
435 if (len > 0 && strp[len - 1] == '\n') {
436 strp[len - 1] = '\0';
437 }
438 LOG_PRI(priority, "SELinux", "%s", strp);
439 if (add_to_event_log) {
440 LOG_EVENT_STRING(AUDITD_LOG_TAG, strp);
441 }
442 free(strp);
443 }
444
selinux_log_callback(int type,const char * fmt,...)445 int selinux_log_callback(int type, const char *fmt, ...)
446 {
447 va_list ap;
448 va_start(ap, fmt);
449 __selinux_log_callback(true, type, fmt, ap);
450 va_end(ap);
451 return 0;
452 }
453
selinux_vendor_log_callback(int type,const char * fmt,...)454 int selinux_vendor_log_callback(int type, const char *fmt, ...)
455 {
456 va_list ap;
457 va_start(ap, fmt);
458 __selinux_log_callback(false, type, fmt, ap);
459 va_end(ap);
460 return 0;
461 }
462