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