• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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