utils.cpp revision 367ace2f77105f7a09b34a50bc875fd4fa591177
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 <cutils/properties.h> 37#include <log/log.h> 38#include <private/android_filesystem_config.h> 39 40#include "globals.h" // extern variables. 41 42#ifndef LOG_TAG 43#define LOG_TAG "installd" 44#endif 45 46#define CACHE_NOISY(x) //x 47#define DEBUG_XATTRS 0 48 49using android::base::StringPrintf; 50 51namespace android { 52namespace installd { 53 54/** 55 * Check that given string is valid filename, and that it attempts no 56 * parent or child directory traversal. 57 */ 58bool is_valid_filename(const std::string& name) { 59 if (name.empty() || (name == ".") || (name == "..") 60 || (name.find('/') != std::string::npos)) { 61 return false; 62 } else { 63 return true; 64 } 65} 66 67static void check_package_name(const char* package_name) { 68 CHECK(is_valid_filename(package_name)); 69 CHECK(is_valid_package_name(package_name)); 70} 71 72/** 73 * Create the path name where package app contents should be stored for 74 * the given volume UUID and package name. An empty UUID is assumed to 75 * be internal storage. 76 */ 77std::string create_data_app_package_path(const char* volume_uuid, 78 const char* package_name) { 79 check_package_name(package_name); 80 return StringPrintf("%s/%s", 81 create_data_app_path(volume_uuid).c_str(), package_name); 82} 83 84/** 85 * Create the path name where package data should be stored for the given 86 * volume UUID, package name, and user ID. An empty UUID is assumed to be 87 * internal storage. 88 */ 89std::string create_data_user_ce_package_path(const char* volume_uuid, 90 userid_t user, const char* package_name) { 91 check_package_name(package_name); 92 return StringPrintf("%s/%s", 93 create_data_user_ce_path(volume_uuid, user).c_str(), package_name); 94} 95 96std::string create_data_user_ce_package_path(const char* volume_uuid, userid_t user, 97 const char* package_name, ino_t ce_data_inode) { 98 // For testing purposes, rely on the inode when defined; this could be 99 // optimized to use access() in the future. 100 auto fallback = create_data_user_ce_package_path(volume_uuid, user, package_name); 101 if (ce_data_inode != 0) { 102 auto user_path = create_data_user_ce_path(volume_uuid, user); 103 DIR* dir = opendir(user_path.c_str()); 104 if (dir == nullptr) { 105 PLOG(ERROR) << "Failed to opendir " << user_path; 106 return fallback; 107 } 108 109 struct dirent* ent; 110 while ((ent = readdir(dir))) { 111 if (ent->d_ino == ce_data_inode) { 112 auto resolved = StringPrintf("%s/%s", user_path.c_str(), ent->d_name); 113#if DEBUG_XATTRS 114 if (resolved != fallback) { 115 LOG(DEBUG) << "Resolved path " << resolved << " for inode " << ce_data_inode 116 << " instead of " << fallback; 117 } 118#endif 119 closedir(dir); 120 return resolved; 121 } 122 } 123 LOG(WARNING) << "Failed to resolve inode " << ce_data_inode << "; using " << fallback; 124 closedir(dir); 125 return fallback; 126 } else { 127 return fallback; 128 } 129} 130 131std::string create_data_user_de_package_path(const char* volume_uuid, 132 userid_t user, const char* package_name) { 133 check_package_name(package_name); 134 return StringPrintf("%s/%s", 135 create_data_user_de_path(volume_uuid, user).c_str(), package_name); 136} 137 138int create_pkg_path(char path[PKG_PATH_MAX], const char *pkgname, 139 const char *postfix, userid_t userid) { 140 if (!is_valid_package_name(pkgname)) { 141 path[0] = '\0'; 142 return -1; 143 } 144 145 std::string _tmp(create_data_user_ce_package_path(nullptr, userid, pkgname) + postfix); 146 const char* tmp = _tmp.c_str(); 147 if (strlen(tmp) >= PKG_PATH_MAX) { 148 path[0] = '\0'; 149 return -1; 150 } else { 151 strcpy(path, tmp); 152 return 0; 153 } 154} 155 156std::string create_data_path(const char* volume_uuid) { 157 if (volume_uuid == nullptr) { 158 return "/data"; 159 } else if (!strcmp(volume_uuid, "TEST")) { 160 CHECK(property_get_bool("ro.debuggable", false)); 161 return "/data/local/tmp"; 162 } else { 163 CHECK(is_valid_filename(volume_uuid)); 164 return StringPrintf("/mnt/expand/%s", volume_uuid); 165 } 166} 167 168/** 169 * Create the path name for app data. 170 */ 171std::string create_data_app_path(const char* volume_uuid) { 172 return StringPrintf("%s/app", create_data_path(volume_uuid).c_str()); 173} 174 175/** 176 * Create the path name for user data for a certain userid. 177 */ 178std::string create_data_user_ce_path(const char* volume_uuid, userid_t userid) { 179 std::string data(create_data_path(volume_uuid)); 180 if (volume_uuid == nullptr) { 181 if (userid == 0) { 182 return StringPrintf("%s/data", data.c_str()); 183 } else { 184 return StringPrintf("%s/user/%u", data.c_str(), userid); 185 } 186 } else { 187 return StringPrintf("%s/user/%u", data.c_str(), userid); 188 } 189} 190 191/** 192 * Create the path name for device encrypted user data for a certain userid. 193 */ 194std::string create_data_user_de_path(const char* volume_uuid, userid_t userid) { 195 std::string data(create_data_path(volume_uuid)); 196 return StringPrintf("%s/user_de/%u", data.c_str(), userid); 197} 198 199/** 200 * Create the path name for media for a certain userid. 201 */ 202std::string create_data_media_path(const char* volume_uuid, userid_t userid) { 203 return StringPrintf("%s/media/%u", create_data_path(volume_uuid).c_str(), userid); 204} 205 206std::string create_data_media_obb_path(const char* volume_uuid, const char* package_name) { 207 return StringPrintf("%s/media/obb/%s", create_data_path(volume_uuid).c_str(), package_name); 208} 209 210std::string create_data_media_package_path(const char* volume_uuid, userid_t userid, 211 const char* data_type, const char* package_name) { 212 return StringPrintf("%s/Android/%s/%s", create_data_media_path(volume_uuid, userid).c_str(), 213 data_type, package_name); 214} 215 216std::string create_data_misc_legacy_path(userid_t userid) { 217 return StringPrintf("%s/misc/user/%u", create_data_path(nullptr).c_str(), userid); 218} 219 220std::string create_data_user_profile_path(userid_t userid) { 221 return StringPrintf("%s/cur/%u", android_profiles_dir.path, userid); 222} 223 224std::string create_data_user_profile_package_path(userid_t user, const char* package_name) { 225 check_package_name(package_name); 226 return StringPrintf("%s/%s",create_data_user_profile_path(user).c_str(), package_name); 227} 228 229std::string create_data_ref_profile_path() { 230 return StringPrintf("%s/ref", android_profiles_dir.path); 231} 232 233std::string create_data_ref_profile_package_path(const char* package_name) { 234 check_package_name(package_name); 235 return StringPrintf("%s/ref/%s", android_profiles_dir.path, package_name); 236} 237 238std::string create_data_dalvik_cache_path() { 239 return "/data/dalvik-cache"; 240} 241 242std::string create_data_misc_foreign_dex_path(userid_t userid) { 243 return StringPrintf("/data/misc/profiles/cur/%d/foreign-dex", userid); 244} 245 246// Keep profile paths in sync with ActivityThread. 247constexpr const char* PRIMARY_PROFILE_NAME = "primary.prof"; 248 249std::string create_primary_profile(const std::string& profile_dir) { 250 return StringPrintf("%s/%s", profile_dir.c_str(), PRIMARY_PROFILE_NAME); 251} 252 253std::vector<userid_t> get_known_users(const char* volume_uuid) { 254 std::vector<userid_t> users; 255 256 // We always have an owner 257 users.push_back(0); 258 259 std::string path(create_data_path(volume_uuid) + "/" + SECONDARY_USER_PREFIX); 260 DIR* dir = opendir(path.c_str()); 261 if (dir == NULL) { 262 // Unable to discover other users, but at least return owner 263 PLOG(ERROR) << "Failed to opendir " << path; 264 return users; 265 } 266 267 struct dirent* ent; 268 while ((ent = readdir(dir))) { 269 if (ent->d_type != DT_DIR) { 270 continue; 271 } 272 273 char* end; 274 userid_t user = strtol(ent->d_name, &end, 10); 275 if (*end == '\0' && user != 0) { 276 LOG(DEBUG) << "Found valid user " << user; 277 users.push_back(user); 278 } 279 } 280 closedir(dir); 281 282 return users; 283} 284 285int calculate_tree_size(const std::string& path, int64_t* size, 286 int32_t include_gid, int32_t exclude_gid, bool exclude_apps) { 287 FTS *fts; 288 FTSENT *p; 289 int64_t matchedSize = 0; 290 char *argv[] = { (char*) path.c_str(), nullptr }; 291 if (!(fts = fts_open(argv, FTS_PHYSICAL | FTS_XDEV, NULL))) { 292 if (errno != ENOENT) { 293 PLOG(ERROR) << "Failed to fts_open " << path; 294 } 295 return -1; 296 } 297 while ((p = fts_read(fts)) != NULL) { 298 switch (p->fts_info) { 299 case FTS_D: 300 case FTS_DEFAULT: 301 case FTS_F: 302 case FTS_SL: 303 case FTS_SLNONE: 304 int32_t uid = p->fts_statp->st_uid; 305 int32_t gid = p->fts_statp->st_gid; 306 int32_t user_uid = multiuser_get_app_id(uid); 307 int32_t user_gid = multiuser_get_app_id(gid); 308 if (exclude_apps && ((user_uid >= AID_APP_START && user_uid <= AID_APP_END) 309 || (user_gid >= AID_CACHE_GID_START && user_gid <= AID_CACHE_GID_END) 310 || (user_gid >= AID_SHARED_GID_START && user_gid <= AID_SHARED_GID_END))) { 311 // Don't traverse inside or measure 312 fts_set(fts, p, FTS_SKIP); 313 break; 314 } 315 if (include_gid != -1 && gid != include_gid) { 316 break; 317 } 318 if (exclude_gid != -1 && gid == exclude_gid) { 319 break; 320 } 321 matchedSize += (p->fts_statp->st_blocks * 512); 322 break; 323 } 324 } 325 fts_close(fts); 326#if MEASURE_DEBUG 327 if ((include_gid == -1) && (exclude_gid == -1)) { 328 LOG(DEBUG) << "Measured " << path << " size " << matchedSize; 329 } else { 330 LOG(DEBUG) << "Measured " << path << " size " << matchedSize << "; include " << include_gid 331 << " exclude " << exclude_gid; 332 } 333#endif 334 *size += matchedSize; 335 return 0; 336} 337 338int create_move_path(char path[PKG_PATH_MAX], 339 const char* pkgname, 340 const char* leaf, 341 userid_t userid ATTRIBUTE_UNUSED) 342{ 343 if ((android_data_dir.len + strlen(PRIMARY_USER_PREFIX) + strlen(pkgname) + strlen(leaf) + 1) 344 >= PKG_PATH_MAX) { 345 return -1; 346 } 347 348 sprintf(path, "%s%s%s/%s", android_data_dir.path, PRIMARY_USER_PREFIX, pkgname, leaf); 349 return 0; 350} 351 352/** 353 * Checks whether the package name is valid. Returns -1 on error and 354 * 0 on success. 355 */ 356bool is_valid_package_name(const std::string& packageName) { 357 // This logic is borrowed from PackageParser.java 358 bool hasSep = false; 359 bool front = true; 360 361 auto it = packageName.begin(); 362 for (; it != packageName.end() && *it != '-'; it++) { 363 char c = *it; 364 if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) { 365 front = false; 366 continue; 367 } 368 if (!front) { 369 if ((c >= '0' && c <= '9') || c == '_') { 370 continue; 371 } 372 } 373 if (c == '.') { 374 hasSep = true; 375 front = true; 376 continue; 377 } 378 LOG(WARNING) << "Bad package character " << c << " in " << packageName; 379 return false; 380 } 381 382 if (!hasSep || front) { 383 LOG(WARNING) << "Missing separator in " << packageName; 384 return false; 385 } 386 387 for (; it != packageName.end(); it++) { 388 char c = *it; 389 if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) continue; 390 if ((c >= '0' && c <= '9') || c == '_' || c == '-' || c == '=') continue; 391 LOG(WARNING) << "Bad suffix character " << c << " in " << packageName; 392 return false; 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 1006void add_preloads_file_cache(cache_t* cache, const char* volume_uuid) { 1007 char dirname[PATH_MAX]; 1008 DIR* subdir; 1009 auto cache_path = StringPrintf("%s/preloads/file_cache", create_data_path(volume_uuid).c_str()); 1010 strcpy(dirname, cache_path.c_str()); 1011 CACHE_NOISY(ALOGI("add_preloads_file_cache: dirname=%s\n", dirname)); 1012 subdir = opendir(dirname); 1013 if (subdir != NULL) { 1014 size_t dirnameLen = strlen(dirname); 1015 _add_cache_files(cache, NULL, dirname, subdir, dirname, dirname + dirnameLen, 1016 PATH_MAX - dirnameLen); 1017 closedir(subdir); 1018 } 1019} 1020 1021static char *create_dir_path(char path[PATH_MAX], cache_dir_t* dir) 1022{ 1023 char *pos = path; 1024 if (dir->parent != NULL) { 1025 pos = create_dir_path(path, dir->parent); 1026 } 1027 // Note that we don't need to worry about going beyond the buffer, 1028 // since when we were constructing the cache entries our maximum 1029 // buffer size for full paths was PATH_MAX. 1030 strcpy(pos, dir->name); 1031 pos += strlen(pos); 1032 *pos = '/'; 1033 pos++; 1034 *pos = 0; 1035 return pos; 1036} 1037 1038static void delete_cache_dir(char path[PATH_MAX], cache_dir_t* dir) 1039{ 1040 if (dir->parent != NULL) { 1041 create_dir_path(path, dir); 1042 ALOGI("DEL DIR %s\n", path); 1043 if (dir->hiddenCount <= 0) { 1044 if (rmdir(path)) { 1045 ALOGE("Couldn't rmdir %s: %s\n", path, strerror(errno)); 1046 return; 1047 } 1048 } else { 1049 // The directory contains hidden files so we need to delete 1050 // them along with the directory itself. 1051 if (delete_dir_contents(path, 1, NULL)) { 1052 return; 1053 } 1054 } 1055 dir->parent->childCount--; 1056 dir->deleted = 1; 1057 if (dir->parent->childCount <= 0) { 1058 delete_cache_dir(path, dir->parent); 1059 } 1060 } else if (dir->hiddenCount > 0) { 1061 // This is a root directory, but it has hidden files. Get rid of 1062 // all of those files, but not the directory itself. 1063 create_dir_path(path, dir); 1064 ALOGI("DEL CONTENTS %s\n", path); 1065 delete_dir_contents(path, 0, NULL); 1066 } 1067} 1068 1069static int cache_modtime_sort(const void *lhsP, const void *rhsP) 1070{ 1071 const cache_file_t *lhs = *(const cache_file_t**)lhsP; 1072 const cache_file_t *rhs = *(const cache_file_t**)rhsP; 1073 return lhs->modTime < rhs->modTime ? -1 : (lhs->modTime > rhs->modTime ? 1 : 0); 1074} 1075 1076void clear_cache_files(const std::string& data_path, cache_t* cache, int64_t free_size) 1077{ 1078 size_t i; 1079 int skip = 0; 1080 char path[PATH_MAX]; 1081 1082 ALOGI("Collected cache files: %zd directories, %zd files", 1083 cache->numDirs, cache->numFiles); 1084 1085 CACHE_NOISY(ALOGI("Sorting files...")); 1086 qsort(cache->files, cache->numFiles, sizeof(cache_file_t*), 1087 cache_modtime_sort); 1088 1089 CACHE_NOISY(ALOGI("Cleaning empty directories...")); 1090 for (i=cache->numDirs; i>0; i--) { 1091 cache_dir_t* dir = cache->dirs[i-1]; 1092 if (dir->childCount <= 0 && !dir->deleted) { 1093 delete_cache_dir(path, dir); 1094 } 1095 } 1096 1097 CACHE_NOISY(ALOGI("Trimming files...")); 1098 for (i=0; i<cache->numFiles; i++) { 1099 skip++; 1100 if (skip > 10) { 1101 if (data_disk_free(data_path) > free_size) { 1102 return; 1103 } 1104 skip = 0; 1105 } 1106 cache_file_t* file = cache->files[i]; 1107 strcpy(create_dir_path(path, file->dir), file->name); 1108 ALOGI("DEL (mod %d) %s\n", (int)file->modTime, path); 1109 if (unlink(path) < 0) { 1110 ALOGE("Couldn't unlink %s: %s\n", path, strerror(errno)); 1111 } 1112 file->dir->childCount--; 1113 if (file->dir->childCount <= 0) { 1114 delete_cache_dir(path, file->dir); 1115 } 1116 } 1117} 1118 1119void finish_cache_collection(cache_t* cache) 1120{ 1121 CACHE_NOISY(size_t i;) 1122 1123 CACHE_NOISY(ALOGI("clear_cache_files: %zu dirs, %zu files\n", cache->numDirs, cache->numFiles)); 1124 CACHE_NOISY( 1125 for (i=0; i<cache->numDirs; i++) { 1126 cache_dir_t* dir = cache->dirs[i]; 1127 ALOGI("dir #%zu: %p %s parent=%p\n", i, dir, dir->name, dir->parent); 1128 }) 1129 CACHE_NOISY( 1130 for (i=0; i<cache->numFiles; i++) { 1131 cache_file_t* file = cache->files[i]; 1132 ALOGI("file #%zu: %p %s time=%d dir=%p\n", i, file, file->name, 1133 (int)file->modTime, file->dir); 1134 }) 1135 void* block = cache->memBlocks; 1136 while (block != NULL) { 1137 void* nextBlock = *(void**)block; 1138 CACHE_NOISY(ALOGI("Freeing cache mem block: %p", block)); 1139 free(block); 1140 block = nextBlock; 1141 } 1142 free(cache); 1143} 1144 1145/** 1146 * Validate that the path is valid in the context of the provided directory. 1147 * The path is allowed to have at most one subdirectory and no indirections 1148 * to top level directories (i.e. have ".."). 1149 */ 1150static int validate_path(const dir_rec_t* dir, const char* path, int maxSubdirs) { 1151 size_t dir_len = dir->len; 1152 const char* subdir = strchr(path + dir_len, '/'); 1153 1154 // Only allow the path to have at most one subdirectory. 1155 if (subdir != NULL) { 1156 ++subdir; 1157 if ((--maxSubdirs == 0) && strchr(subdir, '/') != NULL) { 1158 ALOGE("invalid apk path '%s' (subdir?)\n", path); 1159 return -1; 1160 } 1161 } 1162 1163 // Directories can't have a period directly after the directory markers to prevent "..". 1164 if ((path[dir_len] == '.') || ((subdir != NULL) && (*subdir == '.'))) { 1165 ALOGE("invalid apk path '%s' (trickery)\n", path); 1166 return -1; 1167 } 1168 1169 return 0; 1170} 1171 1172/** 1173 * Checks whether a path points to a system app (.apk file). Returns 0 1174 * if it is a system app or -1 if it is not. 1175 */ 1176int validate_system_app_path(const char* path) { 1177 size_t i; 1178 1179 for (i = 0; i < android_system_dirs.count; i++) { 1180 const size_t dir_len = android_system_dirs.dirs[i].len; 1181 if (!strncmp(path, android_system_dirs.dirs[i].path, dir_len)) { 1182 return validate_path(android_system_dirs.dirs + i, path, 1); 1183 } 1184 } 1185 1186 return -1; 1187} 1188 1189bool validate_secondary_dex_path(const char* pkgname, const char* path, 1190 const char* volume_uuid, int uid, int storage_flag) { 1191 CHECK(storage_flag == FLAG_STORAGE_CE || storage_flag == FLAG_STORAGE_DE); 1192 1193 std::string app_private_dir = storage_flag == FLAG_STORAGE_CE 1194 ? create_data_user_ce_package_path(volume_uuid, multiuser_get_user_id(uid), pkgname) 1195 : create_data_user_de_package_path(volume_uuid, multiuser_get_user_id(uid), pkgname); 1196 dir_rec_t dir; 1197 if (get_path_from_string(&dir, app_private_dir.c_str()) != 0) { 1198 LOG(WARNING) << "Could not get dir rec for " << app_private_dir; 1199 return false; 1200 } 1201 // Usually secondary dex files have a nested directory structure. 1202 // Pick at most 10 subdirectories when validating (arbitrary value). 1203 // If the secondary dex file is >10 directory nested then validation will 1204 // fail and the file will not be compiled. 1205 return validate_path(&dir, path, /*max_subdirs*/ 10) == 0; 1206} 1207 1208/** 1209 * Get the contents of a environment variable that contains a path. Caller 1210 * owns the string that is inserted into the directory record. Returns 1211 * 0 on success and -1 on error. 1212 */ 1213int get_path_from_env(dir_rec_t* rec, const char* var) { 1214 const char* path = getenv(var); 1215 int ret = get_path_from_string(rec, path); 1216 if (ret < 0) { 1217 ALOGW("Problem finding value for environment variable %s\n", var); 1218 } 1219 return ret; 1220} 1221 1222/** 1223 * Puts the string into the record as a directory. Appends '/' to the end 1224 * of all paths. Caller owns the string that is inserted into the directory 1225 * record. A null value will result in an error. 1226 * 1227 * Returns 0 on success and -1 on error. 1228 */ 1229int get_path_from_string(dir_rec_t* rec, const char* path) { 1230 if (path == NULL) { 1231 return -1; 1232 } else { 1233 const size_t path_len = strlen(path); 1234 if (path_len <= 0) { 1235 return -1; 1236 } 1237 1238 // Make sure path is absolute. 1239 if (path[0] != '/') { 1240 return -1; 1241 } 1242 1243 if (path[path_len - 1] == '/') { 1244 // Path ends with a forward slash. Make our own copy. 1245 1246 rec->path = strdup(path); 1247 if (rec->path == NULL) { 1248 return -1; 1249 } 1250 1251 rec->len = path_len; 1252 } else { 1253 // Path does not end with a slash. Generate a new string. 1254 char *dst; 1255 1256 // Add space for slash and terminating null. 1257 size_t dst_size = path_len + 2; 1258 1259 rec->path = (char*) malloc(dst_size); 1260 if (rec->path == NULL) { 1261 return -1; 1262 } 1263 1264 dst = rec->path; 1265 1266 if (append_and_increment(&dst, path, &dst_size) < 0 1267 || append_and_increment(&dst, "/", &dst_size)) { 1268 ALOGE("Error canonicalizing path"); 1269 return -1; 1270 } 1271 1272 rec->len = dst - rec->path; 1273 } 1274 } 1275 return 0; 1276} 1277 1278int copy_and_append(dir_rec_t* dst, const dir_rec_t* src, const char* suffix) { 1279 dst->len = src->len + strlen(suffix); 1280 const size_t dstSize = dst->len + 1; 1281 dst->path = (char*) malloc(dstSize); 1282 1283 if (dst->path == NULL 1284 || snprintf(dst->path, dstSize, "%s%s", src->path, suffix) 1285 != (ssize_t) dst->len) { 1286 ALOGE("Could not allocate memory to hold appended path; aborting\n"); 1287 return -1; 1288 } 1289 1290 return 0; 1291} 1292 1293/** 1294 * Check whether path points to a valid path for an APK file. The path must 1295 * begin with a whitelisted prefix path and must be no deeper than |maxSubdirs| within 1296 * that path. Returns -1 when an invalid path is encountered and 0 when a valid path 1297 * is encountered. 1298 */ 1299static int validate_apk_path_internal(const char *path, int maxSubdirs) { 1300 const dir_rec_t* dir = NULL; 1301 if (!strncmp(path, android_app_dir.path, android_app_dir.len)) { 1302 dir = &android_app_dir; 1303 } else if (!strncmp(path, android_app_private_dir.path, android_app_private_dir.len)) { 1304 dir = &android_app_private_dir; 1305 } else if (!strncmp(path, android_app_ephemeral_dir.path, android_app_ephemeral_dir.len)) { 1306 dir = &android_app_ephemeral_dir; 1307 } else if (!strncmp(path, android_asec_dir.path, android_asec_dir.len)) { 1308 dir = &android_asec_dir; 1309 } else if (!strncmp(path, android_mnt_expand_dir.path, android_mnt_expand_dir.len)) { 1310 dir = &android_mnt_expand_dir; 1311 if (maxSubdirs < 2) { 1312 maxSubdirs = 2; 1313 } 1314 } else { 1315 return -1; 1316 } 1317 1318 return validate_path(dir, path, maxSubdirs); 1319} 1320 1321int validate_apk_path(const char* path) { 1322 return validate_apk_path_internal(path, 1 /* maxSubdirs */); 1323} 1324 1325int validate_apk_path_subdirs(const char* path) { 1326 return validate_apk_path_internal(path, 3 /* maxSubdirs */); 1327} 1328 1329int append_and_increment(char** dst, const char* src, size_t* dst_size) { 1330 ssize_t ret = strlcpy(*dst, src, *dst_size); 1331 if (ret < 0 || (size_t) ret >= *dst_size) { 1332 return -1; 1333 } 1334 *dst += ret; 1335 *dst_size -= ret; 1336 return 0; 1337} 1338 1339char *build_string2(const char *s1, const char *s2) { 1340 if (s1 == NULL || s2 == NULL) return NULL; 1341 1342 int len_s1 = strlen(s1); 1343 int len_s2 = strlen(s2); 1344 int len = len_s1 + len_s2 + 1; 1345 char *result = (char *) malloc(len); 1346 if (result == NULL) return NULL; 1347 1348 strcpy(result, s1); 1349 strcpy(result + len_s1, s2); 1350 1351 return result; 1352} 1353 1354char *build_string3(const char *s1, const char *s2, const char *s3) { 1355 if (s1 == NULL || s2 == NULL || s3 == NULL) return NULL; 1356 1357 int len_s1 = strlen(s1); 1358 int len_s2 = strlen(s2); 1359 int len_s3 = strlen(s3); 1360 int len = len_s1 + len_s2 + len_s3 + 1; 1361 char *result = (char *) malloc(len); 1362 if (result == NULL) return NULL; 1363 1364 strcpy(result, s1); 1365 strcpy(result + len_s1, s2); 1366 strcpy(result + len_s1 + len_s2, s3); 1367 1368 return result; 1369} 1370 1371int ensure_config_user_dirs(userid_t userid) { 1372 // writable by system, readable by any app within the same user 1373 const int uid = multiuser_get_uid(userid, AID_SYSTEM); 1374 const int gid = multiuser_get_uid(userid, AID_EVERYBODY); 1375 1376 // Ensure /data/misc/user/<userid> exists 1377 auto path = create_data_misc_legacy_path(userid); 1378 return fs_prepare_dir(path.c_str(), 0750, uid, gid); 1379} 1380 1381int wait_child(pid_t pid) 1382{ 1383 int status; 1384 pid_t got_pid; 1385 1386 while (1) { 1387 got_pid = waitpid(pid, &status, 0); 1388 if (got_pid == -1 && errno == EINTR) { 1389 printf("waitpid interrupted, retrying\n"); 1390 } else { 1391 break; 1392 } 1393 } 1394 if (got_pid != pid) { 1395 ALOGW("waitpid failed: wanted %d, got %d: %s\n", 1396 (int) pid, (int) got_pid, strerror(errno)); 1397 return 1; 1398 } 1399 1400 if (WIFEXITED(status) && WEXITSTATUS(status) == 0) { 1401 return 0; 1402 } else { 1403 return status; /* always nonzero */ 1404 } 1405} 1406 1407/** 1408 * Prepare an app cache directory, which offers to fix-up the GID and 1409 * directory mode flags during a platform upgrade. 1410 * The app cache directory path will be 'parent'/'name'. 1411 */ 1412int prepare_app_cache_dir(const std::string& parent, const char* name, mode_t target_mode, 1413 uid_t uid, gid_t gid) { 1414 auto path = StringPrintf("%s/%s", parent.c_str(), name); 1415 struct stat st; 1416 if (stat(path.c_str(), &st) != 0) { 1417 if (errno == ENOENT) { 1418 // This is fine, just create it 1419 if (fs_prepare_dir_strict(path.c_str(), target_mode, uid, gid) != 0) { 1420 PLOG(ERROR) << "Failed to prepare " << path; 1421 return -1; 1422 } else { 1423 return 0; 1424 } 1425 } else { 1426 PLOG(ERROR) << "Failed to stat " << path; 1427 return -1; 1428 } 1429 } 1430 1431 mode_t actual_mode = st.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO | S_ISGID); 1432 if (st.st_uid != uid) { 1433 // Mismatched UID is real trouble; we can't recover 1434 LOG(ERROR) << "Mismatched UID at " << path << ": found " << st.st_uid 1435 << " but expected " << uid; 1436 return -1; 1437 } else if (st.st_gid == gid && actual_mode == target_mode) { 1438 // Everything looks good! 1439 return 0; 1440 } 1441 1442 // Directory is owned correctly, but GID or mode mismatch means it's 1443 // probably a platform upgrade so we need to fix them 1444 FTS *fts; 1445 FTSENT *p; 1446 char *argv[] = { (char*) path.c_str(), nullptr }; 1447 if (!(fts = fts_open(argv, FTS_PHYSICAL | FTS_XDEV, NULL))) { 1448 PLOG(ERROR) << "Failed to fts_open " << path; 1449 return -1; 1450 } 1451 while ((p = fts_read(fts)) != NULL) { 1452 switch (p->fts_info) { 1453 case FTS_DP: 1454 if (chmod(p->fts_accpath, target_mode) != 0) { 1455 PLOG(WARNING) << "Failed to chmod " << p->fts_path; 1456 } 1457 // Intentional fall through to also set GID 1458 case FTS_F: 1459 if (chown(p->fts_accpath, -1, gid) != 0) { 1460 PLOG(WARNING) << "Failed to chown " << p->fts_path; 1461 } 1462 break; 1463 case FTS_SL: 1464 case FTS_SLNONE: 1465 if (lchown(p->fts_accpath, -1, gid) != 0) { 1466 PLOG(WARNING) << "Failed to chown " << p->fts_path; 1467 } 1468 break; 1469 } 1470 } 1471 fts_close(fts); 1472 return 0; 1473} 1474 1475} // namespace installd 1476} // namespace android 1477