1f074036424618c130dacb3464465a8b40bffef5Stephen Smalley#include <sys/types.h>
2f074036424618c130dacb3464465a8b40bffef5Stephen Smalley#include <unistd.h>
3f074036424618c130dacb3464465a8b40bffef5Stephen Smalley#include <string.h>
4f074036424618c130dacb3464465a8b40bffef5Stephen Smalley#include <stdio.h>
5f074036424618c130dacb3464465a8b40bffef5Stephen Smalley#include <stdlib.h>
6f074036424618c130dacb3464465a8b40bffef5Stephen Smalley#include <ctype.h>
7f074036424618c130dacb3464465a8b40bffef5Stephen Smalley#include <errno.h>
8f074036424618c130dacb3464465a8b40bffef5Stephen Smalley#include <pwd.h>
9f074036424618c130dacb3464465a8b40bffef5Stephen Smalley#include <grp.h>
10f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig#include <sys/mman.h>
11f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig#include <sys/mount.h>
12f074036424618c130dacb3464465a8b40bffef5Stephen Smalley#include <sys/types.h>
13f074036424618c130dacb3464465a8b40bffef5Stephen Smalley#include <sys/stat.h>
14f074036424618c130dacb3464465a8b40bffef5Stephen Smalley#include <fcntl.h>
15f074036424618c130dacb3464465a8b40bffef5Stephen Smalley#include <selinux/selinux.h>
16f074036424618c130dacb3464465a8b40bffef5Stephen Smalley#include <selinux/context.h>
17f074036424618c130dacb3464465a8b40bffef5Stephen Smalley#include <selinux/android.h>
180ca91b300c711079816fa67b4148cac3cd1eef8cStephen Smalley#include <selinux/label.h>
19e8b0fd8c21a68fd0a7fcf656a7b6eae10e61c8e5Stephen Smalley#include <selinux/avc.h>
20895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley#include <private/android_filesystem_config.h>
21f074036424618c130dacb3464465a8b40bffef5Stephen Smalley#include "callbacks.h"
22f074036424618c130dacb3464465a8b40bffef5Stephen Smalley#include "selinux_internal.h"
23f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
24f074036424618c130dacb3464465a8b40bffef5Stephen Smalley/*
25f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * XXX Where should this configuration file be located?
26f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * Needs to be accessible by zygote and installd when
27f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * setting credentials for app processes and setting permissions
28f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * on app data directories.
29f074036424618c130dacb3464465a8b40bffef5Stephen Smalley */
307446c917148c778315e511ad5c990492d3c8cdb8Stephen Smalleystatic char const * const seapp_contexts_file[] = {
317446c917148c778315e511ad5c990492d3c8cdb8Stephen Smalley	"/data/system/seapp_contexts",
327446c917148c778315e511ad5c990492d3c8cdb8Stephen Smalley	"/seapp_contexts",
337446c917148c778315e511ad5c990492d3c8cdb8Stephen Smalley	0 };
34f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
3532ebfe869edfc32633cf4f2ee2b56b7d8ce97a19Stephen Smalleystatic const struct selinux_opt seopts[] = {
3632ebfe869edfc32633cf4f2ee2b56b7d8ce97a19Stephen Smalley	{ SELABEL_OPT_PATH, "/data/system/file_contexts" },
3732ebfe869edfc32633cf4f2ee2b56b7d8ce97a19Stephen Smalley	{ SELABEL_OPT_PATH, "/file_contexts" },
3832ebfe869edfc32633cf4f2ee2b56b7d8ce97a19Stephen Smalley	{ 0, NULL } };
397446c917148c778315e511ad5c990492d3c8cdb8Stephen Smalley
404a655eca75a79149c25616c4a5a44f5b8d26b28fStephen Smalleystatic const char *const sepolicy_file[] = {
41f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig        "/data/system/sepolicy",
42f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig        "/sepolicy",
43f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig        0 };
44f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig
45f074036424618c130dacb3464465a8b40bffef5Stephen Smalleystruct seapp_context {
46f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	/* input selectors */
47f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	char isSystemServer;
48f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	char *user;
49f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	size_t len;
50f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	char prefix;
51f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	char *seinfo;
52f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	char *name;
53f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	/* outputs */
54f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	char *domain;
55f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	char *type;
56f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	char *level;
571b36ad00bfbea16ad4456a9fd715e594d57f2fd6William Roberts	char *sebool;
58f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	char levelFromUid;
59f074036424618c130dacb3464465a8b40bffef5Stephen Smalley};
60f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
61f074036424618c130dacb3464465a8b40bffef5Stephen Smalleystatic int seapp_context_cmp(const void *A, const void *B)
62f074036424618c130dacb3464465a8b40bffef5Stephen Smalley{
63f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	const struct seapp_context **sp1 = A, **sp2 = B;
64f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	const struct seapp_context *s1 = *sp1, *s2 = *sp2;
65f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
66f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	/* Give precedence to isSystemServer=true. */
67f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	if (s1->isSystemServer != s2->isSystemServer)
68f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		return (s1->isSystemServer ? -1 : 1);
69f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
70f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	/* Give precedence to a specified user= over an unspecified user=. */
71f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	if (s1->user && !s2->user)
72f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		return -1;
73f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	if (!s1->user && s2->user)
74f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		return 1;
75f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
76f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	if (s1->user) {
77f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		/* Give precedence to a fixed user= string over a prefix. */
78f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		if (s1->prefix != s2->prefix)
79f074036424618c130dacb3464465a8b40bffef5Stephen Smalley			return (s2->prefix ? -1 : 1);
80f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
81f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		/* Give precedence to a longer prefix over a shorter prefix. */
82f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		if (s1->prefix && s1->len != s2->len)
83f074036424618c130dacb3464465a8b40bffef5Stephen Smalley			return (s1->len > s2->len) ? -1 : 1;
84f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	}
85f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
86f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	/* Give precedence to a specified seinfo= over an unspecified seinfo=. */
87f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	if (s1->seinfo && !s2->seinfo)
88f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		return -1;
89f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	if (!s1->seinfo && s2->seinfo)
90f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		return 1;
91f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
92f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	/* Give precedence to a specified name= over an unspecified name=. */
93f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	if (s1->name && !s2->name)
94f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		return -1;
95f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	if (!s1->name && s2->name)
96f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		return 1;
97f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
981b36ad00bfbea16ad4456a9fd715e594d57f2fd6William Roberts        /* Give precedence to a specified sebool= over an unspecified sebool=. */
991b36ad00bfbea16ad4456a9fd715e594d57f2fd6William Roberts        if (s1->sebool && !s2->sebool)
1001b36ad00bfbea16ad4456a9fd715e594d57f2fd6William Roberts                return -1;
1011b36ad00bfbea16ad4456a9fd715e594d57f2fd6William Roberts        if (!s1->sebool && s2->sebool)
1021b36ad00bfbea16ad4456a9fd715e594d57f2fd6William Roberts                return 1;
1031b36ad00bfbea16ad4456a9fd715e594d57f2fd6William Roberts
104f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	/* Anything else has equal precedence. */
105f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	return 0;
106f074036424618c130dacb3464465a8b40bffef5Stephen Smalley}
107f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
108f074036424618c130dacb3464465a8b40bffef5Stephen Smalleystatic struct seapp_context **seapp_contexts = NULL;
109f074036424618c130dacb3464465a8b40bffef5Stephen Smalleystatic int nspec = 0;
110f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
1117446c917148c778315e511ad5c990492d3c8cdb8Stephen Smalleyint selinux_android_seapp_context_reload(void)
112f074036424618c130dacb3464465a8b40bffef5Stephen Smalley{
1137446c917148c778315e511ad5c990492d3c8cdb8Stephen Smalley	FILE *fp = NULL;
114f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	char line_buf[BUFSIZ];
115f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	char *token;
116f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	unsigned lineno;
117f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	struct seapp_context *cur;
118f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	char *p, *name = NULL, *value = NULL, *saveptr;
119f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	size_t len;
1207446c917148c778315e511ad5c990492d3c8cdb8Stephen Smalley	int i = 0, ret;
1217446c917148c778315e511ad5c990492d3c8cdb8Stephen Smalley
1227446c917148c778315e511ad5c990492d3c8cdb8Stephen Smalley	while ((fp==NULL) && seapp_contexts_file[i])
1237446c917148c778315e511ad5c990492d3c8cdb8Stephen Smalley		fp = fopen(seapp_contexts_file[i++], "r");
124f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
125f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	if (!fp) {
1267446c917148c778315e511ad5c990492d3c8cdb8Stephen Smalley		selinux_log(SELINUX_ERROR, "%s:  could not open any seapp_contexts file", __FUNCTION__);
1277446c917148c778315e511ad5c990492d3c8cdb8Stephen Smalley		return -1;
128f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	}
129f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
130f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	nspec = 0;
131f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	while (fgets(line_buf, sizeof line_buf - 1, fp)) {
132f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		p = line_buf;
133f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		while (isspace(*p))
134f074036424618c130dacb3464465a8b40bffef5Stephen Smalley			p++;
135f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		if (*p == '#' || *p == 0)
136f074036424618c130dacb3464465a8b40bffef5Stephen Smalley			continue;
137f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		nspec++;
138f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	}
139f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
140f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	seapp_contexts = calloc(nspec, sizeof(struct seapp_context *));
141f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	if (!seapp_contexts)
142f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		goto oom;
143f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
144f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	rewind(fp);
145f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	nspec = 0;
146f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	lineno = 1;
147f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	while (fgets(line_buf, sizeof line_buf - 1, fp)) {
148f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		len = strlen(line_buf);
149f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		if (line_buf[len - 1] == '\n')
150f074036424618c130dacb3464465a8b40bffef5Stephen Smalley			line_buf[len - 1] = 0;
151f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		p = line_buf;
152f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		while (isspace(*p))
153f074036424618c130dacb3464465a8b40bffef5Stephen Smalley			p++;
154f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		if (*p == '#' || *p == 0)
155f074036424618c130dacb3464465a8b40bffef5Stephen Smalley			continue;
156f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
157f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		cur = calloc(1, sizeof(struct seapp_context));
158f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		if (!cur)
159f074036424618c130dacb3464465a8b40bffef5Stephen Smalley			goto oom;
160f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
161f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		token = strtok_r(p, " \t", &saveptr);
162f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		if (!token)
163f074036424618c130dacb3464465a8b40bffef5Stephen Smalley			goto err;
164f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
165f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		while (1) {
166f074036424618c130dacb3464465a8b40bffef5Stephen Smalley			name = token;
167f074036424618c130dacb3464465a8b40bffef5Stephen Smalley			value = strchr(name, '=');
168f074036424618c130dacb3464465a8b40bffef5Stephen Smalley			if (!value)
169f074036424618c130dacb3464465a8b40bffef5Stephen Smalley				goto err;
170f074036424618c130dacb3464465a8b40bffef5Stephen Smalley			*value++ = 0;
171f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
172f074036424618c130dacb3464465a8b40bffef5Stephen Smalley			if (!strcasecmp(name, "isSystemServer")) {
173f074036424618c130dacb3464465a8b40bffef5Stephen Smalley				if (!strcasecmp(value, "true"))
174f074036424618c130dacb3464465a8b40bffef5Stephen Smalley					cur->isSystemServer = 1;
175f074036424618c130dacb3464465a8b40bffef5Stephen Smalley				else if (!strcasecmp(value, "false"))
176f074036424618c130dacb3464465a8b40bffef5Stephen Smalley					cur->isSystemServer = 0;
177f074036424618c130dacb3464465a8b40bffef5Stephen Smalley				else {
178f074036424618c130dacb3464465a8b40bffef5Stephen Smalley					goto err;
179f074036424618c130dacb3464465a8b40bffef5Stephen Smalley				}
180f074036424618c130dacb3464465a8b40bffef5Stephen Smalley			} else if (!strcasecmp(name, "user")) {
181f074036424618c130dacb3464465a8b40bffef5Stephen Smalley				cur->user = strdup(value);
182f074036424618c130dacb3464465a8b40bffef5Stephen Smalley				if (!cur->user)
183f074036424618c130dacb3464465a8b40bffef5Stephen Smalley					goto oom;
184f074036424618c130dacb3464465a8b40bffef5Stephen Smalley				cur->len = strlen(cur->user);
185f074036424618c130dacb3464465a8b40bffef5Stephen Smalley				if (cur->user[cur->len-1] == '*')
186f074036424618c130dacb3464465a8b40bffef5Stephen Smalley					cur->prefix = 1;
187f074036424618c130dacb3464465a8b40bffef5Stephen Smalley			} else if (!strcasecmp(name, "seinfo")) {
188f074036424618c130dacb3464465a8b40bffef5Stephen Smalley				cur->seinfo = strdup(value);
189f074036424618c130dacb3464465a8b40bffef5Stephen Smalley				if (!cur->seinfo)
190f074036424618c130dacb3464465a8b40bffef5Stephen Smalley					goto oom;
191f074036424618c130dacb3464465a8b40bffef5Stephen Smalley			} else if (!strcasecmp(name, "name")) {
192f074036424618c130dacb3464465a8b40bffef5Stephen Smalley				cur->name = strdup(value);
193f074036424618c130dacb3464465a8b40bffef5Stephen Smalley				if (!cur->name)
194f074036424618c130dacb3464465a8b40bffef5Stephen Smalley					goto oom;
195f074036424618c130dacb3464465a8b40bffef5Stephen Smalley			} else if (!strcasecmp(name, "domain")) {
196f074036424618c130dacb3464465a8b40bffef5Stephen Smalley				cur->domain = strdup(value);
197f074036424618c130dacb3464465a8b40bffef5Stephen Smalley				if (!cur->domain)
198f074036424618c130dacb3464465a8b40bffef5Stephen Smalley					goto oom;
199f074036424618c130dacb3464465a8b40bffef5Stephen Smalley			} else if (!strcasecmp(name, "type")) {
200f074036424618c130dacb3464465a8b40bffef5Stephen Smalley				cur->type = strdup(value);
201f074036424618c130dacb3464465a8b40bffef5Stephen Smalley				if (!cur->type)
202f074036424618c130dacb3464465a8b40bffef5Stephen Smalley					goto oom;
203f074036424618c130dacb3464465a8b40bffef5Stephen Smalley			} else if (!strcasecmp(name, "levelFromUid")) {
204f074036424618c130dacb3464465a8b40bffef5Stephen Smalley				if (!strcasecmp(value, "true"))
205f074036424618c130dacb3464465a8b40bffef5Stephen Smalley					cur->levelFromUid = 1;
206f074036424618c130dacb3464465a8b40bffef5Stephen Smalley				else if (!strcasecmp(value, "false"))
207f074036424618c130dacb3464465a8b40bffef5Stephen Smalley					cur->levelFromUid = 0;
208f074036424618c130dacb3464465a8b40bffef5Stephen Smalley				else {
209f074036424618c130dacb3464465a8b40bffef5Stephen Smalley					goto err;
210f074036424618c130dacb3464465a8b40bffef5Stephen Smalley				}
211f074036424618c130dacb3464465a8b40bffef5Stephen Smalley			} else if (!strcasecmp(name, "level")) {
212f074036424618c130dacb3464465a8b40bffef5Stephen Smalley				cur->level = strdup(value);
213f074036424618c130dacb3464465a8b40bffef5Stephen Smalley				if (!cur->level)
214f074036424618c130dacb3464465a8b40bffef5Stephen Smalley					goto oom;
2151b36ad00bfbea16ad4456a9fd715e594d57f2fd6William Roberts			} else if (!strcasecmp(name, "sebool")) {
2161b36ad00bfbea16ad4456a9fd715e594d57f2fd6William Roberts				cur->sebool = strdup(value);
2171b36ad00bfbea16ad4456a9fd715e594d57f2fd6William Roberts				if (!cur->sebool)
2181b36ad00bfbea16ad4456a9fd715e594d57f2fd6William Roberts					goto oom;
219f074036424618c130dacb3464465a8b40bffef5Stephen Smalley			} else
220f074036424618c130dacb3464465a8b40bffef5Stephen Smalley				goto err;
221f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
222f074036424618c130dacb3464465a8b40bffef5Stephen Smalley			token = strtok_r(NULL, " \t", &saveptr);
223f074036424618c130dacb3464465a8b40bffef5Stephen Smalley			if (!token)
224f074036424618c130dacb3464465a8b40bffef5Stephen Smalley				break;
225f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		}
226f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
227f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		seapp_contexts[nspec] = cur;
228f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		nspec++;
229f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		lineno++;
230f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	}
231f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
232f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	qsort(seapp_contexts, nspec, sizeof(struct seapp_context *),
233f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	      seapp_context_cmp);
234f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
235f074036424618c130dacb3464465a8b40bffef5Stephen Smalley#if DEBUG
236f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	{
237f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		int i;
238f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		for (i = 0; i < nspec; i++) {
239f074036424618c130dacb3464465a8b40bffef5Stephen Smalley			cur = seapp_contexts[i];
2401b36ad00bfbea16ad4456a9fd715e594d57f2fd6William Roberts			selinux_log(SELINUX_INFO, "%s:  isSystemServer=%s user=%s seinfo=%s name=%s sebool=%s -> domain=%s type=%s level=%s levelFromUid=%s",
2411b36ad00bfbea16ad4456a9fd715e594d57f2fd6William Roberts			__FUNCTION__,
2421b36ad00bfbea16ad4456a9fd715e594d57f2fd6William Roberts			cur->isSystemServer ? "true" : "false", cur->user,
2431b36ad00bfbea16ad4456a9fd715e594d57f2fd6William Roberts			cur->seinfo, cur->name, cur->sebool, cur->domain,
2441b36ad00bfbea16ad4456a9fd715e594d57f2fd6William Roberts			cur->type, cur->level,
2451b36ad00bfbea16ad4456a9fd715e594d57f2fd6William Roberts			cur->levelFromUid ? "true" : "false");
246f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		}
247f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	}
248f074036424618c130dacb3464465a8b40bffef5Stephen Smalley#endif
249f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
2507446c917148c778315e511ad5c990492d3c8cdb8Stephen Smalley	ret = 0;
2517446c917148c778315e511ad5c990492d3c8cdb8Stephen Smalley
252f074036424618c130dacb3464465a8b40bffef5Stephen Smalleyout:
253f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	fclose(fp);
2547446c917148c778315e511ad5c990492d3c8cdb8Stephen Smalley	return ret;
255f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
256f074036424618c130dacb3464465a8b40bffef5Stephen Smalleyerr:
257f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	selinux_log(SELINUX_ERROR, "%s:  Error reading %s, line %u, name %s, value %s\n",
2587446c917148c778315e511ad5c990492d3c8cdb8Stephen Smalley		    __FUNCTION__, seapp_contexts_file[i - 1], lineno, name, value);
2597446c917148c778315e511ad5c990492d3c8cdb8Stephen Smalley	ret = -1;
260f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	goto out;
261f074036424618c130dacb3464465a8b40bffef5Stephen Smalleyoom:
262f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	selinux_log(SELINUX_ERROR,
263f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		    "%s:  Out of memory\n", __FUNCTION__);
2647446c917148c778315e511ad5c990492d3c8cdb8Stephen Smalley	ret = -1;
265f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	goto out;
266f074036424618c130dacb3464465a8b40bffef5Stephen Smalley}
267f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
2687446c917148c778315e511ad5c990492d3c8cdb8Stephen Smalley
2697446c917148c778315e511ad5c990492d3c8cdb8Stephen Smalleystatic void seapp_context_init(void)
2707446c917148c778315e511ad5c990492d3c8cdb8Stephen Smalley{
2717446c917148c778315e511ad5c990492d3c8cdb8Stephen Smalley        selinux_android_seapp_context_reload();
2727446c917148c778315e511ad5c990492d3c8cdb8Stephen Smalley}
2737446c917148c778315e511ad5c990492d3c8cdb8Stephen Smalley
274f074036424618c130dacb3464465a8b40bffef5Stephen Smalleystatic pthread_once_t once = PTHREAD_ONCE_INIT;
275f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
276895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley#define SEAPP_TYPE 1
277895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley#define SEAPP_DOMAIN 2
278895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalleystatic int seapp_context_lookup(int kind,
279895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley				uid_t uid,
280895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley				int isSystemServer,
281edfaad87e34e7a5bb691d45fd6df3e0b5ad0bb1aStephen Smalley				const char *seinfo,
282895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley				const char *pkgname,
283895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley				context_t ctx)
284f074036424618c130dacb3464465a8b40bffef5Stephen Smalley{
285895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley	const char *username = NULL;
286895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley	char *end = NULL;
287f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	struct passwd *pw;
288f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	struct seapp_context *cur;
289895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley	int i;
290895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley	size_t n;
291895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley	uid_t appid = 0;
292895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley
293895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley	appid = uid % AID_USER;
294895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley	if (appid < AID_APP) {
295895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley		for (n = 0; n < android_id_count; n++) {
296895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley			if (android_ids[n].aid == appid) {
297895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley				username = android_ids[n].name;
298895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley				break;
299895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley			}
300ce4e2e6a0819b0a23d80fa137b5ee0e351aff855Stephen Smalley		}
301895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley		if (!username)
302895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley			goto err;
303895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley	} else if (appid < AID_ISOLATED_START) {
304895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley		username = "app_";
305895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley		appid -= AID_APP;
306895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley	} else {
307895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley		username = "isolated";
308895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley		appid -= AID_ISOLATED_START;
309ba70ee4c5ab8026e97fce5c2452dfe588dfaac3eStephen Smalley	}
310f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
311895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley	if (appid >= MLS_CATS)
312895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley		goto err;
313895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley
314f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	for (i = 0; i < nspec; i++) {
315f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		cur = seapp_contexts[i];
316f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
317895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley		if (cur->isSystemServer != isSystemServer)
318f074036424618c130dacb3464465a8b40bffef5Stephen Smalley			continue;
319f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
320f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		if (cur->user) {
321f074036424618c130dacb3464465a8b40bffef5Stephen Smalley			if (cur->prefix) {
322ba70ee4c5ab8026e97fce5c2452dfe588dfaac3eStephen Smalley				if (strncasecmp(username, cur->user, cur->len-1))
323f074036424618c130dacb3464465a8b40bffef5Stephen Smalley					continue;
324f074036424618c130dacb3464465a8b40bffef5Stephen Smalley			} else {
325ba70ee4c5ab8026e97fce5c2452dfe588dfaac3eStephen Smalley				if (strcasecmp(username, cur->user))
326f074036424618c130dacb3464465a8b40bffef5Stephen Smalley					continue;
327f074036424618c130dacb3464465a8b40bffef5Stephen Smalley			}
328f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		}
329f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
330edfaad87e34e7a5bb691d45fd6df3e0b5ad0bb1aStephen Smalley		if (cur->seinfo) {
331edfaad87e34e7a5bb691d45fd6df3e0b5ad0bb1aStephen Smalley			if (!seinfo || strcasecmp(seinfo, cur->seinfo))
332edfaad87e34e7a5bb691d45fd6df3e0b5ad0bb1aStephen Smalley				continue;
333edfaad87e34e7a5bb691d45fd6df3e0b5ad0bb1aStephen Smalley		}
334f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
335f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		if (cur->name) {
336ba70ee4c5ab8026e97fce5c2452dfe588dfaac3eStephen Smalley			if (!pkgname || strcasecmp(pkgname, cur->name))
337f074036424618c130dacb3464465a8b40bffef5Stephen Smalley				continue;
338f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		}
339f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
340895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley		if (kind == SEAPP_TYPE && !cur->type)
341895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley			continue;
342895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley		else if (kind == SEAPP_DOMAIN && !cur->domain)
343f074036424618c130dacb3464465a8b40bffef5Stephen Smalley			continue;
344f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
3451b36ad00bfbea16ad4456a9fd715e594d57f2fd6William Roberts		if (cur->sebool) {
3461b36ad00bfbea16ad4456a9fd715e594d57f2fd6William Roberts			int value = security_get_boolean_active(cur->sebool);
3471b36ad00bfbea16ad4456a9fd715e594d57f2fd6William Roberts			if (value == 0)
3481b36ad00bfbea16ad4456a9fd715e594d57f2fd6William Roberts				continue;
3491b36ad00bfbea16ad4456a9fd715e594d57f2fd6William Roberts			else if (value == -1) {
3501b36ad00bfbea16ad4456a9fd715e594d57f2fd6William Roberts				selinux_log(SELINUX_ERROR, \
3511b36ad00bfbea16ad4456a9fd715e594d57f2fd6William Roberts				"Could not find boolean: %s ", cur->sebool);
3521b36ad00bfbea16ad4456a9fd715e594d57f2fd6William Roberts				goto err;
3531b36ad00bfbea16ad4456a9fd715e594d57f2fd6William Roberts			}
3541b36ad00bfbea16ad4456a9fd715e594d57f2fd6William Roberts		}
3551b36ad00bfbea16ad4456a9fd715e594d57f2fd6William Roberts
356895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley		if (kind == SEAPP_TYPE) {
357895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley			if (context_type_set(ctx, cur->type))
358895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley				goto oom;
359895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley		} else if (kind == SEAPP_DOMAIN) {
360895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley			if (context_type_set(ctx, cur->domain))
361895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley				goto oom;
362895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley		}
363f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
364c9726aba339f3d935ff14c0734edf13116af3cbfStephen Smalley		if (cur->levelFromUid) {
365f074036424618c130dacb3464465a8b40bffef5Stephen Smalley			char level[255];
366f074036424618c130dacb3464465a8b40bffef5Stephen Smalley			snprintf(level, sizeof level, "%s:c%lu",
367895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley				 context_range_get(ctx), appid);
368f074036424618c130dacb3464465a8b40bffef5Stephen Smalley			if (context_range_set(ctx, level))
369f074036424618c130dacb3464465a8b40bffef5Stephen Smalley				goto oom;
370f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		} else if (cur->level) {
371f074036424618c130dacb3464465a8b40bffef5Stephen Smalley			if (context_range_set(ctx, cur->level))
372f074036424618c130dacb3464465a8b40bffef5Stephen Smalley				goto oom;
373f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		}
3741b36ad00bfbea16ad4456a9fd715e594d57f2fd6William Roberts
375f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		break;
376f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	}
377f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
378895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley	if (kind == SEAPP_DOMAIN && i == nspec) {
379895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley		/*
380895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley		 * No match.
381895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley		 * Fail to prevent staying in the zygote's context.
382895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley		 */
383895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley		selinux_log(SELINUX_ERROR,
384895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley			    "%s:  No match for app with uid %d, seinfo %s, name %s\n",
385895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley			    __FUNCTION__, uid, seinfo, pkgname);
386895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley
387895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley		if (security_getenforce() == 1)
388895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley			goto err;
389895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley	}
390895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley
391895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley	return 0;
392895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalleyerr:
393895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley	return -1;
394895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalleyoom:
395895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley	return -2;
396895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley}
397895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley
398895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalleyint selinux_android_setfilecon2(const char *pkgdir,
399895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley				const char *pkgname,
400895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley				const char *seinfo,
401895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley				uid_t uid)
402895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley{
403895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley	char *orig_ctx_str = NULL, *ctx_str;
404895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley	context_t ctx = NULL;
405895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley	int rc;
406895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley
407895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley	if (is_selinux_enabled() <= 0)
408895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley		return 0;
409895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley
410895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley	__selinux_once(once, seapp_context_init);
411895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley
412895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley	rc = getfilecon(pkgdir, &ctx_str);
413895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley	if (rc < 0)
414895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley		goto err;
415895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley
416895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley	ctx = context_new(ctx_str);
417895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley	orig_ctx_str = ctx_str;
418895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley	if (!ctx)
419895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley		goto oom;
420895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley
421895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley	rc = seapp_context_lookup(SEAPP_TYPE, uid, 0, seinfo, pkgname, ctx);
422895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley	if (rc == -1)
423895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley		goto err;
424895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley	else if (rc == -2)
425895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley		goto oom;
426895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley
427f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	ctx_str = context_str(ctx);
428f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	if (!ctx_str)
429f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		goto oom;
430f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
431f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	rc = security_check_context(ctx_str);
432f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	if (rc < 0)
433f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		goto err;
434f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
435f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	if (strcmp(ctx_str, orig_ctx_str)) {
436f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		rc = setfilecon(pkgdir, ctx_str);
437f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		if (rc < 0)
438f074036424618c130dacb3464465a8b40bffef5Stephen Smalley			goto err;
439f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	}
440f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
441f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	rc = 0;
442f074036424618c130dacb3464465a8b40bffef5Stephen Smalleyout:
443f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	freecon(orig_ctx_str);
444f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	context_free(ctx);
445f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	return rc;
446f074036424618c130dacb3464465a8b40bffef5Stephen Smalleyerr:
447f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	selinux_log(SELINUX_ERROR, "%s:  Error setting context for pkgdir %s, uid %d: %s\n",
448f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		    __FUNCTION__, pkgdir, uid, strerror(errno));
449f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	rc = -1;
450f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	goto out;
451f074036424618c130dacb3464465a8b40bffef5Stephen Smalleyoom:
452f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	selinux_log(SELINUX_ERROR, "%s:  Out of memory\n", __FUNCTION__);
453f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	rc = -1;
454f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	goto out;
455f074036424618c130dacb3464465a8b40bffef5Stephen Smalley}
456f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
457edfaad87e34e7a5bb691d45fd6df3e0b5ad0bb1aStephen Smalleyint selinux_android_setfilecon(const char *pkgdir,
458edfaad87e34e7a5bb691d45fd6df3e0b5ad0bb1aStephen Smalley			       const char *pkgname,
459edfaad87e34e7a5bb691d45fd6df3e0b5ad0bb1aStephen Smalley			       uid_t uid)
460edfaad87e34e7a5bb691d45fd6df3e0b5ad0bb1aStephen Smalley{
461edfaad87e34e7a5bb691d45fd6df3e0b5ad0bb1aStephen Smalley	return selinux_android_setfilecon2(pkgdir, pkgname, NULL, uid);
462edfaad87e34e7a5bb691d45fd6df3e0b5ad0bb1aStephen Smalley}
463edfaad87e34e7a5bb691d45fd6df3e0b5ad0bb1aStephen Smalley
464f074036424618c130dacb3464465a8b40bffef5Stephen Smalleyint selinux_android_setcontext(uid_t uid,
465f074036424618c130dacb3464465a8b40bffef5Stephen Smalley			       int isSystemServer,
466f074036424618c130dacb3464465a8b40bffef5Stephen Smalley			       const char *seinfo,
467ba70ee4c5ab8026e97fce5c2452dfe588dfaac3eStephen Smalley			       const char *pkgname)
468f074036424618c130dacb3464465a8b40bffef5Stephen Smalley{
469895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley	char *orig_ctx_str = NULL, *ctx_str;
470f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	context_t ctx = NULL;
471895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley	int rc;
472f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
473f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	if (is_selinux_enabled() <= 0)
474f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		return 0;
475f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
476f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	__selinux_once(once, seapp_context_init);
477f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
478f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	rc = getcon(&ctx_str);
479f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	if (rc)
480f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		goto err;
481f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
482f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	ctx = context_new(ctx_str);
483f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	orig_ctx_str = ctx_str;
484f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	if (!ctx)
485f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		goto oom;
486f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
487895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley	rc = seapp_context_lookup(SEAPP_DOMAIN, uid, isSystemServer, seinfo, pkgname, ctx);
488895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley	if (rc == -1)
489f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		goto err;
490895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley	else if (rc == -2)
491895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley		goto oom;
492f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
493f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	ctx_str = context_str(ctx);
494f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	if (!ctx_str)
495f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		goto oom;
496f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
497f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	rc = security_check_context(ctx_str);
498f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	if (rc < 0)
499f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		goto err;
500f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
501f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	if (strcmp(ctx_str, orig_ctx_str)) {
502f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		rc = setcon(ctx_str);
503f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		if (rc < 0)
504f074036424618c130dacb3464465a8b40bffef5Stephen Smalley			goto err;
505f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	}
506f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
507f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	rc = 0;
508f074036424618c130dacb3464465a8b40bffef5Stephen Smalleyout:
509f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	freecon(orig_ctx_str);
510f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	context_free(ctx);
511e8b0fd8c21a68fd0a7fcf656a7b6eae10e61c8e5Stephen Smalley	avc_netlink_close();
512f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	return rc;
513f074036424618c130dacb3464465a8b40bffef5Stephen Smalleyerr:
514f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	if (isSystemServer)
515f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		selinux_log(SELINUX_ERROR,
516f074036424618c130dacb3464465a8b40bffef5Stephen Smalley			    "%s:  Error setting context for system server: %s\n",
517f074036424618c130dacb3464465a8b40bffef5Stephen Smalley			    __FUNCTION__, strerror(errno));
518f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	else
519f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		selinux_log(SELINUX_ERROR,
520f074036424618c130dacb3464465a8b40bffef5Stephen Smalley			    "%s:  Error setting context for app with uid %d, seinfo %s: %s\n",
521f074036424618c130dacb3464465a8b40bffef5Stephen Smalley			    __FUNCTION__, uid, seinfo, strerror(errno));
522f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
523f77e60de67dbc84d06aa77adef6bdf80455ee9f5Stephen Smalley	rc = -1;
524f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	goto out;
525f074036424618c130dacb3464465a8b40bffef5Stephen Smalleyoom:
526f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	selinux_log(SELINUX_ERROR, "%s:  Out of memory\n", __FUNCTION__);
527f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	rc = -1;
528f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	goto out;
529f074036424618c130dacb3464465a8b40bffef5Stephen Smalley}
530f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
5310ca91b300c711079816fa67b4148cac3cd1eef8cStephen Smalleystatic struct selabel_handle *sehandle = NULL;
5320ca91b300c711079816fa67b4148cac3cd1eef8cStephen Smalley
533906742dfd76bf9f21bddbddc43966c2cc9b0da0eStephen Smalleystatic struct selabel_handle *file_context_open(void)
5340ca91b300c711079816fa67b4148cac3cd1eef8cStephen Smalley{
535906742dfd76bf9f21bddbddc43966c2cc9b0da0eStephen Smalley	struct selabel_handle *h;
53632ebfe869edfc32633cf4f2ee2b56b7d8ce97a19Stephen Smalley	int i = 0;
5370ca91b300c711079816fa67b4148cac3cd1eef8cStephen Smalley
538906742dfd76bf9f21bddbddc43966c2cc9b0da0eStephen Smalley	h = NULL;
539906742dfd76bf9f21bddbddc43966c2cc9b0da0eStephen Smalley	while ((h == NULL) && seopts[i].value) {
540906742dfd76bf9f21bddbddc43966c2cc9b0da0eStephen Smalley		h = selabel_open(SELABEL_CTX_FILE, &seopts[i], 1);
54132ebfe869edfc32633cf4f2ee2b56b7d8ce97a19Stephen Smalley		i++;
54232ebfe869edfc32633cf4f2ee2b56b7d8ce97a19Stephen Smalley	}
5430ca91b300c711079816fa67b4148cac3cd1eef8cStephen Smalley
544906742dfd76bf9f21bddbddc43966c2cc9b0da0eStephen Smalley	if (!h)
545f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig		selinux_log(SELINUX_ERROR, "%s: Error getting sehandle label (%s)\n",
5460ca91b300c711079816fa67b4148cac3cd1eef8cStephen Smalley			    __FUNCTION__, strerror(errno));
547906742dfd76bf9f21bddbddc43966c2cc9b0da0eStephen Smalley	return h;
548906742dfd76bf9f21bddbddc43966c2cc9b0da0eStephen Smalley}
549906742dfd76bf9f21bddbddc43966c2cc9b0da0eStephen Smalley
550906742dfd76bf9f21bddbddc43966c2cc9b0da0eStephen Smalleystatic void file_context_init(void)
551906742dfd76bf9f21bddbddc43966c2cc9b0da0eStephen Smalley{
552906742dfd76bf9f21bddbddc43966c2cc9b0da0eStephen Smalley	sehandle = file_context_open();
5530ca91b300c711079816fa67b4148cac3cd1eef8cStephen Smalley}
5540ca91b300c711079816fa67b4148cac3cd1eef8cStephen Smalley
5550ca91b300c711079816fa67b4148cac3cd1eef8cStephen Smalleystatic pthread_once_t fc_once = PTHREAD_ONCE_INIT;
5560ca91b300c711079816fa67b4148cac3cd1eef8cStephen Smalley
5570ca91b300c711079816fa67b4148cac3cd1eef8cStephen Smalleyint selinux_android_restorecon(const char *pathname)
5580ca91b300c711079816fa67b4148cac3cd1eef8cStephen Smalley{
5590ca91b300c711079816fa67b4148cac3cd1eef8cStephen Smalley
5600ca91b300c711079816fa67b4148cac3cd1eef8cStephen Smalley	__selinux_once(fc_once, file_context_init);
5610ca91b300c711079816fa67b4148cac3cd1eef8cStephen Smalley
5620ca91b300c711079816fa67b4148cac3cd1eef8cStephen Smalley	int ret;
5630ca91b300c711079816fa67b4148cac3cd1eef8cStephen Smalley
5640ca91b300c711079816fa67b4148cac3cd1eef8cStephen Smalley	if (!sehandle)
5650ca91b300c711079816fa67b4148cac3cd1eef8cStephen Smalley		goto bail;
5660ca91b300c711079816fa67b4148cac3cd1eef8cStephen Smalley
5670ca91b300c711079816fa67b4148cac3cd1eef8cStephen Smalley	struct stat sb;
5680ca91b300c711079816fa67b4148cac3cd1eef8cStephen Smalley
5690ca91b300c711079816fa67b4148cac3cd1eef8cStephen Smalley	if (lstat(pathname, &sb) < 0)
5700ca91b300c711079816fa67b4148cac3cd1eef8cStephen Smalley		goto err;
5710ca91b300c711079816fa67b4148cac3cd1eef8cStephen Smalley
5720ca91b300c711079816fa67b4148cac3cd1eef8cStephen Smalley	char *oldcontext, *newcontext;
5730ca91b300c711079816fa67b4148cac3cd1eef8cStephen Smalley
5740ca91b300c711079816fa67b4148cac3cd1eef8cStephen Smalley	if (lgetfilecon(pathname, &oldcontext) < 0)
5750ca91b300c711079816fa67b4148cac3cd1eef8cStephen Smalley		goto err;
5760ca91b300c711079816fa67b4148cac3cd1eef8cStephen Smalley
5770ca91b300c711079816fa67b4148cac3cd1eef8cStephen Smalley	if (selabel_lookup(sehandle, &newcontext, pathname, sb.st_mode) < 0)
5780ca91b300c711079816fa67b4148cac3cd1eef8cStephen Smalley		goto err;
5790ca91b300c711079816fa67b4148cac3cd1eef8cStephen Smalley
5800ca91b300c711079816fa67b4148cac3cd1eef8cStephen Smalley	if (strcmp(newcontext, "<<none>>") && strcmp(oldcontext, newcontext))
5810ca91b300c711079816fa67b4148cac3cd1eef8cStephen Smalley		if (lsetfilecon(pathname, newcontext) < 0)
5820ca91b300c711079816fa67b4148cac3cd1eef8cStephen Smalley			goto err;
5830ca91b300c711079816fa67b4148cac3cd1eef8cStephen Smalley
5840ca91b300c711079816fa67b4148cac3cd1eef8cStephen Smalley	ret = 0;
5850ca91b300c711079816fa67b4148cac3cd1eef8cStephen Smalleyout:
5860ca91b300c711079816fa67b4148cac3cd1eef8cStephen Smalley	if (oldcontext)
5870ca91b300c711079816fa67b4148cac3cd1eef8cStephen Smalley		freecon(oldcontext);
5880ca91b300c711079816fa67b4148cac3cd1eef8cStephen Smalley	if (newcontext)
5890ca91b300c711079816fa67b4148cac3cd1eef8cStephen Smalley		freecon(newcontext);
5900ca91b300c711079816fa67b4148cac3cd1eef8cStephen Smalley
5910ca91b300c711079816fa67b4148cac3cd1eef8cStephen Smalley	return ret;
5920ca91b300c711079816fa67b4148cac3cd1eef8cStephen Smalley
5930ca91b300c711079816fa67b4148cac3cd1eef8cStephen Smalleyerr:
5940ca91b300c711079816fa67b4148cac3cd1eef8cStephen Smalley	selinux_log(SELINUX_ERROR,
5950ca91b300c711079816fa67b4148cac3cd1eef8cStephen Smalley		    "%s:  Error restoring context for %s (%s)\n",
5960ca91b300c711079816fa67b4148cac3cd1eef8cStephen Smalley		    __FUNCTION__, pathname, strerror(errno));
5970ca91b300c711079816fa67b4148cac3cd1eef8cStephen Smalley
5980ca91b300c711079816fa67b4148cac3cd1eef8cStephen Smalleybail:
5990ca91b300c711079816fa67b4148cac3cd1eef8cStephen Smalley	ret = -1;
6000ca91b300c711079816fa67b4148cac3cd1eef8cStephen Smalley	goto out;
6010ca91b300c711079816fa67b4148cac3cd1eef8cStephen Smalley}
6029b10083ab40e78cce8cc2b940ce22db6d1095fc5rpcraig
6039b10083ab40e78cce8cc2b940ce22db6d1095fc5rpcraig
604f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraigstruct selabel_handle* selinux_android_file_context_handle(void)
605f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig{
606906742dfd76bf9f21bddbddc43966c2cc9b0da0eStephen Smalley        return file_context_open();
607f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig}
608f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig
609f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraigint selinux_android_reload_policy(void)
610f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig{
611f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig	char path[PATH_MAX];
6124a655eca75a79149c25616c4a5a44f5b8d26b28fStephen Smalley	int fd = -1, rc;
613f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig	struct stat sb;
614f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig	void *map = NULL;
615f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig	int i = 0;
616f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig
6174a655eca75a79149c25616c4a5a44f5b8d26b28fStephen Smalley	while (fd < 0 && sepolicy_file[i]) {
6184a655eca75a79149c25616c4a5a44f5b8d26b28fStephen Smalley		snprintf(path, sizeof(path), "%s",
6194a655eca75a79149c25616c4a5a44f5b8d26b28fStephen Smalley			sepolicy_file[i]);
620f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig		fd = open(path, O_RDONLY);
621f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig		i++;
622f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig	}
623f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig	if (fd < 0) {
624f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig		selinux_log(SELINUX_ERROR, "SELinux:  Could not open sepolicy:  %s\n",
625f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig				strerror(errno));
626f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig		return -1;
627f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig	}
628f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig	if (fstat(fd, &sb) < 0) {
629f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig		selinux_log(SELINUX_ERROR, "SELinux:  Could not stat %s:  %s\n",
630f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig				path, strerror(errno));
631f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig		close(fd);
632f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig		return -1;
633f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig	}
634f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig	map = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
635f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig	if (map == MAP_FAILED) {
636f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig		selinux_log(SELINUX_ERROR, "SELinux:  Could not map %s:  %s\n",
637f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig			path, strerror(errno));
638f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig		close(fd);
639f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig		return -1;
640f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig	}
641f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig
642f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig	rc = security_load_policy(map, sb.st_size);
643f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig	if (rc < 0) {
644f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig		selinux_log(SELINUX_ERROR, "SELinux:  Could not load policy:  %s\n",
645f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig			strerror(errno));
646f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig		munmap(map, sb.st_size);
647f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig		close(fd);
648f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig		return -1;
649f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig	}
650f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig
651f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig	munmap(map, sb.st_size);
652f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig	close(fd);
653f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig	selinux_log(SELINUX_INFO, "SELinux: Loaded policy from %s\n", path);
654f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig
655f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig	return 0;
656f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig}
6579b10083ab40e78cce8cc2b940ce22db6d1095fc5rpcraig
658f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraigint selinux_android_load_policy(void)
659f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig{
660f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig	mkdir(SELINUXMNT, 0755);
661f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig	if (mount("selinuxfs", SELINUXMNT, "selinuxfs", 0, NULL)) {
662f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig		if (errno == ENODEV) {
663f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig			/* SELinux not enabled in kernel */
664f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig			return -1;
665f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig		}
666f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig		selinux_log(SELINUX_ERROR,"SELinux:  Could not mount selinuxfs:  %s\n",
667f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig				strerror(errno));
668f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig		return -1;
669f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig	}
670f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig	set_selinuxmnt(SELINUXMNT);
6719b10083ab40e78cce8cc2b940ce22db6d1095fc5rpcraig
672f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig	return selinux_android_reload_policy();
6739b10083ab40e78cce8cc2b940ce22db6d1095fc5rpcraig}
674