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