1 #include <sys/types.h> 2 #include <unistd.h> 3 #include <string.h> 4 #include <stdio.h> 5 #include <stdlib.h> 6 #include <stdbool.h> 7 #include <ctype.h> 8 #include <errno.h> 9 #include <pwd.h> 10 #include <grp.h> 11 #include <sys/mman.h> 12 #include <sys/mount.h> 13 #include <sys/types.h> 14 #include <sys/stat.h> 15 #include <sys/xattr.h> 16 #include <fcntl.h> 17 #include <fts.h> 18 #include <selinux/selinux.h> 19 #include <selinux/context.h> 20 #include <selinux/android.h> 21 #include <selinux/label.h> 22 #include <selinux/avc.h> 23 #include <mincrypt/sha.h> 24 #include <private/android_filesystem_config.h> 25 #include <log/log.h> 26 #include "policy.h" 27 #include "callbacks.h" 28 #include "selinux_internal.h" 29 #include "label_internal.h" 30 31 /* 32 * XXX Where should this configuration file be located? 33 * Needs to be accessible by zygote and installd when 34 * setting credentials for app processes and setting permissions 35 * on app data directories. 36 */ 37 static char const * const seapp_contexts_file[] = { 38 "/seapp_contexts", 39 "/data/security/current/seapp_contexts", 40 NULL }; 41 42 static const struct selinux_opt seopts[] = { 43 { SELABEL_OPT_PATH, "/file_contexts" }, 44 { SELABEL_OPT_PATH, "/data/security/current/file_contexts" }, 45 { 0, NULL } }; 46 47 static const char *const sepolicy_file[] = { 48 "/sepolicy", 49 "/data/security/current/sepolicy", 50 NULL }; 51 52 static const struct selinux_opt seopts_service[] = { 53 { SELABEL_OPT_PATH, "/service_contexts" }, 54 { SELABEL_OPT_PATH, "/data/security/current/service_contexts" }, 55 { 0, NULL } 56 }; 57 58 enum levelFrom { 59 LEVELFROM_NONE, 60 LEVELFROM_APP, 61 LEVELFROM_USER, 62 LEVELFROM_ALL 63 }; 64 65 #define POLICY_OVERRIDE_VERSION "/data/security/current/selinux_version" 66 #define POLICY_BASE_VERSION "/selinux_version" 67 static int policy_index = 0; 68 69 static void set_policy_index(void) 70 { 71 int fd_base = -1, fd_override = -1; 72 struct stat sb_base; 73 struct stat sb_override; 74 void *map_base, *map_override; 75 76 policy_index = 0; 77 78 fd_base = open(POLICY_BASE_VERSION, O_RDONLY | O_NOFOLLOW); 79 if (fd_base < 0) 80 return; 81 82 if (fstat(fd_base, &sb_base) < 0) { 83 close(fd_base); 84 return; 85 } 86 87 fd_override = open(POLICY_OVERRIDE_VERSION, O_RDONLY | O_NOFOLLOW); 88 if (fd_override < 0) { 89 close(fd_base); 90 return; 91 } 92 93 if (fstat(fd_override, &sb_override) < 0) { 94 close(fd_base); 95 close(fd_override); 96 return; 97 } 98 99 if (sb_base.st_size != sb_override.st_size) { 100 close(fd_base); 101 close(fd_override); 102 return; 103 } 104 105 map_base = mmap(NULL, sb_base.st_size, PROT_READ, MAP_PRIVATE, fd_base, 0); 106 if (map_base == MAP_FAILED) { 107 close(fd_base); 108 close(fd_override); 109 return; 110 } 111 112 map_override = mmap(NULL, sb_override.st_size, PROT_READ, MAP_PRIVATE, fd_override, 0); 113 if (map_override == MAP_FAILED) { 114 munmap(map_base, sb_base.st_size); 115 close(fd_base); 116 close(fd_override); 117 return; 118 } 119 120 if (memcmp(map_base, map_override, sb_base.st_size) == 0) 121 policy_index = 1; 122 123 124 close(fd_base); 125 close(fd_override); 126 munmap(map_base, sb_base.st_size); 127 munmap(map_override, sb_override.st_size); 128 } 129 130 bool selinux_android_use_data_policy(void) 131 { 132 set_policy_index(); 133 return (policy_index == 1); 134 } 135 136 #if DEBUG 137 static char const * const levelFromName[] = { 138 "none", 139 "app", 140 "user", 141 "all" 142 }; 143 #endif 144 145 struct prefix_str { 146 size_t len; 147 char *str; 148 char is_prefix; 149 }; 150 151 static void free_prefix_str(struct prefix_str *p) 152 { 153 if (!p) 154 return; 155 free(p->str); 156 } 157 158 struct seapp_context { 159 /* input selectors */ 160 char isSystemServer; 161 struct prefix_str user; 162 char *seinfo; 163 struct prefix_str name; 164 struct prefix_str path; 165 /* outputs */ 166 char *domain; 167 char *type; 168 char *level; 169 char *sebool; 170 enum levelFrom levelFrom; 171 }; 172 173 static void free_seapp_context(struct seapp_context *s) 174 { 175 if (!s) 176 return; 177 178 free_prefix_str(&s->user); 179 free(s->seinfo); 180 free_prefix_str(&s->name); 181 free_prefix_str(&s->path); 182 free(s->domain); 183 free(s->type); 184 free(s->level); 185 free(s->sebool); 186 } 187 188 static int seapp_context_cmp(const void *A, const void *B) 189 { 190 const struct seapp_context *const *sp1 = (const struct seapp_context *const *) A; 191 const struct seapp_context *const *sp2 = (const struct seapp_context *const *) B; 192 const struct seapp_context *s1 = *sp1, *s2 = *sp2; 193 194 /* Give precedence to isSystemServer=true. */ 195 if (s1->isSystemServer != s2->isSystemServer) 196 return (s1->isSystemServer ? -1 : 1); 197 198 /* Give precedence to a specified user= over an unspecified user=. */ 199 if (s1->user.str && !s2->user.str) 200 return -1; 201 if (!s1->user.str && s2->user.str) 202 return 1; 203 204 if (s1->user.str) { 205 /* Give precedence to a fixed user= string over a prefix. */ 206 if (s1->user.is_prefix != s2->user.is_prefix) 207 return (s2->user.is_prefix ? -1 : 1); 208 209 /* Give precedence to a longer prefix over a shorter prefix. */ 210 if (s1->user.is_prefix && s1->user.len != s2->user.len) 211 return (s1->user.len > s2->user.len) ? -1 : 1; 212 } 213 214 /* Give precedence to a specified seinfo= over an unspecified seinfo=. */ 215 if (s1->seinfo && !s2->seinfo) 216 return -1; 217 if (!s1->seinfo && s2->seinfo) 218 return 1; 219 220 /* Give precedence to a specified name= over an unspecified name=. */ 221 if (s1->name.str && !s2->name.str) 222 return -1; 223 if (!s1->name.str && s2->name.str) 224 return 1; 225 226 if (s1->name.str) { 227 /* Give precedence to a fixed name= string over a prefix. */ 228 if (s1->name.is_prefix != s2->name.is_prefix) 229 return (s2->name.is_prefix ? -1 : 1); 230 231 /* Give precedence to a longer prefix over a shorter prefix. */ 232 if (s1->name.is_prefix && s1->name.len != s2->name.len) 233 return (s1->name.len > s2->name.len) ? -1 : 1; 234 } 235 236 /* Give precedence to a specified path= over an unspecified path=. */ 237 if (s1->path.str && !s2->path.str) 238 return -1; 239 if (!s1->path.str && s2->path.str) 240 return 1; 241 242 if (s1->path.str) { 243 /* Give precedence to a fixed path= string over a prefix. */ 244 if (s1->path.is_prefix != s2->path.is_prefix) 245 return (s2->path.is_prefix ? -1 : 1); 246 247 /* Give precedence to a longer prefix over a shorter prefix. */ 248 if (s1->path.is_prefix && s1->path.len != s2->path.len) 249 return (s1->path.len > s2->path.len) ? -1 : 1; 250 } 251 252 /* Give precedence to a specified sebool= over an unspecified sebool=. */ 253 if (s1->sebool && !s2->sebool) 254 return -1; 255 if (!s1->sebool && s2->sebool) 256 return 1; 257 258 /* Anything else has equal precedence. */ 259 return 0; 260 } 261 262 static struct seapp_context **seapp_contexts = NULL; 263 static int nspec = 0; 264 265 static void free_seapp_contexts(void) 266 { 267 int n; 268 269 if (!seapp_contexts) 270 return; 271 272 for (n = 0; n < nspec; n++) 273 free_seapp_context(seapp_contexts[n]); 274 275 free(seapp_contexts); 276 seapp_contexts = NULL; 277 nspec = 0; 278 } 279 280 int selinux_android_seapp_context_reload(void) 281 { 282 FILE *fp = NULL; 283 char line_buf[BUFSIZ]; 284 char *token; 285 unsigned lineno; 286 struct seapp_context *cur; 287 char *p, *name = NULL, *value = NULL, *saveptr; 288 size_t len; 289 int n, ret; 290 291 set_policy_index(); 292 293 fp = fopen(seapp_contexts_file[policy_index], "r"); 294 if (!fp) { 295 selinux_log(SELINUX_ERROR, "%s: could not open any seapp_contexts file", __FUNCTION__); 296 return -1; 297 } 298 299 free_seapp_contexts(); 300 301 nspec = 0; 302 while (fgets(line_buf, sizeof line_buf - 1, fp)) { 303 p = line_buf; 304 while (isspace(*p)) 305 p++; 306 if (*p == '#' || *p == 0) 307 continue; 308 nspec++; 309 } 310 311 seapp_contexts = (struct seapp_context **) calloc(nspec, sizeof(struct seapp_context *)); 312 if (!seapp_contexts) 313 goto oom; 314 315 rewind(fp); 316 nspec = 0; 317 lineno = 1; 318 while (fgets(line_buf, sizeof line_buf - 1, fp)) { 319 len = strlen(line_buf); 320 if (line_buf[len - 1] == '\n') 321 line_buf[len - 1] = 0; 322 p = line_buf; 323 while (isspace(*p)) 324 p++; 325 if (*p == '#' || *p == 0) 326 continue; 327 328 cur = (struct seapp_context *) calloc(1, sizeof(struct seapp_context)); 329 if (!cur) 330 goto oom; 331 332 token = strtok_r(p, " \t", &saveptr); 333 if (!token) { 334 free_seapp_context(cur); 335 goto err; 336 } 337 338 while (1) { 339 name = token; 340 value = strchr(name, '='); 341 if (!value) { 342 free_seapp_context(cur); 343 goto err; 344 } 345 *value++ = 0; 346 347 if (!strcasecmp(name, "isSystemServer")) { 348 if (!strcasecmp(value, "true")) 349 cur->isSystemServer = 1; 350 else if (!strcasecmp(value, "false")) 351 cur->isSystemServer = 0; 352 else { 353 free_seapp_context(cur); 354 goto err; 355 } 356 } else if (!strcasecmp(name, "user")) { 357 cur->user.str = strdup(value); 358 if (!cur->user.str) { 359 free_seapp_context(cur); 360 goto oom; 361 } 362 cur->user.len = strlen(cur->user.str); 363 if (cur->user.str[cur->user.len-1] == '*') 364 cur->user.is_prefix = 1; 365 } else if (!strcasecmp(name, "seinfo")) { 366 cur->seinfo = strdup(value); 367 if (!cur->seinfo) { 368 free_seapp_context(cur); 369 goto oom; 370 } 371 } else if (!strcasecmp(name, "name")) { 372 cur->name.str = strdup(value); 373 if (!cur->name.str) { 374 free_seapp_context(cur); 375 goto oom; 376 } 377 cur->name.len = strlen(cur->name.str); 378 if (cur->name.str[cur->name.len-1] == '*') 379 cur->name.is_prefix = 1; 380 } else if (!strcasecmp(name, "domain")) { 381 cur->domain = strdup(value); 382 if (!cur->domain) { 383 free_seapp_context(cur); 384 goto oom; 385 } 386 } else if (!strcasecmp(name, "type")) { 387 cur->type = strdup(value); 388 if (!cur->type) { 389 free_seapp_context(cur); 390 goto oom; 391 } 392 } else if (!strcasecmp(name, "levelFromUid")) { 393 if (!strcasecmp(value, "true")) 394 cur->levelFrom = LEVELFROM_APP; 395 else if (!strcasecmp(value, "false")) 396 cur->levelFrom = LEVELFROM_NONE; 397 else { 398 free_seapp_context(cur); 399 goto err; 400 } 401 } else if (!strcasecmp(name, "levelFrom")) { 402 if (!strcasecmp(value, "none")) 403 cur->levelFrom = LEVELFROM_NONE; 404 else if (!strcasecmp(value, "app")) 405 cur->levelFrom = LEVELFROM_APP; 406 else if (!strcasecmp(value, "user")) 407 cur->levelFrom = LEVELFROM_USER; 408 else if (!strcasecmp(value, "all")) 409 cur->levelFrom = LEVELFROM_ALL; 410 else { 411 free_seapp_context(cur); 412 goto err; 413 } 414 } else if (!strcasecmp(name, "level")) { 415 cur->level = strdup(value); 416 if (!cur->level) { 417 free_seapp_context(cur); 418 goto oom; 419 } 420 } else if (!strcasecmp(name, "path")) { 421 cur->path.str = strdup(value); 422 if (!cur->path.str) { 423 free_seapp_context(cur); 424 goto oom; 425 } 426 cur->path.len = strlen(cur->path.str); 427 if (cur->path.str[cur->path.len-1] == '*') 428 cur->path.is_prefix = 1; 429 } else if (!strcasecmp(name, "sebool")) { 430 cur->sebool = strdup(value); 431 if (!cur->sebool) { 432 free_seapp_context(cur); 433 goto oom; 434 } 435 } else { 436 free_seapp_context(cur); 437 goto err; 438 } 439 440 token = strtok_r(NULL, " \t", &saveptr); 441 if (!token) 442 break; 443 } 444 445 if (cur->name.str && 446 (!cur->seinfo || !strcmp(cur->seinfo, "default"))) { 447 selinux_log(SELINUX_ERROR, "%s: No specific seinfo value specified with name=\"%s\", on line %u: insecure configuration!\n", 448 seapp_contexts_file[policy_index], cur->name.str, lineno); 449 free_seapp_context(cur); 450 goto err; 451 } 452 453 seapp_contexts[nspec] = cur; 454 nspec++; 455 lineno++; 456 } 457 458 qsort(seapp_contexts, nspec, sizeof(struct seapp_context *), 459 seapp_context_cmp); 460 461 #if DEBUG 462 { 463 int i; 464 for (i = 0; i < nspec; i++) { 465 cur = seapp_contexts[i]; 466 selinux_log(SELINUX_INFO, "%s: isSystemServer=%s user=%s seinfo=%s name=%s path=%s sebool=%s -> domain=%s type=%s level=%s levelFrom=%s", 467 __FUNCTION__, 468 cur->isSystemServer ? "true" : "false", cur->user.str, 469 cur->seinfo, cur->name.str, cur->path.str, cur->sebool, cur->domain, 470 cur->type, cur->level, 471 levelFromName[cur->levelFrom]); 472 } 473 } 474 #endif 475 476 ret = 0; 477 478 out: 479 fclose(fp); 480 return ret; 481 482 err: 483 selinux_log(SELINUX_ERROR, "%s: Invalid entry on line %u\n", 484 seapp_contexts_file[policy_index], lineno); 485 free_seapp_contexts(); 486 ret = -1; 487 goto out; 488 oom: 489 selinux_log(SELINUX_ERROR, 490 "%s: Out of memory\n", __FUNCTION__); 491 free_seapp_contexts(); 492 ret = -1; 493 goto out; 494 } 495 496 497 static void seapp_context_init(void) 498 { 499 selinux_android_seapp_context_reload(); 500 } 501 502 static pthread_once_t once = PTHREAD_ONCE_INIT; 503 504 /* 505 * Max id that can be mapped to category set uniquely 506 * using the current scheme. 507 */ 508 #define CAT_MAPPING_MAX_ID (0x1<<16) 509 510 enum seapp_kind { 511 SEAPP_TYPE, 512 SEAPP_DOMAIN 513 }; 514 515 static int seapp_context_lookup(enum seapp_kind kind, 516 uid_t uid, 517 int isSystemServer, 518 const char *seinfo, 519 const char *pkgname, 520 const char *path, 521 context_t ctx) 522 { 523 const char *username = NULL; 524 struct seapp_context *cur = NULL; 525 int i; 526 size_t n; 527 uid_t userid; 528 uid_t appid; 529 530 __selinux_once(once, seapp_context_init); 531 532 userid = uid / AID_USER; 533 appid = uid % AID_USER; 534 if (appid < AID_APP) { 535 for (n = 0; n < android_id_count; n++) { 536 if (android_ids[n].aid == appid) { 537 username = android_ids[n].name; 538 break; 539 } 540 } 541 if (!username) 542 goto err; 543 } else if (appid < AID_ISOLATED_START) { 544 username = "_app"; 545 appid -= AID_APP; 546 } else { 547 username = "_isolated"; 548 appid -= AID_ISOLATED_START; 549 } 550 551 if (appid >= CAT_MAPPING_MAX_ID || userid >= CAT_MAPPING_MAX_ID) 552 goto err; 553 554 for (i = 0; i < nspec; i++) { 555 cur = seapp_contexts[i]; 556 557 if (cur->isSystemServer != isSystemServer) 558 continue; 559 560 if (cur->user.str) { 561 if (cur->user.is_prefix) { 562 if (strncasecmp(username, cur->user.str, cur->user.len-1)) 563 continue; 564 } else { 565 if (strcasecmp(username, cur->user.str)) 566 continue; 567 } 568 } 569 570 if (cur->seinfo) { 571 if (!seinfo || strcasecmp(seinfo, cur->seinfo)) 572 continue; 573 } 574 575 if (cur->name.str) { 576 if(!pkgname) 577 continue; 578 579 if (cur->name.is_prefix) { 580 if (strncasecmp(pkgname, cur->name.str, cur->name.len-1)) 581 continue; 582 } else { 583 if (strcasecmp(pkgname, cur->name.str)) 584 continue; 585 } 586 } 587 588 if (cur->path.str) { 589 if (!path) 590 continue; 591 592 if (cur->path.is_prefix) { 593 if (strncmp(path, cur->path.str, cur->path.len-1)) 594 continue; 595 } else { 596 if (strcmp(path, cur->path.str)) 597 continue; 598 } 599 } 600 601 if (kind == SEAPP_TYPE && !cur->type) 602 continue; 603 else if (kind == SEAPP_DOMAIN && !cur->domain) 604 continue; 605 606 if (cur->sebool) { 607 int value = security_get_boolean_active(cur->sebool); 608 if (value == 0) 609 continue; 610 else if (value == -1) { 611 selinux_log(SELINUX_ERROR, \ 612 "Could not find boolean: %s ", cur->sebool); 613 goto err; 614 } 615 } 616 617 if (kind == SEAPP_TYPE) { 618 if (context_type_set(ctx, cur->type)) 619 goto oom; 620 } else if (kind == SEAPP_DOMAIN) { 621 if (context_type_set(ctx, cur->domain)) 622 goto oom; 623 } 624 625 if (cur->levelFrom != LEVELFROM_NONE) { 626 char level[255]; 627 switch (cur->levelFrom) { 628 case LEVELFROM_APP: 629 snprintf(level, sizeof level, "s0:c%u,c%u", 630 appid & 0xff, 631 256 + (appid>>8 & 0xff)); 632 break; 633 case LEVELFROM_USER: 634 snprintf(level, sizeof level, "s0:c%u,c%u", 635 512 + (userid & 0xff), 636 768 + (userid>>8 & 0xff)); 637 break; 638 case LEVELFROM_ALL: 639 snprintf(level, sizeof level, "s0:c%u,c%u,c%u,c%u", 640 appid & 0xff, 641 256 + (appid>>8 & 0xff), 642 512 + (userid & 0xff), 643 768 + (userid>>8 & 0xff)); 644 break; 645 default: 646 goto err; 647 } 648 if (context_range_set(ctx, level)) 649 goto oom; 650 } else if (cur->level) { 651 if (context_range_set(ctx, cur->level)) 652 goto oom; 653 } 654 655 break; 656 } 657 658 if (kind == SEAPP_DOMAIN && i == nspec) { 659 /* 660 * No match. 661 * Fail to prevent staying in the zygote's context. 662 */ 663 selinux_log(SELINUX_ERROR, 664 "%s: No match for app with uid %d, seinfo %s, name %s\n", 665 __FUNCTION__, uid, seinfo, pkgname); 666 667 if (security_getenforce() == 1) 668 goto err; 669 } 670 671 return 0; 672 err: 673 return -1; 674 oom: 675 return -2; 676 } 677 678 int selinux_android_setfilecon(const char *pkgdir, 679 const char *pkgname, 680 const char *seinfo, 681 uid_t uid) 682 { 683 char *orig_ctx_str = NULL; 684 char *ctx_str = NULL; 685 context_t ctx = NULL; 686 int rc = -1; 687 688 if (is_selinux_enabled() <= 0) 689 return 0; 690 691 rc = getfilecon(pkgdir, &ctx_str); 692 if (rc < 0) 693 goto err; 694 695 ctx = context_new(ctx_str); 696 orig_ctx_str = ctx_str; 697 if (!ctx) 698 goto oom; 699 700 rc = seapp_context_lookup(SEAPP_TYPE, uid, 0, seinfo, pkgname, NULL, ctx); 701 if (rc == -1) 702 goto err; 703 else if (rc == -2) 704 goto oom; 705 706 ctx_str = context_str(ctx); 707 if (!ctx_str) 708 goto oom; 709 710 rc = security_check_context(ctx_str); 711 if (rc < 0) 712 goto err; 713 714 if (strcmp(ctx_str, orig_ctx_str)) { 715 rc = setfilecon(pkgdir, ctx_str); 716 if (rc < 0) 717 goto err; 718 } 719 720 rc = 0; 721 out: 722 freecon(orig_ctx_str); 723 context_free(ctx); 724 return rc; 725 err: 726 selinux_log(SELINUX_ERROR, "%s: Error setting context for pkgdir %s, uid %d: %s\n", 727 __FUNCTION__, pkgdir, uid, strerror(errno)); 728 rc = -1; 729 goto out; 730 oom: 731 selinux_log(SELINUX_ERROR, "%s: Out of memory\n", __FUNCTION__); 732 rc = -1; 733 goto out; 734 } 735 736 int selinux_android_setcontext(uid_t uid, 737 int isSystemServer, 738 const char *seinfo, 739 const char *pkgname) 740 { 741 char *orig_ctx_str = NULL, *ctx_str; 742 context_t ctx = NULL; 743 int rc = -1; 744 745 if (is_selinux_enabled() <= 0) 746 return 0; 747 748 rc = getcon(&ctx_str); 749 if (rc) 750 goto err; 751 752 ctx = context_new(ctx_str); 753 orig_ctx_str = ctx_str; 754 if (!ctx) 755 goto oom; 756 757 rc = seapp_context_lookup(SEAPP_DOMAIN, uid, isSystemServer, seinfo, pkgname, NULL, ctx); 758 if (rc == -1) 759 goto err; 760 else if (rc == -2) 761 goto oom; 762 763 ctx_str = context_str(ctx); 764 if (!ctx_str) 765 goto oom; 766 767 rc = security_check_context(ctx_str); 768 if (rc < 0) 769 goto err; 770 771 if (strcmp(ctx_str, orig_ctx_str)) { 772 rc = setcon(ctx_str); 773 if (rc < 0) 774 goto err; 775 } 776 777 rc = 0; 778 out: 779 freecon(orig_ctx_str); 780 context_free(ctx); 781 avc_netlink_close(); 782 return rc; 783 err: 784 if (isSystemServer) 785 selinux_log(SELINUX_ERROR, 786 "%s: Error setting context for system server: %s\n", 787 __FUNCTION__, strerror(errno)); 788 else 789 selinux_log(SELINUX_ERROR, 790 "%s: Error setting context for app with uid %d, seinfo %s: %s\n", 791 __FUNCTION__, uid, seinfo, strerror(errno)); 792 793 rc = -1; 794 goto out; 795 oom: 796 selinux_log(SELINUX_ERROR, "%s: Out of memory\n", __FUNCTION__); 797 rc = -1; 798 goto out; 799 } 800 801 static struct selabel_handle *sehandle = NULL; 802 #define FC_DIGEST_SIZE SHA_DIGEST_SIZE 803 static uint8_t fc_digest[FC_DIGEST_SIZE]; 804 805 static struct selabel_handle *get_selabel_handle(const struct selinux_opt opts[]) 806 { 807 struct selabel_handle *h; 808 int fd; 809 struct stat sb; 810 void *map; 811 812 set_policy_index(); 813 814 h = selabel_open(SELABEL_CTX_FILE, &opts[policy_index], 1); 815 if (!h) 816 return NULL; 817 818 fd = open(opts[policy_index].value, O_RDONLY | O_NOFOLLOW); 819 if (fd < 0) { 820 selinux_log(SELINUX_ERROR, "SELinux: Could not open %s: %s\n", 821 opts[policy_index].value, strerror(errno)); 822 goto err; 823 } 824 if (fstat(fd, &sb) < 0) { 825 selinux_log(SELINUX_ERROR, "SELinux: Could not stat %s: %s\n", 826 opts[policy_index].value, strerror(errno)); 827 close(fd); 828 goto err; 829 } 830 map = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0); 831 if (map == MAP_FAILED) { 832 selinux_log(SELINUX_ERROR, "SELinux: Could not map %s: %s\n", 833 opts[policy_index].value, strerror(errno)); 834 close(fd); 835 goto err; 836 } 837 SHA_hash(map, sb.st_size, fc_digest); 838 munmap(map, sb.st_size); 839 close(fd); 840 841 selinux_log(SELINUX_INFO, "SELinux: Loaded file_contexts from %s\n", 842 opts[policy_index].value); 843 844 return h; 845 846 err: 847 selabel_close(h); 848 return NULL; 849 } 850 851 static struct selabel_handle *file_context_open(void) 852 { 853 struct selabel_handle *h; 854 855 h = get_selabel_handle(seopts); 856 857 if (!h) 858 selinux_log(SELINUX_ERROR, "%s: Error getting file context handle (%s)\n", 859 __FUNCTION__, strerror(errno)); 860 return h; 861 } 862 863 static void file_context_init(void) 864 { 865 if (!sehandle) 866 sehandle = file_context_open(); 867 } 868 869 static struct selabel_handle *service_context_open(void) 870 { 871 struct selabel_handle *handle = NULL; 872 873 set_policy_index(); 874 handle = selabel_open(SELABEL_CTX_ANDROID_PROP, 875 &seopts_service[policy_index], 1); 876 877 if (!handle) { 878 selinux_log(SELINUX_ERROR, "%s: Error getting service context handle (%s)\n", 879 __FUNCTION__, strerror(errno)); 880 } else { 881 selinux_log(SELINUX_INFO, "SELinux: Loaded service contexts from %s.\n", 882 seopts_service[policy_index].value); 883 } 884 885 return handle; 886 } 887 888 static pthread_once_t fc_once = PTHREAD_ONCE_INIT; 889 890 struct pkgInfo { 891 char *name; 892 uid_t uid; 893 bool debuggable; 894 char *dataDir; 895 char *seinfo; 896 struct pkgInfo *next; 897 }; 898 899 #define PKGTAB_SIZE 256 900 static struct pkgInfo *pkgTab[PKGTAB_SIZE]; 901 902 static unsigned int pkghash(const char *pkgname) 903 { 904 unsigned int h = 7; 905 for (; *pkgname; pkgname++) { 906 h = h * 31 + *pkgname; 907 } 908 return h & (PKGTAB_SIZE - 1); 909 } 910 911 /* The file containing the list of installed packages on the system */ 912 #define PACKAGES_LIST_FILE "/data/system/packages.list" 913 914 static void package_info_init(void) 915 { 916 char *buf = NULL; 917 size_t buflen = 0; 918 ssize_t bytesread; 919 FILE *fp; 920 char *cur, *next; 921 struct pkgInfo *pkgInfo = NULL; 922 unsigned int hash; 923 unsigned long lineno = 1; 924 925 fp = fopen(PACKAGES_LIST_FILE, "r"); 926 if (!fp) { 927 selinux_log(SELINUX_ERROR, "SELinux: Could not open %s: %s.\n", 928 PACKAGES_LIST_FILE, strerror(errno)); 929 return; 930 } 931 while ((bytesread = getline(&buf, &buflen, fp)) > 0) { 932 pkgInfo = calloc(1, sizeof(*pkgInfo)); 933 if (!pkgInfo) 934 goto err; 935 next = buf; 936 cur = strsep(&next, " \t\n"); 937 if (!cur) 938 goto err; 939 pkgInfo->name = strdup(cur); 940 if (!pkgInfo->name) 941 goto err; 942 cur = strsep(&next, " \t\n"); 943 if (!cur) 944 goto err; 945 pkgInfo->uid = atoi(cur); 946 if (!pkgInfo->uid) 947 goto err; 948 cur = strsep(&next, " \t\n"); 949 if (!cur) 950 goto err; 951 pkgInfo->debuggable = atoi(cur); 952 cur = strsep(&next, " \t\n"); 953 if (!cur) 954 goto err; 955 pkgInfo->dataDir = strdup(cur); 956 if (!pkgInfo->dataDir) 957 goto err; 958 cur = strsep(&next, " \t\n"); 959 if (!cur) 960 goto err; 961 pkgInfo->seinfo = strdup(cur); 962 if (!pkgInfo->seinfo) 963 goto err; 964 965 hash = pkghash(pkgInfo->name); 966 if (pkgTab[hash]) 967 pkgInfo->next = pkgTab[hash]; 968 pkgTab[hash] = pkgInfo; 969 970 lineno++; 971 } 972 973 #if DEBUG 974 { 975 unsigned int buckets, entries, chainlen, longestchain; 976 977 buckets = entries = longestchain = 0; 978 for (hash = 0; hash < PKGTAB_SIZE; hash++) { 979 if (pkgTab[hash]) { 980 buckets++; 981 chainlen = 0; 982 for (pkgInfo = pkgTab[hash]; pkgInfo; pkgInfo = pkgInfo->next) { 983 chainlen++; 984 selinux_log(SELINUX_INFO, "%s: name=%s uid=%u debuggable=%s dataDir=%s seinfo=%s\n", 985 __FUNCTION__, 986 pkgInfo->name, pkgInfo->uid, pkgInfo->debuggable ? "true" : "false", pkgInfo->dataDir, pkgInfo->seinfo); 987 } 988 entries += chainlen; 989 if (longestchain < chainlen) 990 longestchain = chainlen; 991 } 992 } 993 selinux_log(SELINUX_INFO, "SELinux: %d pkg entries and %d/%d buckets used, longest chain %d\n", entries, buckets, PKGTAB_SIZE, longestchain); 994 } 995 #endif 996 997 out: 998 free(buf); 999 fclose(fp); 1000 return; 1001 1002 err: 1003 selinux_log(SELINUX_ERROR, "SELinux: Error reading %s on line %lu.\n", 1004 PACKAGES_LIST_FILE, lineno); 1005 if (pkgInfo) { 1006 free(pkgInfo->name); 1007 free(pkgInfo->dataDir); 1008 free(pkgInfo->seinfo); 1009 free(pkgInfo); 1010 } 1011 goto out; 1012 } 1013 1014 static pthread_once_t pkg_once = PTHREAD_ONCE_INIT; 1015 1016 struct pkgInfo *package_info_lookup(const char *name) 1017 { 1018 struct pkgInfo *pkgInfo; 1019 unsigned int hash; 1020 1021 __selinux_once(pkg_once, package_info_init); 1022 1023 hash = pkghash(name); 1024 for (pkgInfo = pkgTab[hash]; pkgInfo; pkgInfo = pkgInfo->next) { 1025 if (!strcmp(name, pkgInfo->name)) 1026 return pkgInfo; 1027 } 1028 return NULL; 1029 } 1030 1031 /* The path prefixes of package data directories. */ 1032 #define DATA_DATA_PATH "/data/data" 1033 #define DATA_USER_PATH "/data/user" 1034 #define DATA_DATA_PREFIX DATA_DATA_PATH "/" 1035 #define DATA_USER_PREFIX DATA_USER_PATH "/" 1036 1037 static int pkgdir_selabel_lookup(const char *pathname, 1038 const char *seinfo, 1039 uid_t uid, 1040 char **secontextp) 1041 { 1042 char *pkgname = NULL, *end = NULL; 1043 struct pkgInfo *pkgInfo = NULL; 1044 char *secontext = *secontextp; 1045 context_t ctx = NULL; 1046 int rc = 0; 1047 1048 /* Skip directory prefix before package name. */ 1049 if (!strncmp(pathname, DATA_DATA_PREFIX, sizeof(DATA_DATA_PREFIX)-1)) { 1050 pathname += sizeof(DATA_DATA_PREFIX) - 1; 1051 } else if (!strncmp(pathname, DATA_USER_PREFIX, sizeof(DATA_USER_PREFIX)-1)) { 1052 pathname += sizeof(DATA_USER_PREFIX) - 1; 1053 while (isdigit(*pathname)) 1054 pathname++; 1055 if (*pathname == '/') 1056 pathname++; 1057 else 1058 return 0; 1059 } else 1060 return 0; 1061 1062 if (!(*pathname)) 1063 return 0; 1064 1065 pkgname = strdup(pathname); 1066 if (!pkgname) 1067 return -1; 1068 1069 for (end = pkgname; *end && *end != '/'; end++) 1070 ; 1071 pathname = end; 1072 if (*end) 1073 pathname++; 1074 *end = '\0'; 1075 1076 if (!seinfo) { 1077 pkgInfo = package_info_lookup(pkgname); 1078 if (!pkgInfo) { 1079 selinux_log(SELINUX_WARNING, "SELinux: Could not look up information for package %s, cannot restorecon %s.\n", 1080 pkgname, pathname); 1081 free(pkgname); 1082 return -1; 1083 } 1084 } 1085 1086 ctx = context_new(secontext); 1087 if (!ctx) 1088 goto err; 1089 1090 rc = seapp_context_lookup(SEAPP_TYPE, pkgInfo ? pkgInfo->uid : uid, 0, 1091 pkgInfo ? pkgInfo->seinfo : seinfo, pkgInfo ? pkgInfo->name : pkgname, pathname, ctx); 1092 if (rc < 0) 1093 goto err; 1094 1095 secontext = context_str(ctx); 1096 if (!secontext) 1097 goto err; 1098 1099 if (!strcmp(secontext, *secontextp)) 1100 goto out; 1101 1102 rc = security_check_context(secontext); 1103 if (rc < 0) 1104 goto err; 1105 1106 freecon(*secontextp); 1107 *secontextp = strdup(secontext); 1108 if (!(*secontextp)) 1109 goto err; 1110 1111 rc = 0; 1112 1113 out: 1114 free(pkgname); 1115 context_free(ctx); 1116 return rc; 1117 err: 1118 selinux_log(SELINUX_ERROR, "%s: Error looking up context for path %s, pkgname %s, seinfo %s, uid %u: %s\n", 1119 __FUNCTION__, pathname, pkgname, pkgInfo->seinfo, pkgInfo->uid, strerror(errno)); 1120 rc = -1; 1121 goto out; 1122 } 1123 1124 #define RESTORECON_LAST "security.restorecon_last" 1125 1126 static int restorecon_sb(const char *pathname, const struct stat *sb, 1127 bool nochange, bool verbose, 1128 const char *seinfo, uid_t uid) 1129 { 1130 char *secontext = NULL; 1131 char *oldsecontext = NULL; 1132 int rc = 0; 1133 1134 if (selabel_lookup(sehandle, &secontext, pathname, sb->st_mode) < 0) 1135 return 0; /* no match, but not an error */ 1136 1137 if (lgetfilecon(pathname, &oldsecontext) < 0) 1138 goto err; 1139 1140 /* 1141 * For subdirectories of /data/data or /data/user, we ignore selabel_lookup() 1142 * and use pkgdir_selabel_lookup() instead. Files within those directories 1143 * have different labeling rules, based off of /seapp_contexts, and 1144 * installd is responsible for managing these labels instead of init. 1145 */ 1146 if (!strncmp(pathname, DATA_DATA_PREFIX, sizeof(DATA_DATA_PREFIX)-1) || 1147 !strncmp(pathname, DATA_USER_PREFIX, sizeof(DATA_USER_PREFIX)-1)) { 1148 if (pkgdir_selabel_lookup(pathname, seinfo, uid, &secontext) < 0) 1149 goto err; 1150 } 1151 1152 if (strcmp(oldsecontext, secontext) != 0) { 1153 if (verbose) 1154 selinux_log(SELINUX_INFO, 1155 "SELinux: Relabeling %s from %s to %s.\n", pathname, oldsecontext, secontext); 1156 if (!nochange) { 1157 if (lsetfilecon(pathname, secontext) < 0) 1158 goto err; 1159 } 1160 } 1161 1162 rc = 0; 1163 1164 out: 1165 freecon(oldsecontext); 1166 freecon(secontext); 1167 return rc; 1168 1169 err: 1170 selinux_log(SELINUX_ERROR, 1171 "SELinux: Could not set context for %s: %s\n", 1172 pathname, strerror(errno)); 1173 rc = -1; 1174 goto out; 1175 } 1176 1177 #define SYS_PATH "/sys" 1178 #define SYS_PREFIX SYS_PATH "/" 1179 1180 static int selinux_android_restorecon_common(const char* pathname, 1181 const char *seinfo, 1182 uid_t uid, 1183 unsigned int flags) 1184 { 1185 bool nochange = (flags & SELINUX_ANDROID_RESTORECON_NOCHANGE) ? true : false; 1186 bool verbose = (flags & SELINUX_ANDROID_RESTORECON_VERBOSE) ? true : false; 1187 bool recurse = (flags & SELINUX_ANDROID_RESTORECON_RECURSE) ? true : false; 1188 bool force = (flags & SELINUX_ANDROID_RESTORECON_FORCE) ? true : false; 1189 bool datadata = (flags & SELINUX_ANDROID_RESTORECON_DATADATA) ? true : false; 1190 bool issys = (!strcmp(pathname, SYS_PATH) || !strncmp(pathname, SYS_PREFIX, sizeof(SYS_PREFIX)-1)) ? true : false; 1191 bool setrestoreconlast = true; 1192 struct stat sb; 1193 FTS *fts; 1194 FTSENT *ftsent; 1195 char *const paths[2] = { __UNCONST(pathname), NULL }; 1196 int ftsflags = FTS_COMFOLLOW | FTS_NOCHDIR | FTS_XDEV | FTS_PHYSICAL; 1197 int error, sverrno; 1198 char xattr_value[FC_DIGEST_SIZE]; 1199 ssize_t size; 1200 1201 if (is_selinux_enabled() <= 0) 1202 return 0; 1203 1204 __selinux_once(fc_once, file_context_init); 1205 1206 if (!sehandle) 1207 return 0; 1208 1209 if (!recurse) { 1210 if (lstat(pathname, &sb) < 0) 1211 return -1; 1212 1213 return restorecon_sb(pathname, &sb, nochange, verbose, seinfo, uid); 1214 } 1215 1216 /* 1217 * Ignore restorecon_last on /data/data or /data/user 1218 * since their labeling is based on seapp_contexts and seinfo 1219 * assignments rather than file_contexts and is managed by 1220 * installd rather than init. 1221 */ 1222 if (!strncmp(pathname, DATA_DATA_PREFIX, sizeof(DATA_DATA_PREFIX)-1) || 1223 !strncmp(pathname, DATA_USER_PREFIX, sizeof(DATA_USER_PREFIX)-1)) 1224 setrestoreconlast = false; 1225 1226 /* Also ignore on /sys since it is regenerated on each boot regardless. */ 1227 if (issys) 1228 setrestoreconlast = false; 1229 1230 if (setrestoreconlast) { 1231 size = getxattr(pathname, RESTORECON_LAST, xattr_value, sizeof fc_digest); 1232 if (!force && size == sizeof fc_digest && memcmp(fc_digest, xattr_value, sizeof fc_digest) == 0) { 1233 selinux_log(SELINUX_INFO, 1234 "SELinux: Skipping restorecon_recursive(%s)\n", 1235 pathname); 1236 return 0; 1237 } 1238 } 1239 1240 fts = fts_open(paths, ftsflags, NULL); 1241 if (!fts) 1242 return -1; 1243 1244 error = 0; 1245 while ((ftsent = fts_read(fts)) != NULL) { 1246 switch (ftsent->fts_info) { 1247 case FTS_DC: 1248 selinux_log(SELINUX_ERROR, 1249 "SELinux: Directory cycle on %s.\n", ftsent->fts_path); 1250 errno = ELOOP; 1251 error = -1; 1252 goto out; 1253 case FTS_DP: 1254 continue; 1255 case FTS_DNR: 1256 selinux_log(SELINUX_ERROR, 1257 "SELinux: Could not read %s: %s.\n", ftsent->fts_path, strerror(errno)); 1258 fts_set(fts, ftsent, FTS_SKIP); 1259 continue; 1260 case FTS_NS: 1261 selinux_log(SELINUX_ERROR, 1262 "SELinux: Could not stat %s: %s.\n", ftsent->fts_path, strerror(errno)); 1263 fts_set(fts, ftsent, FTS_SKIP); 1264 continue; 1265 case FTS_ERR: 1266 selinux_log(SELINUX_ERROR, 1267 "SELinux: Error on %s: %s.\n", ftsent->fts_path, strerror(errno)); 1268 fts_set(fts, ftsent, FTS_SKIP); 1269 continue; 1270 case FTS_D: 1271 if (issys && !selabel_partial_match(sehandle, ftsent->fts_path)) { 1272 fts_set(fts, ftsent, FTS_SKIP); 1273 continue; 1274 } 1275 if (!datadata && 1276 (!strcmp(ftsent->fts_path, DATA_DATA_PATH) || 1277 !strncmp(ftsent->fts_path, DATA_USER_PREFIX, sizeof(DATA_USER_PREFIX)-1))) { 1278 // Don't label anything below this directory. 1279 fts_set(fts, ftsent, FTS_SKIP); 1280 // but fall through and make sure we label the directory itself 1281 } 1282 /* fall through */ 1283 default: 1284 error |= restorecon_sb(ftsent->fts_path, ftsent->fts_statp, nochange, verbose, seinfo, uid); 1285 break; 1286 } 1287 } 1288 1289 // Labeling successful. Mark the top level directory as completed. 1290 if (setrestoreconlast && !nochange && !error) 1291 setxattr(pathname, RESTORECON_LAST, fc_digest, sizeof fc_digest, 0); 1292 1293 out: 1294 sverrno = errno; 1295 (void) fts_close(fts); 1296 errno = sverrno; 1297 return error; 1298 } 1299 1300 int selinux_android_restorecon(const char *file, unsigned int flags) 1301 { 1302 return selinux_android_restorecon_common(file, NULL, -1, flags); 1303 } 1304 1305 int selinux_android_restorecon_pkgdir(const char *pkgdir, 1306 const char *seinfo, 1307 uid_t uid, 1308 unsigned int flags) 1309 { 1310 return selinux_android_restorecon_common(pkgdir, seinfo, uid, flags | SELINUX_ANDROID_RESTORECON_DATADATA); 1311 } 1312 1313 struct selabel_handle* selinux_android_file_context_handle(void) 1314 { 1315 return file_context_open(); 1316 } 1317 1318 struct selabel_handle* selinux_android_service_context_handle(void) 1319 { 1320 return service_context_open(); 1321 } 1322 1323 void selinux_android_set_sehandle(const struct selabel_handle *hndl) 1324 { 1325 sehandle = (struct selabel_handle *) hndl; 1326 } 1327 1328 static int selinux_android_load_policy_helper(bool reload) 1329 { 1330 int fd = -1, rc; 1331 struct stat sb; 1332 void *map = NULL; 1333 1334 /* 1335 * If reloading policy and there is no /data policy or 1336 * that /data policy has the wrong version or the /data 1337 * policy is disabled via safe mode, then just return. 1338 * There is no point in reloading policy from / a second time. 1339 */ 1340 if (reload && !selinux_android_use_data_policy()) 1341 return 0; 1342 1343 fd = open(sepolicy_file[policy_index], O_RDONLY | O_NOFOLLOW); 1344 if (fd < 0) { 1345 selinux_log(SELINUX_ERROR, "SELinux: Could not open sepolicy: %s\n", 1346 strerror(errno)); 1347 return -1; 1348 } 1349 if (fstat(fd, &sb) < 0) { 1350 selinux_log(SELINUX_ERROR, "SELinux: Could not stat %s: %s\n", 1351 sepolicy_file[policy_index], strerror(errno)); 1352 close(fd); 1353 return -1; 1354 } 1355 map = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0); 1356 if (map == MAP_FAILED) { 1357 selinux_log(SELINUX_ERROR, "SELinux: Could not map %s: %s\n", 1358 sepolicy_file[policy_index], strerror(errno)); 1359 close(fd); 1360 return -1; 1361 } 1362 1363 rc = security_load_policy(map, sb.st_size); 1364 if (rc < 0) { 1365 selinux_log(SELINUX_ERROR, "SELinux: Could not load policy: %s\n", 1366 strerror(errno)); 1367 munmap(map, sb.st_size); 1368 close(fd); 1369 return -1; 1370 } 1371 1372 munmap(map, sb.st_size); 1373 close(fd); 1374 selinux_log(SELINUX_INFO, "SELinux: Loaded policy from %s\n", sepolicy_file[policy_index]); 1375 1376 return 0; 1377 } 1378 1379 int selinux_android_reload_policy(void) 1380 { 1381 return selinux_android_load_policy_helper(true); 1382 } 1383 1384 int selinux_android_load_policy(void) 1385 { 1386 const char *mnt = SELINUXMNT; 1387 int rc; 1388 rc = mount(SELINUXFS, mnt, SELINUXFS, 0, NULL); 1389 if (rc < 0) { 1390 if (errno == ENODEV) { 1391 /* SELinux not enabled in kernel */ 1392 return -1; 1393 } 1394 if (errno == ENOENT) { 1395 /* Fall back to legacy mountpoint. */ 1396 mnt = OLDSELINUXMNT; 1397 rc = mkdir(mnt, 0755); 1398 if (rc == -1 && errno != EEXIST) { 1399 selinux_log(SELINUX_ERROR,"SELinux: Could not mkdir: %s\n", 1400 strerror(errno)); 1401 return -1; 1402 } 1403 rc = mount(SELINUXFS, mnt, SELINUXFS, 0, NULL); 1404 } 1405 } 1406 if (rc < 0) { 1407 selinux_log(SELINUX_ERROR,"SELinux: Could not mount selinuxfs: %s\n", 1408 strerror(errno)); 1409 return -1; 1410 } 1411 set_selinuxmnt(mnt); 1412 1413 return selinux_android_load_policy_helper(false); 1414 } 1415 1416 int selinux_log_callback(int type, const char *fmt, ...) 1417 { 1418 va_list ap; 1419 int priority; 1420 char *strp; 1421 1422 switch(type) { 1423 case SELINUX_WARNING: 1424 priority = ANDROID_LOG_WARN; 1425 break; 1426 case SELINUX_INFO: 1427 priority = ANDROID_LOG_INFO; 1428 break; 1429 default: 1430 priority = ANDROID_LOG_ERROR; 1431 break; 1432 } 1433 1434 va_start(ap, fmt); 1435 if (vasprintf(&strp, fmt, ap) != -1) { 1436 LOG_PRI(priority, "SELinux", "%s", strp); 1437 LOG_EVENT_STRING(AUDITD_LOG_TAG, strp); 1438 free(strp); 1439 } 1440 va_end(ap); 1441 return 0; 1442 } 1443