blob: 8e39aacc4ab0ea7221e08c47caa091d69f752005 [file] [log] [blame]
Stephen Smalleyf0740362012-01-04 12:30:47 -05001#include <sys/types.h>
2#include <unistd.h>
3#include <string.h>
4#include <stdio.h>
5#include <stdlib.h>
Stephen Smalley826cc292014-01-28 15:04:22 -05006#include <stdbool.h>
Stephen Smalleyf0740362012-01-04 12:30:47 -05007#include <ctype.h>
8#include <errno.h>
9#include <pwd.h>
10#include <grp.h>
rpcraigf1724a32012-08-01 15:35:37 -040011#include <sys/mman.h>
12#include <sys/mount.h>
Stephen Smalleyf0740362012-01-04 12:30:47 -050013#include <sys/types.h>
14#include <sys/stat.h>
Stephen Smalley826cc292014-01-28 15:04:22 -050015#include <sys/xattr.h>
Stephen Smalleyf0740362012-01-04 12:30:47 -050016#include <fcntl.h>
Stephen Smalley08587cf2014-01-30 10:13:12 -050017#include <fts.h>
Stephen Smalleyf0740362012-01-04 12:30:47 -050018#include <selinux/selinux.h>
19#include <selinux/context.h>
20#include <selinux/android.h>
Stephen Smalley0ca91b32012-03-19 10:25:53 -040021#include <selinux/label.h>
Stephen Smalleye8b0fd82012-07-31 09:12:53 -040022#include <selinux/avc.h>
Stephen Smalley826cc292014-01-28 15:04:22 -050023#include <mincrypt/sha.h>
Stephen Smalley895b4462012-09-19 16:27:36 -040024#include <private/android_filesystem_config.h>
Riley Spahnbad0ebb2014-06-11 16:07:53 -070025#include <log/log.h>
Stephen Smalleyd10c3432012-11-05 11:49:35 -050026#include "policy.h"
Stephen Smalleyf0740362012-01-04 12:30:47 -050027#include "callbacks.h"
28#include "selinux_internal.h"
Stephen Smalley0e7340f2014-04-30 15:13:30 -070029#include "label_internal.h"
Stephen Smalleyf0740362012-01-04 12:30:47 -050030
31/*
32 * XXX Where should this configuration file be located?
33 * Needs to be accessible by zygote and installd when
34 * setting credentials for app processes and setting permissions
35 * on app data directories.
36 */
Stephen Smalley7446c912012-03-19 10:37:05 -040037static char const * const seapp_contexts_file[] = {
Stephen Smalley7446c912012-03-19 10:37:05 -040038 "/seapp_contexts",
Robert Craig5b5183f2014-03-17 20:53:06 -040039 "/data/security/current/seapp_contexts",
William Roberts8ed42422013-04-15 16:13:30 -070040 NULL };
Stephen Smalleyf0740362012-01-04 12:30:47 -050041
Stephen Smalley32ebfe82012-03-20 13:05:37 -040042static const struct selinux_opt seopts[] = {
Stephen Smalley32ebfe82012-03-20 13:05:37 -040043 { SELABEL_OPT_PATH, "/file_contexts" },
Robert Craig5b5183f2014-03-17 20:53:06 -040044 { SELABEL_OPT_PATH, "/data/security/current/file_contexts" },
Stephen Smalley32ebfe82012-03-20 13:05:37 -040045 { 0, NULL } };
Stephen Smalley7446c912012-03-19 10:37:05 -040046
Stephen Smalley4a655ec2012-09-18 15:08:32 -040047static const char *const sepolicy_file[] = {
Robert Craig5b5183f2014-03-17 20:53:06 -040048 "/sepolicy",
49 "/data/security/current/sepolicy",
50 NULL };
rpcraigf1724a32012-08-01 15:35:37 -040051
dcashman965141a2014-12-03 12:51:50 -080052static const struct selinux_opt seopts_prop[] = {
53 { SELABEL_OPT_PATH, "/property_contexts" },
54 { SELABEL_OPT_PATH, "/data/security/current/property_contexts" },
55 { 0, NULL }
56};
57
Riley Spahnbad0ebb2014-06-11 16:07:53 -070058static const struct selinux_opt seopts_service[] = {
59 { SELABEL_OPT_PATH, "/service_contexts" },
60 { SELABEL_OPT_PATH, "/data/security/current/service_contexts" },
61 { 0, NULL }
62};
63
Stephen Smalleya8795982012-11-28 10:42:46 -050064enum levelFrom {
65 LEVELFROM_NONE,
66 LEVELFROM_APP,
67 LEVELFROM_USER,
68 LEVELFROM_ALL
69};
70
Robert Craig5b5183f2014-03-17 20:53:06 -040071#define POLICY_OVERRIDE_VERSION "/data/security/current/selinux_version"
72#define POLICY_BASE_VERSION "/selinux_version"
73static int policy_index = 0;
74
75static void set_policy_index(void)
76{
77 int fd_base = -1, fd_override = -1;
78 struct stat sb_base;
79 struct stat sb_override;
80 void *map_base, *map_override;
81
82 policy_index = 0;
83
84 fd_base = open(POLICY_BASE_VERSION, O_RDONLY | O_NOFOLLOW);
85 if (fd_base < 0)
86 return;
87
Stephen Smalley1e9d2762015-02-19 09:42:58 -050088 if (fstat(fd_base, &sb_base) < 0)
89 goto close_base;
Robert Craig5b5183f2014-03-17 20:53:06 -040090
91 fd_override = open(POLICY_OVERRIDE_VERSION, O_RDONLY | O_NOFOLLOW);
Stephen Smalley1e9d2762015-02-19 09:42:58 -050092 if (fd_override < 0)
93 goto close_base;
Robert Craig5b5183f2014-03-17 20:53:06 -040094
Stephen Smalley1e9d2762015-02-19 09:42:58 -050095 if (fstat(fd_override, &sb_override) < 0)
96 goto close_override;
Robert Craig5b5183f2014-03-17 20:53:06 -040097
Stephen Smalley1e9d2762015-02-19 09:42:58 -050098 if (sb_base.st_size != sb_override.st_size)
99 goto close_override;
Robert Craig5b5183f2014-03-17 20:53:06 -0400100
101 map_base = mmap(NULL, sb_base.st_size, PROT_READ, MAP_PRIVATE, fd_base, 0);
Stephen Smalley1e9d2762015-02-19 09:42:58 -0500102 if (map_base == MAP_FAILED)
103 goto close_override;
Robert Craig5b5183f2014-03-17 20:53:06 -0400104
105 map_override = mmap(NULL, sb_override.st_size, PROT_READ, MAP_PRIVATE, fd_override, 0);
Stephen Smalley1e9d2762015-02-19 09:42:58 -0500106 if (map_override == MAP_FAILED)
107 goto unmap_base;
Robert Craig5b5183f2014-03-17 20:53:06 -0400108
Stephen Smalley1e9d2762015-02-19 09:42:58 -0500109 if (memcmp(map_base, map_override, sb_base.st_size) != 0)
110 goto unmap_override;
Robert Craig5b5183f2014-03-17 20:53:06 -0400111
Stephen Smalley1e9d2762015-02-19 09:42:58 -0500112 if (access(sepolicy_file[1], R_OK) != 0)
113 goto unmap_override;
Robert Craig5b5183f2014-03-17 20:53:06 -0400114
Stephen Smalley1e9d2762015-02-19 09:42:58 -0500115 if (access(seopts[1].value, R_OK) != 0)
116 goto unmap_override;
117
118 if (access(seopts_prop[1].value, R_OK) != 0)
119 goto unmap_override;
120
121 if (access(seopts_service[1].value, R_OK) != 0)
122 goto unmap_override;
123
124 if (access(seapp_contexts_file[1], R_OK) != 0)
125 goto unmap_override;
126
127 policy_index = 1;
128
129unmap_override:
Robert Craig5b5183f2014-03-17 20:53:06 -0400130 munmap(map_override, sb_override.st_size);
Stephen Smalley1e9d2762015-02-19 09:42:58 -0500131unmap_base:
132 munmap(map_base, sb_base.st_size);
133close_override:
134 close(fd_override);
135close_base:
136 close(fd_base);
137 return;
Robert Craig5b5183f2014-03-17 20:53:06 -0400138}
139
Stephen Smalleya8795982012-11-28 10:42:46 -0500140#if DEBUG
141static char const * const levelFromName[] = {
142 "none",
143 "app",
144 "user",
145 "all"
146};
147#endif
148
William Robertse3615f92013-09-11 20:35:53 -0700149struct prefix_str {
150 size_t len;
151 char *str;
152 char is_prefix;
153};
154
Stephen Smalley13319cf2014-04-04 15:44:23 -0400155static void free_prefix_str(struct prefix_str *p)
156{
157 if (!p)
158 return;
159 free(p->str);
160}
161
Stephen Smalleyf0740362012-01-04 12:30:47 -0500162struct seapp_context {
163 /* input selectors */
164 char isSystemServer;
Stephen Smalleyf76c30b2014-09-15 15:06:46 -0400165 bool isOwnerSet;
166 bool isOwner;
William Robertse3615f92013-09-11 20:35:53 -0700167 struct prefix_str user;
Stephen Smalleyf0740362012-01-04 12:30:47 -0500168 char *seinfo;
William Robertse3615f92013-09-11 20:35:53 -0700169 struct prefix_str name;
Stephen Smalley274e0f62014-02-19 10:53:09 -0500170 struct prefix_str path;
Stephen Smalleyf0740362012-01-04 12:30:47 -0500171 /* outputs */
172 char *domain;
173 char *type;
174 char *level;
Stephen Smalleya8795982012-11-28 10:42:46 -0500175 enum levelFrom levelFrom;
Stephen Smalleyf0740362012-01-04 12:30:47 -0500176};
177
Stephen Smalley13319cf2014-04-04 15:44:23 -0400178static void free_seapp_context(struct seapp_context *s)
179{
180 if (!s)
181 return;
182
183 free_prefix_str(&s->user);
184 free(s->seinfo);
185 free_prefix_str(&s->name);
186 free_prefix_str(&s->path);
187 free(s->domain);
188 free(s->type);
189 free(s->level);
Stephen Smalley13319cf2014-04-04 15:44:23 -0400190}
191
Stephen Smalleyf0740362012-01-04 12:30:47 -0500192static int seapp_context_cmp(const void *A, const void *B)
193{
Nick Kralevich833cba62013-11-19 11:24:33 -0800194 const struct seapp_context *const *sp1 = (const struct seapp_context *const *) A;
195 const struct seapp_context *const *sp2 = (const struct seapp_context *const *) B;
Stephen Smalleyf0740362012-01-04 12:30:47 -0500196 const struct seapp_context *s1 = *sp1, *s2 = *sp2;
197
198 /* Give precedence to isSystemServer=true. */
199 if (s1->isSystemServer != s2->isSystemServer)
200 return (s1->isSystemServer ? -1 : 1);
201
Stephen Smalleyf76c30b2014-09-15 15:06:46 -0400202 /* Give precedence to a specified isOwner= over an unspecified isOwner=. */
203 if (s1->isOwnerSet != s2->isOwnerSet)
204 return (s1->isOwnerSet ? -1 : 1);
205
Stephen Smalleyf0740362012-01-04 12:30:47 -0500206 /* Give precedence to a specified user= over an unspecified user=. */
William Robertse3615f92013-09-11 20:35:53 -0700207 if (s1->user.str && !s2->user.str)
Stephen Smalleyf0740362012-01-04 12:30:47 -0500208 return -1;
William Robertse3615f92013-09-11 20:35:53 -0700209 if (!s1->user.str && s2->user.str)
Stephen Smalleyf0740362012-01-04 12:30:47 -0500210 return 1;
211
William Robertse3615f92013-09-11 20:35:53 -0700212 if (s1->user.str) {
Stephen Smalleyf0740362012-01-04 12:30:47 -0500213 /* Give precedence to a fixed user= string over a prefix. */
William Robertse3615f92013-09-11 20:35:53 -0700214 if (s1->user.is_prefix != s2->user.is_prefix)
215 return (s2->user.is_prefix ? -1 : 1);
Stephen Smalleyf0740362012-01-04 12:30:47 -0500216
217 /* Give precedence to a longer prefix over a shorter prefix. */
William Robertse3615f92013-09-11 20:35:53 -0700218 if (s1->user.is_prefix && s1->user.len != s2->user.len)
219 return (s1->user.len > s2->user.len) ? -1 : 1;
Stephen Smalleyf0740362012-01-04 12:30:47 -0500220 }
221
222 /* Give precedence to a specified seinfo= over an unspecified seinfo=. */
223 if (s1->seinfo && !s2->seinfo)
224 return -1;
225 if (!s1->seinfo && s2->seinfo)
226 return 1;
227
228 /* Give precedence to a specified name= over an unspecified name=. */
William Robertse3615f92013-09-11 20:35:53 -0700229 if (s1->name.str && !s2->name.str)
Stephen Smalleyf0740362012-01-04 12:30:47 -0500230 return -1;
William Robertse3615f92013-09-11 20:35:53 -0700231 if (!s1->name.str && s2->name.str)
Stephen Smalleyf0740362012-01-04 12:30:47 -0500232 return 1;
233
William Robertse3615f92013-09-11 20:35:53 -0700234 if (s1->name.str) {
235 /* Give precedence to a fixed name= string over a prefix. */
236 if (s1->name.is_prefix != s2->name.is_prefix)
237 return (s2->name.is_prefix ? -1 : 1);
238
239 /* Give precedence to a longer prefix over a shorter prefix. */
240 if (s1->name.is_prefix && s1->name.len != s2->name.len)
241 return (s1->name.len > s2->name.len) ? -1 : 1;
242 }
243
Stephen Smalley274e0f62014-02-19 10:53:09 -0500244 /* Give precedence to a specified path= over an unspecified path=. */
245 if (s1->path.str && !s2->path.str)
246 return -1;
247 if (!s1->path.str && s2->path.str)
248 return 1;
249
250 if (s1->path.str) {
251 /* Give precedence to a fixed path= string over a prefix. */
252 if (s1->path.is_prefix != s2->path.is_prefix)
253 return (s2->path.is_prefix ? -1 : 1);
254
255 /* Give precedence to a longer prefix over a shorter prefix. */
256 if (s1->path.is_prefix && s1->path.len != s2->path.len)
257 return (s1->path.len > s2->path.len) ? -1 : 1;
258 }
259
Stephen Smalleyf0740362012-01-04 12:30:47 -0500260 /* Anything else has equal precedence. */
261 return 0;
262}
263
264static struct seapp_context **seapp_contexts = NULL;
265static int nspec = 0;
266
Stephen Smalley13319cf2014-04-04 15:44:23 -0400267static void free_seapp_contexts(void)
268{
269 int n;
270
271 if (!seapp_contexts)
272 return;
273
274 for (n = 0; n < nspec; n++)
275 free_seapp_context(seapp_contexts[n]);
276
277 free(seapp_contexts);
278 seapp_contexts = NULL;
279 nspec = 0;
280}
281
Stephen Smalley7446c912012-03-19 10:37:05 -0400282int selinux_android_seapp_context_reload(void)
Stephen Smalleyf0740362012-01-04 12:30:47 -0500283{
Stephen Smalley7446c912012-03-19 10:37:05 -0400284 FILE *fp = NULL;
Stephen Smalleyf0740362012-01-04 12:30:47 -0500285 char line_buf[BUFSIZ];
Stephen Smalleyf0740362012-01-04 12:30:47 -0500286 char *token;
287 unsigned lineno;
288 struct seapp_context *cur;
289 char *p, *name = NULL, *value = NULL, *saveptr;
290 size_t len;
Robert Craig5b5183f2014-03-17 20:53:06 -0400291 int n, ret;
Stephen Smalleyf0740362012-01-04 12:30:47 -0500292
Robert Craig5b5183f2014-03-17 20:53:06 -0400293 set_policy_index();
Stephen Smalley7446c912012-03-19 10:37:05 -0400294
Robert Craig5b5183f2014-03-17 20:53:06 -0400295 fp = fopen(seapp_contexts_file[policy_index], "r");
Stephen Smalleyf0740362012-01-04 12:30:47 -0500296 if (!fp) {
Stephen Smalley7446c912012-03-19 10:37:05 -0400297 selinux_log(SELINUX_ERROR, "%s: could not open any seapp_contexts file", __FUNCTION__);
298 return -1;
Stephen Smalleyf0740362012-01-04 12:30:47 -0500299 }
300
Stephen Smalley13319cf2014-04-04 15:44:23 -0400301 free_seapp_contexts();
Stephen Smalley300bebb2013-04-16 15:33:16 -0400302
Stephen Smalleyf0740362012-01-04 12:30:47 -0500303 nspec = 0;
304 while (fgets(line_buf, sizeof line_buf - 1, fp)) {
305 p = line_buf;
306 while (isspace(*p))
307 p++;
308 if (*p == '#' || *p == 0)
309 continue;
310 nspec++;
311 }
312
Nick Kralevich833cba62013-11-19 11:24:33 -0800313 seapp_contexts = (struct seapp_context **) calloc(nspec, sizeof(struct seapp_context *));
Stephen Smalleyf0740362012-01-04 12:30:47 -0500314 if (!seapp_contexts)
315 goto oom;
316
317 rewind(fp);
318 nspec = 0;
319 lineno = 1;
320 while (fgets(line_buf, sizeof line_buf - 1, fp)) {
321 len = strlen(line_buf);
322 if (line_buf[len - 1] == '\n')
323 line_buf[len - 1] = 0;
324 p = line_buf;
325 while (isspace(*p))
326 p++;
327 if (*p == '#' || *p == 0)
328 continue;
329
Nick Kralevich833cba62013-11-19 11:24:33 -0800330 cur = (struct seapp_context *) calloc(1, sizeof(struct seapp_context));
Stephen Smalleyf0740362012-01-04 12:30:47 -0500331 if (!cur)
332 goto oom;
333
334 token = strtok_r(p, " \t", &saveptr);
Stephen Smalley13319cf2014-04-04 15:44:23 -0400335 if (!token) {
336 free_seapp_context(cur);
Stephen Smalleyf0740362012-01-04 12:30:47 -0500337 goto err;
Stephen Smalley13319cf2014-04-04 15:44:23 -0400338 }
Stephen Smalleyf0740362012-01-04 12:30:47 -0500339
340 while (1) {
341 name = token;
342 value = strchr(name, '=');
Stephen Smalley13319cf2014-04-04 15:44:23 -0400343 if (!value) {
344 free_seapp_context(cur);
Stephen Smalleyf0740362012-01-04 12:30:47 -0500345 goto err;
Stephen Smalley13319cf2014-04-04 15:44:23 -0400346 }
Stephen Smalleyf0740362012-01-04 12:30:47 -0500347 *value++ = 0;
348
349 if (!strcasecmp(name, "isSystemServer")) {
350 if (!strcasecmp(value, "true"))
351 cur->isSystemServer = 1;
352 else if (!strcasecmp(value, "false"))
353 cur->isSystemServer = 0;
354 else {
Stephen Smalley13319cf2014-04-04 15:44:23 -0400355 free_seapp_context(cur);
Stephen Smalleyf0740362012-01-04 12:30:47 -0500356 goto err;
357 }
Stephen Smalleyf76c30b2014-09-15 15:06:46 -0400358 } else if (!strcasecmp(name, "isOwner")) {
359 cur->isOwnerSet = true;
360 if (!strcasecmp(value, "true"))
361 cur->isOwner = true;
362 else if (!strcasecmp(value, "false"))
363 cur->isOwner = false;
364 else {
365 free_seapp_context(cur);
366 goto err;
367 }
Stephen Smalleyf0740362012-01-04 12:30:47 -0500368 } else if (!strcasecmp(name, "user")) {
William Robertse3615f92013-09-11 20:35:53 -0700369 cur->user.str = strdup(value);
Stephen Smalley13319cf2014-04-04 15:44:23 -0400370 if (!cur->user.str) {
371 free_seapp_context(cur);
Stephen Smalleyf0740362012-01-04 12:30:47 -0500372 goto oom;
Stephen Smalley13319cf2014-04-04 15:44:23 -0400373 }
William Robertse3615f92013-09-11 20:35:53 -0700374 cur->user.len = strlen(cur->user.str);
375 if (cur->user.str[cur->user.len-1] == '*')
376 cur->user.is_prefix = 1;
Stephen Smalleyf0740362012-01-04 12:30:47 -0500377 } else if (!strcasecmp(name, "seinfo")) {
378 cur->seinfo = strdup(value);
Stephen Smalley13319cf2014-04-04 15:44:23 -0400379 if (!cur->seinfo) {
380 free_seapp_context(cur);
Stephen Smalleyf0740362012-01-04 12:30:47 -0500381 goto oom;
Stephen Smalley13319cf2014-04-04 15:44:23 -0400382 }
Stephen Smalleyf0740362012-01-04 12:30:47 -0500383 } else if (!strcasecmp(name, "name")) {
William Robertse3615f92013-09-11 20:35:53 -0700384 cur->name.str = strdup(value);
Stephen Smalley13319cf2014-04-04 15:44:23 -0400385 if (!cur->name.str) {
386 free_seapp_context(cur);
Stephen Smalleyf0740362012-01-04 12:30:47 -0500387 goto oom;
Stephen Smalley13319cf2014-04-04 15:44:23 -0400388 }
William Robertse3615f92013-09-11 20:35:53 -0700389 cur->name.len = strlen(cur->name.str);
390 if (cur->name.str[cur->name.len-1] == '*')
391 cur->name.is_prefix = 1;
Stephen Smalleyf0740362012-01-04 12:30:47 -0500392 } else if (!strcasecmp(name, "domain")) {
393 cur->domain = strdup(value);
Stephen Smalley13319cf2014-04-04 15:44:23 -0400394 if (!cur->domain) {
395 free_seapp_context(cur);
Stephen Smalleyf0740362012-01-04 12:30:47 -0500396 goto oom;
Stephen Smalley13319cf2014-04-04 15:44:23 -0400397 }
Stephen Smalleyf0740362012-01-04 12:30:47 -0500398 } else if (!strcasecmp(name, "type")) {
399 cur->type = strdup(value);
Stephen Smalley13319cf2014-04-04 15:44:23 -0400400 if (!cur->type) {
401 free_seapp_context(cur);
Stephen Smalleyf0740362012-01-04 12:30:47 -0500402 goto oom;
Stephen Smalley13319cf2014-04-04 15:44:23 -0400403 }
Stephen Smalleyf0740362012-01-04 12:30:47 -0500404 } else if (!strcasecmp(name, "levelFromUid")) {
405 if (!strcasecmp(value, "true"))
Stephen Smalleya8795982012-11-28 10:42:46 -0500406 cur->levelFrom = LEVELFROM_APP;
Stephen Smalleyf0740362012-01-04 12:30:47 -0500407 else if (!strcasecmp(value, "false"))
Stephen Smalleya8795982012-11-28 10:42:46 -0500408 cur->levelFrom = LEVELFROM_NONE;
409 else {
Stephen Smalley13319cf2014-04-04 15:44:23 -0400410 free_seapp_context(cur);
Stephen Smalleya8795982012-11-28 10:42:46 -0500411 goto err;
412 }
413 } else if (!strcasecmp(name, "levelFrom")) {
414 if (!strcasecmp(value, "none"))
415 cur->levelFrom = LEVELFROM_NONE;
416 else if (!strcasecmp(value, "app"))
417 cur->levelFrom = LEVELFROM_APP;
418 else if (!strcasecmp(value, "user"))
419 cur->levelFrom = LEVELFROM_USER;
420 else if (!strcasecmp(value, "all"))
421 cur->levelFrom = LEVELFROM_ALL;
Stephen Smalleyf0740362012-01-04 12:30:47 -0500422 else {
Stephen Smalley13319cf2014-04-04 15:44:23 -0400423 free_seapp_context(cur);
Stephen Smalleyf0740362012-01-04 12:30:47 -0500424 goto err;
425 }
426 } else if (!strcasecmp(name, "level")) {
427 cur->level = strdup(value);
Stephen Smalley13319cf2014-04-04 15:44:23 -0400428 if (!cur->level) {
429 free_seapp_context(cur);
Stephen Smalleyf0740362012-01-04 12:30:47 -0500430 goto oom;
Stephen Smalley13319cf2014-04-04 15:44:23 -0400431 }
Stephen Smalley274e0f62014-02-19 10:53:09 -0500432 } else if (!strcasecmp(name, "path")) {
433 cur->path.str = strdup(value);
Stephen Smalley13319cf2014-04-04 15:44:23 -0400434 if (!cur->path.str) {
435 free_seapp_context(cur);
Stephen Smalley274e0f62014-02-19 10:53:09 -0500436 goto oom;
Stephen Smalley13319cf2014-04-04 15:44:23 -0400437 }
Stephen Smalley274e0f62014-02-19 10:53:09 -0500438 cur->path.len = strlen(cur->path.str);
439 if (cur->path.str[cur->path.len-1] == '*')
440 cur->path.is_prefix = 1;
Stephen Smalley13319cf2014-04-04 15:44:23 -0400441 } else {
442 free_seapp_context(cur);
Stephen Smalleyf0740362012-01-04 12:30:47 -0500443 goto err;
Stephen Smalley13319cf2014-04-04 15:44:23 -0400444 }
Stephen Smalleyf0740362012-01-04 12:30:47 -0500445
446 token = strtok_r(NULL, " \t", &saveptr);
447 if (!token)
448 break;
449 }
450
Stephen Smalley13319cf2014-04-04 15:44:23 -0400451 if (cur->name.str &&
452 (!cur->seinfo || !strcmp(cur->seinfo, "default"))) {
453 selinux_log(SELINUX_ERROR, "%s: No specific seinfo value specified with name=\"%s\", on line %u: insecure configuration!\n",
Robert Craig5b5183f2014-03-17 20:53:06 -0400454 seapp_contexts_file[policy_index], cur->name.str, lineno);
Stephen Smalley13319cf2014-04-04 15:44:23 -0400455 free_seapp_context(cur);
456 goto err;
457 }
458
Stephen Smalleyf0740362012-01-04 12:30:47 -0500459 seapp_contexts[nspec] = cur;
460 nspec++;
461 lineno++;
462 }
463
464 qsort(seapp_contexts, nspec, sizeof(struct seapp_context *),
465 seapp_context_cmp);
466
467#if DEBUG
468 {
469 int i;
470 for (i = 0; i < nspec; i++) {
471 cur = seapp_contexts[i];
Stephen Smalley3fb00962015-02-13 15:59:32 -0500472 selinux_log(SELINUX_INFO, "%s: isSystemServer=%s isOwner=%s user=%s seinfo=%s name=%s path=%s -> domain=%s type=%s level=%s levelFrom=%s",
Stephen Smalleyf76c30b2014-09-15 15:06:46 -0400473 __FUNCTION__,
474 cur->isSystemServer ? "true" : "false",
475 cur->isOwnerSet ? (cur->isOwner ? "true" : "false") : "null",
476 cur->user.str,
Stephen Smalley3fb00962015-02-13 15:59:32 -0500477 cur->seinfo, cur->name.str, cur->path.str, cur->domain,
Stephen Smalleyf76c30b2014-09-15 15:06:46 -0400478 cur->type, cur->level,
479 levelFromName[cur->levelFrom]);
Stephen Smalleyf0740362012-01-04 12:30:47 -0500480 }
481 }
482#endif
483
Stephen Smalley7446c912012-03-19 10:37:05 -0400484 ret = 0;
485
Stephen Smalleyf0740362012-01-04 12:30:47 -0500486out:
487 fclose(fp);
Stephen Smalley7446c912012-03-19 10:37:05 -0400488 return ret;
Stephen Smalleyf0740362012-01-04 12:30:47 -0500489
490err:
Stephen Smalley13319cf2014-04-04 15:44:23 -0400491 selinux_log(SELINUX_ERROR, "%s: Invalid entry on line %u\n",
Robert Craig5b5183f2014-03-17 20:53:06 -0400492 seapp_contexts_file[policy_index], lineno);
Stephen Smalley13319cf2014-04-04 15:44:23 -0400493 free_seapp_contexts();
Stephen Smalley7446c912012-03-19 10:37:05 -0400494 ret = -1;
Stephen Smalleyf0740362012-01-04 12:30:47 -0500495 goto out;
496oom:
497 selinux_log(SELINUX_ERROR,
498 "%s: Out of memory\n", __FUNCTION__);
Stephen Smalley13319cf2014-04-04 15:44:23 -0400499 free_seapp_contexts();
Stephen Smalley7446c912012-03-19 10:37:05 -0400500 ret = -1;
Stephen Smalleyf0740362012-01-04 12:30:47 -0500501 goto out;
502}
503
Stephen Smalley7446c912012-03-19 10:37:05 -0400504
505static void seapp_context_init(void)
506{
507 selinux_android_seapp_context_reload();
508}
509
Stephen Smalleyf0740362012-01-04 12:30:47 -0500510static pthread_once_t once = PTHREAD_ONCE_INIT;
511
Stephen Smalleyd23b9e02012-09-21 10:45:39 -0400512/*
Stephen Smalleya8795982012-11-28 10:42:46 -0500513 * Max id that can be mapped to category set uniquely
Stephen Smalleyd23b9e02012-09-21 10:45:39 -0400514 * using the current scheme.
515 */
Stephen Smalleya8795982012-11-28 10:42:46 -0500516#define CAT_MAPPING_MAX_ID (0x1<<16)
Stephen Smalleyd23b9e02012-09-21 10:45:39 -0400517
518enum seapp_kind {
519 SEAPP_TYPE,
520 SEAPP_DOMAIN
521};
522
523static int seapp_context_lookup(enum seapp_kind kind,
Stephen Smalley895b4462012-09-19 16:27:36 -0400524 uid_t uid,
525 int isSystemServer,
Stephen Smalleyedfaad82012-07-12 11:30:24 -0400526 const char *seinfo,
Stephen Smalley895b4462012-09-19 16:27:36 -0400527 const char *pkgname,
Stephen Smalley274e0f62014-02-19 10:53:09 -0500528 const char *path,
Stephen Smalley895b4462012-09-19 16:27:36 -0400529 context_t ctx)
Stephen Smalleyf0740362012-01-04 12:30:47 -0500530{
Stephen Smalleyf76c30b2014-09-15 15:06:46 -0400531 bool isOwner;
Stephen Smalley895b4462012-09-19 16:27:36 -0400532 const char *username = NULL;
Nick Kralevichb1ae15a2013-07-11 17:35:53 -0700533 struct seapp_context *cur = NULL;
Stephen Smalley895b4462012-09-19 16:27:36 -0400534 int i;
535 size_t n;
Stephen Smalleya8795982012-11-28 10:42:46 -0500536 uid_t userid;
537 uid_t appid;
Stephen Smalleyf0740362012-01-04 12:30:47 -0500538
Stephen Smalleye183cec2014-02-05 16:41:47 -0500539 __selinux_once(once, seapp_context_init);
540
Stephen Smalleya8795982012-11-28 10:42:46 -0500541 userid = uid / AID_USER;
Stephen Smalleyf76c30b2014-09-15 15:06:46 -0400542 isOwner = (userid == 0);
Stephen Smalley895b4462012-09-19 16:27:36 -0400543 appid = uid % AID_USER;
544 if (appid < AID_APP) {
545 for (n = 0; n < android_id_count; n++) {
546 if (android_ids[n].aid == appid) {
547 username = android_ids[n].name;
548 break;
549 }
Stephen Smalleyce4e2e62012-08-23 12:20:42 -0400550 }
Stephen Smalley895b4462012-09-19 16:27:36 -0400551 if (!username)
552 goto err;
553 } else if (appid < AID_ISOLATED_START) {
Stephen Smalley525a2242012-09-24 10:22:45 -0400554 username = "_app";
Stephen Smalley895b4462012-09-19 16:27:36 -0400555 appid -= AID_APP;
556 } else {
Stephen Smalley525a2242012-09-24 10:22:45 -0400557 username = "_isolated";
Stephen Smalley895b4462012-09-19 16:27:36 -0400558 appid -= AID_ISOLATED_START;
Stephen Smalleyba70ee42012-07-10 15:49:04 -0400559 }
Stephen Smalleyf0740362012-01-04 12:30:47 -0500560
Stephen Smalleya8795982012-11-28 10:42:46 -0500561 if (appid >= CAT_MAPPING_MAX_ID || userid >= CAT_MAPPING_MAX_ID)
Stephen Smalley895b4462012-09-19 16:27:36 -0400562 goto err;
563
Stephen Smalleyf0740362012-01-04 12:30:47 -0500564 for (i = 0; i < nspec; i++) {
565 cur = seapp_contexts[i];
566
Stephen Smalley895b4462012-09-19 16:27:36 -0400567 if (cur->isSystemServer != isSystemServer)
Stephen Smalleyf0740362012-01-04 12:30:47 -0500568 continue;
569
Stephen Smalleyf76c30b2014-09-15 15:06:46 -0400570 if (cur->isOwnerSet && cur->isOwner != isOwner)
571 continue;
572
William Robertse3615f92013-09-11 20:35:53 -0700573 if (cur->user.str) {
574 if (cur->user.is_prefix) {
575 if (strncasecmp(username, cur->user.str, cur->user.len-1))
Stephen Smalleyf0740362012-01-04 12:30:47 -0500576 continue;
577 } else {
William Robertse3615f92013-09-11 20:35:53 -0700578 if (strcasecmp(username, cur->user.str))
Stephen Smalleyf0740362012-01-04 12:30:47 -0500579 continue;
580 }
581 }
582
Stephen Smalleyedfaad82012-07-12 11:30:24 -0400583 if (cur->seinfo) {
584 if (!seinfo || strcasecmp(seinfo, cur->seinfo))
585 continue;
586 }
Stephen Smalleyf0740362012-01-04 12:30:47 -0500587
William Robertse3615f92013-09-11 20:35:53 -0700588 if (cur->name.str) {
589 if(!pkgname)
Stephen Smalleyf0740362012-01-04 12:30:47 -0500590 continue;
William Robertse3615f92013-09-11 20:35:53 -0700591
592 if (cur->name.is_prefix) {
593 if (strncasecmp(pkgname, cur->name.str, cur->name.len-1))
594 continue;
595 } else {
596 if (strcasecmp(pkgname, cur->name.str))
597 continue;
598 }
Stephen Smalleyf0740362012-01-04 12:30:47 -0500599 }
600
Stephen Smalley274e0f62014-02-19 10:53:09 -0500601 if (cur->path.str) {
602 if (!path)
603 continue;
604
605 if (cur->path.is_prefix) {
606 if (strncmp(path, cur->path.str, cur->path.len-1))
607 continue;
608 } else {
609 if (strcmp(path, cur->path.str))
610 continue;
611 }
612 }
613
Stephen Smalley895b4462012-09-19 16:27:36 -0400614 if (kind == SEAPP_TYPE && !cur->type)
615 continue;
616 else if (kind == SEAPP_DOMAIN && !cur->domain)
Stephen Smalleyf0740362012-01-04 12:30:47 -0500617 continue;
618
Stephen Smalley895b4462012-09-19 16:27:36 -0400619 if (kind == SEAPP_TYPE) {
620 if (context_type_set(ctx, cur->type))
621 goto oom;
622 } else if (kind == SEAPP_DOMAIN) {
623 if (context_type_set(ctx, cur->domain))
624 goto oom;
625 }
Stephen Smalleyf0740362012-01-04 12:30:47 -0500626
Stephen Smalleya8795982012-11-28 10:42:46 -0500627 if (cur->levelFrom != LEVELFROM_NONE) {
Stephen Smalleyf0740362012-01-04 12:30:47 -0500628 char level[255];
Stephen Smalleya8795982012-11-28 10:42:46 -0500629 switch (cur->levelFrom) {
630 case LEVELFROM_APP:
Stephen Smalleydf1ece22013-12-02 10:07:48 -0500631 snprintf(level, sizeof level, "s0:c%u,c%u",
632 appid & 0xff,
Stephen Smalleya8795982012-11-28 10:42:46 -0500633 256 + (appid>>8 & 0xff));
634 break;
635 case LEVELFROM_USER:
Stephen Smalleydf1ece22013-12-02 10:07:48 -0500636 snprintf(level, sizeof level, "s0:c%u,c%u",
Stephen Smalleya8795982012-11-28 10:42:46 -0500637 512 + (userid & 0xff),
638 768 + (userid>>8 & 0xff));
639 break;
640 case LEVELFROM_ALL:
Stephen Smalleydf1ece22013-12-02 10:07:48 -0500641 snprintf(level, sizeof level, "s0:c%u,c%u,c%u,c%u",
642 appid & 0xff,
Stephen Smalleya8795982012-11-28 10:42:46 -0500643 256 + (appid>>8 & 0xff),
644 512 + (userid & 0xff),
645 768 + (userid>>8 & 0xff));
646 break;
647 default:
648 goto err;
649 }
Stephen Smalleyf0740362012-01-04 12:30:47 -0500650 if (context_range_set(ctx, level))
651 goto oom;
652 } else if (cur->level) {
653 if (context_range_set(ctx, cur->level))
654 goto oom;
655 }
William Roberts1b36ad02012-07-27 13:52:33 -0700656
Stephen Smalleyf0740362012-01-04 12:30:47 -0500657 break;
658 }
659
Stephen Smalley895b4462012-09-19 16:27:36 -0400660 if (kind == SEAPP_DOMAIN && i == nspec) {
661 /*
662 * No match.
663 * Fail to prevent staying in the zygote's context.
664 */
665 selinux_log(SELINUX_ERROR,
666 "%s: No match for app with uid %d, seinfo %s, name %s\n",
667 __FUNCTION__, uid, seinfo, pkgname);
668
669 if (security_getenforce() == 1)
670 goto err;
671 }
672
673 return 0;
674err:
675 return -1;
676oom:
677 return -2;
678}
679
Stephen Smalley1b478ea2014-02-07 09:32:41 -0500680int selinux_android_setfilecon(const char *pkgdir,
Stephen Smalley895b4462012-09-19 16:27:36 -0400681 const char *pkgname,
682 const char *seinfo,
683 uid_t uid)
684{
Nick Kralevich9ca40882013-07-11 16:58:44 -0700685 char *orig_ctx_str = NULL;
686 char *ctx_str = NULL;
Stephen Smalley895b4462012-09-19 16:27:36 -0400687 context_t ctx = NULL;
Nick Kralevich9ca40882013-07-11 16:58:44 -0700688 int rc = -1;
Stephen Smalley895b4462012-09-19 16:27:36 -0400689
690 if (is_selinux_enabled() <= 0)
691 return 0;
692
Stephen Smalley895b4462012-09-19 16:27:36 -0400693 rc = getfilecon(pkgdir, &ctx_str);
694 if (rc < 0)
695 goto err;
696
697 ctx = context_new(ctx_str);
698 orig_ctx_str = ctx_str;
699 if (!ctx)
700 goto oom;
701
Stephen Smalley274e0f62014-02-19 10:53:09 -0500702 rc = seapp_context_lookup(SEAPP_TYPE, uid, 0, seinfo, pkgname, NULL, ctx);
Stephen Smalley895b4462012-09-19 16:27:36 -0400703 if (rc == -1)
704 goto err;
705 else if (rc == -2)
706 goto oom;
707
Stephen Smalleyf0740362012-01-04 12:30:47 -0500708 ctx_str = context_str(ctx);
709 if (!ctx_str)
710 goto oom;
711
712 rc = security_check_context(ctx_str);
713 if (rc < 0)
714 goto err;
715
716 if (strcmp(ctx_str, orig_ctx_str)) {
717 rc = setfilecon(pkgdir, ctx_str);
718 if (rc < 0)
719 goto err;
720 }
721
722 rc = 0;
723out:
724 freecon(orig_ctx_str);
725 context_free(ctx);
726 return rc;
727err:
728 selinux_log(SELINUX_ERROR, "%s: Error setting context for pkgdir %s, uid %d: %s\n",
729 __FUNCTION__, pkgdir, uid, strerror(errno));
730 rc = -1;
731 goto out;
732oom:
733 selinux_log(SELINUX_ERROR, "%s: Out of memory\n", __FUNCTION__);
734 rc = -1;
735 goto out;
736}
737
738int selinux_android_setcontext(uid_t uid,
739 int isSystemServer,
740 const char *seinfo,
Stephen Smalleyba70ee42012-07-10 15:49:04 -0400741 const char *pkgname)
Stephen Smalleyf0740362012-01-04 12:30:47 -0500742{
Stephen Smalley895b4462012-09-19 16:27:36 -0400743 char *orig_ctx_str = NULL, *ctx_str;
Stephen Smalleyf0740362012-01-04 12:30:47 -0500744 context_t ctx = NULL;
Nick Kralevich9ca40882013-07-11 16:58:44 -0700745 int rc = -1;
Stephen Smalleyf0740362012-01-04 12:30:47 -0500746
747 if (is_selinux_enabled() <= 0)
748 return 0;
749
Stephen Smalleyf0740362012-01-04 12:30:47 -0500750 rc = getcon(&ctx_str);
751 if (rc)
752 goto err;
753
754 ctx = context_new(ctx_str);
755 orig_ctx_str = ctx_str;
756 if (!ctx)
757 goto oom;
758
Stephen Smalley274e0f62014-02-19 10:53:09 -0500759 rc = seapp_context_lookup(SEAPP_DOMAIN, uid, isSystemServer, seinfo, pkgname, NULL, ctx);
Stephen Smalley895b4462012-09-19 16:27:36 -0400760 if (rc == -1)
Stephen Smalleyf0740362012-01-04 12:30:47 -0500761 goto err;
Stephen Smalley895b4462012-09-19 16:27:36 -0400762 else if (rc == -2)
763 goto oom;
Stephen Smalleyf0740362012-01-04 12:30:47 -0500764
765 ctx_str = context_str(ctx);
766 if (!ctx_str)
767 goto oom;
768
769 rc = security_check_context(ctx_str);
770 if (rc < 0)
771 goto err;
772
773 if (strcmp(ctx_str, orig_ctx_str)) {
774 rc = setcon(ctx_str);
775 if (rc < 0)
776 goto err;
777 }
778
779 rc = 0;
780out:
781 freecon(orig_ctx_str);
782 context_free(ctx);
Stephen Smalleye8b0fd82012-07-31 09:12:53 -0400783 avc_netlink_close();
Stephen Smalleyf0740362012-01-04 12:30:47 -0500784 return rc;
785err:
786 if (isSystemServer)
787 selinux_log(SELINUX_ERROR,
Geremy Condra60646432013-04-10 17:58:48 -0700788 "%s: Error setting context for system server: %s\n",
789 __FUNCTION__, strerror(errno));
Stephen Smalleyf0740362012-01-04 12:30:47 -0500790 else
791 selinux_log(SELINUX_ERROR,
Geremy Condra60646432013-04-10 17:58:48 -0700792 "%s: Error setting context for app with uid %d, seinfo %s: %s\n",
793 __FUNCTION__, uid, seinfo, strerror(errno));
Stephen Smalleyf0740362012-01-04 12:30:47 -0500794
Stephen Smalleyf77e60d2012-07-27 15:41:10 -0400795 rc = -1;
Stephen Smalleyf0740362012-01-04 12:30:47 -0500796 goto out;
797oom:
798 selinux_log(SELINUX_ERROR, "%s: Out of memory\n", __FUNCTION__);
799 rc = -1;
800 goto out;
801}
802
dcashman965141a2014-12-03 12:51:50 -0800803static struct selabel_handle *fc_sehandle = NULL;
Stephen Smalley826cc292014-01-28 15:04:22 -0500804#define FC_DIGEST_SIZE SHA_DIGEST_SIZE
805static uint8_t fc_digest[FC_DIGEST_SIZE];
Stephen Smalley0ca91b32012-03-19 10:25:53 -0400806
dcashman965141a2014-12-03 12:51:50 -0800807static bool compute_contexts_hash(const struct selinux_opt opts[], uint8_t c_digest[])
Stephen Smalley826cc292014-01-28 15:04:22 -0500808{
Stephen Smalley826cc292014-01-28 15:04:22 -0500809 int fd;
810 struct stat sb;
811 void *map;
Stephen Smalley0ca91b32012-03-19 10:25:53 -0400812
dcashman965141a2014-12-03 12:51:50 -0800813 fd = open(opts[policy_index].value, O_CLOEXEC | O_RDONLY | O_NOFOLLOW);
Stephen Smalley826cc292014-01-28 15:04:22 -0500814 if (fd < 0) {
815 selinux_log(SELINUX_ERROR, "SELinux: Could not open %s: %s\n",
Robert Craig5b5183f2014-03-17 20:53:06 -0400816 opts[policy_index].value, strerror(errno));
dcashman965141a2014-12-03 12:51:50 -0800817 return false;
Stephen Smalley826cc292014-01-28 15:04:22 -0500818 }
819 if (fstat(fd, &sb) < 0) {
820 selinux_log(SELINUX_ERROR, "SELinux: Could not stat %s: %s\n",
Robert Craig5b5183f2014-03-17 20:53:06 -0400821 opts[policy_index].value, strerror(errno));
Stephen Smalley826cc292014-01-28 15:04:22 -0500822 close(fd);
dcashman965141a2014-12-03 12:51:50 -0800823 return false;
Stephen Smalley826cc292014-01-28 15:04:22 -0500824 }
825 map = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
826 if (map == MAP_FAILED) {
827 selinux_log(SELINUX_ERROR, "SELinux: Could not map %s: %s\n",
Robert Craig5b5183f2014-03-17 20:53:06 -0400828 opts[policy_index].value, strerror(errno));
Stephen Smalley826cc292014-01-28 15:04:22 -0500829 close(fd);
dcashman965141a2014-12-03 12:51:50 -0800830 return false;
Stephen Smalley826cc292014-01-28 15:04:22 -0500831 }
dcashman965141a2014-12-03 12:51:50 -0800832 SHA_hash(map, sb.st_size, c_digest);
Stephen Smalley826cc292014-01-28 15:04:22 -0500833 munmap(map, sb.st_size);
834 close(fd);
835
dcashman965141a2014-12-03 12:51:50 -0800836 return true;
Geremy Condra60646432013-04-10 17:58:48 -0700837}
838
Stephen Smalley906742d2012-08-23 16:04:59 -0400839static void file_context_init(void)
840{
dcashman965141a2014-12-03 12:51:50 -0800841 if (!fc_sehandle)
842 fc_sehandle = selinux_android_file_context_handle();
Stephen Smalley7fc97fb2014-01-28 10:37:58 -0500843}
844
Riley Spahnbad0ebb2014-06-11 16:07:53 -0700845
Riley Spahnbad0ebb2014-06-11 16:07:53 -0700846
Stephen Smalley08587cf2014-01-30 10:13:12 -0500847static pthread_once_t fc_once = PTHREAD_ONCE_INIT;
848
Stephen Smalleye183cec2014-02-05 16:41:47 -0500849struct pkgInfo {
850 char *name;
851 uid_t uid;
852 bool debuggable;
853 char *dataDir;
854 char *seinfo;
855 struct pkgInfo *next;
856};
857
858#define PKGTAB_SIZE 256
859static struct pkgInfo *pkgTab[PKGTAB_SIZE];
860
861static unsigned int pkghash(const char *pkgname)
862{
863 unsigned int h = 7;
864 for (; *pkgname; pkgname++) {
865 h = h * 31 + *pkgname;
866 }
867 return h & (PKGTAB_SIZE - 1);
868}
869
870/* The file containing the list of installed packages on the system */
871#define PACKAGES_LIST_FILE "/data/system/packages.list"
872
873static void package_info_init(void)
874{
875 char *buf = NULL;
876 size_t buflen = 0;
877 ssize_t bytesread;
878 FILE *fp;
879 char *cur, *next;
880 struct pkgInfo *pkgInfo = NULL;
881 unsigned int hash;
882 unsigned long lineno = 1;
883
884 fp = fopen(PACKAGES_LIST_FILE, "r");
885 if (!fp) {
886 selinux_log(SELINUX_ERROR, "SELinux: Could not open %s: %s.\n",
887 PACKAGES_LIST_FILE, strerror(errno));
888 return;
889 }
890 while ((bytesread = getline(&buf, &buflen, fp)) > 0) {
891 pkgInfo = calloc(1, sizeof(*pkgInfo));
892 if (!pkgInfo)
893 goto err;
894 next = buf;
895 cur = strsep(&next, " \t\n");
896 if (!cur)
897 goto err;
898 pkgInfo->name = strdup(cur);
899 if (!pkgInfo->name)
900 goto err;
901 cur = strsep(&next, " \t\n");
902 if (!cur)
903 goto err;
904 pkgInfo->uid = atoi(cur);
905 if (!pkgInfo->uid)
906 goto err;
907 cur = strsep(&next, " \t\n");
908 if (!cur)
909 goto err;
910 pkgInfo->debuggable = atoi(cur);
911 cur = strsep(&next, " \t\n");
912 if (!cur)
913 goto err;
914 pkgInfo->dataDir = strdup(cur);
915 if (!pkgInfo->dataDir)
916 goto err;
917 cur = strsep(&next, " \t\n");
918 if (!cur)
919 goto err;
920 pkgInfo->seinfo = strdup(cur);
921 if (!pkgInfo->seinfo)
922 goto err;
923
924 hash = pkghash(pkgInfo->name);
925 if (pkgTab[hash])
926 pkgInfo->next = pkgTab[hash];
927 pkgTab[hash] = pkgInfo;
928
929 lineno++;
930 }
931
932#if DEBUG
933 {
934 unsigned int buckets, entries, chainlen, longestchain;
935
936 buckets = entries = longestchain = 0;
937 for (hash = 0; hash < PKGTAB_SIZE; hash++) {
938 if (pkgTab[hash]) {
939 buckets++;
940 chainlen = 0;
941 for (pkgInfo = pkgTab[hash]; pkgInfo; pkgInfo = pkgInfo->next) {
942 chainlen++;
943 selinux_log(SELINUX_INFO, "%s: name=%s uid=%u debuggable=%s dataDir=%s seinfo=%s\n",
944 __FUNCTION__,
945 pkgInfo->name, pkgInfo->uid, pkgInfo->debuggable ? "true" : "false", pkgInfo->dataDir, pkgInfo->seinfo);
946 }
947 entries += chainlen;
948 if (longestchain < chainlen)
949 longestchain = chainlen;
950 }
951 }
952 selinux_log(SELINUX_INFO, "SELinux: %d pkg entries and %d/%d buckets used, longest chain %d\n", entries, buckets, PKGTAB_SIZE, longestchain);
953 }
954#endif
955
956out:
957 free(buf);
958 fclose(fp);
959 return;
960
961err:
962 selinux_log(SELINUX_ERROR, "SELinux: Error reading %s on line %lu.\n",
963 PACKAGES_LIST_FILE, lineno);
964 if (pkgInfo) {
965 free(pkgInfo->name);
966 free(pkgInfo->dataDir);
967 free(pkgInfo->seinfo);
968 free(pkgInfo);
969 }
970 goto out;
971}
972
973static pthread_once_t pkg_once = PTHREAD_ONCE_INIT;
974
975struct pkgInfo *package_info_lookup(const char *name)
976{
977 struct pkgInfo *pkgInfo;
978 unsigned int hash;
979
980 __selinux_once(pkg_once, package_info_init);
981
982 hash = pkghash(name);
983 for (pkgInfo = pkgTab[hash]; pkgInfo; pkgInfo = pkgInfo->next) {
984 if (!strcmp(name, pkgInfo->name))
985 return pkgInfo;
986 }
987 return NULL;
988}
989
990/* The path prefixes of package data directories. */
Stephen Smalley027670d2014-02-18 11:04:37 -0500991#define DATA_DATA_PATH "/data/data"
992#define DATA_USER_PATH "/data/user"
993#define DATA_DATA_PREFIX DATA_DATA_PATH "/"
994#define DATA_USER_PREFIX DATA_USER_PATH "/"
Stephen Smalleye183cec2014-02-05 16:41:47 -0500995
Stephen Smalley1d66afb2014-03-27 08:47:15 -0400996static int pkgdir_selabel_lookup(const char *pathname,
997 const char *seinfo,
998 uid_t uid,
999 char **secontextp)
Stephen Smalleye183cec2014-02-05 16:41:47 -05001000{
1001 char *pkgname = NULL, *end = NULL;
1002 struct pkgInfo *pkgInfo = NULL;
1003 char *secontext = *secontextp;
1004 context_t ctx = NULL;
1005 int rc = 0;
1006
1007 /* Skip directory prefix before package name. */
1008 if (!strncmp(pathname, DATA_DATA_PREFIX, sizeof(DATA_DATA_PREFIX)-1)) {
1009 pathname += sizeof(DATA_DATA_PREFIX) - 1;
1010 } else if (!strncmp(pathname, DATA_USER_PREFIX, sizeof(DATA_USER_PREFIX)-1)) {
1011 pathname += sizeof(DATA_USER_PREFIX) - 1;
1012 while (isdigit(*pathname))
1013 pathname++;
1014 if (*pathname == '/')
1015 pathname++;
1016 else
1017 return 0;
1018 } else
1019 return 0;
1020
1021 if (!(*pathname))
1022 return 0;
1023
1024 pkgname = strdup(pathname);
1025 if (!pkgname)
1026 return -1;
1027
1028 for (end = pkgname; *end && *end != '/'; end++)
1029 ;
Stephen Smalley274e0f62014-02-19 10:53:09 -05001030 pathname = end;
1031 if (*end)
1032 pathname++;
Stephen Smalleye183cec2014-02-05 16:41:47 -05001033 *end = '\0';
1034
Stephen Smalley1d66afb2014-03-27 08:47:15 -04001035 if (!seinfo) {
1036 pkgInfo = package_info_lookup(pkgname);
1037 if (!pkgInfo) {
1038 selinux_log(SELINUX_WARNING, "SELinux: Could not look up information for package %s, cannot restorecon %s.\n",
1039 pkgname, pathname);
1040 free(pkgname);
1041 return -1;
1042 }
Stephen Smalleye183cec2014-02-05 16:41:47 -05001043 }
1044
1045 ctx = context_new(secontext);
1046 if (!ctx)
1047 goto err;
1048
Stephen Smalley1d66afb2014-03-27 08:47:15 -04001049 rc = seapp_context_lookup(SEAPP_TYPE, pkgInfo ? pkgInfo->uid : uid, 0,
1050 pkgInfo ? pkgInfo->seinfo : seinfo, pkgInfo ? pkgInfo->name : pkgname, pathname, ctx);
Stephen Smalleye183cec2014-02-05 16:41:47 -05001051 if (rc < 0)
1052 goto err;
1053
1054 secontext = context_str(ctx);
1055 if (!secontext)
1056 goto err;
1057
1058 if (!strcmp(secontext, *secontextp))
1059 goto out;
1060
1061 rc = security_check_context(secontext);
1062 if (rc < 0)
1063 goto err;
1064
1065 freecon(*secontextp);
1066 *secontextp = strdup(secontext);
1067 if (!(*secontextp))
1068 goto err;
1069
1070 rc = 0;
1071
1072out:
1073 free(pkgname);
1074 context_free(ctx);
1075 return rc;
1076err:
1077 selinux_log(SELINUX_ERROR, "%s: Error looking up context for path %s, pkgname %s, seinfo %s, uid %u: %s\n",
1078 __FUNCTION__, pathname, pkgname, pkgInfo->seinfo, pkgInfo->uid, strerror(errno));
1079 rc = -1;
1080 goto out;
1081}
1082
Stephen Smalley826cc292014-01-28 15:04:22 -05001083#define RESTORECON_LAST "security.restorecon_last"
1084
Stephen Smalley1d66afb2014-03-27 08:47:15 -04001085static int restorecon_sb(const char *pathname, const struct stat *sb,
Nick Kralevicha8e4ad32014-05-19 13:45:59 -07001086 bool nochange, bool verbose,
Stephen Smalley1d66afb2014-03-27 08:47:15 -04001087 const char *seinfo, uid_t uid)
Stephen Smalley7fc97fb2014-01-28 10:37:58 -05001088{
1089 char *secontext = NULL;
1090 char *oldsecontext = NULL;
Stephen Smalleye183cec2014-02-05 16:41:47 -05001091 int rc = 0;
Stephen Smalley7fc97fb2014-01-28 10:37:58 -05001092
dcashman965141a2014-12-03 12:51:50 -08001093 if (selabel_lookup(fc_sehandle, &secontext, pathname, sb->st_mode) < 0)
Nick Kralevicha8e4ad32014-05-19 13:45:59 -07001094 return 0; /* no match, but not an error */
Stephen Smalley7fc97fb2014-01-28 10:37:58 -05001095
Stephen Smalleye183cec2014-02-05 16:41:47 -05001096 if (lgetfilecon(pathname, &oldsecontext) < 0)
1097 goto err;
1098
Stephen Smalley833cbd62014-02-27 13:08:40 -05001099 /*
Nick Kralevicha8e4ad32014-05-19 13:45:59 -07001100 * For subdirectories of /data/data or /data/user, we ignore selabel_lookup()
1101 * and use pkgdir_selabel_lookup() instead. Files within those directories
1102 * have different labeling rules, based off of /seapp_contexts, and
1103 * installd is responsible for managing these labels instead of init.
Stephen Smalley833cbd62014-02-27 13:08:40 -05001104 */
Stephen Smalleye183cec2014-02-05 16:41:47 -05001105 if (!strncmp(pathname, DATA_DATA_PREFIX, sizeof(DATA_DATA_PREFIX)-1) ||
1106 !strncmp(pathname, DATA_USER_PREFIX, sizeof(DATA_USER_PREFIX)-1)) {
Stephen Smalley1d66afb2014-03-27 08:47:15 -04001107 if (pkgdir_selabel_lookup(pathname, seinfo, uid, &secontext) < 0)
Stephen Smalleye183cec2014-02-05 16:41:47 -05001108 goto err;
Stephen Smalley7fc97fb2014-01-28 10:37:58 -05001109 }
1110
1111 if (strcmp(oldsecontext, secontext) != 0) {
Stephen Smalley08587cf2014-01-30 10:13:12 -05001112 if (verbose)
1113 selinux_log(SELINUX_INFO,
1114 "SELinux: Relabeling %s from %s to %s.\n", pathname, oldsecontext, secontext);
1115 if (!nochange) {
Stephen Smalleye183cec2014-02-05 16:41:47 -05001116 if (lsetfilecon(pathname, secontext) < 0)
1117 goto err;
Stephen Smalley7fc97fb2014-01-28 10:37:58 -05001118 }
1119 }
Stephen Smalley826cc292014-01-28 15:04:22 -05001120
Stephen Smalleye183cec2014-02-05 16:41:47 -05001121 rc = 0;
1122
1123out:
1124 freecon(oldsecontext);
1125 freecon(secontext);
1126 return rc;
1127
1128err:
1129 selinux_log(SELINUX_ERROR,
1130 "SELinux: Could not set context for %s: %s\n",
1131 pathname, strerror(errno));
1132 rc = -1;
1133 goto out;
Stephen Smalley0ca91b32012-03-19 10:25:53 -04001134}
1135
Stephen Smalleyda4208c2014-07-07 14:59:06 -04001136#define SYS_PATH "/sys"
1137#define SYS_PREFIX SYS_PATH "/"
1138
Stephen Smalley1d66afb2014-03-27 08:47:15 -04001139static int selinux_android_restorecon_common(const char* pathname,
1140 const char *seinfo,
1141 uid_t uid,
1142 unsigned int flags)
Stephen Smalley0ca91b32012-03-19 10:25:53 -04001143{
Stephen Smalley08587cf2014-01-30 10:13:12 -05001144 bool nochange = (flags & SELINUX_ANDROID_RESTORECON_NOCHANGE) ? true : false;
1145 bool verbose = (flags & SELINUX_ANDROID_RESTORECON_VERBOSE) ? true : false;
1146 bool recurse = (flags & SELINUX_ANDROID_RESTORECON_RECURSE) ? true : false;
1147 bool force = (flags & SELINUX_ANDROID_RESTORECON_FORCE) ? true : false;
Stephen Smalley027670d2014-02-18 11:04:37 -05001148 bool datadata = (flags & SELINUX_ANDROID_RESTORECON_DATADATA) ? true : false;
Stephen Smalleyda4208c2014-07-07 14:59:06 -04001149 bool issys = (!strcmp(pathname, SYS_PATH) || !strncmp(pathname, SYS_PREFIX, sizeof(SYS_PREFIX)-1)) ? true : false;
Nick Kralevicha8e4ad32014-05-19 13:45:59 -07001150 bool setrestoreconlast = true;
Stephen Smalley7fc97fb2014-01-28 10:37:58 -05001151 struct stat sb;
Stephen Smalley08587cf2014-01-30 10:13:12 -05001152 FTS *fts;
1153 FTSENT *ftsent;
1154 char *const paths[2] = { __UNCONST(pathname), NULL };
Stephen Smalleydfb9fe22014-09-02 12:52:57 -04001155 int ftsflags = FTS_NOCHDIR | FTS_XDEV | FTS_PHYSICAL;
Stephen Smalley08587cf2014-01-30 10:13:12 -05001156 int error, sverrno;
Stephen Smalley826cc292014-01-28 15:04:22 -05001157 char xattr_value[FC_DIGEST_SIZE];
1158 ssize_t size;
Stephen Smalley0ca91b32012-03-19 10:25:53 -04001159
Stephen Smalley7fc97fb2014-01-28 10:37:58 -05001160 if (is_selinux_enabled() <= 0)
1161 return 0;
Stephen Smalley0ca91b32012-03-19 10:25:53 -04001162
Stephen Smalley7fc97fb2014-01-28 10:37:58 -05001163 __selinux_once(fc_once, file_context_init);
Stephen Smalley0ca91b32012-03-19 10:25:53 -04001164
dcashman965141a2014-12-03 12:51:50 -08001165 if (!fc_sehandle)
Stephen Smalley7fc97fb2014-01-28 10:37:58 -05001166 return 0;
Stephen Smalley0ca91b32012-03-19 10:25:53 -04001167
Stephen Smalley08587cf2014-01-30 10:13:12 -05001168 if (!recurse) {
1169 if (lstat(pathname, &sb) < 0)
1170 return -1;
1171
Nick Kralevicha8e4ad32014-05-19 13:45:59 -07001172 return restorecon_sb(pathname, &sb, nochange, verbose, seinfo, uid);
Stephen Smalley08587cf2014-01-30 10:13:12 -05001173 }
1174
Stephen Smalley833cbd62014-02-27 13:08:40 -05001175 /*
1176 * Ignore restorecon_last on /data/data or /data/user
1177 * since their labeling is based on seapp_contexts and seinfo
1178 * assignments rather than file_contexts and is managed by
1179 * installd rather than init.
1180 */
Nick Kralevicha8e4ad32014-05-19 13:45:59 -07001181 if (!strncmp(pathname, DATA_DATA_PREFIX, sizeof(DATA_DATA_PREFIX)-1) ||
1182 !strncmp(pathname, DATA_USER_PREFIX, sizeof(DATA_USER_PREFIX)-1))
1183 setrestoreconlast = false;
Stephen Smalley833cbd62014-02-27 13:08:40 -05001184
Stephen Smalleyda4208c2014-07-07 14:59:06 -04001185 /* Also ignore on /sys since it is regenerated on each boot regardless. */
1186 if (issys)
1187 setrestoreconlast = false;
1188
Nick Kralevicha8e4ad32014-05-19 13:45:59 -07001189 if (setrestoreconlast) {
1190 size = getxattr(pathname, RESTORECON_LAST, xattr_value, sizeof fc_digest);
1191 if (!force && size == sizeof fc_digest && memcmp(fc_digest, xattr_value, sizeof fc_digest) == 0) {
1192 selinux_log(SELINUX_INFO,
1193 "SELinux: Skipping restorecon_recursive(%s)\n",
1194 pathname);
1195 return 0;
1196 }
Stephen Smalley826cc292014-01-28 15:04:22 -05001197 }
1198
Stephen Smalley08587cf2014-01-30 10:13:12 -05001199 fts = fts_open(paths, ftsflags, NULL);
1200 if (!fts)
1201 return -1;
1202
1203 error = 0;
1204 while ((ftsent = fts_read(fts)) != NULL) {
1205 switch (ftsent->fts_info) {
1206 case FTS_DC:
1207 selinux_log(SELINUX_ERROR,
1208 "SELinux: Directory cycle on %s.\n", ftsent->fts_path);
1209 errno = ELOOP;
1210 error = -1;
1211 goto out;
1212 case FTS_DP:
1213 continue;
1214 case FTS_DNR:
1215 selinux_log(SELINUX_ERROR,
1216 "SELinux: Could not read %s: %s.\n", ftsent->fts_path, strerror(errno));
1217 fts_set(fts, ftsent, FTS_SKIP);
1218 continue;
1219 case FTS_NS:
1220 selinux_log(SELINUX_ERROR,
1221 "SELinux: Could not stat %s: %s.\n", ftsent->fts_path, strerror(errno));
1222 fts_set(fts, ftsent, FTS_SKIP);
1223 continue;
1224 case FTS_ERR:
1225 selinux_log(SELINUX_ERROR,
1226 "SELinux: Error on %s: %s.\n", ftsent->fts_path, strerror(errno));
1227 fts_set(fts, ftsent, FTS_SKIP);
1228 continue;
Stephen Smalley027670d2014-02-18 11:04:37 -05001229 case FTS_D:
dcashman965141a2014-12-03 12:51:50 -08001230 if (issys && !selabel_partial_match(fc_sehandle, ftsent->fts_path)) {
Stephen Smalley0e7340f2014-04-30 15:13:30 -07001231 fts_set(fts, ftsent, FTS_SKIP);
1232 continue;
1233 }
Nick Kralevich4b130cc2014-05-16 17:31:31 -07001234 if (!datadata &&
1235 (!strcmp(ftsent->fts_path, DATA_DATA_PATH) ||
Stephen Smalleyb4c98082014-05-28 08:48:59 -04001236 !strncmp(ftsent->fts_path, DATA_USER_PREFIX, sizeof(DATA_USER_PREFIX)-1))) {
Nick Kralevich4b130cc2014-05-16 17:31:31 -07001237 // Don't label anything below this directory.
1238 fts_set(fts, ftsent, FTS_SKIP);
1239 // but fall through and make sure we label the directory itself
1240 }
Stephen Smalley027670d2014-02-18 11:04:37 -05001241 /* fall through */
Stephen Smalley08587cf2014-01-30 10:13:12 -05001242 default:
Nick Kralevicha8e4ad32014-05-19 13:45:59 -07001243 error |= restorecon_sb(ftsent->fts_path, ftsent->fts_statp, nochange, verbose, seinfo, uid);
Stephen Smalley08587cf2014-01-30 10:13:12 -05001244 break;
1245 }
1246 }
1247
Nick Kralevicha8e4ad32014-05-19 13:45:59 -07001248 // Labeling successful. Mark the top level directory as completed.
1249 if (setrestoreconlast && !nochange && !error)
1250 setxattr(pathname, RESTORECON_LAST, fc_digest, sizeof fc_digest, 0);
1251
Stephen Smalley08587cf2014-01-30 10:13:12 -05001252out:
1253 sverrno = errno;
1254 (void) fts_close(fts);
Nick Kralevicha8e4ad32014-05-19 13:45:59 -07001255 errno = sverrno;
Stephen Smalley08587cf2014-01-30 10:13:12 -05001256 return error;
1257}
1258
Stephen Smalley1d66afb2014-03-27 08:47:15 -04001259int selinux_android_restorecon(const char *file, unsigned int flags)
1260{
1261 return selinux_android_restorecon_common(file, NULL, -1, flags);
1262}
1263
1264int selinux_android_restorecon_pkgdir(const char *pkgdir,
1265 const char *seinfo,
1266 uid_t uid,
1267 unsigned int flags)
1268{
1269 return selinux_android_restorecon_common(pkgdir, seinfo, uid, flags | SELINUX_ANDROID_RESTORECON_DATADATA);
1270}
1271
rpcraigf1724a32012-08-01 15:35:37 -04001272struct selabel_handle* selinux_android_file_context_handle(void)
1273{
dcashman965141a2014-12-03 12:51:50 -08001274 struct selabel_handle *sehandle;
1275
1276 set_policy_index();
1277 sehandle = selabel_open(SELABEL_CTX_FILE, &seopts[policy_index], 1);
1278
1279 if (!sehandle) {
1280 selinux_log(SELINUX_ERROR, "%s: Error getting file context handle (%s)\n",
1281 __FUNCTION__, strerror(errno));
1282 return NULL;
1283 }
1284 if (!compute_contexts_hash(seopts, fc_digest)) {
1285 selabel_close(sehandle);
1286 return NULL;
1287 }
1288 selinux_log(SELINUX_INFO, "SELinux: Loaded file_contexts contexts from %s.\n",
1289 seopts[policy_index].value);
1290
1291 return sehandle;
1292}
1293
1294struct selabel_handle* selinux_android_prop_context_handle(void)
1295{
1296 struct selabel_handle* sehandle;
1297
1298 set_policy_index();
1299 sehandle = selabel_open(SELABEL_CTX_ANDROID_PROP,
1300 &seopts_prop[policy_index], 1);
1301 if (!sehandle) {
1302 selinux_log(SELINUX_ERROR, "%s: Error getting property context handle (%s)\n",
1303 __FUNCTION__, strerror(errno));
1304 return NULL;
1305 }
1306 selinux_log(SELINUX_INFO, "SELinux: Loaded property_contexts from %s.\n",
1307 seopts_prop[policy_index].value);
1308
1309 return sehandle;
Stephen Smalley7fc97fb2014-01-28 10:37:58 -05001310}
1311
Riley Spahnbad0ebb2014-06-11 16:07:53 -07001312struct selabel_handle* selinux_android_service_context_handle(void)
1313{
dcashman965141a2014-12-03 12:51:50 -08001314 struct selabel_handle* sehandle;
1315
1316 set_policy_index();
1317 sehandle = selabel_open(SELABEL_CTX_ANDROID_PROP,
1318 &seopts_service[policy_index], 1);
1319
1320 if (!sehandle) {
1321 selinux_log(SELINUX_ERROR, "%s: Error getting service context handle (%s)\n",
1322 __FUNCTION__, strerror(errno));
1323 return NULL;
1324 }
1325 selinux_log(SELINUX_INFO, "SELinux: Loaded service_contexts from %s.\n",
1326 seopts_service[policy_index].value);
1327
1328 return sehandle;
Riley Spahnbad0ebb2014-06-11 16:07:53 -07001329}
1330
Stephen Smalley7fc97fb2014-01-28 10:37:58 -05001331void selinux_android_set_sehandle(const struct selabel_handle *hndl)
1332{
dcashman965141a2014-12-03 12:51:50 -08001333 fc_sehandle = (struct selabel_handle *) hndl;
rpcraigf1724a32012-08-01 15:35:37 -04001334}
rpcraig9b100832012-07-27 06:36:59 -04001335
Robert Craig5b5183f2014-03-17 20:53:06 -04001336static int selinux_android_load_policy_helper(bool reload)
rpcraigf1724a32012-08-01 15:35:37 -04001337{
Stephen Smalley4a655ec2012-09-18 15:08:32 -04001338 int fd = -1, rc;
rpcraigf1724a32012-08-01 15:35:37 -04001339 struct stat sb;
1340 void *map = NULL;
Stephen Smalley818815e2015-02-18 17:32:13 -05001341 int old_policy_index = policy_index;
rpcraigf1724a32012-08-01 15:35:37 -04001342
Robert Craig5b5183f2014-03-17 20:53:06 -04001343 /*
1344 * If reloading policy and there is no /data policy or
Stephen Smalley818815e2015-02-18 17:32:13 -05001345 * that /data policy has the wrong version and our prior
1346 * load was from the / policy, then just return.
Robert Craig5b5183f2014-03-17 20:53:06 -04001347 * There is no point in reloading policy from / a second time.
1348 */
dcashman965141a2014-12-03 12:51:50 -08001349 set_policy_index();
Stephen Smalley818815e2015-02-18 17:32:13 -05001350 if (reload && !policy_index && !old_policy_index)
Robert Craig5b5183f2014-03-17 20:53:06 -04001351 return 0;
1352
1353 fd = open(sepolicy_file[policy_index], O_RDONLY | O_NOFOLLOW);
rpcraigf1724a32012-08-01 15:35:37 -04001354 if (fd < 0) {
1355 selinux_log(SELINUX_ERROR, "SELinux: Could not open sepolicy: %s\n",
1356 strerror(errno));
1357 return -1;
1358 }
1359 if (fstat(fd, &sb) < 0) {
1360 selinux_log(SELINUX_ERROR, "SELinux: Could not stat %s: %s\n",
Robert Craig5b5183f2014-03-17 20:53:06 -04001361 sepolicy_file[policy_index], strerror(errno));
rpcraigf1724a32012-08-01 15:35:37 -04001362 close(fd);
1363 return -1;
1364 }
1365 map = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
1366 if (map == MAP_FAILED) {
1367 selinux_log(SELINUX_ERROR, "SELinux: Could not map %s: %s\n",
dcashman965141a2014-12-03 12:51:50 -08001368 sepolicy_file[policy_index], strerror(errno));
rpcraigf1724a32012-08-01 15:35:37 -04001369 close(fd);
1370 return -1;
1371 }
1372
1373 rc = security_load_policy(map, sb.st_size);
1374 if (rc < 0) {
1375 selinux_log(SELINUX_ERROR, "SELinux: Could not load policy: %s\n",
dcashman965141a2014-12-03 12:51:50 -08001376 strerror(errno));
rpcraigf1724a32012-08-01 15:35:37 -04001377 munmap(map, sb.st_size);
1378 close(fd);
1379 return -1;
1380 }
1381
1382 munmap(map, sb.st_size);
1383 close(fd);
Robert Craig5b5183f2014-03-17 20:53:06 -04001384 selinux_log(SELINUX_INFO, "SELinux: Loaded policy from %s\n", sepolicy_file[policy_index]);
rpcraigf1724a32012-08-01 15:35:37 -04001385
1386 return 0;
1387}
1388
Robert Craig5b5183f2014-03-17 20:53:06 -04001389int selinux_android_reload_policy(void)
1390{
1391 return selinux_android_load_policy_helper(true);
1392}
1393
rpcraigf1724a32012-08-01 15:35:37 -04001394int selinux_android_load_policy(void)
1395{
Nick Kralevich833cba62013-11-19 11:24:33 -08001396 const char *mnt = SELINUXMNT;
Stephen Smalleyd10c3432012-11-05 11:49:35 -05001397 int rc;
1398 rc = mount(SELINUXFS, mnt, SELINUXFS, 0, NULL);
1399 if (rc < 0) {
rpcraigf1724a32012-08-01 15:35:37 -04001400 if (errno == ENODEV) {
1401 /* SELinux not enabled in kernel */
1402 return -1;
1403 }
Stephen Smalleyd10c3432012-11-05 11:49:35 -05001404 if (errno == ENOENT) {
1405 /* Fall back to legacy mountpoint. */
1406 mnt = OLDSELINUXMNT;
Alice Chud2302ca2013-01-04 16:02:46 -08001407 rc = mkdir(mnt, 0755);
1408 if (rc == -1 && errno != EEXIST) {
1409 selinux_log(SELINUX_ERROR,"SELinux: Could not mkdir: %s\n",
1410 strerror(errno));
1411 return -1;
1412 }
Stephen Smalleyd10c3432012-11-05 11:49:35 -05001413 rc = mount(SELINUXFS, mnt, SELINUXFS, 0, NULL);
1414 }
1415 }
1416 if (rc < 0) {
rpcraigf1724a32012-08-01 15:35:37 -04001417 selinux_log(SELINUX_ERROR,"SELinux: Could not mount selinuxfs: %s\n",
1418 strerror(errno));
1419 return -1;
1420 }
Stephen Smalleyd10c3432012-11-05 11:49:35 -05001421 set_selinuxmnt(mnt);
rpcraigf1724a32012-08-01 15:35:37 -04001422
Robert Craig5b5183f2014-03-17 20:53:06 -04001423 return selinux_android_load_policy_helper(false);
rpcraig9b100832012-07-27 06:36:59 -04001424}
Riley Spahnbad0ebb2014-06-11 16:07:53 -07001425
1426int selinux_log_callback(int type, const char *fmt, ...)
1427{
1428 va_list ap;
1429 int priority;
Nick Kralevichf58dbdd2014-07-01 11:01:13 -07001430 char *strp;
Riley Spahnbad0ebb2014-06-11 16:07:53 -07001431
1432 switch(type) {
1433 case SELINUX_WARNING:
1434 priority = ANDROID_LOG_WARN;
1435 break;
1436 case SELINUX_INFO:
1437 priority = ANDROID_LOG_INFO;
1438 break;
1439 default:
1440 priority = ANDROID_LOG_ERROR;
1441 break;
1442 }
1443
1444 va_start(ap, fmt);
Nick Kralevichf58dbdd2014-07-01 11:01:13 -07001445 if (vasprintf(&strp, fmt, ap) != -1) {
1446 LOG_PRI(priority, "SELinux", "%s", strp);
1447 LOG_EVENT_STRING(AUDITD_LOG_TAG, strp);
1448 free(strp);
1449 }
Riley Spahnbad0ebb2014-06-11 16:07:53 -07001450 va_end(ap);
1451 return 0;
1452}