1 #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>
10 #include <dirent.h>
11 #include <sys/mman.h>
12 #include <sys/mount.h>
13 #include <sys/types.h>
14 #include <sys/stat.h>
15 #include <fcntl.h>
16 #include <selinux/selinux.h>
17 #include <selinux/context.h>
18 #include <selinux/android.h>
19 #include <selinux/label.h>
20 #include <selinux/avc.h>
21 #include <private/android_filesystem_config.h>
22 #include "policy.h"
23 #include "callbacks.h"
24 #include "selinux_internal.h"
25
26 /*
27 * XXX Where should this configuration file be located?
28 * Needs to be accessible by zygote and installd when
29 * setting credentials for app processes and setting permissions
30 * on app data directories.
31 */
32 static char const * const seapp_contexts_file[] = {
33 "/data/security/current/seapp_contexts",
34 "/seapp_contexts",
35 0 };
36
37 static const struct selinux_opt seopts[] = {
38 { SELABEL_OPT_PATH, "/data/security/current/file_contexts" },
39 { SELABEL_OPT_PATH, "/file_contexts" },
40 { 0, NULL } };
41
42 static const struct selinux_opt seopt_backup[] = {
43 { SELABEL_OPT_PATH, "/data/security/current/file_contexts_backup" },
44 { SELABEL_OPT_PATH, "/file_contexts" },
45 { 0, NULL } };
46
47 static const char *const sepolicy_file[] = {
48 "/data/security/current/sepolicy",
49 "/sepolicy",
50 0 };
51
52 enum levelFrom {
53 LEVELFROM_NONE,
54 LEVELFROM_APP,
55 LEVELFROM_USER,
56 LEVELFROM_ALL
57 };
58
59 #if DEBUG
60 static char const * const levelFromName[] = {
61 "none",
62 "app",
63 "user",
64 "all"
65 };
66 #endif
67
68 struct seapp_context {
69 /* input selectors */
70 char isSystemServer;
71 char *user;
72 size_t len;
73 char prefix;
74 char *seinfo;
75 char *name;
76 /* outputs */
77 char *domain;
78 char *type;
79 char *level;
80 char *sebool;
81 enum levelFrom levelFrom;
82 };
83
seapp_context_cmp(const void * A,const void * B)84 static int seapp_context_cmp(const void *A, const void *B)
85 {
86 const struct seapp_context *const *sp1 = A, *const *sp2 = B;
87 const struct seapp_context *s1 = *sp1, *s2 = *sp2;
88
89 /* Give precedence to isSystemServer=true. */
90 if (s1->isSystemServer != s2->isSystemServer)
91 return (s1->isSystemServer ? -1 : 1);
92
93 /* Give precedence to a specified user= over an unspecified user=. */
94 if (s1->user && !s2->user)
95 return -1;
96 if (!s1->user && s2->user)
97 return 1;
98
99 if (s1->user) {
100 /* Give precedence to a fixed user= string over a prefix. */
101 if (s1->prefix != s2->prefix)
102 return (s2->prefix ? -1 : 1);
103
104 /* Give precedence to a longer prefix over a shorter prefix. */
105 if (s1->prefix && s1->len != s2->len)
106 return (s1->len > s2->len) ? -1 : 1;
107 }
108
109 /* Give precedence to a specified seinfo= over an unspecified seinfo=. */
110 if (s1->seinfo && !s2->seinfo)
111 return -1;
112 if (!s1->seinfo && s2->seinfo)
113 return 1;
114
115 /* Give precedence to a specified name= over an unspecified name=. */
116 if (s1->name && !s2->name)
117 return -1;
118 if (!s1->name && s2->name)
119 return 1;
120
121 /* Give precedence to a specified sebool= over an unspecified sebool=. */
122 if (s1->sebool && !s2->sebool)
123 return -1;
124 if (!s1->sebool && s2->sebool)
125 return 1;
126
127 /* Anything else has equal precedence. */
128 return 0;
129 }
130
131 static struct seapp_context **seapp_contexts = NULL;
132 static int nspec = 0;
133
selinux_android_seapp_context_reload(void)134 int selinux_android_seapp_context_reload(void)
135 {
136 FILE *fp = NULL;
137 char line_buf[BUFSIZ];
138 char *token;
139 unsigned lineno;
140 struct seapp_context *cur;
141 char *p, *name = NULL, *value = NULL, *saveptr;
142 size_t len;
143 int i = 0, ret;
144
145 while ((fp==NULL) && seapp_contexts_file[i])
146 fp = fopen(seapp_contexts_file[i++], "r");
147
148 if (!fp) {
149 selinux_log(SELINUX_ERROR, "%s: could not open any seapp_contexts file", __FUNCTION__);
150 return -1;
151 }
152
153 nspec = 0;
154 while (fgets(line_buf, sizeof line_buf - 1, fp)) {
155 p = line_buf;
156 while (isspace(*p))
157 p++;
158 if (*p == '#' || *p == 0)
159 continue;
160 nspec++;
161 }
162
163 seapp_contexts = calloc(nspec, sizeof(struct seapp_context *));
164 if (!seapp_contexts)
165 goto oom;
166
167 rewind(fp);
168 nspec = 0;
169 lineno = 1;
170 while (fgets(line_buf, sizeof line_buf - 1, fp)) {
171 len = strlen(line_buf);
172 if (line_buf[len - 1] == '\n')
173 line_buf[len - 1] = 0;
174 p = line_buf;
175 while (isspace(*p))
176 p++;
177 if (*p == '#' || *p == 0)
178 continue;
179
180 cur = calloc(1, sizeof(struct seapp_context));
181 if (!cur)
182 goto oom;
183
184 token = strtok_r(p, " \t", &saveptr);
185 if (!token)
186 goto err;
187
188 while (1) {
189 name = token;
190 value = strchr(name, '=');
191 if (!value)
192 goto err;
193 *value++ = 0;
194
195 if (!strcasecmp(name, "isSystemServer")) {
196 if (!strcasecmp(value, "true"))
197 cur->isSystemServer = 1;
198 else if (!strcasecmp(value, "false"))
199 cur->isSystemServer = 0;
200 else {
201 goto err;
202 }
203 } else if (!strcasecmp(name, "user")) {
204 cur->user = strdup(value);
205 if (!cur->user)
206 goto oom;
207 cur->len = strlen(cur->user);
208 if (cur->user[cur->len-1] == '*')
209 cur->prefix = 1;
210 } else if (!strcasecmp(name, "seinfo")) {
211 cur->seinfo = strdup(value);
212 if (!cur->seinfo)
213 goto oom;
214 } else if (!strcasecmp(name, "name")) {
215 cur->name = strdup(value);
216 if (!cur->name)
217 goto oom;
218 } else if (!strcasecmp(name, "domain")) {
219 cur->domain = strdup(value);
220 if (!cur->domain)
221 goto oom;
222 } else if (!strcasecmp(name, "type")) {
223 cur->type = strdup(value);
224 if (!cur->type)
225 goto oom;
226 } else if (!strcasecmp(name, "levelFromUid")) {
227 if (!strcasecmp(value, "true"))
228 cur->levelFrom = LEVELFROM_APP;
229 else if (!strcasecmp(value, "false"))
230 cur->levelFrom = LEVELFROM_NONE;
231 else {
232 goto err;
233 }
234 } else if (!strcasecmp(name, "levelFrom")) {
235 if (!strcasecmp(value, "none"))
236 cur->levelFrom = LEVELFROM_NONE;
237 else if (!strcasecmp(value, "app"))
238 cur->levelFrom = LEVELFROM_APP;
239 else if (!strcasecmp(value, "user"))
240 cur->levelFrom = LEVELFROM_USER;
241 else if (!strcasecmp(value, "all"))
242 cur->levelFrom = LEVELFROM_ALL;
243 else {
244 goto err;
245 }
246 } else if (!strcasecmp(name, "level")) {
247 cur->level = strdup(value);
248 if (!cur->level)
249 goto oom;
250 } else if (!strcasecmp(name, "sebool")) {
251 cur->sebool = strdup(value);
252 if (!cur->sebool)
253 goto oom;
254 } else
255 goto err;
256
257 token = strtok_r(NULL, " \t", &saveptr);
258 if (!token)
259 break;
260 }
261
262 seapp_contexts[nspec] = cur;
263 nspec++;
264 lineno++;
265 }
266
267 qsort(seapp_contexts, nspec, sizeof(struct seapp_context *),
268 seapp_context_cmp);
269
270 #if DEBUG
271 {
272 int i;
273 for (i = 0; i < nspec; i++) {
274 cur = seapp_contexts[i];
275 selinux_log(SELINUX_INFO, "%s: isSystemServer=%s user=%s seinfo=%s name=%s sebool=%s -> domain=%s type=%s level=%s levelFrom=%s",
276 __FUNCTION__,
277 cur->isSystemServer ? "true" : "false", cur->user,
278 cur->seinfo, cur->name, cur->sebool, cur->domain,
279 cur->type, cur->level,
280 levelFromName[cur->levelFrom]);
281 }
282 }
283 #endif
284
285 ret = 0;
286
287 out:
288 fclose(fp);
289 return ret;
290
291 err:
292 selinux_log(SELINUX_ERROR, "%s: Error reading %s, line %u, name %s, value %s\n",
293 __FUNCTION__, seapp_contexts_file[i - 1], lineno, name, value);
294 ret = -1;
295 goto out;
296 oom:
297 selinux_log(SELINUX_ERROR,
298 "%s: Out of memory\n", __FUNCTION__);
299 ret = -1;
300 goto out;
301 }
302
303
seapp_context_init(void)304 static void seapp_context_init(void)
305 {
306 selinux_android_seapp_context_reload();
307 }
308
309 static pthread_once_t once = PTHREAD_ONCE_INIT;
310
311 /*
312 * Max id that can be mapped to category set uniquely
313 * using the current scheme.
314 */
315 #define CAT_MAPPING_MAX_ID (0x1<<16)
316
317 enum seapp_kind {
318 SEAPP_TYPE,
319 SEAPP_DOMAIN
320 };
321
seapp_context_lookup(enum seapp_kind kind,uid_t uid,int isSystemServer,const char * seinfo,const char * pkgname,context_t ctx)322 static int seapp_context_lookup(enum seapp_kind kind,
323 uid_t uid,
324 int isSystemServer,
325 const char *seinfo,
326 const char *pkgname,
327 context_t ctx)
328 {
329 const char *username = NULL;
330 char *end = NULL;
331 struct passwd *pw;
332 struct seapp_context *cur;
333 int i;
334 size_t n;
335 uid_t userid;
336 uid_t appid;
337
338 userid = uid / AID_USER;
339 appid = uid % AID_USER;
340 if (appid < AID_APP) {
341 for (n = 0; n < android_id_count; n++) {
342 if (android_ids[n].aid == appid) {
343 username = android_ids[n].name;
344 break;
345 }
346 }
347 if (!username)
348 goto err;
349 } else if (appid < AID_ISOLATED_START) {
350 username = "_app";
351 appid -= AID_APP;
352 } else {
353 username = "_isolated";
354 appid -= AID_ISOLATED_START;
355 }
356
357 if (appid >= CAT_MAPPING_MAX_ID || userid >= CAT_MAPPING_MAX_ID)
358 goto err;
359
360 for (i = 0; i < nspec; i++) {
361 cur = seapp_contexts[i];
362
363 if (cur->isSystemServer != isSystemServer)
364 continue;
365
366 if (cur->user) {
367 if (cur->prefix) {
368 if (strncasecmp(username, cur->user, cur->len-1))
369 continue;
370 } else {
371 if (strcasecmp(username, cur->user))
372 continue;
373 }
374 }
375
376 if (cur->seinfo) {
377 if (!seinfo || strcasecmp(seinfo, cur->seinfo))
378 continue;
379 }
380
381 if (cur->name) {
382 if (!pkgname || strcasecmp(pkgname, cur->name))
383 continue;
384 }
385
386 if (kind == SEAPP_TYPE && !cur->type)
387 continue;
388 else if (kind == SEAPP_DOMAIN && !cur->domain)
389 continue;
390
391 if (cur->sebool) {
392 int value = security_get_boolean_active(cur->sebool);
393 if (value == 0)
394 continue;
395 else if (value == -1) {
396 selinux_log(SELINUX_ERROR, \
397 "Could not find boolean: %s ", cur->sebool);
398 goto err;
399 }
400 }
401
402 if (kind == SEAPP_TYPE) {
403 if (context_type_set(ctx, cur->type))
404 goto oom;
405 } else if (kind == SEAPP_DOMAIN) {
406 if (context_type_set(ctx, cur->domain))
407 goto oom;
408 }
409
410 if (cur->levelFrom != LEVELFROM_NONE) {
411 char level[255];
412 switch (cur->levelFrom) {
413 case LEVELFROM_APP:
414 snprintf(level, sizeof level, "%s:c%u,c%u",
415 context_range_get(ctx), appid & 0xff,
416 256 + (appid>>8 & 0xff));
417 break;
418 case LEVELFROM_USER:
419 snprintf(level, sizeof level, "%s:c%u,c%u",
420 context_range_get(ctx),
421 512 + (userid & 0xff),
422 768 + (userid>>8 & 0xff));
423 break;
424 case LEVELFROM_ALL:
425 snprintf(level, sizeof level, "%s:c%u,c%u,c%u,c%u",
426 context_range_get(ctx), appid & 0xff,
427 256 + (appid>>8 & 0xff),
428 512 + (userid & 0xff),
429 768 + (userid>>8 & 0xff));
430 break;
431 default:
432 goto err;
433 }
434 if (context_range_set(ctx, level))
435 goto oom;
436 } else if (cur->level) {
437 if (context_range_set(ctx, cur->level))
438 goto oom;
439 }
440
441 break;
442 }
443
444 if (kind == SEAPP_DOMAIN && i == nspec) {
445 /*
446 * No match.
447 * Fail to prevent staying in the zygote's context.
448 */
449 selinux_log(SELINUX_ERROR,
450 "%s: No match for app with uid %d, seinfo %s, name %s\n",
451 __FUNCTION__, uid, seinfo, pkgname);
452
453 if (security_getenforce() == 1)
454 goto err;
455 }
456
457 return 0;
458 err:
459 return -1;
460 oom:
461 return -2;
462 }
463
selinux_android_setfilecon2(const char * pkgdir,const char * pkgname,const char * seinfo,uid_t uid)464 int selinux_android_setfilecon2(const char *pkgdir,
465 const char *pkgname,
466 const char *seinfo,
467 uid_t uid)
468 {
469 char *orig_ctx_str = NULL, *ctx_str;
470 context_t ctx = NULL;
471 int rc;
472
473 if (is_selinux_enabled() <= 0)
474 return 0;
475
476 __selinux_once(once, seapp_context_init);
477
478 rc = getfilecon(pkgdir, &ctx_str);
479 if (rc < 0)
480 goto err;
481
482 ctx = context_new(ctx_str);
483 orig_ctx_str = ctx_str;
484 if (!ctx)
485 goto oom;
486
487 rc = seapp_context_lookup(SEAPP_TYPE, uid, 0, seinfo, pkgname, ctx);
488 if (rc == -1)
489 goto err;
490 else if (rc == -2)
491 goto oom;
492
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 = setfilecon(pkgdir, ctx_str);
503 if (rc < 0)
504 goto err;
505 }
506
507 rc = 0;
508 out:
509 freecon(orig_ctx_str);
510 context_free(ctx);
511 return rc;
512 err:
513 selinux_log(SELINUX_ERROR, "%s: Error setting context for pkgdir %s, uid %d: %s\n",
514 __FUNCTION__, pkgdir, uid, strerror(errno));
515 rc = -1;
516 goto out;
517 oom:
518 selinux_log(SELINUX_ERROR, "%s: Out of memory\n", __FUNCTION__);
519 rc = -1;
520 goto out;
521 }
522
selinux_android_setfilecon(const char * pkgdir,const char * pkgname,uid_t uid)523 int selinux_android_setfilecon(const char *pkgdir,
524 const char *pkgname,
525 uid_t uid)
526 {
527 return selinux_android_setfilecon2(pkgdir, pkgname, NULL, uid);
528 }
529
selinux_android_setcontext(uid_t uid,int isSystemServer,const char * seinfo,const char * pkgname)530 int selinux_android_setcontext(uid_t uid,
531 int isSystemServer,
532 const char *seinfo,
533 const char *pkgname)
534 {
535 char *orig_ctx_str = NULL, *ctx_str;
536 context_t ctx = NULL;
537 int rc;
538
539 if (is_selinux_enabled() <= 0)
540 return 0;
541
542 __selinux_once(once, seapp_context_init);
543
544 rc = getcon(&ctx_str);
545 if (rc)
546 goto err;
547
548 ctx = context_new(ctx_str);
549 orig_ctx_str = ctx_str;
550 if (!ctx)
551 goto oom;
552
553 rc = seapp_context_lookup(SEAPP_DOMAIN, uid, isSystemServer, seinfo, pkgname, ctx);
554 if (rc == -1)
555 goto err;
556 else if (rc == -2)
557 goto oom;
558
559 ctx_str = context_str(ctx);
560 if (!ctx_str)
561 goto oom;
562
563 rc = security_check_context(ctx_str);
564 if (rc < 0)
565 goto err;
566
567 if (strcmp(ctx_str, orig_ctx_str)) {
568 rc = setcon(ctx_str);
569 if (rc < 0)
570 goto err;
571 }
572
573 rc = 0;
574 out:
575 freecon(orig_ctx_str);
576 context_free(ctx);
577 avc_netlink_close();
578 return rc;
579 err:
580 if (isSystemServer)
581 selinux_log(SELINUX_ERROR,
582 "%s: Error setting context for system server: %s\n",
583 __FUNCTION__, strerror(errno));
584 else
585 selinux_log(SELINUX_ERROR,
586 "%s: Error setting context for app with uid %d, seinfo %s: %s\n",
587 __FUNCTION__, uid, seinfo, strerror(errno));
588
589 rc = -1;
590 goto out;
591 oom:
592 selinux_log(SELINUX_ERROR, "%s: Out of memory\n", __FUNCTION__);
593 rc = -1;
594 goto out;
595 }
596
597 static struct selabel_handle *sehandle = NULL;
598
get_selabel_handle(const struct selinux_opt opts[])599 static struct selabel_handle *get_selabel_handle(const struct selinux_opt opts[]) {
600 struct selabel_handle *h;
601 int i = 0;
602
603 h = NULL;
604 while ((h == NULL) && opts[i].value) {
605 h = selabel_open(SELABEL_CTX_FILE, &opts[i], 1);
606 i++;
607 }
608
609 return h;
610 }
611
file_context_open(void)612 static struct selabel_handle *file_context_open(void)
613 {
614 struct selabel_handle *h;
615
616 h = get_selabel_handle(seopts);
617
618 if (!h)
619 selinux_log(SELINUX_ERROR, "%s: Error getting file context handle (%s)\n",
620 __FUNCTION__, strerror(errno));
621 return h;
622 }
623
file_context_backup_open(void)624 static struct selabel_handle *file_context_backup_open(void)
625 {
626 struct selabel_handle *h;
627
628 h = get_selabel_handle(seopt_backup);
629
630 if (!h)
631 selinux_log(SELINUX_ERROR, "%s: Error getting backup file context handle (%s)\n",
632 __FUNCTION__, strerror(errno));
633 return h;
634 }
635
file_context_init(void)636 static void file_context_init(void)
637 {
638 sehandle = file_context_open();
639 }
640
641 static pthread_once_t fc_once = PTHREAD_ONCE_INIT;
642
selinux_android_restorecon(const char * pathname)643 int selinux_android_restorecon(const char *pathname)
644 {
645
646 if (is_selinux_enabled() <= 0)
647 return 0;
648
649 __selinux_once(fc_once, file_context_init);
650
651 int ret;
652
653 if (!sehandle)
654 goto bail;
655
656 struct stat sb;
657
658 if (lstat(pathname, &sb) < 0)
659 goto err;
660
661 char *oldcontext, *newcontext;
662
663 if (lgetfilecon(pathname, &oldcontext) < 0)
664 goto err;
665
666 if (selabel_lookup(sehandle, &newcontext, pathname, sb.st_mode) < 0)
667 goto err;
668
669 if (strcmp(newcontext, "<<none>>") && strcmp(oldcontext, newcontext))
670 if (lsetfilecon(pathname, newcontext) < 0)
671 goto err;
672
673 ret = 0;
674 out:
675 if (oldcontext)
676 freecon(oldcontext);
677 if (newcontext)
678 freecon(newcontext);
679
680 return ret;
681
682 err:
683 selinux_log(SELINUX_ERROR,
684 "%s: Error restoring context for %s (%s)\n",
685 __FUNCTION__, pathname, strerror(errno));
686
687 bail:
688 ret = -1;
689 goto out;
690 }
691
file_requires_fixup(const char * pathname,struct selabel_handle * sehandle_old,struct selabel_handle * sehandle_new)692 static int file_requires_fixup(const char *pathname,
693 struct selabel_handle *sehandle_old,
694 struct selabel_handle *sehandle_new)
695 {
696 int ret;
697 struct stat sb;
698 char *current_context, *old_context, *new_context;
699
700 ret = 0;
701 old_context = NULL;
702 new_context = NULL;
703 current_context = NULL;
704
705 if (lstat(pathname, &sb) < 0) {
706 ret = -1;
707 goto err;
708 }
709
710 if (lgetfilecon(pathname, ¤t_context) < 0) {
711 ret = -1;
712 goto err;
713 }
714
715 if (selabel_lookup(sehandle_old, &old_context, pathname, sb.st_mode) < 0) {
716 ret = -1;
717 goto err;
718 }
719
720 if (selabel_lookup(sehandle_new, &new_context, pathname, sb.st_mode) < 0) {
721 ret = -1;
722 goto err;
723 }
724
725 if (strstr(current_context, "unlabeled") != NULL) {
726 ret = 1;
727 goto out;
728 }
729
730 ret = (strcmp(old_context, new_context) && !strcmp(current_context, old_context));
731 goto out;
732
733 err:
734 selinux_log(SELINUX_ERROR,
735 "%s: Error comparing context for %s (%s)\n",
736 __FUNCTION__,
737 pathname,
738 strerror(errno));
739
740 out:
741 if (current_context)
742 freecon(current_context);
743 if (new_context)
744 freecon(new_context);
745 if (old_context)
746 freecon(old_context);
747 return ret;
748 }
749
fixcon_file(const char * pathname,struct selabel_handle * sehandle_old,struct selabel_handle * sehandle_new)750 static int fixcon_file(const char *pathname,
751 struct selabel_handle *sehandle_old,
752 struct selabel_handle *sehandle_new)
753 {
754 int requires_fixup;
755
756 requires_fixup = file_requires_fixup(pathname, sehandle_old, sehandle_new);
757 if (requires_fixup < 0)
758 return -1;
759
760 if (requires_fixup)
761 selinux_android_restorecon(pathname);
762
763 return 0;
764 }
765
fixcon_recursive(const char * pathname,struct selabel_handle * sehandle_old,struct selabel_handle * sehandle_new)766 static int fixcon_recursive(const char *pathname,
767 struct selabel_handle *sehandle_old,
768 struct selabel_handle *sehandle_new)
769 {
770 struct stat statresult;
771 if (lstat(pathname, &statresult) < 0)
772 return -1;
773
774 if (!S_ISDIR(statresult.st_mode))
775 return fixcon_file(pathname, sehandle_old, sehandle_new);
776
777 DIR *dir = opendir(pathname);
778 if (dir == NULL)
779 return -1;
780
781 struct dirent *entry;
782 while ((entry = readdir(dir)) != NULL) {
783 char *entryname;
784 if (!strcmp(entry->d_name, ".."))
785 continue;
786 if (!strcmp(entry->d_name, "."))
787 continue;
788 if (asprintf(&entryname, "%s/%s", pathname, entry->d_name) == -1)
789 continue;
790 fixcon_recursive(entryname, sehandle_old, sehandle_new);
791 free(entryname);
792 }
793
794 if (closedir(dir) < 0)
795 return -1;
796
797 return fixcon_file(pathname, sehandle_old, sehandle_new);
798 }
799
selinux_android_fixcon(const char * pathname)800 int selinux_android_fixcon(const char *pathname)
801 {
802 struct selabel_handle *sehandle_old, *sehandle_new;
803
804 sehandle_old = file_context_backup_open();
805 if (sehandle_old == NULL)
806 return -1;
807
808 sehandle_new = file_context_open();
809 if (sehandle_new == NULL)
810 return -1;
811
812 return fixcon_recursive(pathname, sehandle_old, sehandle_new);
813 }
814
selinux_android_file_context_handle(void)815 struct selabel_handle* selinux_android_file_context_handle(void)
816 {
817 return file_context_open();
818 }
819
selinux_android_reload_policy(void)820 int selinux_android_reload_policy(void)
821 {
822 int fd = -1, rc;
823 struct stat sb;
824 void *map = NULL;
825 int i = 0;
826
827 while (fd < 0 && sepolicy_file[i]) {
828 fd = open(sepolicy_file[i], O_RDONLY | O_NOFOLLOW);
829 i++;
830 }
831 if (fd < 0) {
832 selinux_log(SELINUX_ERROR, "SELinux: Could not open sepolicy: %s\n",
833 strerror(errno));
834 return -1;
835 }
836 if (fstat(fd, &sb) < 0) {
837 selinux_log(SELINUX_ERROR, "SELinux: Could not stat %s: %s\n",
838 sepolicy_file[i], strerror(errno));
839 close(fd);
840 return -1;
841 }
842 map = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
843 if (map == MAP_FAILED) {
844 selinux_log(SELINUX_ERROR, "SELinux: Could not map %s: %s\n",
845 sepolicy_file[i], strerror(errno));
846 close(fd);
847 return -1;
848 }
849
850 rc = security_load_policy(map, sb.st_size);
851 if (rc < 0) {
852 selinux_log(SELINUX_ERROR, "SELinux: Could not load policy: %s\n",
853 strerror(errno));
854 munmap(map, sb.st_size);
855 close(fd);
856 return -1;
857 }
858
859 munmap(map, sb.st_size);
860 close(fd);
861 selinux_log(SELINUX_INFO, "SELinux: Loaded policy from %s\n", sepolicy_file[i]);
862
863 return 0;
864 }
865
selinux_android_load_policy(void)866 int selinux_android_load_policy(void)
867 {
868 char *mnt = SELINUXMNT;
869 int rc;
870 rc = mount(SELINUXFS, mnt, SELINUXFS, 0, NULL);
871 if (rc < 0) {
872 if (errno == ENODEV) {
873 /* SELinux not enabled in kernel */
874 return -1;
875 }
876 if (errno == ENOENT) {
877 /* Fall back to legacy mountpoint. */
878 mnt = OLDSELINUXMNT;
879 rc = mkdir(mnt, 0755);
880 if (rc == -1 && errno != EEXIST) {
881 selinux_log(SELINUX_ERROR,"SELinux: Could not mkdir: %s\n",
882 strerror(errno));
883 return -1;
884 }
885 rc = mount(SELINUXFS, mnt, SELINUXFS, 0, NULL);
886 }
887 }
888 if (rc < 0) {
889 selinux_log(SELINUX_ERROR,"SELinux: Could not mount selinuxfs: %s\n",
890 strerror(errno));
891 return -1;
892 }
893 set_selinuxmnt(mnt);
894
895 return selinux_android_reload_policy();
896 }
897