blob: 1ed6184bf43b5f5ca377c76ccfaae6dee7a81ff8 [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>
6#include <ctype.h>
7#include <errno.h>
8#include <pwd.h>
9#include <grp.h>
rpcraigf1724a32012-08-01 15:35:37 -040010#include <sys/mman.h>
11#include <sys/mount.h>
Stephen Smalleyf0740362012-01-04 12:30:47 -050012#include <sys/types.h>
13#include <sys/stat.h>
14#include <fcntl.h>
15#include <selinux/selinux.h>
16#include <selinux/context.h>
17#include <selinux/android.h>
Stephen Smalley0ca91b32012-03-19 10:25:53 -040018#include <selinux/label.h>
Stephen Smalleye8b0fd82012-07-31 09:12:53 -040019#include <selinux/avc.h>
Stephen Smalley895b4462012-09-19 16:27:36 -040020#include <private/android_filesystem_config.h>
Stephen Smalleyf0740362012-01-04 12:30:47 -050021#include "callbacks.h"
22#include "selinux_internal.h"
23
24/*
25 * XXX Where should this configuration file be located?
26 * Needs to be accessible by zygote and installd when
27 * setting credentials for app processes and setting permissions
28 * on app data directories.
29 */
Stephen Smalley7446c912012-03-19 10:37:05 -040030static char const * const seapp_contexts_file[] = {
31 "/data/system/seapp_contexts",
32 "/seapp_contexts",
33 0 };
Stephen Smalleyf0740362012-01-04 12:30:47 -050034
Stephen Smalley32ebfe82012-03-20 13:05:37 -040035static const struct selinux_opt seopts[] = {
36 { SELABEL_OPT_PATH, "/data/system/file_contexts" },
37 { SELABEL_OPT_PATH, "/file_contexts" },
38 { 0, NULL } };
Stephen Smalley7446c912012-03-19 10:37:05 -040039
Stephen Smalley4a655ec2012-09-18 15:08:32 -040040static const char *const sepolicy_file[] = {
rpcraigf1724a32012-08-01 15:35:37 -040041 "/data/system/sepolicy",
42 "/sepolicy",
43 0 };
44
Stephen Smalleyf0740362012-01-04 12:30:47 -050045struct seapp_context {
46 /* input selectors */
47 char isSystemServer;
48 char *user;
49 size_t len;
50 char prefix;
51 char *seinfo;
52 char *name;
53 /* outputs */
54 char *domain;
55 char *type;
56 char *level;
William Roberts1b36ad02012-07-27 13:52:33 -070057 char *sebool;
Stephen Smalleyf0740362012-01-04 12:30:47 -050058 char levelFromUid;
59};
60
61static int seapp_context_cmp(const void *A, const void *B)
62{
63 const struct seapp_context **sp1 = A, **sp2 = B;
64 const struct seapp_context *s1 = *sp1, *s2 = *sp2;
65
66 /* Give precedence to isSystemServer=true. */
67 if (s1->isSystemServer != s2->isSystemServer)
68 return (s1->isSystemServer ? -1 : 1);
69
70 /* Give precedence to a specified user= over an unspecified user=. */
71 if (s1->user && !s2->user)
72 return -1;
73 if (!s1->user && s2->user)
74 return 1;
75
76 if (s1->user) {
77 /* Give precedence to a fixed user= string over a prefix. */
78 if (s1->prefix != s2->prefix)
79 return (s2->prefix ? -1 : 1);
80
81 /* Give precedence to a longer prefix over a shorter prefix. */
82 if (s1->prefix && s1->len != s2->len)
83 return (s1->len > s2->len) ? -1 : 1;
84 }
85
86 /* Give precedence to a specified seinfo= over an unspecified seinfo=. */
87 if (s1->seinfo && !s2->seinfo)
88 return -1;
89 if (!s1->seinfo && s2->seinfo)
90 return 1;
91
92 /* Give precedence to a specified name= over an unspecified name=. */
93 if (s1->name && !s2->name)
94 return -1;
95 if (!s1->name && s2->name)
96 return 1;
97
William Roberts1b36ad02012-07-27 13:52:33 -070098 /* Give precedence to a specified sebool= over an unspecified sebool=. */
99 if (s1->sebool && !s2->sebool)
100 return -1;
101 if (!s1->sebool && s2->sebool)
102 return 1;
103
Stephen Smalleyf0740362012-01-04 12:30:47 -0500104 /* Anything else has equal precedence. */
105 return 0;
106}
107
108static struct seapp_context **seapp_contexts = NULL;
109static int nspec = 0;
110
Stephen Smalley7446c912012-03-19 10:37:05 -0400111int selinux_android_seapp_context_reload(void)
Stephen Smalleyf0740362012-01-04 12:30:47 -0500112{
Stephen Smalley7446c912012-03-19 10:37:05 -0400113 FILE *fp = NULL;
Stephen Smalleyf0740362012-01-04 12:30:47 -0500114 char line_buf[BUFSIZ];
Stephen Smalleyf0740362012-01-04 12:30:47 -0500115 char *token;
116 unsigned lineno;
117 struct seapp_context *cur;
118 char *p, *name = NULL, *value = NULL, *saveptr;
119 size_t len;
Stephen Smalley7446c912012-03-19 10:37:05 -0400120 int i = 0, ret;
Stephen Smalleyf0740362012-01-04 12:30:47 -0500121
Stephen Smalley7446c912012-03-19 10:37:05 -0400122 while ((fp==NULL) && seapp_contexts_file[i])
123 fp = fopen(seapp_contexts_file[i++], "r");
124
Stephen Smalleyf0740362012-01-04 12:30:47 -0500125 if (!fp) {
Stephen Smalley7446c912012-03-19 10:37:05 -0400126 selinux_log(SELINUX_ERROR, "%s: could not open any seapp_contexts file", __FUNCTION__);
127 return -1;
Stephen Smalleyf0740362012-01-04 12:30:47 -0500128 }
129
130 nspec = 0;
131 while (fgets(line_buf, sizeof line_buf - 1, fp)) {
132 p = line_buf;
133 while (isspace(*p))
134 p++;
135 if (*p == '#' || *p == 0)
136 continue;
137 nspec++;
138 }
139
140 seapp_contexts = calloc(nspec, sizeof(struct seapp_context *));
141 if (!seapp_contexts)
142 goto oom;
143
144 rewind(fp);
145 nspec = 0;
146 lineno = 1;
147 while (fgets(line_buf, sizeof line_buf - 1, fp)) {
148 len = strlen(line_buf);
149 if (line_buf[len - 1] == '\n')
150 line_buf[len - 1] = 0;
151 p = line_buf;
152 while (isspace(*p))
153 p++;
154 if (*p == '#' || *p == 0)
155 continue;
156
157 cur = calloc(1, sizeof(struct seapp_context));
158 if (!cur)
159 goto oom;
160
161 token = strtok_r(p, " \t", &saveptr);
162 if (!token)
163 goto err;
164
165 while (1) {
166 name = token;
167 value = strchr(name, '=');
168 if (!value)
169 goto err;
170 *value++ = 0;
171
172 if (!strcasecmp(name, "isSystemServer")) {
173 if (!strcasecmp(value, "true"))
174 cur->isSystemServer = 1;
175 else if (!strcasecmp(value, "false"))
176 cur->isSystemServer = 0;
177 else {
178 goto err;
179 }
180 } else if (!strcasecmp(name, "user")) {
181 cur->user = strdup(value);
182 if (!cur->user)
183 goto oom;
184 cur->len = strlen(cur->user);
185 if (cur->user[cur->len-1] == '*')
186 cur->prefix = 1;
187 } else if (!strcasecmp(name, "seinfo")) {
188 cur->seinfo = strdup(value);
189 if (!cur->seinfo)
190 goto oom;
191 } else if (!strcasecmp(name, "name")) {
192 cur->name = strdup(value);
193 if (!cur->name)
194 goto oom;
195 } else if (!strcasecmp(name, "domain")) {
196 cur->domain = strdup(value);
197 if (!cur->domain)
198 goto oom;
199 } else if (!strcasecmp(name, "type")) {
200 cur->type = strdup(value);
201 if (!cur->type)
202 goto oom;
203 } else if (!strcasecmp(name, "levelFromUid")) {
204 if (!strcasecmp(value, "true"))
205 cur->levelFromUid = 1;
206 else if (!strcasecmp(value, "false"))
207 cur->levelFromUid = 0;
208 else {
209 goto err;
210 }
211 } else if (!strcasecmp(name, "level")) {
212 cur->level = strdup(value);
213 if (!cur->level)
214 goto oom;
William Roberts1b36ad02012-07-27 13:52:33 -0700215 } else if (!strcasecmp(name, "sebool")) {
216 cur->sebool = strdup(value);
217 if (!cur->sebool)
218 goto oom;
Stephen Smalleyf0740362012-01-04 12:30:47 -0500219 } else
220 goto err;
221
222 token = strtok_r(NULL, " \t", &saveptr);
223 if (!token)
224 break;
225 }
226
227 seapp_contexts[nspec] = cur;
228 nspec++;
229 lineno++;
230 }
231
232 qsort(seapp_contexts, nspec, sizeof(struct seapp_context *),
233 seapp_context_cmp);
234
235#if DEBUG
236 {
237 int i;
238 for (i = 0; i < nspec; i++) {
239 cur = seapp_contexts[i];
William Roberts1b36ad02012-07-27 13:52:33 -0700240 selinux_log(SELINUX_INFO, "%s: isSystemServer=%s user=%s seinfo=%s name=%s sebool=%s -> domain=%s type=%s level=%s levelFromUid=%s",
241 __FUNCTION__,
242 cur->isSystemServer ? "true" : "false", cur->user,
243 cur->seinfo, cur->name, cur->sebool, cur->domain,
244 cur->type, cur->level,
245 cur->levelFromUid ? "true" : "false");
Stephen Smalleyf0740362012-01-04 12:30:47 -0500246 }
247 }
248#endif
249
Stephen Smalley7446c912012-03-19 10:37:05 -0400250 ret = 0;
251
Stephen Smalleyf0740362012-01-04 12:30:47 -0500252out:
253 fclose(fp);
Stephen Smalley7446c912012-03-19 10:37:05 -0400254 return ret;
Stephen Smalleyf0740362012-01-04 12:30:47 -0500255
256err:
257 selinux_log(SELINUX_ERROR, "%s: Error reading %s, line %u, name %s, value %s\n",
Stephen Smalley7446c912012-03-19 10:37:05 -0400258 __FUNCTION__, seapp_contexts_file[i - 1], lineno, name, value);
259 ret = -1;
Stephen Smalleyf0740362012-01-04 12:30:47 -0500260 goto out;
261oom:
262 selinux_log(SELINUX_ERROR,
263 "%s: Out of memory\n", __FUNCTION__);
Stephen Smalley7446c912012-03-19 10:37:05 -0400264 ret = -1;
Stephen Smalleyf0740362012-01-04 12:30:47 -0500265 goto out;
266}
267
Stephen Smalley7446c912012-03-19 10:37:05 -0400268
269static void seapp_context_init(void)
270{
271 selinux_android_seapp_context_reload();
272}
273
Stephen Smalleyf0740362012-01-04 12:30:47 -0500274static pthread_once_t once = PTHREAD_ONCE_INIT;
275
Stephen Smalley895b4462012-09-19 16:27:36 -0400276#define SEAPP_TYPE 1
277#define SEAPP_DOMAIN 2
278static int seapp_context_lookup(int kind,
279 uid_t uid,
280 int isSystemServer,
Stephen Smalleyedfaad82012-07-12 11:30:24 -0400281 const char *seinfo,
Stephen Smalley895b4462012-09-19 16:27:36 -0400282 const char *pkgname,
283 context_t ctx)
Stephen Smalleyf0740362012-01-04 12:30:47 -0500284{
Stephen Smalley895b4462012-09-19 16:27:36 -0400285 const char *username = NULL;
286 char *end = NULL;
Stephen Smalleyf0740362012-01-04 12:30:47 -0500287 struct passwd *pw;
288 struct seapp_context *cur;
Stephen Smalley895b4462012-09-19 16:27:36 -0400289 int i;
290 size_t n;
291 uid_t appid = 0;
Stephen Smalleyf0740362012-01-04 12:30:47 -0500292
Stephen Smalley895b4462012-09-19 16:27:36 -0400293 appid = uid % AID_USER;
294 if (appid < AID_APP) {
295 for (n = 0; n < android_id_count; n++) {
296 if (android_ids[n].aid == appid) {
297 username = android_ids[n].name;
298 break;
299 }
Stephen Smalleyce4e2e62012-08-23 12:20:42 -0400300 }
Stephen Smalley895b4462012-09-19 16:27:36 -0400301 if (!username)
302 goto err;
303 } else if (appid < AID_ISOLATED_START) {
304 username = "app_";
305 appid -= AID_APP;
306 } else {
307 username = "isolated";
308 appid -= AID_ISOLATED_START;
Stephen Smalleyba70ee42012-07-10 15:49:04 -0400309 }
Stephen Smalleyf0740362012-01-04 12:30:47 -0500310
Stephen Smalley895b4462012-09-19 16:27:36 -0400311 if (appid >= MLS_CATS)
312 goto err;
313
Stephen Smalleyf0740362012-01-04 12:30:47 -0500314 for (i = 0; i < nspec; i++) {
315 cur = seapp_contexts[i];
316
Stephen Smalley895b4462012-09-19 16:27:36 -0400317 if (cur->isSystemServer != isSystemServer)
Stephen Smalleyf0740362012-01-04 12:30:47 -0500318 continue;
319
320 if (cur->user) {
321 if (cur->prefix) {
Stephen Smalleyba70ee42012-07-10 15:49:04 -0400322 if (strncasecmp(username, cur->user, cur->len-1))
Stephen Smalleyf0740362012-01-04 12:30:47 -0500323 continue;
324 } else {
Stephen Smalleyba70ee42012-07-10 15:49:04 -0400325 if (strcasecmp(username, cur->user))
Stephen Smalleyf0740362012-01-04 12:30:47 -0500326 continue;
327 }
328 }
329
Stephen Smalleyedfaad82012-07-12 11:30:24 -0400330 if (cur->seinfo) {
331 if (!seinfo || strcasecmp(seinfo, cur->seinfo))
332 continue;
333 }
Stephen Smalleyf0740362012-01-04 12:30:47 -0500334
335 if (cur->name) {
Stephen Smalleyba70ee42012-07-10 15:49:04 -0400336 if (!pkgname || strcasecmp(pkgname, cur->name))
Stephen Smalleyf0740362012-01-04 12:30:47 -0500337 continue;
338 }
339
Stephen Smalley895b4462012-09-19 16:27:36 -0400340 if (kind == SEAPP_TYPE && !cur->type)
341 continue;
342 else if (kind == SEAPP_DOMAIN && !cur->domain)
Stephen Smalleyf0740362012-01-04 12:30:47 -0500343 continue;
344
William Roberts1b36ad02012-07-27 13:52:33 -0700345 if (cur->sebool) {
346 int value = security_get_boolean_active(cur->sebool);
347 if (value == 0)
348 continue;
349 else if (value == -1) {
350 selinux_log(SELINUX_ERROR, \
351 "Could not find boolean: %s ", cur->sebool);
352 goto err;
353 }
354 }
355
Stephen Smalley895b4462012-09-19 16:27:36 -0400356 if (kind == SEAPP_TYPE) {
357 if (context_type_set(ctx, cur->type))
358 goto oom;
359 } else if (kind == SEAPP_DOMAIN) {
360 if (context_type_set(ctx, cur->domain))
361 goto oom;
362 }
Stephen Smalleyf0740362012-01-04 12:30:47 -0500363
Stephen Smalleyc9726ab2012-07-11 16:10:13 -0400364 if (cur->levelFromUid) {
Stephen Smalleyf0740362012-01-04 12:30:47 -0500365 char level[255];
Stephen Smalleyf0740362012-01-04 12:30:47 -0500366 snprintf(level, sizeof level, "%s:c%lu",
Stephen Smalley895b4462012-09-19 16:27:36 -0400367 context_range_get(ctx), appid);
Stephen Smalleyf0740362012-01-04 12:30:47 -0500368 if (context_range_set(ctx, level))
369 goto oom;
370 } else if (cur->level) {
371 if (context_range_set(ctx, cur->level))
372 goto oom;
373 }
William Roberts1b36ad02012-07-27 13:52:33 -0700374
Stephen Smalleyf0740362012-01-04 12:30:47 -0500375 break;
376 }
377
Stephen Smalley895b4462012-09-19 16:27:36 -0400378 if (kind == SEAPP_DOMAIN && i == nspec) {
379 /*
380 * No match.
381 * Fail to prevent staying in the zygote's context.
382 */
383 selinux_log(SELINUX_ERROR,
384 "%s: No match for app with uid %d, seinfo %s, name %s\n",
385 __FUNCTION__, uid, seinfo, pkgname);
386
387 if (security_getenforce() == 1)
388 goto err;
389 }
390
391 return 0;
392err:
393 return -1;
394oom:
395 return -2;
396}
397
398int selinux_android_setfilecon2(const char *pkgdir,
399 const char *pkgname,
400 const char *seinfo,
401 uid_t uid)
402{
403 char *orig_ctx_str = NULL, *ctx_str;
404 context_t ctx = NULL;
405 int rc;
406
407 if (is_selinux_enabled() <= 0)
408 return 0;
409
410 __selinux_once(once, seapp_context_init);
411
412 rc = getfilecon(pkgdir, &ctx_str);
413 if (rc < 0)
414 goto err;
415
416 ctx = context_new(ctx_str);
417 orig_ctx_str = ctx_str;
418 if (!ctx)
419 goto oom;
420
421 rc = seapp_context_lookup(SEAPP_TYPE, uid, 0, seinfo, pkgname, ctx);
422 if (rc == -1)
423 goto err;
424 else if (rc == -2)
425 goto oom;
426
Stephen Smalleyf0740362012-01-04 12:30:47 -0500427 ctx_str = context_str(ctx);
428 if (!ctx_str)
429 goto oom;
430
431 rc = security_check_context(ctx_str);
432 if (rc < 0)
433 goto err;
434
435 if (strcmp(ctx_str, orig_ctx_str)) {
436 rc = setfilecon(pkgdir, ctx_str);
437 if (rc < 0)
438 goto err;
439 }
440
441 rc = 0;
442out:
443 freecon(orig_ctx_str);
444 context_free(ctx);
445 return rc;
446err:
447 selinux_log(SELINUX_ERROR, "%s: Error setting context for pkgdir %s, uid %d: %s\n",
448 __FUNCTION__, pkgdir, uid, strerror(errno));
449 rc = -1;
450 goto out;
451oom:
452 selinux_log(SELINUX_ERROR, "%s: Out of memory\n", __FUNCTION__);
453 rc = -1;
454 goto out;
455}
456
Stephen Smalleyedfaad82012-07-12 11:30:24 -0400457int selinux_android_setfilecon(const char *pkgdir,
458 const char *pkgname,
459 uid_t uid)
460{
461 return selinux_android_setfilecon2(pkgdir, pkgname, NULL, uid);
462}
463
Stephen Smalleyf0740362012-01-04 12:30:47 -0500464int selinux_android_setcontext(uid_t uid,
465 int isSystemServer,
466 const char *seinfo,
Stephen Smalleyba70ee42012-07-10 15:49:04 -0400467 const char *pkgname)
Stephen Smalleyf0740362012-01-04 12:30:47 -0500468{
Stephen Smalley895b4462012-09-19 16:27:36 -0400469 char *orig_ctx_str = NULL, *ctx_str;
Stephen Smalleyf0740362012-01-04 12:30:47 -0500470 context_t ctx = NULL;
Stephen Smalley895b4462012-09-19 16:27:36 -0400471 int rc;
Stephen Smalleyf0740362012-01-04 12:30:47 -0500472
473 if (is_selinux_enabled() <= 0)
474 return 0;
475
476 __selinux_once(once, seapp_context_init);
477
478 rc = getcon(&ctx_str);
479 if (rc)
480 goto err;
481
482 ctx = context_new(ctx_str);
483 orig_ctx_str = ctx_str;
484 if (!ctx)
485 goto oom;
486
Stephen Smalley895b4462012-09-19 16:27:36 -0400487 rc = seapp_context_lookup(SEAPP_DOMAIN, uid, isSystemServer, seinfo, pkgname, ctx);
488 if (rc == -1)
Stephen Smalleyf0740362012-01-04 12:30:47 -0500489 goto err;
Stephen Smalley895b4462012-09-19 16:27:36 -0400490 else if (rc == -2)
491 goto oom;
Stephen Smalleyf0740362012-01-04 12:30:47 -0500492
493 ctx_str = context_str(ctx);
494 if (!ctx_str)
495 goto oom;
496
497 rc = security_check_context(ctx_str);
498 if (rc < 0)
499 goto err;
500
501 if (strcmp(ctx_str, orig_ctx_str)) {
502 rc = setcon(ctx_str);
503 if (rc < 0)
504 goto err;
505 }
506
507 rc = 0;
508out:
509 freecon(orig_ctx_str);
510 context_free(ctx);
Stephen Smalleye8b0fd82012-07-31 09:12:53 -0400511 avc_netlink_close();
Stephen Smalleyf0740362012-01-04 12:30:47 -0500512 return rc;
513err:
514 if (isSystemServer)
515 selinux_log(SELINUX_ERROR,
516 "%s: Error setting context for system server: %s\n",
517 __FUNCTION__, strerror(errno));
518 else
519 selinux_log(SELINUX_ERROR,
520 "%s: Error setting context for app with uid %d, seinfo %s: %s\n",
521 __FUNCTION__, uid, seinfo, strerror(errno));
522
Stephen Smalleyf77e60d2012-07-27 15:41:10 -0400523 rc = -1;
Stephen Smalleyf0740362012-01-04 12:30:47 -0500524 goto out;
525oom:
526 selinux_log(SELINUX_ERROR, "%s: Out of memory\n", __FUNCTION__);
527 rc = -1;
528 goto out;
529}
530
Stephen Smalley0ca91b32012-03-19 10:25:53 -0400531static struct selabel_handle *sehandle = NULL;
532
Stephen Smalley906742d2012-08-23 16:04:59 -0400533static struct selabel_handle *file_context_open(void)
Stephen Smalley0ca91b32012-03-19 10:25:53 -0400534{
Stephen Smalley906742d2012-08-23 16:04:59 -0400535 struct selabel_handle *h;
Stephen Smalley32ebfe82012-03-20 13:05:37 -0400536 int i = 0;
Stephen Smalley0ca91b32012-03-19 10:25:53 -0400537
Stephen Smalley906742d2012-08-23 16:04:59 -0400538 h = NULL;
539 while ((h == NULL) && seopts[i].value) {
540 h = selabel_open(SELABEL_CTX_FILE, &seopts[i], 1);
Stephen Smalley32ebfe82012-03-20 13:05:37 -0400541 i++;
542 }
Stephen Smalley0ca91b32012-03-19 10:25:53 -0400543
Stephen Smalley906742d2012-08-23 16:04:59 -0400544 if (!h)
rpcraigf1724a32012-08-01 15:35:37 -0400545 selinux_log(SELINUX_ERROR, "%s: Error getting sehandle label (%s)\n",
Stephen Smalley0ca91b32012-03-19 10:25:53 -0400546 __FUNCTION__, strerror(errno));
Stephen Smalley906742d2012-08-23 16:04:59 -0400547 return h;
548}
549
550static void file_context_init(void)
551{
552 sehandle = file_context_open();
Stephen Smalley0ca91b32012-03-19 10:25:53 -0400553}
554
555static pthread_once_t fc_once = PTHREAD_ONCE_INIT;
556
557int selinux_android_restorecon(const char *pathname)
558{
559
560 __selinux_once(fc_once, file_context_init);
561
562 int ret;
563
564 if (!sehandle)
565 goto bail;
566
567 struct stat sb;
568
569 if (lstat(pathname, &sb) < 0)
570 goto err;
571
572 char *oldcontext, *newcontext;
573
574 if (lgetfilecon(pathname, &oldcontext) < 0)
575 goto err;
576
577 if (selabel_lookup(sehandle, &newcontext, pathname, sb.st_mode) < 0)
578 goto err;
579
580 if (strcmp(newcontext, "<<none>>") && strcmp(oldcontext, newcontext))
581 if (lsetfilecon(pathname, newcontext) < 0)
582 goto err;
583
584 ret = 0;
585out:
586 if (oldcontext)
587 freecon(oldcontext);
588 if (newcontext)
589 freecon(newcontext);
590
591 return ret;
592
593err:
594 selinux_log(SELINUX_ERROR,
595 "%s: Error restoring context for %s (%s)\n",
596 __FUNCTION__, pathname, strerror(errno));
597
598bail:
599 ret = -1;
600 goto out;
601}
rpcraig9b100832012-07-27 06:36:59 -0400602
603
rpcraigf1724a32012-08-01 15:35:37 -0400604struct selabel_handle* selinux_android_file_context_handle(void)
605{
Stephen Smalley906742d2012-08-23 16:04:59 -0400606 return file_context_open();
rpcraigf1724a32012-08-01 15:35:37 -0400607}
rpcraig9b100832012-07-27 06:36:59 -0400608
rpcraigf1724a32012-08-01 15:35:37 -0400609int selinux_android_reload_policy(void)
610{
611 char path[PATH_MAX];
Stephen Smalley4a655ec2012-09-18 15:08:32 -0400612 int fd = -1, rc;
rpcraigf1724a32012-08-01 15:35:37 -0400613 struct stat sb;
614 void *map = NULL;
615 int i = 0;
616
Stephen Smalley4a655ec2012-09-18 15:08:32 -0400617 while (fd < 0 && sepolicy_file[i]) {
618 snprintf(path, sizeof(path), "%s",
619 sepolicy_file[i]);
rpcraigf1724a32012-08-01 15:35:37 -0400620 fd = open(path, O_RDONLY);
rpcraigf1724a32012-08-01 15:35:37 -0400621 i++;
622 }
623 if (fd < 0) {
624 selinux_log(SELINUX_ERROR, "SELinux: Could not open sepolicy: %s\n",
625 strerror(errno));
626 return -1;
627 }
628 if (fstat(fd, &sb) < 0) {
629 selinux_log(SELINUX_ERROR, "SELinux: Could not stat %s: %s\n",
630 path, strerror(errno));
631 close(fd);
632 return -1;
633 }
634 map = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
635 if (map == MAP_FAILED) {
636 selinux_log(SELINUX_ERROR, "SELinux: Could not map %s: %s\n",
637 path, strerror(errno));
638 close(fd);
639 return -1;
640 }
641
642 rc = security_load_policy(map, sb.st_size);
643 if (rc < 0) {
644 selinux_log(SELINUX_ERROR, "SELinux: Could not load policy: %s\n",
645 strerror(errno));
646 munmap(map, sb.st_size);
647 close(fd);
648 return -1;
649 }
650
651 munmap(map, sb.st_size);
652 close(fd);
653 selinux_log(SELINUX_INFO, "SELinux: Loaded policy from %s\n", path);
654
655 return 0;
656}
657
658int selinux_android_load_policy(void)
659{
660 mkdir(SELINUXMNT, 0755);
661 if (mount("selinuxfs", SELINUXMNT, "selinuxfs", 0, NULL)) {
662 if (errno == ENODEV) {
663 /* SELinux not enabled in kernel */
664 return -1;
665 }
666 selinux_log(SELINUX_ERROR,"SELinux: Could not mount selinuxfs: %s\n",
667 strerror(errno));
668 return -1;
669 }
670 set_selinuxmnt(SELINUXMNT);
671
672 return selinux_android_reload_policy();
rpcraig9b100832012-07-27 06:36:59 -0400673}