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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 815 struct selabel_handle* selinux_android_file_context_handle(void) 816 { 817 return file_context_open(); 818 } 819 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 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