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