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