utils.cpp revision 42451c029b0e87990e5833daea2286bb12c21df5
1/* 2** Copyright 2008, The Android Open Source Project 3** 4** Licensed under the Apache License, Version 2.0 (the "License"); 5** you may not use this file except in compliance with the License. 6** You may obtain a copy of the License at 7** 8** http://www.apache.org/licenses/LICENSE-2.0 9** 10** Unless required by applicable law or agreed to in writing, software 11** distributed under the License is distributed on an "AS IS" BASIS, 12** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13** See the License for the specific language governing permissions and 14** limitations under the License. 15*/ 16 17#include "utils.h" 18 19#include <errno.h> 20#include <fcntl.h> 21#include <fts.h> 22#include <stdlib.h> 23#include <sys/stat.h> 24#include <sys/wait.h> 25#include <sys/xattr.h> 26 27#if defined(__APPLE__) 28#include <sys/mount.h> 29#else 30#include <sys/statfs.h> 31#endif 32 33#include <android-base/logging.h> 34#include <android-base/stringprintf.h> 35#include <cutils/fs.h> 36#include <log/log.h> 37#include <private/android_filesystem_config.h> 38 39#include "globals.h" // extern variables. 40 41#ifndef LOG_TAG 42#define LOG_TAG "installd" 43#endif 44 45#define CACHE_NOISY(x) //x 46#define DEBUG_XATTRS 0 47 48using android::base::StringPrintf; 49 50namespace android { 51namespace installd { 52 53/** 54 * Check that given string is valid filename, and that it attempts no 55 * parent or child directory traversal. 56 */ 57bool is_valid_filename(const std::string& name) { 58 if (name.empty() || (name == ".") || (name == "..") 59 || (name.find('/') != std::string::npos)) { 60 return false; 61 } else { 62 return true; 63 } 64} 65 66static void check_package_name(const char* package_name) { 67 CHECK(is_valid_filename(package_name)); 68 CHECK(is_valid_package_name(package_name)); 69} 70 71/** 72 * Create the path name where package app contents should be stored for 73 * the given volume UUID and package name. An empty UUID is assumed to 74 * be internal storage. 75 */ 76std::string create_data_app_package_path(const char* volume_uuid, 77 const char* package_name) { 78 check_package_name(package_name); 79 return StringPrintf("%s/%s", 80 create_data_app_path(volume_uuid).c_str(), package_name); 81} 82 83/** 84 * Create the path name where package data should be stored for the given 85 * volume UUID, package name, and user ID. An empty UUID is assumed to be 86 * internal storage. 87 */ 88std::string create_data_user_ce_package_path(const char* volume_uuid, 89 userid_t user, const char* package_name) { 90 check_package_name(package_name); 91 return StringPrintf("%s/%s", 92 create_data_user_ce_path(volume_uuid, user).c_str(), package_name); 93} 94 95std::string create_data_user_ce_package_path(const char* volume_uuid, userid_t user, 96 const char* package_name, ino_t ce_data_inode) { 97 // For testing purposes, rely on the inode when defined; this could be 98 // optimized to use access() in the future. 99 auto fallback = create_data_user_ce_package_path(volume_uuid, user, package_name); 100 if (ce_data_inode != 0) { 101 auto user_path = create_data_user_ce_path(volume_uuid, user); 102 DIR* dir = opendir(user_path.c_str()); 103 if (dir == nullptr) { 104 PLOG(ERROR) << "Failed to opendir " << user_path; 105 return fallback; 106 } 107 108 struct dirent* ent; 109 while ((ent = readdir(dir))) { 110 if (ent->d_ino == ce_data_inode) { 111 auto resolved = StringPrintf("%s/%s", user_path.c_str(), ent->d_name); 112#if DEBUG_XATTRS 113 if (resolved != fallback) { 114 LOG(DEBUG) << "Resolved path " << resolved << " for inode " << ce_data_inode 115 << " instead of " << fallback; 116 } 117#endif 118 closedir(dir); 119 return resolved; 120 } 121 } 122 LOG(WARNING) << "Failed to resolve inode " << ce_data_inode << "; using " << fallback; 123 closedir(dir); 124 return fallback; 125 } else { 126 return fallback; 127 } 128} 129 130std::string create_data_user_de_package_path(const char* volume_uuid, 131 userid_t user, const char* package_name) { 132 check_package_name(package_name); 133 return StringPrintf("%s/%s", 134 create_data_user_de_path(volume_uuid, user).c_str(), package_name); 135} 136 137int create_pkg_path(char path[PKG_PATH_MAX], const char *pkgname, 138 const char *postfix, userid_t userid) { 139 if (!is_valid_package_name(pkgname)) { 140 path[0] = '\0'; 141 return -1; 142 } 143 144 std::string _tmp(create_data_user_ce_package_path(nullptr, userid, pkgname) + postfix); 145 const char* tmp = _tmp.c_str(); 146 if (strlen(tmp) >= PKG_PATH_MAX) { 147 path[0] = '\0'; 148 return -1; 149 } else { 150 strcpy(path, tmp); 151 return 0; 152 } 153} 154 155std::string create_data_path(const char* volume_uuid) { 156 if (volume_uuid == nullptr) { 157 return "/data"; 158 } else { 159 CHECK(is_valid_filename(volume_uuid)); 160 return StringPrintf("/mnt/expand/%s", volume_uuid); 161 } 162} 163 164/** 165 * Create the path name for app data. 166 */ 167std::string create_data_app_path(const char* volume_uuid) { 168 return StringPrintf("%s/app", create_data_path(volume_uuid).c_str()); 169} 170 171/** 172 * Create the path name for user data for a certain userid. 173 */ 174std::string create_data_user_ce_path(const char* volume_uuid, userid_t userid) { 175 std::string data(create_data_path(volume_uuid)); 176 if (volume_uuid == nullptr) { 177 if (userid == 0) { 178 return StringPrintf("%s/data", data.c_str()); 179 } else { 180 return StringPrintf("%s/user/%u", data.c_str(), userid); 181 } 182 } else { 183 return StringPrintf("%s/user/%u", data.c_str(), userid); 184 } 185} 186 187/** 188 * Create the path name for device encrypted user data for a certain userid. 189 */ 190std::string create_data_user_de_path(const char* volume_uuid, userid_t userid) { 191 std::string data(create_data_path(volume_uuid)); 192 return StringPrintf("%s/user_de/%u", data.c_str(), userid); 193} 194 195/** 196 * Create the path name for media for a certain userid. 197 */ 198std::string create_data_media_path(const char* volume_uuid, userid_t userid) { 199 return StringPrintf("%s/media/%u", create_data_path(volume_uuid).c_str(), userid); 200} 201 202std::string create_data_media_obb_path(const char* volume_uuid, const char* package_name) { 203 return StringPrintf("%s/media/obb/%s", create_data_path(volume_uuid).c_str(), package_name); 204} 205 206std::string create_data_media_package_path(const char* volume_uuid, userid_t userid, 207 const char* data_type, const char* package_name) { 208 return StringPrintf("%s/Android/%s/%s", create_data_media_path(volume_uuid, userid).c_str(), 209 data_type, package_name); 210} 211 212std::string create_data_misc_legacy_path(userid_t userid) { 213 return StringPrintf("%s/misc/user/%u", create_data_path(nullptr).c_str(), userid); 214} 215 216std::string create_data_user_profile_path(userid_t userid) { 217 return StringPrintf("%s/cur/%u", android_profiles_dir.path, userid); 218} 219 220std::string create_data_user_profile_package_path(userid_t user, const char* package_name) { 221 check_package_name(package_name); 222 return StringPrintf("%s/%s",create_data_user_profile_path(user).c_str(), package_name); 223} 224 225std::string create_data_ref_profile_path() { 226 return StringPrintf("%s/ref", android_profiles_dir.path); 227} 228 229std::string create_data_ref_profile_package_path(const char* package_name) { 230 check_package_name(package_name); 231 return StringPrintf("%s/ref/%s", android_profiles_dir.path, package_name); 232} 233 234std::string create_data_dalvik_cache_path() { 235 return "/data/dalvik-cache"; 236} 237 238std::string create_data_misc_foreign_dex_path(userid_t userid) { 239 return StringPrintf("/data/misc/profiles/cur/%d/foreign-dex", userid); 240} 241 242// Keep profile paths in sync with ActivityThread. 243constexpr const char* PRIMARY_PROFILE_NAME = "primary.prof"; 244 245std::string create_primary_profile(const std::string& profile_dir) { 246 return StringPrintf("%s/%s", profile_dir.c_str(), PRIMARY_PROFILE_NAME); 247} 248 249std::vector<userid_t> get_known_users(const char* volume_uuid) { 250 std::vector<userid_t> users; 251 252 // We always have an owner 253 users.push_back(0); 254 255 std::string path(create_data_path(volume_uuid) + "/" + SECONDARY_USER_PREFIX); 256 DIR* dir = opendir(path.c_str()); 257 if (dir == NULL) { 258 // Unable to discover other users, but at least return owner 259 PLOG(ERROR) << "Failed to opendir " << path; 260 return users; 261 } 262 263 struct dirent* ent; 264 while ((ent = readdir(dir))) { 265 if (ent->d_type != DT_DIR) { 266 continue; 267 } 268 269 char* end; 270 userid_t user = strtol(ent->d_name, &end, 10); 271 if (*end == '\0' && user != 0) { 272 LOG(DEBUG) << "Found valid user " << user; 273 users.push_back(user); 274 } 275 } 276 closedir(dir); 277 278 return users; 279} 280 281int calculate_tree_size(const std::string& path, int64_t* size, 282 int32_t include_gid, int32_t exclude_gid, bool exclude_apps) { 283 FTS *fts; 284 FTSENT *p; 285 int64_t matchedSize = 0; 286 char *argv[] = { (char*) path.c_str(), nullptr }; 287 if (!(fts = fts_open(argv, FTS_PHYSICAL | FTS_XDEV, NULL))) { 288 if (errno != ENOENT) { 289 PLOG(ERROR) << "Failed to fts_open " << path; 290 } 291 return -1; 292 } 293 while ((p = fts_read(fts)) != NULL) { 294 switch (p->fts_info) { 295 case FTS_D: 296 case FTS_DEFAULT: 297 case FTS_F: 298 case FTS_SL: 299 case FTS_SLNONE: 300 int32_t uid = p->fts_statp->st_uid; 301 int32_t gid = p->fts_statp->st_gid; 302 int32_t user_uid = multiuser_get_app_id(uid); 303 int32_t user_gid = multiuser_get_app_id(gid); 304 if (exclude_apps && ((user_uid >= AID_APP_START && user_uid <= AID_APP_END) 305 || (user_gid >= AID_CACHE_GID_START && user_gid <= AID_CACHE_GID_END) 306 || (user_gid >= AID_SHARED_GID_START && user_gid <= AID_SHARED_GID_END))) { 307 // Don't traverse inside or measure 308 fts_set(fts, p, FTS_SKIP); 309 break; 310 } 311 if (include_gid != -1 && gid != include_gid) { 312 break; 313 } 314 if (exclude_gid != -1 && gid == exclude_gid) { 315 break; 316 } 317 matchedSize += (p->fts_statp->st_blocks * 512); 318 break; 319 } 320 } 321 fts_close(fts); 322#if MEASURE_DEBUG 323 if ((include_gid == -1) && (exclude_gid == -1)) { 324 LOG(DEBUG) << "Measured " << path << " size " << matchedSize; 325 } else { 326 LOG(DEBUG) << "Measured " << path << " size " << matchedSize << "; include " << include_gid 327 << " exclude " << exclude_gid; 328 } 329#endif 330 *size += matchedSize; 331 return 0; 332} 333 334int create_move_path(char path[PKG_PATH_MAX], 335 const char* pkgname, 336 const char* leaf, 337 userid_t userid ATTRIBUTE_UNUSED) 338{ 339 if ((android_data_dir.len + strlen(PRIMARY_USER_PREFIX) + strlen(pkgname) + strlen(leaf) + 1) 340 >= PKG_PATH_MAX) { 341 return -1; 342 } 343 344 sprintf(path, "%s%s%s/%s", android_data_dir.path, PRIMARY_USER_PREFIX, pkgname, leaf); 345 return 0; 346} 347 348/** 349 * Checks whether the package name is valid. Returns -1 on error and 350 * 0 on success. 351 */ 352bool is_valid_package_name(const std::string& packageName) { 353 const char* pkgname = packageName.c_str(); 354 const char *x = pkgname; 355 int alpha = -1; 356 357 if (strlen(pkgname) > PKG_NAME_MAX) { 358 return false; 359 } 360 361 while (*x) { 362 if (isalnum(*x) || (*x == '_')) { 363 /* alphanumeric or underscore are fine */ 364 } else if (*x == '.') { 365 if ((x == pkgname) || (x[1] == '.') || (x[1] == 0)) { 366 /* periods must not be first, last, or doubled */ 367 ALOGE("invalid package name '%s'\n", pkgname); 368 return false; 369 } 370 } else if (*x == '-') { 371 /* Suffix -X is fine to let versioning of packages. 372 But whatever follows should be alphanumeric.*/ 373 alpha = 1; 374 } else { 375 /* anything not A-Z, a-z, 0-9, _, or . is invalid */ 376 ALOGE("invalid package name '%s'\n", pkgname); 377 return false; 378 } 379 380 x++; 381 } 382 383 if (alpha == 1) { 384 // Skip current character 385 x++; 386 while (*x) { 387 if (!isalnum(*x)) { 388 ALOGE("invalid package name '%s' should include only numbers after -\n", pkgname); 389 return false; 390 } 391 x++; 392 } 393 } 394 395 return true; 396} 397 398static int _delete_dir_contents(DIR *d, 399 int (*exclusion_predicate)(const char *name, const int is_dir)) 400{ 401 int result = 0; 402 struct dirent *de; 403 int dfd; 404 405 dfd = dirfd(d); 406 407 if (dfd < 0) return -1; 408 409 while ((de = readdir(d))) { 410 const char *name = de->d_name; 411 412 /* check using the exclusion predicate, if provided */ 413 if (exclusion_predicate && exclusion_predicate(name, (de->d_type == DT_DIR))) { 414 continue; 415 } 416 417 if (de->d_type == DT_DIR) { 418 int subfd; 419 DIR *subdir; 420 421 /* always skip "." and ".." */ 422 if (name[0] == '.') { 423 if (name[1] == 0) continue; 424 if ((name[1] == '.') && (name[2] == 0)) continue; 425 } 426 427 subfd = openat(dfd, name, O_RDONLY | O_DIRECTORY | O_NOFOLLOW | O_CLOEXEC); 428 if (subfd < 0) { 429 ALOGE("Couldn't openat %s: %s\n", name, strerror(errno)); 430 result = -1; 431 continue; 432 } 433 subdir = fdopendir(subfd); 434 if (subdir == NULL) { 435 ALOGE("Couldn't fdopendir %s: %s\n", name, strerror(errno)); 436 close(subfd); 437 result = -1; 438 continue; 439 } 440 if (_delete_dir_contents(subdir, exclusion_predicate)) { 441 result = -1; 442 } 443 closedir(subdir); 444 if (unlinkat(dfd, name, AT_REMOVEDIR) < 0) { 445 ALOGE("Couldn't unlinkat %s: %s\n", name, strerror(errno)); 446 result = -1; 447 } 448 } else { 449 if (unlinkat(dfd, name, 0) < 0) { 450 ALOGE("Couldn't unlinkat %s: %s\n", name, strerror(errno)); 451 result = -1; 452 } 453 } 454 } 455 456 return result; 457} 458 459int delete_dir_contents(const std::string& pathname, bool ignore_if_missing) { 460 return delete_dir_contents(pathname.c_str(), 0, NULL, ignore_if_missing); 461} 462 463int delete_dir_contents_and_dir(const std::string& pathname, bool ignore_if_missing) { 464 return delete_dir_contents(pathname.c_str(), 1, NULL, ignore_if_missing); 465} 466 467int delete_dir_contents(const char *pathname, 468 int also_delete_dir, 469 int (*exclusion_predicate)(const char*, const int), 470 bool ignore_if_missing) 471{ 472 int res = 0; 473 DIR *d; 474 475 d = opendir(pathname); 476 if (d == NULL) { 477 if (ignore_if_missing && (errno == ENOENT)) { 478 return 0; 479 } 480 ALOGE("Couldn't opendir %s: %s\n", pathname, strerror(errno)); 481 return -errno; 482 } 483 res = _delete_dir_contents(d, exclusion_predicate); 484 closedir(d); 485 if (also_delete_dir) { 486 if (rmdir(pathname)) { 487 ALOGE("Couldn't rmdir %s: %s\n", pathname, strerror(errno)); 488 res = -1; 489 } 490 } 491 return res; 492} 493 494int delete_dir_contents_fd(int dfd, const char *name) 495{ 496 int fd, res; 497 DIR *d; 498 499 fd = openat(dfd, name, O_RDONLY | O_DIRECTORY | O_NOFOLLOW | O_CLOEXEC); 500 if (fd < 0) { 501 ALOGE("Couldn't openat %s: %s\n", name, strerror(errno)); 502 return -1; 503 } 504 d = fdopendir(fd); 505 if (d == NULL) { 506 ALOGE("Couldn't fdopendir %s: %s\n", name, strerror(errno)); 507 close(fd); 508 return -1; 509 } 510 res = _delete_dir_contents(d, 0); 511 closedir(d); 512 return res; 513} 514 515static int _copy_owner_permissions(int srcfd, int dstfd) 516{ 517 struct stat st; 518 if (fstat(srcfd, &st) != 0) { 519 return -1; 520 } 521 if (fchmod(dstfd, st.st_mode) != 0) { 522 return -1; 523 } 524 return 0; 525} 526 527static int _copy_dir_files(int sdfd, int ddfd, uid_t owner, gid_t group) 528{ 529 int result = 0; 530 if (_copy_owner_permissions(sdfd, ddfd) != 0) { 531 ALOGE("_copy_dir_files failed to copy dir permissions\n"); 532 } 533 if (fchown(ddfd, owner, group) != 0) { 534 ALOGE("_copy_dir_files failed to change dir owner\n"); 535 } 536 537 DIR *ds = fdopendir(sdfd); 538 if (ds == NULL) { 539 ALOGE("Couldn't fdopendir: %s\n", strerror(errno)); 540 return -1; 541 } 542 struct dirent *de; 543 while ((de = readdir(ds))) { 544 if (de->d_type != DT_REG) { 545 continue; 546 } 547 548 const char *name = de->d_name; 549 int fsfd = openat(sdfd, name, O_RDONLY | O_NOFOLLOW | O_CLOEXEC); 550 int fdfd = openat(ddfd, name, O_WRONLY | O_NOFOLLOW | O_CLOEXEC | O_CREAT, 0600); 551 if (fsfd == -1 || fdfd == -1) { 552 ALOGW("Couldn't copy %s: %s\n", name, strerror(errno)); 553 } else { 554 if (_copy_owner_permissions(fsfd, fdfd) != 0) { 555 ALOGE("Failed to change file permissions\n"); 556 } 557 if (fchown(fdfd, owner, group) != 0) { 558 ALOGE("Failed to change file owner\n"); 559 } 560 561 char buf[8192]; 562 ssize_t size; 563 while ((size = read(fsfd, buf, sizeof(buf))) > 0) { 564 write(fdfd, buf, size); 565 } 566 if (size < 0) { 567 ALOGW("Couldn't copy %s: %s\n", name, strerror(errno)); 568 result = -1; 569 } 570 } 571 close(fdfd); 572 close(fsfd); 573 } 574 575 return result; 576} 577 578int copy_dir_files(const char *srcname, 579 const char *dstname, 580 uid_t owner, 581 uid_t group) 582{ 583 int res = 0; 584 DIR *ds = NULL; 585 DIR *dd = NULL; 586 587 ds = opendir(srcname); 588 if (ds == NULL) { 589 ALOGE("Couldn't opendir %s: %s\n", srcname, strerror(errno)); 590 return -errno; 591 } 592 593 mkdir(dstname, 0600); 594 dd = opendir(dstname); 595 if (dd == NULL) { 596 ALOGE("Couldn't opendir %s: %s\n", dstname, strerror(errno)); 597 closedir(ds); 598 return -errno; 599 } 600 601 int sdfd = dirfd(ds); 602 int ddfd = dirfd(dd); 603 if (sdfd != -1 && ddfd != -1) { 604 res = _copy_dir_files(sdfd, ddfd, owner, group); 605 } else { 606 res = -errno; 607 } 608 closedir(dd); 609 closedir(ds); 610 return res; 611} 612 613int64_t data_disk_free(const std::string& data_path) 614{ 615 struct statfs sfs; 616 if (statfs(data_path.c_str(), &sfs) == 0) { 617 return sfs.f_bavail * sfs.f_bsize; 618 } else { 619 PLOG(ERROR) << "Couldn't statfs " << data_path; 620 return -1; 621 } 622} 623 624cache_t* start_cache_collection() 625{ 626 cache_t* cache = (cache_t*)calloc(1, sizeof(cache_t)); 627 return cache; 628} 629 630#define CACHE_BLOCK_SIZE (512*1024) 631 632static void* _cache_malloc(cache_t* cache, size_t len) 633{ 634 len = (len+3)&~3; 635 if (len > (CACHE_BLOCK_SIZE/2)) { 636 // It doesn't make sense to try to put this allocation into one 637 // of our blocks, because it is so big. Instead, make a new dedicated 638 // block for it. 639 int8_t* res = (int8_t*)malloc(len+sizeof(void*)); 640 if (res == NULL) { 641 return NULL; 642 } 643 CACHE_NOISY(ALOGI("Allocated large cache mem block: %p size %zu", res, len)); 644 // Link it into our list of blocks, not disrupting the current one. 645 if (cache->memBlocks == NULL) { 646 *(void**)res = NULL; 647 cache->memBlocks = res; 648 } else { 649 *(void**)res = *(void**)cache->memBlocks; 650 *(void**)cache->memBlocks = res; 651 } 652 return res + sizeof(void*); 653 } 654 int8_t* res = cache->curMemBlockAvail; 655 int8_t* nextPos = res + len; 656 if (cache->memBlocks == NULL || nextPos > cache->curMemBlockEnd) { 657 int8_t* newBlock = (int8_t*) malloc(CACHE_BLOCK_SIZE); 658 if (newBlock == NULL) { 659 return NULL; 660 } 661 CACHE_NOISY(ALOGI("Allocated new cache mem block: %p", newBlock)); 662 *(void**)newBlock = cache->memBlocks; 663 cache->memBlocks = newBlock; 664 res = cache->curMemBlockAvail = newBlock + sizeof(void*); 665 cache->curMemBlockEnd = newBlock + CACHE_BLOCK_SIZE; 666 nextPos = res + len; 667 } 668 CACHE_NOISY(ALOGI("cache_malloc: ret %p size %zu, block=%p, nextPos=%p", 669 res, len, cache->memBlocks, nextPos)); 670 cache->curMemBlockAvail = nextPos; 671 return res; 672} 673 674static void* _cache_realloc(cache_t* cache, void* cur, size_t origLen, size_t len) 675{ 676 // This isn't really a realloc, but it is good enough for our purposes here. 677 void* alloc = _cache_malloc(cache, len); 678 if (alloc != NULL && cur != NULL) { 679 memcpy(alloc, cur, origLen < len ? origLen : len); 680 } 681 return alloc; 682} 683 684static void _inc_num_cache_collected(cache_t* cache) 685{ 686 cache->numCollected++; 687 if ((cache->numCollected%20000) == 0) { 688 ALOGI("Collected cache so far: %zd directories, %zd files", 689 cache->numDirs, cache->numFiles); 690 } 691} 692 693static cache_dir_t* _add_cache_dir_t(cache_t* cache, cache_dir_t* parent, const char *name) 694{ 695 size_t nameLen = strlen(name); 696 cache_dir_t* dir = (cache_dir_t*)_cache_malloc(cache, sizeof(cache_dir_t)+nameLen+1); 697 if (dir != NULL) { 698 dir->parent = parent; 699 dir->childCount = 0; 700 dir->hiddenCount = 0; 701 dir->deleted = 0; 702 strcpy(dir->name, name); 703 if (cache->numDirs >= cache->availDirs) { 704 size_t newAvail = cache->availDirs < 1000 ? 1000 : cache->availDirs*2; 705 cache_dir_t** newDirs = (cache_dir_t**)_cache_realloc(cache, cache->dirs, 706 cache->availDirs*sizeof(cache_dir_t*), newAvail*sizeof(cache_dir_t*)); 707 if (newDirs == NULL) { 708 ALOGE("Failure growing cache dirs array for %s\n", name); 709 return NULL; 710 } 711 cache->availDirs = newAvail; 712 cache->dirs = newDirs; 713 } 714 cache->dirs[cache->numDirs] = dir; 715 cache->numDirs++; 716 if (parent != NULL) { 717 parent->childCount++; 718 } 719 _inc_num_cache_collected(cache); 720 } else { 721 ALOGE("Failure allocating cache_dir_t for %s\n", name); 722 } 723 return dir; 724} 725 726static cache_file_t* _add_cache_file_t(cache_t* cache, cache_dir_t* dir, time_t modTime, 727 const char *name) 728{ 729 size_t nameLen = strlen(name); 730 cache_file_t* file = (cache_file_t*)_cache_malloc(cache, sizeof(cache_file_t)+nameLen+1); 731 if (file != NULL) { 732 file->dir = dir; 733 file->modTime = modTime; 734 strcpy(file->name, name); 735 if (cache->numFiles >= cache->availFiles) { 736 size_t newAvail = cache->availFiles < 1000 ? 1000 : cache->availFiles*2; 737 cache_file_t** newFiles = (cache_file_t**)_cache_realloc(cache, cache->files, 738 cache->availFiles*sizeof(cache_file_t*), newAvail*sizeof(cache_file_t*)); 739 if (newFiles == NULL) { 740 ALOGE("Failure growing cache file array for %s\n", name); 741 return NULL; 742 } 743 cache->availFiles = newAvail; 744 cache->files = newFiles; 745 } 746 CACHE_NOISY(ALOGI("Setting file %p at position %zd in array %p", file, 747 cache->numFiles, cache->files)); 748 cache->files[cache->numFiles] = file; 749 cache->numFiles++; 750 dir->childCount++; 751 _inc_num_cache_collected(cache); 752 } else { 753 ALOGE("Failure allocating cache_file_t for %s\n", name); 754 } 755 return file; 756} 757 758static int _add_cache_files(cache_t *cache, cache_dir_t *parentDir, const char *dirName, 759 DIR* dir, char *pathBase, char *pathPos, size_t pathAvailLen) 760{ 761 struct dirent *de; 762 cache_dir_t* cacheDir = NULL; 763 int dfd; 764 765 CACHE_NOISY(ALOGI("_add_cache_files: parent=%p dirName=%s dir=%p pathBase=%s", 766 parentDir, dirName, dir, pathBase)); 767 768 dfd = dirfd(dir); 769 770 if (dfd < 0) return 0; 771 772 // Sub-directories always get added to the data structure, so if they 773 // are empty we will know about them to delete them later. 774 cacheDir = _add_cache_dir_t(cache, parentDir, dirName); 775 776 while ((de = readdir(dir))) { 777 const char *name = de->d_name; 778 779 if (de->d_type == DT_DIR) { 780 int subfd; 781 DIR *subdir; 782 783 /* always skip "." and ".." */ 784 if (name[0] == '.') { 785 if (name[1] == 0) continue; 786 if ((name[1] == '.') && (name[2] == 0)) continue; 787 } 788 789 subfd = openat(dfd, name, O_RDONLY | O_DIRECTORY | O_NOFOLLOW | O_CLOEXEC); 790 if (subfd < 0) { 791 ALOGE("Couldn't openat %s: %s\n", name, strerror(errno)); 792 continue; 793 } 794 subdir = fdopendir(subfd); 795 if (subdir == NULL) { 796 ALOGE("Couldn't fdopendir %s: %s\n", name, strerror(errno)); 797 close(subfd); 798 continue; 799 } 800 if (cacheDir == NULL) { 801 cacheDir = _add_cache_dir_t(cache, parentDir, dirName); 802 } 803 if (cacheDir != NULL) { 804 // Update pathBase for the new path... this may change dirName 805 // if that is also pointing to the path, but we are done with it 806 // now. 807 size_t finallen = snprintf(pathPos, pathAvailLen, "/%s", name); 808 CACHE_NOISY(ALOGI("Collecting dir %s\n", pathBase)); 809 if (finallen < pathAvailLen) { 810 _add_cache_files(cache, cacheDir, name, subdir, pathBase, 811 pathPos+finallen, pathAvailLen-finallen); 812 } else { 813 // Whoops, the final path is too long! We'll just delete 814 // this directory. 815 ALOGW("Cache dir %s truncated in path %s; deleting dir\n", 816 name, pathBase); 817 _delete_dir_contents(subdir, NULL); 818 if (unlinkat(dfd, name, AT_REMOVEDIR) < 0) { 819 ALOGE("Couldn't unlinkat %s: %s\n", name, strerror(errno)); 820 } 821 } 822 } 823 closedir(subdir); 824 } else if (de->d_type == DT_REG) { 825 // Skip files that start with '.'; they will be deleted if 826 // their entire directory is deleted. This allows for metadata 827 // like ".nomedia" to remain in the directory until the entire 828 // directory is deleted. 829 if (cacheDir == NULL) { 830 cacheDir = _add_cache_dir_t(cache, parentDir, dirName); 831 } 832 if (name[0] == '.') { 833 cacheDir->hiddenCount++; 834 continue; 835 } 836 if (cacheDir != NULL) { 837 // Build final full path for file... this may change dirName 838 // if that is also pointing to the path, but we are done with it 839 // now. 840 size_t finallen = snprintf(pathPos, pathAvailLen, "/%s", name); 841 CACHE_NOISY(ALOGI("Collecting file %s\n", pathBase)); 842 if (finallen < pathAvailLen) { 843 struct stat s; 844 if (stat(pathBase, &s) >= 0) { 845 _add_cache_file_t(cache, cacheDir, s.st_mtime, name); 846 } else { 847 ALOGW("Unable to stat cache file %s; deleting\n", pathBase); 848 if (unlink(pathBase) < 0) { 849 ALOGE("Couldn't unlink %s: %s\n", pathBase, strerror(errno)); 850 } 851 } 852 } else { 853 // Whoops, the final path is too long! We'll just delete 854 // this file. 855 ALOGW("Cache file %s truncated in path %s; deleting\n", 856 name, pathBase); 857 if (unlinkat(dfd, name, 0) < 0) { 858 *pathPos = 0; 859 ALOGE("Couldn't unlinkat %s in %s: %s\n", name, pathBase, 860 strerror(errno)); 861 } 862 } 863 } 864 } else { 865 cacheDir->hiddenCount++; 866 } 867 } 868 return 0; 869} 870 871int get_path_inode(const std::string& path, ino_t *inode) { 872 struct stat buf; 873 memset(&buf, 0, sizeof(buf)); 874 if (stat(path.c_str(), &buf) != 0) { 875 PLOG(WARNING) << "Failed to stat " << path; 876 return -1; 877 } else { 878 *inode = buf.st_ino; 879 return 0; 880 } 881} 882 883/** 884 * Write the inode of a specific child file into the given xattr on the 885 * parent directory. This allows you to find the child later, even if its 886 * name is encrypted. 887 */ 888int write_path_inode(const std::string& parent, const char* name, const char* inode_xattr) { 889 ino_t inode = 0; 890 uint64_t inode_raw = 0; 891 auto path = StringPrintf("%s/%s", parent.c_str(), name); 892 893 if (get_path_inode(path, &inode) != 0) { 894 // Path probably doesn't exist yet; ignore 895 return 0; 896 } 897 898 // Check to see if already set correctly 899 if (getxattr(parent.c_str(), inode_xattr, &inode_raw, sizeof(inode_raw)) == sizeof(inode_raw)) { 900 if (inode_raw == inode) { 901 // Already set correctly; skip writing 902 return 0; 903 } else { 904 PLOG(WARNING) << "Mismatched inode value; found " << inode 905 << " on disk but marked value was " << inode_raw << "; overwriting"; 906 } 907 } 908 909 inode_raw = inode; 910 if (setxattr(parent.c_str(), inode_xattr, &inode_raw, sizeof(inode_raw), 0) != 0 && errno != EOPNOTSUPP) { 911 PLOG(ERROR) << "Failed to write xattr " << inode_xattr << " at " << parent; 912 return -1; 913 } else { 914 return 0; 915 } 916} 917 918/** 919 * Read the inode of a specific child file from the given xattr on the 920 * parent directory. Returns a currently valid path for that child, which 921 * might have an encrypted name. 922 */ 923std::string read_path_inode(const std::string& parent, const char* name, const char* inode_xattr) { 924 ino_t inode = 0; 925 uint64_t inode_raw = 0; 926 auto fallback = StringPrintf("%s/%s", parent.c_str(), name); 927 928 // Lookup the inode value written earlier 929 if (getxattr(parent.c_str(), inode_xattr, &inode_raw, sizeof(inode_raw)) == sizeof(inode_raw)) { 930 inode = inode_raw; 931 } 932 933 // For testing purposes, rely on the inode when defined; this could be 934 // optimized to use access() in the future. 935 if (inode != 0) { 936 DIR* dir = opendir(parent.c_str()); 937 if (dir == nullptr) { 938 PLOG(ERROR) << "Failed to opendir " << parent; 939 return fallback; 940 } 941 942 struct dirent* ent; 943 while ((ent = readdir(dir))) { 944 if (ent->d_ino == inode) { 945 auto resolved = StringPrintf("%s/%s", parent.c_str(), ent->d_name); 946#if DEBUG_XATTRS 947 if (resolved != fallback) { 948 LOG(DEBUG) << "Resolved path " << resolved << " for inode " << inode 949 << " instead of " << fallback; 950 } 951#endif 952 closedir(dir); 953 return resolved; 954 } 955 } 956 LOG(WARNING) << "Failed to resolve inode " << inode << "; using " << fallback; 957 closedir(dir); 958 return fallback; 959 } else { 960 return fallback; 961 } 962} 963 964void add_cache_files(cache_t* cache, const std::string& data_path) { 965 DIR *d; 966 struct dirent *de; 967 char dirname[PATH_MAX]; 968 969 const char* basepath = data_path.c_str(); 970 CACHE_NOISY(ALOGI("add_cache_files: basepath=%s\n", basepath)); 971 972 d = opendir(basepath); 973 if (d == NULL) { 974 return; 975 } 976 977 while ((de = readdir(d))) { 978 if (de->d_type == DT_DIR) { 979 DIR* subdir; 980 const char *name = de->d_name; 981 982 /* always skip "." and ".." */ 983 if (name[0] == '.') { 984 if (name[1] == 0) continue; 985 if ((name[1] == '.') && (name[2] == 0)) continue; 986 } 987 988 auto parent = StringPrintf("%s/%s", basepath, name); 989 auto resolved = read_path_inode(parent, "cache", kXattrInodeCache); 990 strcpy(dirname, resolved.c_str()); 991 CACHE_NOISY(ALOGI("Adding cache files from dir: %s\n", dirname)); 992 993 subdir = opendir(dirname); 994 if (subdir != NULL) { 995 size_t dirnameLen = strlen(dirname); 996 _add_cache_files(cache, NULL, dirname, subdir, dirname, dirname+dirnameLen, 997 PATH_MAX - dirnameLen); 998 closedir(subdir); 999 } 1000 } 1001 } 1002 1003 closedir(d); 1004} 1005 1006static char *create_dir_path(char path[PATH_MAX], cache_dir_t* dir) 1007{ 1008 char *pos = path; 1009 if (dir->parent != NULL) { 1010 pos = create_dir_path(path, dir->parent); 1011 } 1012 // Note that we don't need to worry about going beyond the buffer, 1013 // since when we were constructing the cache entries our maximum 1014 // buffer size for full paths was PATH_MAX. 1015 strcpy(pos, dir->name); 1016 pos += strlen(pos); 1017 *pos = '/'; 1018 pos++; 1019 *pos = 0; 1020 return pos; 1021} 1022 1023static void delete_cache_dir(char path[PATH_MAX], cache_dir_t* dir) 1024{ 1025 if (dir->parent != NULL) { 1026 create_dir_path(path, dir); 1027 ALOGI("DEL DIR %s\n", path); 1028 if (dir->hiddenCount <= 0) { 1029 if (rmdir(path)) { 1030 ALOGE("Couldn't rmdir %s: %s\n", path, strerror(errno)); 1031 return; 1032 } 1033 } else { 1034 // The directory contains hidden files so we need to delete 1035 // them along with the directory itself. 1036 if (delete_dir_contents(path, 1, NULL)) { 1037 return; 1038 } 1039 } 1040 dir->parent->childCount--; 1041 dir->deleted = 1; 1042 if (dir->parent->childCount <= 0) { 1043 delete_cache_dir(path, dir->parent); 1044 } 1045 } else if (dir->hiddenCount > 0) { 1046 // This is a root directory, but it has hidden files. Get rid of 1047 // all of those files, but not the directory itself. 1048 create_dir_path(path, dir); 1049 ALOGI("DEL CONTENTS %s\n", path); 1050 delete_dir_contents(path, 0, NULL); 1051 } 1052} 1053 1054static int cache_modtime_sort(const void *lhsP, const void *rhsP) 1055{ 1056 const cache_file_t *lhs = *(const cache_file_t**)lhsP; 1057 const cache_file_t *rhs = *(const cache_file_t**)rhsP; 1058 return lhs->modTime < rhs->modTime ? -1 : (lhs->modTime > rhs->modTime ? 1 : 0); 1059} 1060 1061void clear_cache_files(const std::string& data_path, cache_t* cache, int64_t free_size) 1062{ 1063 size_t i; 1064 int skip = 0; 1065 char path[PATH_MAX]; 1066 1067 ALOGI("Collected cache files: %zd directories, %zd files", 1068 cache->numDirs, cache->numFiles); 1069 1070 CACHE_NOISY(ALOGI("Sorting files...")); 1071 qsort(cache->files, cache->numFiles, sizeof(cache_file_t*), 1072 cache_modtime_sort); 1073 1074 CACHE_NOISY(ALOGI("Cleaning empty directories...")); 1075 for (i=cache->numDirs; i>0; i--) { 1076 cache_dir_t* dir = cache->dirs[i-1]; 1077 if (dir->childCount <= 0 && !dir->deleted) { 1078 delete_cache_dir(path, dir); 1079 } 1080 } 1081 1082 CACHE_NOISY(ALOGI("Trimming files...")); 1083 for (i=0; i<cache->numFiles; i++) { 1084 skip++; 1085 if (skip > 10) { 1086 if (data_disk_free(data_path) > free_size) { 1087 return; 1088 } 1089 skip = 0; 1090 } 1091 cache_file_t* file = cache->files[i]; 1092 strcpy(create_dir_path(path, file->dir), file->name); 1093 ALOGI("DEL (mod %d) %s\n", (int)file->modTime, path); 1094 if (unlink(path) < 0) { 1095 ALOGE("Couldn't unlink %s: %s\n", path, strerror(errno)); 1096 } 1097 file->dir->childCount--; 1098 if (file->dir->childCount <= 0) { 1099 delete_cache_dir(path, file->dir); 1100 } 1101 } 1102} 1103 1104void finish_cache_collection(cache_t* cache) 1105{ 1106 CACHE_NOISY(size_t i;) 1107 1108 CACHE_NOISY(ALOGI("clear_cache_files: %zu dirs, %zu files\n", cache->numDirs, cache->numFiles)); 1109 CACHE_NOISY( 1110 for (i=0; i<cache->numDirs; i++) { 1111 cache_dir_t* dir = cache->dirs[i]; 1112 ALOGI("dir #%zu: %p %s parent=%p\n", i, dir, dir->name, dir->parent); 1113 }) 1114 CACHE_NOISY( 1115 for (i=0; i<cache->numFiles; i++) { 1116 cache_file_t* file = cache->files[i]; 1117 ALOGI("file #%zu: %p %s time=%d dir=%p\n", i, file, file->name, 1118 (int)file->modTime, file->dir); 1119 }) 1120 void* block = cache->memBlocks; 1121 while (block != NULL) { 1122 void* nextBlock = *(void**)block; 1123 CACHE_NOISY(ALOGI("Freeing cache mem block: %p", block)); 1124 free(block); 1125 block = nextBlock; 1126 } 1127 free(cache); 1128} 1129 1130/** 1131 * Validate that the path is valid in the context of the provided directory. 1132 * The path is allowed to have at most one subdirectory and no indirections 1133 * to top level directories (i.e. have ".."). 1134 */ 1135static int validate_path(const dir_rec_t* dir, const char* path, int maxSubdirs) { 1136 size_t dir_len = dir->len; 1137 const char* subdir = strchr(path + dir_len, '/'); 1138 1139 // Only allow the path to have at most one subdirectory. 1140 if (subdir != NULL) { 1141 ++subdir; 1142 if ((--maxSubdirs == 0) && strchr(subdir, '/') != NULL) { 1143 ALOGE("invalid apk path '%s' (subdir?)\n", path); 1144 return -1; 1145 } 1146 } 1147 1148 // Directories can't have a period directly after the directory markers to prevent "..". 1149 if ((path[dir_len] == '.') || ((subdir != NULL) && (*subdir == '.'))) { 1150 ALOGE("invalid apk path '%s' (trickery)\n", path); 1151 return -1; 1152 } 1153 1154 return 0; 1155} 1156 1157/** 1158 * Checks whether a path points to a system app (.apk file). Returns 0 1159 * if it is a system app or -1 if it is not. 1160 */ 1161int validate_system_app_path(const char* path) { 1162 size_t i; 1163 1164 for (i = 0; i < android_system_dirs.count; i++) { 1165 const size_t dir_len = android_system_dirs.dirs[i].len; 1166 if (!strncmp(path, android_system_dirs.dirs[i].path, dir_len)) { 1167 return validate_path(android_system_dirs.dirs + i, path, 1); 1168 } 1169 } 1170 1171 return -1; 1172} 1173 1174bool validate_secondary_dex_path(const char* pkgname, const char* path, 1175 const char* volume_uuid, int uid, int storage_flag) { 1176 CHECK(storage_flag == FLAG_STORAGE_CE || storage_flag == FLAG_STORAGE_DE); 1177 1178 std::string app_private_dir = storage_flag == FLAG_STORAGE_CE 1179 ? create_data_user_ce_package_path(volume_uuid, multiuser_get_user_id(uid), pkgname) 1180 : create_data_user_de_package_path(volume_uuid, multiuser_get_user_id(uid), pkgname); 1181 dir_rec_t dir; 1182 if (get_path_from_string(&dir, app_private_dir.c_str()) != 0) { 1183 LOG(WARNING) << "Could not get dir rec for " << app_private_dir; 1184 return false; 1185 } 1186 // Usually secondary dex files have a nested directory structure. 1187 // Pick at most 10 subdirectories when validating (arbitrary value). 1188 // If the secondary dex file is >10 directory nested then validation will 1189 // fail and the file will not be compiled. 1190 return validate_path(&dir, path, /*max_subdirs*/ 10) == 0; 1191} 1192 1193/** 1194 * Get the contents of a environment variable that contains a path. Caller 1195 * owns the string that is inserted into the directory record. Returns 1196 * 0 on success and -1 on error. 1197 */ 1198int get_path_from_env(dir_rec_t* rec, const char* var) { 1199 const char* path = getenv(var); 1200 int ret = get_path_from_string(rec, path); 1201 if (ret < 0) { 1202 ALOGW("Problem finding value for environment variable %s\n", var); 1203 } 1204 return ret; 1205} 1206 1207/** 1208 * Puts the string into the record as a directory. Appends '/' to the end 1209 * of all paths. Caller owns the string that is inserted into the directory 1210 * record. A null value will result in an error. 1211 * 1212 * Returns 0 on success and -1 on error. 1213 */ 1214int get_path_from_string(dir_rec_t* rec, const char* path) { 1215 if (path == NULL) { 1216 return -1; 1217 } else { 1218 const size_t path_len = strlen(path); 1219 if (path_len <= 0) { 1220 return -1; 1221 } 1222 1223 // Make sure path is absolute. 1224 if (path[0] != '/') { 1225 return -1; 1226 } 1227 1228 if (path[path_len - 1] == '/') { 1229 // Path ends with a forward slash. Make our own copy. 1230 1231 rec->path = strdup(path); 1232 if (rec->path == NULL) { 1233 return -1; 1234 } 1235 1236 rec->len = path_len; 1237 } else { 1238 // Path does not end with a slash. Generate a new string. 1239 char *dst; 1240 1241 // Add space for slash and terminating null. 1242 size_t dst_size = path_len + 2; 1243 1244 rec->path = (char*) malloc(dst_size); 1245 if (rec->path == NULL) { 1246 return -1; 1247 } 1248 1249 dst = rec->path; 1250 1251 if (append_and_increment(&dst, path, &dst_size) < 0 1252 || append_and_increment(&dst, "/", &dst_size)) { 1253 ALOGE("Error canonicalizing path"); 1254 return -1; 1255 } 1256 1257 rec->len = dst - rec->path; 1258 } 1259 } 1260 return 0; 1261} 1262 1263int copy_and_append(dir_rec_t* dst, const dir_rec_t* src, const char* suffix) { 1264 dst->len = src->len + strlen(suffix); 1265 const size_t dstSize = dst->len + 1; 1266 dst->path = (char*) malloc(dstSize); 1267 1268 if (dst->path == NULL 1269 || snprintf(dst->path, dstSize, "%s%s", src->path, suffix) 1270 != (ssize_t) dst->len) { 1271 ALOGE("Could not allocate memory to hold appended path; aborting\n"); 1272 return -1; 1273 } 1274 1275 return 0; 1276} 1277 1278/** 1279 * Check whether path points to a valid path for an APK file. The path must 1280 * begin with a whitelisted prefix path and must be no deeper than |maxSubdirs| within 1281 * that path. Returns -1 when an invalid path is encountered and 0 when a valid path 1282 * is encountered. 1283 */ 1284static int validate_apk_path_internal(const char *path, int maxSubdirs) { 1285 const dir_rec_t* dir = NULL; 1286 if (!strncmp(path, android_app_dir.path, android_app_dir.len)) { 1287 dir = &android_app_dir; 1288 } else if (!strncmp(path, android_app_private_dir.path, android_app_private_dir.len)) { 1289 dir = &android_app_private_dir; 1290 } else if (!strncmp(path, android_app_ephemeral_dir.path, android_app_ephemeral_dir.len)) { 1291 dir = &android_app_ephemeral_dir; 1292 } else if (!strncmp(path, android_asec_dir.path, android_asec_dir.len)) { 1293 dir = &android_asec_dir; 1294 } else if (!strncmp(path, android_mnt_expand_dir.path, android_mnt_expand_dir.len)) { 1295 dir = &android_mnt_expand_dir; 1296 if (maxSubdirs < 2) { 1297 maxSubdirs = 2; 1298 } 1299 } else { 1300 return -1; 1301 } 1302 1303 return validate_path(dir, path, maxSubdirs); 1304} 1305 1306int validate_apk_path(const char* path) { 1307 return validate_apk_path_internal(path, 1 /* maxSubdirs */); 1308} 1309 1310int validate_apk_path_subdirs(const char* path) { 1311 return validate_apk_path_internal(path, 3 /* maxSubdirs */); 1312} 1313 1314int append_and_increment(char** dst, const char* src, size_t* dst_size) { 1315 ssize_t ret = strlcpy(*dst, src, *dst_size); 1316 if (ret < 0 || (size_t) ret >= *dst_size) { 1317 return -1; 1318 } 1319 *dst += ret; 1320 *dst_size -= ret; 1321 return 0; 1322} 1323 1324char *build_string2(const char *s1, const char *s2) { 1325 if (s1 == NULL || s2 == NULL) return NULL; 1326 1327 int len_s1 = strlen(s1); 1328 int len_s2 = strlen(s2); 1329 int len = len_s1 + len_s2 + 1; 1330 char *result = (char *) malloc(len); 1331 if (result == NULL) return NULL; 1332 1333 strcpy(result, s1); 1334 strcpy(result + len_s1, s2); 1335 1336 return result; 1337} 1338 1339char *build_string3(const char *s1, const char *s2, const char *s3) { 1340 if (s1 == NULL || s2 == NULL || s3 == NULL) return NULL; 1341 1342 int len_s1 = strlen(s1); 1343 int len_s2 = strlen(s2); 1344 int len_s3 = strlen(s3); 1345 int len = len_s1 + len_s2 + len_s3 + 1; 1346 char *result = (char *) malloc(len); 1347 if (result == NULL) return NULL; 1348 1349 strcpy(result, s1); 1350 strcpy(result + len_s1, s2); 1351 strcpy(result + len_s1 + len_s2, s3); 1352 1353 return result; 1354} 1355 1356int ensure_config_user_dirs(userid_t userid) { 1357 // writable by system, readable by any app within the same user 1358 const int uid = multiuser_get_uid(userid, AID_SYSTEM); 1359 const int gid = multiuser_get_uid(userid, AID_EVERYBODY); 1360 1361 // Ensure /data/misc/user/<userid> exists 1362 auto path = create_data_misc_legacy_path(userid); 1363 return fs_prepare_dir(path.c_str(), 0750, uid, gid); 1364} 1365 1366int wait_child(pid_t pid) 1367{ 1368 int status; 1369 pid_t got_pid; 1370 1371 while (1) { 1372 got_pid = waitpid(pid, &status, 0); 1373 if (got_pid == -1 && errno == EINTR) { 1374 printf("waitpid interrupted, retrying\n"); 1375 } else { 1376 break; 1377 } 1378 } 1379 if (got_pid != pid) { 1380 ALOGW("waitpid failed: wanted %d, got %d: %s\n", 1381 (int) pid, (int) got_pid, strerror(errno)); 1382 return 1; 1383 } 1384 1385 if (WIFEXITED(status) && WEXITSTATUS(status) == 0) { 1386 return 0; 1387 } else { 1388 return status; /* always nonzero */ 1389 } 1390} 1391 1392/** 1393 * Prepare an app cache directory, which offers to fix-up the GID and 1394 * directory mode flags during a platform upgrade. 1395 * The app cache directory path will be 'parent'/'name'. 1396 */ 1397int prepare_app_cache_dir(const std::string& parent, const char* name, mode_t target_mode, 1398 uid_t uid, gid_t gid) { 1399 auto path = StringPrintf("%s/%s", parent.c_str(), name); 1400 struct stat st; 1401 if (stat(path.c_str(), &st) != 0) { 1402 if (errno == ENOENT) { 1403 // This is fine, just create it 1404 if (fs_prepare_dir_strict(path.c_str(), target_mode, uid, gid) != 0) { 1405 PLOG(ERROR) << "Failed to prepare " << path; 1406 return -1; 1407 } else { 1408 return 0; 1409 } 1410 } else { 1411 PLOG(ERROR) << "Failed to stat " << path; 1412 return -1; 1413 } 1414 } 1415 1416 mode_t actual_mode = st.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO | S_ISGID); 1417 if (st.st_uid != uid) { 1418 // Mismatched UID is real trouble; we can't recover 1419 LOG(ERROR) << "Mismatched UID at " << path << ": found " << st.st_uid 1420 << " but expected " << uid; 1421 return -1; 1422 } else if (st.st_gid == gid && actual_mode == target_mode) { 1423 // Everything looks good! 1424 return 0; 1425 } 1426 1427 // Directory is owned correctly, but GID or mode mismatch means it's 1428 // probably a platform upgrade so we need to fix them 1429 FTS *fts; 1430 FTSENT *p; 1431 char *argv[] = { (char*) path.c_str(), nullptr }; 1432 if (!(fts = fts_open(argv, FTS_PHYSICAL | FTS_XDEV, NULL))) { 1433 PLOG(ERROR) << "Failed to fts_open " << path; 1434 return -1; 1435 } 1436 while ((p = fts_read(fts)) != NULL) { 1437 switch (p->fts_info) { 1438 case FTS_DP: 1439 if (chmod(p->fts_accpath, target_mode) != 0) { 1440 PLOG(WARNING) << "Failed to chmod " << p->fts_path; 1441 } 1442 // Intentional fall through to also set GID 1443 case FTS_F: 1444 if (chown(p->fts_accpath, -1, gid) != 0) { 1445 PLOG(WARNING) << "Failed to chown " << p->fts_path; 1446 } 1447 break; 1448 case FTS_SL: 1449 case FTS_SLNONE: 1450 if (lchown(p->fts_accpath, -1, gid) != 0) { 1451 PLOG(WARNING) << "Failed to chown " << p->fts_path; 1452 } 1453 break; 1454 } 1455 } 1456 fts_close(fts); 1457 return 0; 1458} 1459 1460} // namespace installd 1461} // namespace android 1462