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, 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 301 out: 302 fclose(fp); 303 return ret; 304 305 err: 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; 310 oom: 311 selinux_log(SELINUX_ERROR, 312 "%s: Out of memory\n", __FUNCTION__); 313 ret = -1; 314 goto out; 315 } 316 317 318 static void seapp_context_init(void) 319 { 320 selinux_android_seapp_context_reload(); 321 } 322 323 static 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 331 enum seapp_kind { 332 SEAPP_TYPE, 333 SEAPP_DOMAIN 334 }; 335 336 static 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 struct seapp_context *cur = NULL; 345 int i; 346 size_t n; 347 uid_t userid; 348 uid_t appid; 349 350 userid = uid / AID_USER; 351 appid = uid % AID_USER; 352 if (appid < AID_APP) { 353 for (n = 0; n < android_id_count; n++) { 354 if (android_ids[n].aid == appid) { 355 username = android_ids[n].name; 356 break; 357 } 358 } 359 if (!username) 360 goto err; 361 } else if (appid < AID_ISOLATED_START) { 362 username = "_app"; 363 appid -= AID_APP; 364 } else { 365 username = "_isolated"; 366 appid -= AID_ISOLATED_START; 367 } 368 369 if (appid >= CAT_MAPPING_MAX_ID || userid >= CAT_MAPPING_MAX_ID) 370 goto err; 371 372 for (i = 0; i < nspec; i++) { 373 cur = seapp_contexts[i]; 374 375 if (cur->isSystemServer != isSystemServer) 376 continue; 377 378 if (cur->user) { 379 if (cur->prefix) { 380 if (strncasecmp(username, cur->user, cur->len-1)) 381 continue; 382 } else { 383 if (strcasecmp(username, cur->user)) 384 continue; 385 } 386 } 387 388 if (cur->seinfo) { 389 if (!seinfo || strcasecmp(seinfo, cur->seinfo)) 390 continue; 391 } 392 393 if (cur->name) { 394 if (!pkgname || strcasecmp(pkgname, cur->name)) 395 continue; 396 } 397 398 if (kind == SEAPP_TYPE && !cur->type) 399 continue; 400 else if (kind == SEAPP_DOMAIN && !cur->domain) 401 continue; 402 403 if (cur->sebool) { 404 int value = security_get_boolean_active(cur->sebool); 405 if (value == 0) 406 continue; 407 else if (value == -1) { 408 selinux_log(SELINUX_ERROR, \ 409 "Could not find boolean: %s ", cur->sebool); 410 goto err; 411 } 412 } 413 414 if (kind == SEAPP_TYPE) { 415 if (context_type_set(ctx, cur->type)) 416 goto oom; 417 } else if (kind == SEAPP_DOMAIN) { 418 if (context_type_set(ctx, cur->domain)) 419 goto oom; 420 } 421 422 if (cur->levelFrom != LEVELFROM_NONE) { 423 char level[255]; 424 switch (cur->levelFrom) { 425 case LEVELFROM_APP: 426 snprintf(level, sizeof level, "%s:c%u,c%u", 427 context_range_get(ctx), appid & 0xff, 428 256 + (appid>>8 & 0xff)); 429 break; 430 case LEVELFROM_USER: 431 snprintf(level, sizeof level, "%s:c%u,c%u", 432 context_range_get(ctx), 433 512 + (userid & 0xff), 434 768 + (userid>>8 & 0xff)); 435 break; 436 case LEVELFROM_ALL: 437 snprintf(level, sizeof level, "%s:c%u,c%u,c%u,c%u", 438 context_range_get(ctx), appid & 0xff, 439 256 + (appid>>8 & 0xff), 440 512 + (userid & 0xff), 441 768 + (userid>>8 & 0xff)); 442 break; 443 default: 444 goto err; 445 } 446 if (context_range_set(ctx, level)) 447 goto oom; 448 } else if (cur->level) { 449 if (context_range_set(ctx, cur->level)) 450 goto oom; 451 } 452 453 break; 454 } 455 456 if (kind == SEAPP_DOMAIN && i == nspec) { 457 /* 458 * No match. 459 * Fail to prevent staying in the zygote's context. 460 */ 461 selinux_log(SELINUX_ERROR, 462 "%s: No match for app with uid %d, seinfo %s, name %s\n", 463 __FUNCTION__, uid, seinfo, pkgname); 464 465 if (security_getenforce() == 1) 466 goto err; 467 } 468 469 return 0; 470 err: 471 return -1; 472 oom: 473 return -2; 474 } 475 476 int selinux_android_setfilecon2(const char *pkgdir, 477 const char *pkgname, 478 const char *seinfo, 479 uid_t uid) 480 { 481 char *orig_ctx_str = NULL; 482 char *ctx_str = NULL; 483 context_t ctx = NULL; 484 int rc = -1; 485 486 if (is_selinux_enabled() <= 0) 487 return 0; 488 489 __selinux_once(once, seapp_context_init); 490 491 rc = getfilecon(pkgdir, &ctx_str); 492 if (rc < 0) 493 goto err; 494 495 ctx = context_new(ctx_str); 496 orig_ctx_str = ctx_str; 497 if (!ctx) 498 goto oom; 499 500 rc = seapp_context_lookup(SEAPP_TYPE, uid, 0, seinfo, pkgname, ctx); 501 if (rc == -1) 502 goto err; 503 else if (rc == -2) 504 goto oom; 505 506 ctx_str = context_str(ctx); 507 if (!ctx_str) 508 goto oom; 509 510 rc = security_check_context(ctx_str); 511 if (rc < 0) 512 goto err; 513 514 if (strcmp(ctx_str, orig_ctx_str)) { 515 rc = setfilecon(pkgdir, ctx_str); 516 if (rc < 0) 517 goto err; 518 } 519 520 rc = 0; 521 out: 522 freecon(orig_ctx_str); 523 context_free(ctx); 524 return rc; 525 err: 526 selinux_log(SELINUX_ERROR, "%s: Error setting context for pkgdir %s, uid %d: %s\n", 527 __FUNCTION__, pkgdir, uid, strerror(errno)); 528 rc = -1; 529 goto out; 530 oom: 531 selinux_log(SELINUX_ERROR, "%s: Out of memory\n", __FUNCTION__); 532 rc = -1; 533 goto out; 534 } 535 536 int selinux_android_setfilecon(const char *pkgdir, 537 const char *pkgname, 538 uid_t uid) 539 { 540 return selinux_android_setfilecon2(pkgdir, pkgname, NULL, uid); 541 } 542 543 int selinux_android_setcontext(uid_t uid, 544 int isSystemServer, 545 const char *seinfo, 546 const char *pkgname) 547 { 548 char *orig_ctx_str = NULL, *ctx_str; 549 context_t ctx = NULL; 550 int rc = -1; 551 552 if (is_selinux_enabled() <= 0) 553 return 0; 554 555 __selinux_once(once, seapp_context_init); 556 557 rc = getcon(&ctx_str); 558 if (rc) 559 goto err; 560 561 ctx = context_new(ctx_str); 562 orig_ctx_str = ctx_str; 563 if (!ctx) 564 goto oom; 565 566 rc = seapp_context_lookup(SEAPP_DOMAIN, uid, isSystemServer, seinfo, pkgname, ctx); 567 if (rc == -1) 568 goto err; 569 else if (rc == -2) 570 goto oom; 571 572 ctx_str = context_str(ctx); 573 if (!ctx_str) 574 goto oom; 575 576 rc = security_check_context(ctx_str); 577 if (rc < 0) 578 goto err; 579 580 if (strcmp(ctx_str, orig_ctx_str)) { 581 rc = setcon(ctx_str); 582 if (rc < 0) 583 goto err; 584 } 585 586 rc = 0; 587 out: 588 freecon(orig_ctx_str); 589 context_free(ctx); 590 avc_netlink_close(); 591 return rc; 592 err: 593 if (isSystemServer) 594 selinux_log(SELINUX_ERROR, 595 "%s: Error setting context for system server: %s\n", 596 __FUNCTION__, strerror(errno)); 597 else 598 selinux_log(SELINUX_ERROR, 599 "%s: Error setting context for app with uid %d, seinfo %s: %s\n", 600 __FUNCTION__, uid, seinfo, strerror(errno)); 601 602 rc = -1; 603 goto out; 604 oom: 605 selinux_log(SELINUX_ERROR, "%s: Out of memory\n", __FUNCTION__); 606 rc = -1; 607 goto out; 608 } 609 610 static struct selabel_handle *sehandle = NULL; 611 612 static struct selabel_handle *get_selabel_handle(const struct selinux_opt opts[]) { 613 struct selabel_handle *h; 614 int i = 0; 615 616 h = NULL; 617 while ((h == NULL) && opts[i].value) { 618 h = selabel_open(SELABEL_CTX_FILE, &opts[i], 1); 619 i++; 620 } 621 622 return h; 623 } 624 625 static struct selabel_handle *file_context_open(void) 626 { 627 struct selabel_handle *h; 628 629 h = get_selabel_handle(seopts); 630 631 if (!h) 632 selinux_log(SELINUX_ERROR, "%s: Error getting file context handle (%s)\n", 633 __FUNCTION__, strerror(errno)); 634 return h; 635 } 636 637 static struct selabel_handle *file_context_backup_open(void) 638 { 639 struct selabel_handle *h; 640 641 h = get_selabel_handle(seopt_backup); 642 643 if (!h) 644 selinux_log(SELINUX_ERROR, "%s: Error getting backup file context handle (%s)\n", 645 __FUNCTION__, strerror(errno)); 646 return h; 647 } 648 649 static void file_context_init(void) 650 { 651 sehandle = file_context_open(); 652 } 653 654 static pthread_once_t fc_once = PTHREAD_ONCE_INIT; 655 656 int selinux_android_restorecon(const char *pathname) 657 { 658 659 char* oldcontext = NULL; 660 char* newcontext = NULL; 661 struct stat sb; 662 int ret = -1; 663 664 if (is_selinux_enabled() <= 0) 665 return 0; 666 667 __selinux_once(fc_once, file_context_init); 668 669 if (!sehandle) 670 goto bail; 671 672 if (lstat(pathname, &sb) < 0) 673 goto err; 674 675 if (lgetfilecon(pathname, &oldcontext) < 0) 676 goto err; 677 678 if (selabel_lookup(sehandle, &newcontext, pathname, sb.st_mode) < 0) 679 goto err; 680 681 if (strcmp(newcontext, "<<none>>") && strcmp(oldcontext, newcontext)) 682 if (lsetfilecon(pathname, newcontext) < 0) 683 goto err; 684 685 ret = 0; 686 out: 687 if (oldcontext) 688 freecon(oldcontext); 689 if (newcontext) 690 freecon(newcontext); 691 692 return ret; 693 694 err: 695 selinux_log(SELINUX_ERROR, 696 "%s: Error restoring context for %s (%s)\n", 697 __FUNCTION__, pathname, strerror(errno)); 698 699 bail: 700 ret = -1; 701 goto out; 702 } 703 704 static int file_requires_fixup(const char *pathname, 705 struct selabel_handle *sehandle_old, 706 struct selabel_handle *sehandle_new) 707 { 708 int ret; 709 struct stat sb; 710 char *current_context, *old_context, *new_context; 711 712 ret = 0; 713 old_context = NULL; 714 new_context = NULL; 715 current_context = NULL; 716 717 if (lstat(pathname, &sb) < 0) { 718 ret = -1; 719 goto err; 720 } 721 722 if (lgetfilecon(pathname, ¤t_context) < 0) { 723 ret = -1; 724 goto err; 725 } 726 727 if (selabel_lookup(sehandle_old, &old_context, pathname, sb.st_mode) < 0) { 728 ret = -1; 729 goto err; 730 } 731 732 if (selabel_lookup(sehandle_new, &new_context, pathname, sb.st_mode) < 0) { 733 ret = -1; 734 goto err; 735 } 736 737 if (strstr(current_context, "unlabeled") != NULL) { 738 ret = 1; 739 goto out; 740 } 741 742 ret = (strcmp(old_context, new_context) && !strcmp(current_context, old_context)); 743 goto out; 744 745 err: 746 selinux_log(SELINUX_ERROR, 747 "%s: Error comparing context for %s (%s)\n", 748 __FUNCTION__, 749 pathname, 750 strerror(errno)); 751 752 out: 753 if (current_context) 754 freecon(current_context); 755 if (new_context) 756 freecon(new_context); 757 if (old_context) 758 freecon(old_context); 759 return ret; 760 } 761 762 static int fixcon_file(const char *pathname, 763 struct selabel_handle *sehandle_old, 764 struct selabel_handle *sehandle_new) 765 { 766 int requires_fixup; 767 768 requires_fixup = file_requires_fixup(pathname, sehandle_old, sehandle_new); 769 if (requires_fixup < 0) 770 return -1; 771 772 if (requires_fixup) 773 selinux_android_restorecon(pathname); 774 775 return 0; 776 } 777 778 static int fixcon_recursive(const char *pathname, 779 struct selabel_handle *sehandle_old, 780 struct selabel_handle *sehandle_new) 781 { 782 struct stat statresult; 783 if (lstat(pathname, &statresult) < 0) 784 return -1; 785 786 if (!S_ISDIR(statresult.st_mode)) 787 return fixcon_file(pathname, sehandle_old, sehandle_new); 788 789 DIR *dir = opendir(pathname); 790 if (dir == NULL) 791 return -1; 792 793 struct dirent *entry; 794 while ((entry = readdir(dir)) != NULL) { 795 char *entryname; 796 if (!strcmp(entry->d_name, "..")) 797 continue; 798 if (!strcmp(entry->d_name, ".")) 799 continue; 800 if (asprintf(&entryname, "%s/%s", pathname, entry->d_name) == -1) 801 continue; 802 fixcon_recursive(entryname, sehandle_old, sehandle_new); 803 free(entryname); 804 } 805 806 if (closedir(dir) < 0) 807 return -1; 808 809 return fixcon_file(pathname, sehandle_old, sehandle_new); 810 } 811 812 int selinux_android_fixcon(const char *pathname) 813 { 814 struct selabel_handle *sehandle_old, *sehandle_new; 815 816 sehandle_old = file_context_backup_open(); 817 if (sehandle_old == NULL) 818 return -1; 819 820 sehandle_new = file_context_open(); 821 if (sehandle_new == NULL) 822 return -1; 823 824 return fixcon_recursive(pathname, sehandle_old, sehandle_new); 825 } 826 827 struct selabel_handle* selinux_android_file_context_handle(void) 828 { 829 return file_context_open(); 830 } 831 832 int selinux_android_reload_policy(void) 833 { 834 int fd = -1, rc; 835 struct stat sb; 836 void *map = NULL; 837 int i = 0; 838 839 while (fd < 0 && sepolicy_file[i]) { 840 fd = open(sepolicy_file[i], O_RDONLY | O_NOFOLLOW); 841 i++; 842 } 843 if (fd < 0) { 844 selinux_log(SELINUX_ERROR, "SELinux: Could not open sepolicy: %s\n", 845 strerror(errno)); 846 return -1; 847 } 848 if (fstat(fd, &sb) < 0) { 849 selinux_log(SELINUX_ERROR, "SELinux: Could not stat %s: %s\n", 850 sepolicy_file[i-1], strerror(errno)); 851 close(fd); 852 return -1; 853 } 854 map = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0); 855 if (map == MAP_FAILED) { 856 selinux_log(SELINUX_ERROR, "SELinux: Could not map %s: %s\n", 857 sepolicy_file[i-1], strerror(errno)); 858 close(fd); 859 return -1; 860 } 861 862 rc = security_load_policy(map, sb.st_size); 863 if (rc < 0) { 864 selinux_log(SELINUX_ERROR, "SELinux: Could not load policy: %s\n", 865 strerror(errno)); 866 munmap(map, sb.st_size); 867 close(fd); 868 return -1; 869 } 870 871 munmap(map, sb.st_size); 872 close(fd); 873 selinux_log(SELINUX_INFO, "SELinux: Loaded policy from %s\n", sepolicy_file[i-1]); 874 875 return 0; 876 } 877 878 int selinux_android_load_policy(void) 879 { 880 char *mnt = SELINUXMNT; 881 int rc; 882 rc = mount(SELINUXFS, mnt, SELINUXFS, 0, NULL); 883 if (rc < 0) { 884 if (errno == ENODEV) { 885 /* SELinux not enabled in kernel */ 886 return -1; 887 } 888 if (errno == ENOENT) { 889 /* Fall back to legacy mountpoint. */ 890 mnt = OLDSELINUXMNT; 891 rc = mkdir(mnt, 0755); 892 if (rc == -1 && errno != EEXIST) { 893 selinux_log(SELINUX_ERROR,"SELinux: Could not mkdir: %s\n", 894 strerror(errno)); 895 return -1; 896 } 897 rc = mount(SELINUXFS, mnt, SELINUXFS, 0, NULL); 898 } 899 } 900 if (rc < 0) { 901 selinux_log(SELINUX_ERROR,"SELinux: Could not mount selinuxfs: %s\n", 902 strerror(errno)); 903 return -1; 904 } 905 set_selinuxmnt(mnt); 906 907 return selinux_android_reload_policy(); 908 } 909