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