1 /* 2 * Copyright (C) 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 <dirent.h> 18 #include <errno.h> 19 #include <fcntl.h> 20 #include <fts.h> 21 #include <mntent.h> 22 #include <stdio.h> 23 #include <stdlib.h> 24 #include <string.h> 25 #include <sys/ioctl.h> 26 #include <sys/mount.h> 27 #include <sys/stat.h> 28 #include <sys/types.h> 29 #include <sys/sysmacros.h> 30 #include <sys/wait.h> 31 #include <unistd.h> 32 33 #include <linux/kdev_t.h> 34 35 #define LOG_TAG "Vold" 36 37 #include <openssl/md5.h> 38 39 #include <android-base/logging.h> 40 #include <android-base/stringprintf.h> 41 #include <cutils/fs.h> 42 #include <cutils/log.h> 43 44 #include <selinux/android.h> 45 46 #include <sysutils/NetlinkEvent.h> 47 48 #include <private/android_filesystem_config.h> 49 50 #include "Benchmark.h" 51 #include "EmulatedVolume.h" 52 #include "VolumeManager.h" 53 #include "NetlinkManager.h" 54 #include "ResponseCode.h" 55 #include "Loop.h" 56 #include "fs/Ext4.h" 57 #include "fs/Vfat.h" 58 #include "Utils.h" 59 #include "Devmapper.h" 60 #include "Process.h" 61 #include "Asec.h" 62 #include "VoldUtil.h" 63 #include "cryptfs.h" 64 65 #define MASS_STORAGE_FILE_PATH "/sys/class/android_usb/android0/f_mass_storage/lun/file" 66 67 #define ROUND_UP_POWER_OF_2(number, po2) (((!!((number) & ((1U << (po2)) - 1))) << (po2))\ 68 + ((number) & (~((1U << (po2)) - 1)))) 69 70 using android::base::StringPrintf; 71 72 /* 73 * Path to external storage where *only* root can access ASEC image files 74 */ 75 const char *VolumeManager::SEC_ASECDIR_EXT = "/mnt/secure/asec"; 76 77 /* 78 * Path to internal storage where *only* root can access ASEC image files 79 */ 80 const char *VolumeManager::SEC_ASECDIR_INT = "/data/app-asec"; 81 82 /* 83 * Path to where secure containers are mounted 84 */ 85 const char *VolumeManager::ASECDIR = "/mnt/asec"; 86 87 /* 88 * Path to where OBBs are mounted 89 */ 90 const char *VolumeManager::LOOPDIR = "/mnt/obb"; 91 92 bool VolumeManager::shutting_down = false; 93 94 static const char* kPathUserMount = "/mnt/user"; 95 static const char* kPathVirtualDisk = "/data/misc/vold/virtual_disk"; 96 97 static const char* kPropVirtualDisk = "persist.sys.virtual_disk"; 98 99 /* 512MiB is large enough for testing purposes */ 100 static const unsigned int kSizeVirtualDisk = 536870912; 101 102 static const unsigned int kMajorBlockMmc = 179; 103 static const unsigned int kMajorBlockExperimentalMin = 240; 104 static const unsigned int kMajorBlockExperimentalMax = 254; 105 106 /* writes superblock at end of file or device given by name */ 107 static int writeSuperBlock(const char* name, struct asec_superblock *sb, unsigned int numImgSectors) { 108 int sbfd = open(name, O_RDWR | O_CLOEXEC); 109 if (sbfd < 0) { 110 SLOGE("Failed to open %s for superblock write (%s)", name, strerror(errno)); 111 return -1; 112 } 113 114 if (lseek(sbfd, (numImgSectors * 512), SEEK_SET) < 0) { 115 SLOGE("Failed to lseek for superblock (%s)", strerror(errno)); 116 close(sbfd); 117 return -1; 118 } 119 120 if (write(sbfd, sb, sizeof(struct asec_superblock)) != sizeof(struct asec_superblock)) { 121 SLOGE("Failed to write superblock (%s)", strerror(errno)); 122 close(sbfd); 123 return -1; 124 } 125 close(sbfd); 126 return 0; 127 } 128 129 static unsigned long adjustSectorNumExt4(unsigned long numSectors) { 130 // Ext4 started to reserve 2% or 4096 clusters, whichever is smaller for 131 // preventing costly operations or unexpected ENOSPC error. 132 // Ext4::format() uses default block size without clustering. 133 unsigned long clusterSectors = 4096 / 512; 134 unsigned long reservedSectors = (numSectors * 2)/100 + (numSectors % 50 > 0); 135 numSectors += reservedSectors > (4096 * clusterSectors) ? (4096 * clusterSectors) : reservedSectors; 136 return ROUND_UP_POWER_OF_2(numSectors, 3); 137 } 138 139 static unsigned long adjustSectorNumFAT(unsigned long numSectors) { 140 /* 141 * Add some headroom 142 */ 143 unsigned long fatSize = (((numSectors * 4) / 512) + 1) * 2; 144 numSectors += fatSize + 2; 145 /* 146 * FAT is aligned to 32 kb with 512b sectors. 147 */ 148 return ROUND_UP_POWER_OF_2(numSectors, 6); 149 } 150 151 static int setupLoopDevice(char* buffer, size_t len, const char* asecFileName, const char* idHash, bool debug) { 152 if (Loop::lookupActive(idHash, buffer, len)) { 153 if (Loop::create(idHash, asecFileName, buffer, len)) { 154 SLOGE("ASEC loop device creation failed for %s (%s)", asecFileName, strerror(errno)); 155 return -1; 156 } 157 if (debug) { 158 SLOGD("New loop device created at %s", buffer); 159 } 160 } else { 161 if (debug) { 162 SLOGD("Found active loopback for %s at %s", asecFileName, buffer); 163 } 164 } 165 return 0; 166 } 167 168 static int setupDevMapperDevice(char* buffer, size_t len, const char* loopDevice, const char* asecFileName, const char* key, const char* idHash , unsigned long numImgSectors, bool* createdDMDevice, bool debug) { 169 if (strcmp(key, "none")) { 170 if (Devmapper::lookupActive(idHash, buffer, len)) { 171 if (Devmapper::create(idHash, loopDevice, key, numImgSectors, 172 buffer, len)) { 173 SLOGE("ASEC device mapping failed for %s (%s)", asecFileName, strerror(errno)); 174 return -1; 175 } 176 if (debug) { 177 SLOGD("New devmapper instance created at %s", buffer); 178 } 179 } else { 180 if (debug) { 181 SLOGD("Found active devmapper for %s at %s", asecFileName, buffer); 182 } 183 } 184 *createdDMDevice = true; 185 } else { 186 strlcpy(buffer, loopDevice, len); 187 *createdDMDevice = false; 188 } 189 return 0; 190 } 191 192 static void waitForDevMapper(const char *dmDevice) { 193 /* 194 * Wait for the device mapper node to be created. Sometimes it takes a 195 * while. Wait for up to 1 second. We could also inspect incoming uevents, 196 * but that would take more effort. 197 */ 198 int tries = 25; 199 while (tries--) { 200 if (!access(dmDevice, F_OK) || errno != ENOENT) { 201 break; 202 } 203 usleep(40 * 1000); 204 } 205 } 206 207 VolumeManager *VolumeManager::sInstance = NULL; 208 209 VolumeManager *VolumeManager::Instance() { 210 if (!sInstance) 211 sInstance = new VolumeManager(); 212 return sInstance; 213 } 214 215 VolumeManager::VolumeManager() { 216 mDebug = false; 217 mActiveContainers = new AsecIdCollection(); 218 mBroadcaster = NULL; 219 mUmsSharingCount = 0; 220 mSavedDirtyRatio = -1; 221 // set dirty ratio to 0 when UMS is active 222 mUmsDirtyRatio = 0; 223 } 224 225 VolumeManager::~VolumeManager() { 226 delete mActiveContainers; 227 } 228 229 char *VolumeManager::asecHash(const char *id, char *buffer, size_t len) { 230 static const char* digits = "0123456789abcdef"; 231 232 unsigned char sig[MD5_DIGEST_LENGTH]; 233 234 if (buffer == NULL) { 235 SLOGE("Destination buffer is NULL"); 236 errno = ESPIPE; 237 return NULL; 238 } else if (id == NULL) { 239 SLOGE("Source buffer is NULL"); 240 errno = ESPIPE; 241 return NULL; 242 } else if (len < MD5_ASCII_LENGTH_PLUS_NULL) { 243 SLOGE("Target hash buffer size < %d bytes (%zu)", 244 MD5_ASCII_LENGTH_PLUS_NULL, len); 245 errno = ESPIPE; 246 return NULL; 247 } 248 249 MD5(reinterpret_cast<const unsigned char*>(id), strlen(id), sig); 250 251 char *p = buffer; 252 for (int i = 0; i < MD5_DIGEST_LENGTH; i++) { 253 *p++ = digits[sig[i] >> 4]; 254 *p++ = digits[sig[i] & 0x0F]; 255 } 256 *p = '\0'; 257 258 return buffer; 259 } 260 261 int VolumeManager::updateVirtualDisk() { 262 if (property_get_bool(kPropVirtualDisk, false)) { 263 if (access(kPathVirtualDisk, F_OK) != 0) { 264 Loop::createImageFile(kPathVirtualDisk, kSizeVirtualDisk / 512); 265 } 266 267 if (mVirtualDisk == nullptr) { 268 if (Loop::create(kPathVirtualDisk, mVirtualDiskPath) != 0) { 269 LOG(ERROR) << "Failed to create virtual disk"; 270 return -1; 271 } 272 273 struct stat buf; 274 if (stat(mVirtualDiskPath.c_str(), &buf) < 0) { 275 PLOG(ERROR) << "Failed to stat " << mVirtualDiskPath; 276 return -1; 277 } 278 279 auto disk = new android::vold::Disk("virtual", buf.st_rdev, "virtual", 280 android::vold::Disk::Flags::kAdoptable | android::vold::Disk::Flags::kSd); 281 disk->create(); 282 mVirtualDisk = std::shared_ptr<android::vold::Disk>(disk); 283 mDisks.push_back(mVirtualDisk); 284 } 285 } else { 286 if (mVirtualDisk != nullptr) { 287 dev_t device = mVirtualDisk->getDevice(); 288 289 auto i = mDisks.begin(); 290 while (i != mDisks.end()) { 291 if ((*i)->getDevice() == device) { 292 (*i)->destroy(); 293 i = mDisks.erase(i); 294 } else { 295 ++i; 296 } 297 } 298 299 Loop::destroyByDevice(mVirtualDiskPath.c_str()); 300 mVirtualDisk = nullptr; 301 } 302 303 if (access(kPathVirtualDisk, F_OK) == 0) { 304 unlink(kPathVirtualDisk); 305 } 306 } 307 return 0; 308 } 309 310 int VolumeManager::setDebug(bool enable) { 311 mDebug = enable; 312 return 0; 313 } 314 315 int VolumeManager::start() { 316 // Always start from a clean slate by unmounting everything in 317 // directories that we own, in case we crashed. 318 unmountAll(); 319 320 // Assume that we always have an emulated volume on internal 321 // storage; the framework will decide if it should be mounted. 322 CHECK(mInternalEmulated == nullptr); 323 mInternalEmulated = std::shared_ptr<android::vold::VolumeBase>( 324 new android::vold::EmulatedVolume("/data/media")); 325 mInternalEmulated->create(); 326 327 // Consider creating a virtual disk 328 updateVirtualDisk(); 329 330 return 0; 331 } 332 333 int VolumeManager::stop() { 334 CHECK(mInternalEmulated != nullptr); 335 mInternalEmulated->destroy(); 336 mInternalEmulated = nullptr; 337 return 0; 338 } 339 340 void VolumeManager::handleBlockEvent(NetlinkEvent *evt) { 341 std::lock_guard<std::mutex> lock(mLock); 342 343 if (mDebug) { 344 LOG(VERBOSE) << "----------------"; 345 LOG(VERBOSE) << "handleBlockEvent with action " << (int) evt->getAction(); 346 evt->dump(); 347 } 348 349 std::string eventPath(evt->findParam("DEVPATH")?evt->findParam("DEVPATH"):""); 350 std::string devType(evt->findParam("DEVTYPE")?evt->findParam("DEVTYPE"):""); 351 352 if (devType != "disk") return; 353 354 int major = atoi(evt->findParam("MAJOR")); 355 int minor = atoi(evt->findParam("MINOR")); 356 dev_t device = makedev(major, minor); 357 358 switch (evt->getAction()) { 359 case NetlinkEvent::Action::kAdd: { 360 for (const auto& source : mDiskSources) { 361 if (source->matches(eventPath)) { 362 // For now, assume that MMC and virtio-blk (the latter is 363 // emulator-specific; see Disk.cpp for details) devices are SD, 364 // and that everything else is USB 365 int flags = source->getFlags(); 366 if (major == kMajorBlockMmc 367 || (android::vold::IsRunningInEmulator() 368 && major >= (int) kMajorBlockExperimentalMin 369 && major <= (int) kMajorBlockExperimentalMax)) { 370 flags |= android::vold::Disk::Flags::kSd; 371 } else { 372 flags |= android::vold::Disk::Flags::kUsb; 373 } 374 375 auto disk = new android::vold::Disk(eventPath, device, 376 source->getNickname(), flags); 377 disk->create(); 378 mDisks.push_back(std::shared_ptr<android::vold::Disk>(disk)); 379 break; 380 } 381 } 382 break; 383 } 384 case NetlinkEvent::Action::kChange: { 385 LOG(DEBUG) << "Disk at " << major << ":" << minor << " changed"; 386 for (const auto& disk : mDisks) { 387 if (disk->getDevice() == device) { 388 disk->readMetadata(); 389 disk->readPartitions(); 390 } 391 } 392 break; 393 } 394 case NetlinkEvent::Action::kRemove: { 395 auto i = mDisks.begin(); 396 while (i != mDisks.end()) { 397 if ((*i)->getDevice() == device) { 398 (*i)->destroy(); 399 i = mDisks.erase(i); 400 } else { 401 ++i; 402 } 403 } 404 break; 405 } 406 default: { 407 LOG(WARNING) << "Unexpected block event action " << (int) evt->getAction(); 408 break; 409 } 410 } 411 } 412 413 void VolumeManager::addDiskSource(const std::shared_ptr<DiskSource>& diskSource) { 414 std::lock_guard<std::mutex> lock(mLock); 415 mDiskSources.push_back(diskSource); 416 } 417 418 std::shared_ptr<android::vold::Disk> VolumeManager::findDisk(const std::string& id) { 419 for (auto disk : mDisks) { 420 if (disk->getId() == id) { 421 return disk; 422 } 423 } 424 return nullptr; 425 } 426 427 std::shared_ptr<android::vold::VolumeBase> VolumeManager::findVolume(const std::string& id) { 428 // Vold could receive "mount" after "shutdown" command in the extreme case. 429 // If this happens, mInternalEmulated will equal nullptr and 430 // we need to deal with it in order to avoid null pointer crash. 431 if (mInternalEmulated != nullptr && mInternalEmulated->getId() == id) { 432 return mInternalEmulated; 433 } 434 for (const auto& disk : mDisks) { 435 auto vol = disk->findVolume(id); 436 if (vol != nullptr) { 437 return vol; 438 } 439 } 440 return nullptr; 441 } 442 443 void VolumeManager::listVolumes(android::vold::VolumeBase::Type type, 444 std::list<std::string>& list) { 445 list.clear(); 446 for (const auto& disk : mDisks) { 447 disk->listVolumes(type, list); 448 } 449 } 450 451 nsecs_t VolumeManager::benchmarkPrivate(const std::string& id) { 452 std::string path; 453 if (id == "private" || id == "null") { 454 path = "/data"; 455 } else { 456 auto vol = findVolume(id); 457 if (vol != nullptr && vol->getState() == android::vold::VolumeBase::State::kMounted) { 458 path = vol->getPath(); 459 } 460 } 461 462 if (path.empty()) { 463 LOG(WARNING) << "Failed to find volume for " << id; 464 return -1; 465 } 466 467 return android::vold::BenchmarkPrivate(path); 468 } 469 470 int VolumeManager::forgetPartition(const std::string& partGuid) { 471 std::string normalizedGuid; 472 if (android::vold::NormalizeHex(partGuid, normalizedGuid)) { 473 LOG(WARNING) << "Invalid GUID " << partGuid; 474 return -1; 475 } 476 477 std::string keyPath = android::vold::BuildKeyPath(normalizedGuid); 478 if (unlink(keyPath.c_str()) != 0) { 479 LOG(ERROR) << "Failed to unlink " << keyPath; 480 return -1; 481 } 482 483 return 0; 484 } 485 486 int VolumeManager::linkPrimary(userid_t userId) { 487 std::string source(mPrimary->getPath()); 488 if (mPrimary->getType() == android::vold::VolumeBase::Type::kEmulated) { 489 source = StringPrintf("%s/%d", source.c_str(), userId); 490 fs_prepare_dir(source.c_str(), 0755, AID_ROOT, AID_ROOT); 491 } 492 493 std::string target(StringPrintf("/mnt/user/%d/primary", userId)); 494 if (TEMP_FAILURE_RETRY(unlink(target.c_str()))) { 495 if (errno != ENOENT) { 496 SLOGW("Failed to unlink %s: %s", target.c_str(), strerror(errno)); 497 } 498 } 499 LOG(DEBUG) << "Linking " << source << " to " << target; 500 if (TEMP_FAILURE_RETRY(symlink(source.c_str(), target.c_str()))) { 501 SLOGW("Failed to link %s to %s: %s", source.c_str(), target.c_str(), 502 strerror(errno)); 503 return -errno; 504 } 505 return 0; 506 } 507 508 int VolumeManager::onUserAdded(userid_t userId, int userSerialNumber) { 509 mAddedUsers[userId] = userSerialNumber; 510 return 0; 511 } 512 513 int VolumeManager::onUserRemoved(userid_t userId) { 514 mAddedUsers.erase(userId); 515 return 0; 516 } 517 518 int VolumeManager::onUserStarted(userid_t userId) { 519 // Note that sometimes the system will spin up processes from Zygote 520 // before actually starting the user, so we're okay if Zygote 521 // already created this directory. 522 std::string path(StringPrintf("%s/%d", kPathUserMount, userId)); 523 fs_prepare_dir(path.c_str(), 0755, AID_ROOT, AID_ROOT); 524 525 mStartedUsers.insert(userId); 526 if (mPrimary) { 527 linkPrimary(userId); 528 } 529 return 0; 530 } 531 532 int VolumeManager::onUserStopped(userid_t userId) { 533 mStartedUsers.erase(userId); 534 return 0; 535 } 536 537 int VolumeManager::setPrimary(const std::shared_ptr<android::vold::VolumeBase>& vol) { 538 mPrimary = vol; 539 for (userid_t userId : mStartedUsers) { 540 linkPrimary(userId); 541 } 542 return 0; 543 } 544 545 static int unmount_tree(const char* path) { 546 size_t path_len = strlen(path); 547 548 FILE* fp = setmntent("/proc/mounts", "r"); 549 if (fp == NULL) { 550 ALOGE("Error opening /proc/mounts: %s", strerror(errno)); 551 return -errno; 552 } 553 554 // Some volumes can be stacked on each other, so force unmount in 555 // reverse order to give us the best chance of success. 556 std::list<std::string> toUnmount; 557 mntent* mentry; 558 while ((mentry = getmntent(fp)) != NULL) { 559 if (strncmp(mentry->mnt_dir, path, path_len) == 0) { 560 toUnmount.push_front(std::string(mentry->mnt_dir)); 561 } 562 } 563 endmntent(fp); 564 565 for (const auto& path : toUnmount) { 566 if (umount2(path.c_str(), MNT_DETACH)) { 567 ALOGW("Failed to unmount %s: %s", path.c_str(), strerror(errno)); 568 } 569 } 570 return 0; 571 } 572 573 int VolumeManager::remountUid(uid_t uid, const std::string& mode) { 574 LOG(DEBUG) << "Remounting " << uid << " as mode " << mode; 575 576 DIR* dir; 577 struct dirent* de; 578 char rootName[PATH_MAX]; 579 char pidName[PATH_MAX]; 580 int pidFd; 581 int nsFd; 582 struct stat sb; 583 pid_t child; 584 585 if (!(dir = opendir("/proc"))) { 586 PLOG(ERROR) << "Failed to opendir"; 587 return -1; 588 } 589 590 // Figure out root namespace to compare against below 591 if (android::vold::SaneReadLinkAt(dirfd(dir), "1/ns/mnt", rootName, PATH_MAX) == -1) { 592 PLOG(ERROR) << "Failed to readlink"; 593 closedir(dir); 594 return -1; 595 } 596 597 // Poke through all running PIDs look for apps running as UID 598 while ((de = readdir(dir))) { 599 pidFd = -1; 600 nsFd = -1; 601 602 pidFd = openat(dirfd(dir), de->d_name, O_RDONLY | O_DIRECTORY | O_CLOEXEC); 603 if (pidFd < 0) { 604 goto next; 605 } 606 if (fstat(pidFd, &sb) != 0) { 607 PLOG(WARNING) << "Failed to stat " << de->d_name; 608 goto next; 609 } 610 if (sb.st_uid != uid) { 611 goto next; 612 } 613 614 // Matches so far, but refuse to touch if in root namespace 615 LOG(DEBUG) << "Found matching PID " << de->d_name; 616 if (android::vold::SaneReadLinkAt(pidFd, "ns/mnt", pidName, PATH_MAX) == -1) { 617 PLOG(WARNING) << "Failed to read namespace for " << de->d_name; 618 goto next; 619 } 620 if (!strcmp(rootName, pidName)) { 621 LOG(WARNING) << "Skipping due to root namespace"; 622 goto next; 623 } 624 625 // We purposefully leave the namespace open across the fork 626 nsFd = openat(pidFd, "ns/mnt", O_RDONLY); // not O_CLOEXEC 627 if (nsFd < 0) { 628 PLOG(WARNING) << "Failed to open namespace for " << de->d_name; 629 goto next; 630 } 631 632 if (!(child = fork())) { 633 if (setns(nsFd, CLONE_NEWNS) != 0) { 634 PLOG(ERROR) << "Failed to setns for " << de->d_name; 635 _exit(1); 636 } 637 638 unmount_tree("/storage"); 639 640 std::string storageSource; 641 if (mode == "default") { 642 storageSource = "/mnt/runtime/default"; 643 } else if (mode == "read") { 644 storageSource = "/mnt/runtime/read"; 645 } else if (mode == "write") { 646 storageSource = "/mnt/runtime/write"; 647 } else { 648 // Sane default of no storage visible 649 _exit(0); 650 } 651 if (TEMP_FAILURE_RETRY(mount(storageSource.c_str(), "/storage", 652 NULL, MS_BIND | MS_REC, NULL)) == -1) { 653 PLOG(ERROR) << "Failed to mount " << storageSource << " for " 654 << de->d_name; 655 _exit(1); 656 } 657 if (TEMP_FAILURE_RETRY(mount(NULL, "/storage", NULL, 658 MS_REC | MS_SLAVE, NULL)) == -1) { 659 PLOG(ERROR) << "Failed to set MS_SLAVE to /storage for " 660 << de->d_name; 661 _exit(1); 662 } 663 664 // Mount user-specific symlink helper into place 665 userid_t user_id = multiuser_get_user_id(uid); 666 std::string userSource(StringPrintf("/mnt/user/%d", user_id)); 667 if (TEMP_FAILURE_RETRY(mount(userSource.c_str(), "/storage/self", 668 NULL, MS_BIND, NULL)) == -1) { 669 PLOG(ERROR) << "Failed to mount " << userSource << " for " 670 << de->d_name; 671 _exit(1); 672 } 673 674 _exit(0); 675 } 676 677 if (child == -1) { 678 PLOG(ERROR) << "Failed to fork"; 679 goto next; 680 } else { 681 TEMP_FAILURE_RETRY(waitpid(child, nullptr, 0)); 682 } 683 684 next: 685 close(nsFd); 686 close(pidFd); 687 } 688 closedir(dir); 689 return 0; 690 } 691 692 int VolumeManager::reset() { 693 // Tear down all existing disks/volumes and start from a blank slate so 694 // newly connected framework hears all events. 695 if (mInternalEmulated != nullptr) { 696 mInternalEmulated->destroy(); 697 mInternalEmulated->create(); 698 } 699 for (const auto& disk : mDisks) { 700 disk->destroy(); 701 disk->create(); 702 } 703 updateVirtualDisk(); 704 mAddedUsers.clear(); 705 mStartedUsers.clear(); 706 return 0; 707 } 708 709 // Can be called twice (sequentially) during shutdown. should be safe for that. 710 int VolumeManager::shutdown() { 711 if (mInternalEmulated == nullptr) { 712 return 0; // already shutdown 713 } 714 shutting_down = true; 715 mInternalEmulated->destroy(); 716 mInternalEmulated = nullptr; 717 for (const auto& disk : mDisks) { 718 disk->destroy(); 719 } 720 mDisks.clear(); 721 shutting_down = false; 722 return 0; 723 } 724 725 int VolumeManager::unmountAll() { 726 std::lock_guard<std::mutex> lock(mLock); 727 728 // First, try gracefully unmounting all known devices 729 if (mInternalEmulated != nullptr) { 730 mInternalEmulated->unmount(); 731 } 732 for (const auto& disk : mDisks) { 733 disk->unmountAll(); 734 } 735 736 // Worst case we might have some stale mounts lurking around, so 737 // force unmount those just to be safe. 738 FILE* fp = setmntent("/proc/mounts", "r"); 739 if (fp == NULL) { 740 SLOGE("Error opening /proc/mounts: %s", strerror(errno)); 741 return -errno; 742 } 743 744 // Some volumes can be stacked on each other, so force unmount in 745 // reverse order to give us the best chance of success. 746 std::list<std::string> toUnmount; 747 mntent* mentry; 748 while ((mentry = getmntent(fp)) != NULL) { 749 if (strncmp(mentry->mnt_dir, "/mnt/", 5) == 0 750 || strncmp(mentry->mnt_dir, "/storage/", 9) == 0) { 751 toUnmount.push_front(std::string(mentry->mnt_dir)); 752 } 753 } 754 endmntent(fp); 755 756 for (const auto& path : toUnmount) { 757 SLOGW("Tearing down stale mount %s", path.c_str()); 758 android::vold::ForceUnmount(path); 759 } 760 761 return 0; 762 } 763 764 int VolumeManager::getObbMountPath(const char *sourceFile, char *mountPath, int mountPathLen) { 765 char idHash[33]; 766 if (!asecHash(sourceFile, idHash, sizeof(idHash))) { 767 SLOGE("Hash of '%s' failed (%s)", sourceFile, strerror(errno)); 768 return -1; 769 } 770 771 memset(mountPath, 0, mountPathLen); 772 int written = snprintf(mountPath, mountPathLen, "%s/%s", VolumeManager::LOOPDIR, idHash); 773 if ((written < 0) || (written >= mountPathLen)) { 774 errno = EINVAL; 775 return -1; 776 } 777 778 if (access(mountPath, F_OK)) { 779 errno = ENOENT; 780 return -1; 781 } 782 783 return 0; 784 } 785 786 int VolumeManager::getAsecMountPath(const char *id, char *buffer, int maxlen) { 787 char asecFileName[255]; 788 789 if (!isLegalAsecId(id)) { 790 SLOGE("getAsecMountPath: Invalid asec id \"%s\"", id); 791 errno = EINVAL; 792 return -1; 793 } 794 795 if (findAsec(id, asecFileName, sizeof(asecFileName))) { 796 SLOGE("Couldn't find ASEC %s", id); 797 return -1; 798 } 799 800 memset(buffer, 0, maxlen); 801 if (access(asecFileName, F_OK)) { 802 errno = ENOENT; 803 return -1; 804 } 805 806 int written = snprintf(buffer, maxlen, "%s/%s", VolumeManager::ASECDIR, id); 807 if ((written < 0) || (written >= maxlen)) { 808 SLOGE("getAsecMountPath failed for %s: couldn't construct path in buffer", id); 809 errno = EINVAL; 810 return -1; 811 } 812 813 return 0; 814 } 815 816 int VolumeManager::getAsecFilesystemPath(const char *id, char *buffer, int maxlen) { 817 char asecFileName[255]; 818 819 if (!isLegalAsecId(id)) { 820 SLOGE("getAsecFilesystemPath: Invalid asec id \"%s\"", id); 821 errno = EINVAL; 822 return -1; 823 } 824 825 if (findAsec(id, asecFileName, sizeof(asecFileName))) { 826 SLOGE("Couldn't find ASEC %s", id); 827 return -1; 828 } 829 830 memset(buffer, 0, maxlen); 831 if (access(asecFileName, F_OK)) { 832 errno = ENOENT; 833 return -1; 834 } 835 836 int written = snprintf(buffer, maxlen, "%s", asecFileName); 837 if ((written < 0) || (written >= maxlen)) { 838 errno = EINVAL; 839 return -1; 840 } 841 842 return 0; 843 } 844 845 int VolumeManager::createAsec(const char *id, unsigned long numSectors, const char *fstype, 846 const char *key, const int ownerUid, bool isExternal) { 847 struct asec_superblock sb; 848 memset(&sb, 0, sizeof(sb)); 849 850 if (!isLegalAsecId(id)) { 851 SLOGE("createAsec: Invalid asec id \"%s\"", id); 852 errno = EINVAL; 853 return -1; 854 } 855 856 const bool wantFilesystem = strcmp(fstype, "none"); 857 bool usingExt4 = false; 858 if (wantFilesystem) { 859 usingExt4 = !strcmp(fstype, "ext4"); 860 if (usingExt4) { 861 sb.c_opts |= ASEC_SB_C_OPTS_EXT4; 862 } else if (strcmp(fstype, "fat")) { 863 SLOGE("Invalid filesystem type %s", fstype); 864 errno = EINVAL; 865 return -1; 866 } 867 } 868 869 sb.magic = ASEC_SB_MAGIC; 870 sb.ver = ASEC_SB_VER; 871 872 if (numSectors < ((1024*1024)/512)) { 873 SLOGE("Invalid container size specified (%lu sectors)", numSectors); 874 errno = EINVAL; 875 return -1; 876 } 877 878 char asecFileName[255]; 879 880 if (!findAsec(id, asecFileName, sizeof(asecFileName))) { 881 SLOGE("ASEC file '%s' currently exists - destroy it first! (%s)", 882 asecFileName, strerror(errno)); 883 errno = EADDRINUSE; 884 return -1; 885 } 886 887 const char *asecDir = isExternal ? VolumeManager::SEC_ASECDIR_EXT : VolumeManager::SEC_ASECDIR_INT; 888 889 int written = snprintf(asecFileName, sizeof(asecFileName), "%s/%s.asec", asecDir, id); 890 if ((written < 0) || (size_t(written) >= sizeof(asecFileName))) { 891 errno = EINVAL; 892 return -1; 893 } 894 895 if (!access(asecFileName, F_OK)) { 896 SLOGE("ASEC file '%s' currently exists - destroy it first! (%s)", 897 asecFileName, strerror(errno)); 898 errno = EADDRINUSE; 899 return -1; 900 } 901 902 unsigned long numImgSectors; 903 if (usingExt4) 904 numImgSectors = adjustSectorNumExt4(numSectors); 905 else 906 numImgSectors = adjustSectorNumFAT(numSectors); 907 908 // Add +1 for our superblock which is at the end 909 if (Loop::createImageFile(asecFileName, numImgSectors + 1)) { 910 SLOGE("ASEC image file creation failed (%s)", strerror(errno)); 911 return -1; 912 } 913 914 char idHash[33]; 915 if (!asecHash(id, idHash, sizeof(idHash))) { 916 SLOGE("Hash of '%s' failed (%s)", id, strerror(errno)); 917 unlink(asecFileName); 918 return -1; 919 } 920 921 char loopDevice[255]; 922 if (Loop::create(idHash, asecFileName, loopDevice, sizeof(loopDevice))) { 923 SLOGE("ASEC loop device creation failed (%s)", strerror(errno)); 924 unlink(asecFileName); 925 return -1; 926 } 927 928 char dmDevice[255]; 929 bool cleanupDm = false; 930 931 if (strcmp(key, "none")) { 932 // XXX: This is all we support for now 933 sb.c_cipher = ASEC_SB_C_CIPHER_TWOFISH; 934 if (Devmapper::create(idHash, loopDevice, key, numImgSectors, dmDevice, 935 sizeof(dmDevice))) { 936 SLOGE("ASEC device mapping failed (%s)", strerror(errno)); 937 Loop::destroyByDevice(loopDevice); 938 unlink(asecFileName); 939 return -1; 940 } 941 cleanupDm = true; 942 } else { 943 sb.c_cipher = ASEC_SB_C_CIPHER_NONE; 944 strlcpy(dmDevice, loopDevice, sizeof(dmDevice)); 945 } 946 947 /* 948 * Drop down the superblock at the end of the file 949 */ 950 if (writeSuperBlock(loopDevice, &sb, numImgSectors)) { 951 if (cleanupDm) { 952 Devmapper::destroy(idHash); 953 } 954 Loop::destroyByDevice(loopDevice); 955 unlink(asecFileName); 956 return -1; 957 } 958 959 if (wantFilesystem) { 960 int formatStatus; 961 char mountPoint[255]; 962 963 int written = snprintf(mountPoint, sizeof(mountPoint), "%s/%s", VolumeManager::ASECDIR, id); 964 if ((written < 0) || (size_t(written) >= sizeof(mountPoint))) { 965 SLOGE("ASEC fs format failed: couldn't construct mountPoint"); 966 if (cleanupDm) { 967 Devmapper::destroy(idHash); 968 } 969 Loop::destroyByDevice(loopDevice); 970 unlink(asecFileName); 971 return -1; 972 } 973 974 if (usingExt4) { 975 formatStatus = android::vold::ext4::Format(dmDevice, numImgSectors, mountPoint); 976 } else { 977 formatStatus = android::vold::vfat::Format(dmDevice, numImgSectors); 978 } 979 980 if (formatStatus < 0) { 981 SLOGE("ASEC fs format failed (%s)", strerror(errno)); 982 if (cleanupDm) { 983 Devmapper::destroy(idHash); 984 } 985 Loop::destroyByDevice(loopDevice); 986 unlink(asecFileName); 987 return -1; 988 } 989 990 if (mkdir(mountPoint, 0000)) { 991 if (errno != EEXIST) { 992 SLOGE("Mountpoint creation failed (%s)", strerror(errno)); 993 if (cleanupDm) { 994 Devmapper::destroy(idHash); 995 } 996 Loop::destroyByDevice(loopDevice); 997 unlink(asecFileName); 998 return -1; 999 } 1000 } 1001 1002 int mountStatus; 1003 if (usingExt4) { 1004 mountStatus = android::vold::ext4::Mount(dmDevice, mountPoint, 1005 false, false, false); 1006 } else { 1007 mountStatus = android::vold::vfat::Mount(dmDevice, mountPoint, 1008 false, false, false, ownerUid, 0, 0000, false); 1009 } 1010 1011 if (mountStatus) { 1012 SLOGE("ASEC FAT mount failed (%s)", strerror(errno)); 1013 if (cleanupDm) { 1014 Devmapper::destroy(idHash); 1015 } 1016 Loop::destroyByDevice(loopDevice); 1017 unlink(asecFileName); 1018 return -1; 1019 } 1020 1021 if (usingExt4) { 1022 int dirfd = open(mountPoint, O_DIRECTORY | O_CLOEXEC); 1023 if (dirfd >= 0) { 1024 if (fchown(dirfd, ownerUid, AID_SYSTEM) 1025 || fchmod(dirfd, S_IRUSR | S_IWUSR | S_IXUSR | S_ISGID | S_IRGRP | S_IXGRP)) { 1026 SLOGI("Cannot chown/chmod new ASEC mount point %s", mountPoint); 1027 } 1028 close(dirfd); 1029 } 1030 } 1031 } else { 1032 SLOGI("Created raw secure container %s (no filesystem)", id); 1033 } 1034 1035 mActiveContainers->push_back(new ContainerData(strdup(id), ASEC)); 1036 return 0; 1037 } 1038 1039 int VolumeManager::resizeAsec(const char *id, unsigned long numSectors, const char *key) { 1040 char asecFileName[255]; 1041 char mountPoint[255]; 1042 bool cleanupDm = false; 1043 1044 if (!isLegalAsecId(id)) { 1045 SLOGE("resizeAsec: Invalid asec id \"%s\"", id); 1046 errno = EINVAL; 1047 return -1; 1048 } 1049 1050 if (findAsec(id, asecFileName, sizeof(asecFileName))) { 1051 SLOGE("Couldn't find ASEC %s", id); 1052 return -1; 1053 } 1054 1055 int written = snprintf(mountPoint, sizeof(mountPoint), "%s/%s", VolumeManager::ASECDIR, id); 1056 if ((written < 0) || (size_t(written) >= sizeof(mountPoint))) { 1057 SLOGE("ASEC resize failed for %s: couldn't construct mountpoint", id); 1058 return -1; 1059 } 1060 1061 if (isMountpointMounted(mountPoint)) { 1062 SLOGE("ASEC %s mounted. Unmount before resizing", id); 1063 errno = EBUSY; 1064 return -1; 1065 } 1066 1067 struct asec_superblock sb; 1068 int fd; 1069 unsigned long oldNumSec = 0; 1070 1071 if ((fd = open(asecFileName, O_RDONLY | O_CLOEXEC)) < 0) { 1072 SLOGE("Failed to open ASEC file (%s)", strerror(errno)); 1073 return -1; 1074 } 1075 1076 struct stat info; 1077 if (fstat(fd, &info) < 0) { 1078 SLOGE("Failed to get file size (%s)", strerror(errno)); 1079 close(fd); 1080 return -1; 1081 } 1082 1083 oldNumSec = info.st_size / 512; 1084 1085 /* 1086 * Try to read superblock. 1087 */ 1088 memset(&sb, 0, sizeof(struct asec_superblock)); 1089 if (lseek(fd, ((oldNumSec - 1) * 512), SEEK_SET) < 0) { 1090 SLOGE("lseek failed (%s)", strerror(errno)); 1091 close(fd); 1092 return -1; 1093 } 1094 if (read(fd, &sb, sizeof(struct asec_superblock)) != sizeof(struct asec_superblock)) { 1095 SLOGE("superblock read failed (%s)", strerror(errno)); 1096 close(fd); 1097 return -1; 1098 } 1099 close(fd); 1100 1101 if (mDebug) { 1102 SLOGD("Container sb magic/ver (%.8x/%.2x)", sb.magic, sb.ver); 1103 } 1104 if (sb.magic != ASEC_SB_MAGIC || sb.ver != ASEC_SB_VER) { 1105 SLOGE("Bad container magic/version (%.8x/%.2x)", sb.magic, sb.ver); 1106 errno = EMEDIUMTYPE; 1107 return -1; 1108 } 1109 1110 unsigned long numImgSectors; 1111 if (!(sb.c_opts & ASEC_SB_C_OPTS_EXT4)) { 1112 SLOGE("Only ext4 partitions are supported for resize"); 1113 errno = EINVAL; 1114 return -1; 1115 } else { 1116 numImgSectors = adjustSectorNumExt4(numSectors); 1117 } 1118 1119 /* 1120 * add one block for the superblock 1121 */ 1122 SLOGD("Resizing from %lu sectors to %lu sectors", oldNumSec, numImgSectors + 1); 1123 if (oldNumSec == numImgSectors + 1) { 1124 SLOGW("Size unchanged; ignoring resize request"); 1125 return 0; 1126 } else if (oldNumSec > numImgSectors + 1) { 1127 SLOGE("Only growing is currently supported."); 1128 close(fd); 1129 return -1; 1130 } 1131 1132 if (Loop::resizeImageFile(asecFileName, numImgSectors + 1)) { 1133 SLOGE("Resize of ASEC image file failed. Could not resize %s", id); 1134 return -1; 1135 } 1136 1137 /* 1138 * Drop down a copy of the superblock at the end of the file 1139 */ 1140 if (writeSuperBlock(asecFileName, &sb, numImgSectors)) 1141 goto fail; 1142 1143 char idHash[33]; 1144 if (!asecHash(id, idHash, sizeof(idHash))) { 1145 SLOGE("Hash of '%s' failed (%s)", id, strerror(errno)); 1146 goto fail; 1147 } 1148 1149 char loopDevice[255]; 1150 if (setupLoopDevice(loopDevice, sizeof(loopDevice), asecFileName, idHash, mDebug)) 1151 goto fail; 1152 1153 char dmDevice[255]; 1154 1155 if (setupDevMapperDevice(dmDevice, sizeof(dmDevice), loopDevice, asecFileName, key, idHash, numImgSectors, &cleanupDm, mDebug)) { 1156 Loop::destroyByDevice(loopDevice); 1157 goto fail; 1158 } 1159 1160 /* 1161 * Wait for the device mapper node to be created. 1162 */ 1163 waitForDevMapper(dmDevice); 1164 1165 if (android::vold::ext4::Resize(dmDevice, numImgSectors)) { 1166 SLOGE("Unable to resize %s (%s)", id, strerror(errno)); 1167 if (cleanupDm) { 1168 Devmapper::destroy(idHash); 1169 } 1170 Loop::destroyByDevice(loopDevice); 1171 goto fail; 1172 } 1173 1174 return 0; 1175 fail: 1176 Loop::resizeImageFile(asecFileName, oldNumSec); 1177 return -1; 1178 } 1179 1180 int VolumeManager::finalizeAsec(const char *id) { 1181 char asecFileName[255]; 1182 char loopDevice[255]; 1183 char mountPoint[255]; 1184 1185 if (!isLegalAsecId(id)) { 1186 SLOGE("finalizeAsec: Invalid asec id \"%s\"", id); 1187 errno = EINVAL; 1188 return -1; 1189 } 1190 1191 if (findAsec(id, asecFileName, sizeof(asecFileName))) { 1192 SLOGE("Couldn't find ASEC %s", id); 1193 return -1; 1194 } 1195 1196 char idHash[33]; 1197 if (!asecHash(id, idHash, sizeof(idHash))) { 1198 SLOGE("Hash of '%s' failed (%s)", id, strerror(errno)); 1199 return -1; 1200 } 1201 1202 if (Loop::lookupActive(idHash, loopDevice, sizeof(loopDevice))) { 1203 SLOGE("Unable to finalize %s (%s)", id, strerror(errno)); 1204 return -1; 1205 } 1206 1207 unsigned long nr_sec = 0; 1208 struct asec_superblock sb; 1209 1210 if (Loop::lookupInfo(loopDevice, &sb, &nr_sec)) { 1211 return -1; 1212 } 1213 1214 int written = snprintf(mountPoint, sizeof(mountPoint), "%s/%s", VolumeManager::ASECDIR, id); 1215 if ((written < 0) || (size_t(written) >= sizeof(mountPoint))) { 1216 SLOGE("ASEC finalize failed: couldn't construct mountPoint"); 1217 return -1; 1218 } 1219 1220 int result = 0; 1221 if (sb.c_opts & ASEC_SB_C_OPTS_EXT4) { 1222 result = android::vold::ext4::Mount(loopDevice, mountPoint, 1223 true, true, true); 1224 } else { 1225 result = android::vold::vfat::Mount(loopDevice, mountPoint, 1226 true, true, true, 0, 0, 0227, false); 1227 } 1228 1229 if (result) { 1230 SLOGE("ASEC finalize mount failed (%s)", strerror(errno)); 1231 return -1; 1232 } 1233 1234 if (mDebug) { 1235 SLOGD("ASEC %s finalized", id); 1236 } 1237 return 0; 1238 } 1239 1240 int VolumeManager::fixupAsecPermissions(const char *id, gid_t gid, const char* filename) { 1241 char asecFileName[255]; 1242 char loopDevice[255]; 1243 char mountPoint[255]; 1244 1245 if (gid < AID_APP) { 1246 SLOGE("Group ID is not in application range"); 1247 return -1; 1248 } 1249 1250 if (!isLegalAsecId(id)) { 1251 SLOGE("fixupAsecPermissions: Invalid asec id \"%s\"", id); 1252 errno = EINVAL; 1253 return -1; 1254 } 1255 1256 if (findAsec(id, asecFileName, sizeof(asecFileName))) { 1257 SLOGE("Couldn't find ASEC %s", id); 1258 return -1; 1259 } 1260 1261 char idHash[33]; 1262 if (!asecHash(id, idHash, sizeof(idHash))) { 1263 SLOGE("Hash of '%s' failed (%s)", id, strerror(errno)); 1264 return -1; 1265 } 1266 1267 if (Loop::lookupActive(idHash, loopDevice, sizeof(loopDevice))) { 1268 SLOGE("Unable fix permissions during lookup on %s (%s)", id, strerror(errno)); 1269 return -1; 1270 } 1271 1272 unsigned long nr_sec = 0; 1273 struct asec_superblock sb; 1274 1275 if (Loop::lookupInfo(loopDevice, &sb, &nr_sec)) { 1276 return -1; 1277 } 1278 1279 int written = snprintf(mountPoint, sizeof(mountPoint), "%s/%s", VolumeManager::ASECDIR, id); 1280 if ((written < 0) || (size_t(written) >= sizeof(mountPoint))) { 1281 SLOGE("Unable remount to fix permissions for %s: couldn't construct mountpoint", id); 1282 return -1; 1283 } 1284 1285 int result = 0; 1286 if ((sb.c_opts & ASEC_SB_C_OPTS_EXT4) == 0) { 1287 return 0; 1288 } 1289 1290 int ret = android::vold::ext4::Mount(loopDevice, mountPoint, 1291 false /* read-only */, 1292 true /* remount */, 1293 false /* executable */); 1294 if (ret) { 1295 SLOGE("Unable remount to fix permissions for %s (%s)", id, strerror(errno)); 1296 return -1; 1297 } 1298 1299 char *paths[] = { mountPoint, NULL }; 1300 1301 FTS *fts = fts_open(paths, FTS_PHYSICAL | FTS_NOCHDIR | FTS_XDEV, NULL); 1302 if (fts) { 1303 // Traverse the entire hierarchy and chown to system UID. 1304 for (FTSENT *ftsent = fts_read(fts); ftsent != NULL; ftsent = fts_read(fts)) { 1305 // We don't care about the lost+found directory. 1306 if (!strcmp(ftsent->fts_name, "lost+found")) { 1307 continue; 1308 } 1309 1310 /* 1311 * There can only be one file marked as private right now. 1312 * This should be more robust, but it satisfies the requirements 1313 * we have for right now. 1314 */ 1315 const bool privateFile = !strcmp(ftsent->fts_name, filename); 1316 1317 int fd = open(ftsent->fts_accpath, O_NOFOLLOW | O_CLOEXEC); 1318 if (fd < 0) { 1319 SLOGE("Couldn't open file %s: %s", ftsent->fts_accpath, strerror(errno)); 1320 result = -1; 1321 continue; 1322 } 1323 1324 result |= fchown(fd, AID_SYSTEM, privateFile? gid : AID_SYSTEM); 1325 1326 if (ftsent->fts_info & FTS_D) { 1327 result |= fchmod(fd, 0755); 1328 } else if (ftsent->fts_info & FTS_F) { 1329 result |= fchmod(fd, privateFile ? 0640 : 0644); 1330 } 1331 1332 if (selinux_android_restorecon(ftsent->fts_path, 0) < 0) { 1333 SLOGE("restorecon failed for %s: %s\n", ftsent->fts_path, strerror(errno)); 1334 result |= -1; 1335 } 1336 1337 close(fd); 1338 } 1339 fts_close(fts); 1340 1341 // Finally make the directory readable by everyone. 1342 int dirfd = open(mountPoint, O_DIRECTORY | O_CLOEXEC); 1343 if (dirfd < 0 || fchmod(dirfd, 0755)) { 1344 SLOGE("Couldn't change owner of existing directory %s: %s", mountPoint, strerror(errno)); 1345 result |= -1; 1346 } 1347 close(dirfd); 1348 } else { 1349 result |= -1; 1350 } 1351 1352 result |= android::vold::ext4::Mount(loopDevice, mountPoint, 1353 true /* read-only */, 1354 true /* remount */, 1355 true /* execute */); 1356 1357 if (result) { 1358 SLOGE("ASEC fix permissions failed (%s)", strerror(errno)); 1359 return -1; 1360 } 1361 1362 if (mDebug) { 1363 SLOGD("ASEC %s permissions fixed", id); 1364 } 1365 return 0; 1366 } 1367 1368 int VolumeManager::renameAsec(const char *id1, const char *id2) { 1369 char asecFilename1[255]; 1370 char *asecFilename2; 1371 char mountPoint[255]; 1372 1373 const char *dir; 1374 1375 if (!isLegalAsecId(id1)) { 1376 SLOGE("renameAsec: Invalid asec id1 \"%s\"", id1); 1377 errno = EINVAL; 1378 return -1; 1379 } 1380 1381 if (!isLegalAsecId(id2)) { 1382 SLOGE("renameAsec: Invalid asec id2 \"%s\"", id2); 1383 errno = EINVAL; 1384 return -1; 1385 } 1386 1387 if (findAsec(id1, asecFilename1, sizeof(asecFilename1), &dir)) { 1388 SLOGE("Couldn't find ASEC %s", id1); 1389 return -1; 1390 } 1391 1392 asprintf(&asecFilename2, "%s/%s.asec", dir, id2); 1393 1394 int written = snprintf(mountPoint, sizeof(mountPoint), "%s/%s", VolumeManager::ASECDIR, id1); 1395 if ((written < 0) || (size_t(written) >= sizeof(mountPoint))) { 1396 SLOGE("Rename failed: couldn't construct mountpoint"); 1397 goto out_err; 1398 } 1399 1400 if (isMountpointMounted(mountPoint)) { 1401 SLOGW("Rename attempt when src mounted"); 1402 errno = EBUSY; 1403 goto out_err; 1404 } 1405 1406 written = snprintf(mountPoint, sizeof(mountPoint), "%s/%s", VolumeManager::ASECDIR, id2); 1407 if ((written < 0) || (size_t(written) >= sizeof(mountPoint))) { 1408 SLOGE("Rename failed: couldn't construct mountpoint2"); 1409 goto out_err; 1410 } 1411 1412 if (isMountpointMounted(mountPoint)) { 1413 SLOGW("Rename attempt when dst mounted"); 1414 errno = EBUSY; 1415 goto out_err; 1416 } 1417 1418 if (!access(asecFilename2, F_OK)) { 1419 SLOGE("Rename attempt when dst exists"); 1420 errno = EADDRINUSE; 1421 goto out_err; 1422 } 1423 1424 if (rename(asecFilename1, asecFilename2)) { 1425 SLOGE("Rename of '%s' to '%s' failed (%s)", asecFilename1, asecFilename2, strerror(errno)); 1426 goto out_err; 1427 } 1428 1429 free(asecFilename2); 1430 return 0; 1431 1432 out_err: 1433 free(asecFilename2); 1434 return -1; 1435 } 1436 1437 #define UNMOUNT_RETRIES 5 1438 #define UNMOUNT_SLEEP_BETWEEN_RETRY_MS (1000 * 1000) 1439 int VolumeManager::unmountAsec(const char *id, bool force) { 1440 char asecFileName[255]; 1441 char mountPoint[255]; 1442 1443 if (!isLegalAsecId(id)) { 1444 SLOGE("unmountAsec: Invalid asec id \"%s\"", id); 1445 errno = EINVAL; 1446 return -1; 1447 } 1448 1449 if (findAsec(id, asecFileName, sizeof(asecFileName))) { 1450 SLOGE("Couldn't find ASEC %s", id); 1451 return -1; 1452 } 1453 1454 int written = snprintf(mountPoint, sizeof(mountPoint), "%s/%s", VolumeManager::ASECDIR, id); 1455 if ((written < 0) || (size_t(written) >= sizeof(mountPoint))) { 1456 SLOGE("ASEC unmount failed for %s: couldn't construct mountpoint", id); 1457 return -1; 1458 } 1459 1460 char idHash[33]; 1461 if (!asecHash(id, idHash, sizeof(idHash))) { 1462 SLOGE("Hash of '%s' failed (%s)", id, strerror(errno)); 1463 return -1; 1464 } 1465 1466 return unmountLoopImage(id, idHash, asecFileName, mountPoint, force); 1467 } 1468 1469 int VolumeManager::unmountObb(const char *fileName, bool force) { 1470 char mountPoint[255]; 1471 1472 char idHash[33]; 1473 if (!asecHash(fileName, idHash, sizeof(idHash))) { 1474 SLOGE("Hash of '%s' failed (%s)", fileName, strerror(errno)); 1475 return -1; 1476 } 1477 1478 int written = snprintf(mountPoint, sizeof(mountPoint), "%s/%s", VolumeManager::LOOPDIR, idHash); 1479 if ((written < 0) || (size_t(written) >= sizeof(mountPoint))) { 1480 SLOGE("OBB unmount failed for %s: couldn't construct mountpoint", fileName); 1481 return -1; 1482 } 1483 1484 return unmountLoopImage(fileName, idHash, fileName, mountPoint, force); 1485 } 1486 1487 int VolumeManager::unmountLoopImage(const char *id, const char *idHash, 1488 const char *fileName, const char *mountPoint, bool force) { 1489 if (!isMountpointMounted(mountPoint)) { 1490 SLOGE("Unmount request for %s when not mounted", id); 1491 errno = ENOENT; 1492 return -1; 1493 } 1494 1495 int i, rc; 1496 for (i = 1; i <= UNMOUNT_RETRIES; i++) { 1497 rc = umount(mountPoint); 1498 if (!rc) { 1499 break; 1500 } 1501 if (rc && (errno == EINVAL || errno == ENOENT)) { 1502 SLOGI("Container %s unmounted OK", id); 1503 rc = 0; 1504 break; 1505 } 1506 SLOGW("%s unmount attempt %d failed (%s)", 1507 id, i, strerror(errno)); 1508 1509 int signal = 0; // default is to just complain 1510 1511 if (force) { 1512 if (i > (UNMOUNT_RETRIES - 2)) 1513 signal = SIGKILL; 1514 else if (i > (UNMOUNT_RETRIES - 3)) 1515 signal = SIGTERM; 1516 } 1517 1518 Process::killProcessesWithOpenFiles(mountPoint, signal); 1519 usleep(UNMOUNT_SLEEP_BETWEEN_RETRY_MS); 1520 } 1521 1522 if (rc) { 1523 errno = EBUSY; 1524 SLOGE("Failed to unmount container %s (%s)", id, strerror(errno)); 1525 return -1; 1526 } 1527 1528 int retries = 10; 1529 1530 while(retries--) { 1531 if (!rmdir(mountPoint)) { 1532 break; 1533 } 1534 1535 SLOGW("Failed to rmdir %s (%s)", mountPoint, strerror(errno)); 1536 usleep(UNMOUNT_SLEEP_BETWEEN_RETRY_MS); 1537 } 1538 1539 if (!retries) { 1540 SLOGE("Timed out trying to rmdir %s (%s)", mountPoint, strerror(errno)); 1541 } 1542 1543 for (i=1; i <= UNMOUNT_RETRIES; i++) { 1544 if (Devmapper::destroy(idHash) && errno != ENXIO) { 1545 SLOGE("Failed to destroy devmapper instance (%s)", strerror(errno)); 1546 usleep(UNMOUNT_SLEEP_BETWEEN_RETRY_MS); 1547 continue; 1548 } else { 1549 break; 1550 } 1551 } 1552 1553 char loopDevice[255]; 1554 if (!Loop::lookupActive(idHash, loopDevice, sizeof(loopDevice))) { 1555 Loop::destroyByDevice(loopDevice); 1556 } else { 1557 SLOGW("Failed to find loop device for {%s} (%s)", fileName, strerror(errno)); 1558 } 1559 1560 AsecIdCollection::iterator it; 1561 for (it = mActiveContainers->begin(); it != mActiveContainers->end(); ++it) { 1562 ContainerData* cd = *it; 1563 if (!strcmp(cd->id, id)) { 1564 free(*it); 1565 mActiveContainers->erase(it); 1566 break; 1567 } 1568 } 1569 if (it == mActiveContainers->end()) { 1570 SLOGW("mActiveContainers is inconsistent!"); 1571 } 1572 return 0; 1573 } 1574 1575 int VolumeManager::destroyAsec(const char *id, bool force) { 1576 char asecFileName[255]; 1577 char mountPoint[255]; 1578 1579 if (!isLegalAsecId(id)) { 1580 SLOGE("destroyAsec: Invalid asec id \"%s\"", id); 1581 errno = EINVAL; 1582 return -1; 1583 } 1584 1585 if (findAsec(id, asecFileName, sizeof(asecFileName))) { 1586 SLOGE("Couldn't find ASEC %s", id); 1587 return -1; 1588 } 1589 1590 int written = snprintf(mountPoint, sizeof(mountPoint), "%s/%s", VolumeManager::ASECDIR, id); 1591 if ((written < 0) || (size_t(written) >= sizeof(mountPoint))) { 1592 SLOGE("ASEC destroy failed for %s: couldn't construct mountpoint", id); 1593 return -1; 1594 } 1595 1596 if (isMountpointMounted(mountPoint)) { 1597 if (mDebug) { 1598 SLOGD("Unmounting container before destroy"); 1599 } 1600 if (unmountAsec(id, force)) { 1601 SLOGE("Failed to unmount asec %s for destroy (%s)", id, strerror(errno)); 1602 return -1; 1603 } 1604 } 1605 1606 if (unlink(asecFileName)) { 1607 SLOGE("Failed to unlink asec '%s' (%s)", asecFileName, strerror(errno)); 1608 return -1; 1609 } 1610 1611 if (mDebug) { 1612 SLOGD("ASEC %s destroyed", id); 1613 } 1614 return 0; 1615 } 1616 1617 /* 1618 * Legal ASEC ids consist of alphanumeric characters, '-', 1619 * '_', or '.'. ".." is not allowed. The first or last character 1620 * of the ASEC id cannot be '.' (dot). 1621 */ 1622 bool VolumeManager::isLegalAsecId(const char *id) const { 1623 size_t i; 1624 size_t len = strlen(id); 1625 1626 if (len == 0) { 1627 return false; 1628 } 1629 if ((id[0] == '.') || (id[len - 1] == '.')) { 1630 return false; 1631 } 1632 1633 for (i = 0; i < len; i++) { 1634 if (id[i] == '.') { 1635 // i=0 is guaranteed never to have a dot. See above. 1636 if (id[i-1] == '.') return false; 1637 continue; 1638 } 1639 if (id[i] == '_' || id[i] == '-') continue; 1640 if (id[i] >= 'a' && id[i] <= 'z') continue; 1641 if (id[i] >= 'A' && id[i] <= 'Z') continue; 1642 if (id[i] >= '0' && id[i] <= '9') continue; 1643 return false; 1644 } 1645 1646 return true; 1647 } 1648 1649 bool VolumeManager::isAsecInDirectory(const char *dir, const char *asecName) const { 1650 int dirfd = open(dir, O_DIRECTORY | O_CLOEXEC); 1651 if (dirfd < 0) { 1652 SLOGE("Couldn't open internal ASEC dir (%s)", strerror(errno)); 1653 return false; 1654 } 1655 1656 struct stat sb; 1657 bool ret = (fstatat(dirfd, asecName, &sb, AT_SYMLINK_NOFOLLOW) == 0) 1658 && S_ISREG(sb.st_mode); 1659 1660 close(dirfd); 1661 1662 return ret; 1663 } 1664 1665 int VolumeManager::findAsec(const char *id, char *asecPath, size_t asecPathLen, 1666 const char **directory) const { 1667 char *asecName; 1668 1669 if (!isLegalAsecId(id)) { 1670 SLOGE("findAsec: Invalid asec id \"%s\"", id); 1671 errno = EINVAL; 1672 return -1; 1673 } 1674 1675 if (asprintf(&asecName, "%s.asec", id) < 0) { 1676 SLOGE("Couldn't allocate string to write ASEC name"); 1677 return -1; 1678 } 1679 1680 const char *dir; 1681 if (isAsecInDirectory(VolumeManager::SEC_ASECDIR_INT, asecName)) { 1682 dir = VolumeManager::SEC_ASECDIR_INT; 1683 } else if (isAsecInDirectory(VolumeManager::SEC_ASECDIR_EXT, asecName)) { 1684 dir = VolumeManager::SEC_ASECDIR_EXT; 1685 } else { 1686 free(asecName); 1687 return -1; 1688 } 1689 1690 if (directory != NULL) { 1691 *directory = dir; 1692 } 1693 1694 if (asecPath != NULL) { 1695 int written = snprintf(asecPath, asecPathLen, "%s/%s", dir, asecName); 1696 if ((written < 0) || (size_t(written) >= asecPathLen)) { 1697 SLOGE("findAsec failed for %s: couldn't construct ASEC path", id); 1698 free(asecName); 1699 return -1; 1700 } 1701 } 1702 1703 free(asecName); 1704 return 0; 1705 } 1706 1707 int VolumeManager::mountAsec(const char *id, const char *key, int ownerUid, bool readOnly) { 1708 char asecFileName[255]; 1709 char mountPoint[255]; 1710 1711 if (!isLegalAsecId(id)) { 1712 SLOGE("mountAsec: Invalid asec id \"%s\"", id); 1713 errno = EINVAL; 1714 return -1; 1715 } 1716 1717 if (findAsec(id, asecFileName, sizeof(asecFileName))) { 1718 SLOGE("Couldn't find ASEC %s", id); 1719 return -1; 1720 } 1721 1722 int written = snprintf(mountPoint, sizeof(mountPoint), "%s/%s", VolumeManager::ASECDIR, id); 1723 if ((written < 0) || (size_t(written) >= sizeof(mountPoint))) { 1724 SLOGE("ASEC mount failed for %s: couldn't construct mountpoint", id); 1725 return -1; 1726 } 1727 1728 if (isMountpointMounted(mountPoint)) { 1729 SLOGE("ASEC %s already mounted", id); 1730 errno = EBUSY; 1731 return -1; 1732 } 1733 1734 char idHash[33]; 1735 if (!asecHash(id, idHash, sizeof(idHash))) { 1736 SLOGE("Hash of '%s' failed (%s)", id, strerror(errno)); 1737 return -1; 1738 } 1739 1740 char loopDevice[255]; 1741 if (setupLoopDevice(loopDevice, sizeof(loopDevice), asecFileName, idHash, mDebug)) 1742 return -1; 1743 1744 char dmDevice[255]; 1745 bool cleanupDm = false; 1746 1747 unsigned long nr_sec = 0; 1748 struct asec_superblock sb; 1749 1750 if (Loop::lookupInfo(loopDevice, &sb, &nr_sec)) { 1751 return -1; 1752 } 1753 1754 if (mDebug) { 1755 SLOGD("Container sb magic/ver (%.8x/%.2x)", sb.magic, sb.ver); 1756 } 1757 if (sb.magic != ASEC_SB_MAGIC || sb.ver != ASEC_SB_VER) { 1758 SLOGE("Bad container magic/version (%.8x/%.2x)", sb.magic, sb.ver); 1759 Loop::destroyByDevice(loopDevice); 1760 errno = EMEDIUMTYPE; 1761 return -1; 1762 } 1763 nr_sec--; // We don't want the devmapping to extend onto our superblock 1764 1765 if (setupDevMapperDevice(dmDevice, sizeof(dmDevice), loopDevice, asecFileName, key, idHash , nr_sec, &cleanupDm, mDebug)) { 1766 Loop::destroyByDevice(loopDevice); 1767 return -1; 1768 } 1769 1770 if (mkdir(mountPoint, 0000)) { 1771 if (errno != EEXIST) { 1772 SLOGE("Mountpoint creation failed (%s)", strerror(errno)); 1773 if (cleanupDm) { 1774 Devmapper::destroy(idHash); 1775 } 1776 Loop::destroyByDevice(loopDevice); 1777 return -1; 1778 } 1779 } 1780 1781 /* 1782 * Wait for the device mapper node to be created. 1783 */ 1784 waitForDevMapper(dmDevice); 1785 1786 int result; 1787 if (sb.c_opts & ASEC_SB_C_OPTS_EXT4) { 1788 result = android::vold::ext4::Mount(dmDevice, mountPoint, 1789 readOnly, false, readOnly); 1790 } else { 1791 result = android::vold::vfat::Mount(dmDevice, mountPoint, 1792 readOnly, false, readOnly, ownerUid, 0, 0222, false); 1793 } 1794 1795 if (result) { 1796 SLOGE("ASEC mount failed (%s)", strerror(errno)); 1797 if (cleanupDm) { 1798 Devmapper::destroy(idHash); 1799 } 1800 Loop::destroyByDevice(loopDevice); 1801 return -1; 1802 } 1803 1804 mActiveContainers->push_back(new ContainerData(strdup(id), ASEC)); 1805 if (mDebug) { 1806 SLOGD("ASEC %s mounted", id); 1807 } 1808 return 0; 1809 } 1810 1811 /** 1812 * Mounts an image file <code>img</code>. 1813 */ 1814 int VolumeManager::mountObb(const char *img, const char *key, int ownerGid) { 1815 char mountPoint[255]; 1816 1817 char idHash[33]; 1818 if (!asecHash(img, idHash, sizeof(idHash))) { 1819 SLOGE("Hash of '%s' failed (%s)", img, strerror(errno)); 1820 return -1; 1821 } 1822 1823 int written = snprintf(mountPoint, sizeof(mountPoint), "%s/%s", VolumeManager::LOOPDIR, idHash); 1824 if ((written < 0) || (size_t(written) >= sizeof(mountPoint))) { 1825 SLOGE("OBB mount failed for %s: couldn't construct mountpoint", img); 1826 return -1; 1827 } 1828 1829 if (isMountpointMounted(mountPoint)) { 1830 SLOGE("Image %s already mounted", img); 1831 errno = EBUSY; 1832 return -1; 1833 } 1834 1835 char loopDevice[255]; 1836 if (setupLoopDevice(loopDevice, sizeof(loopDevice), img, idHash, mDebug)) 1837 return -1; 1838 1839 char dmDevice[255]; 1840 bool cleanupDm = false; 1841 int fd; 1842 unsigned long nr_sec = 0; 1843 1844 if ((fd = open(loopDevice, O_RDWR | O_CLOEXEC)) < 0) { 1845 SLOGE("Failed to open loopdevice (%s)", strerror(errno)); 1846 Loop::destroyByDevice(loopDevice); 1847 return -1; 1848 } 1849 1850 get_blkdev_size(fd, &nr_sec); 1851 if (nr_sec == 0) { 1852 SLOGE("Failed to get loop size (%s)", strerror(errno)); 1853 Loop::destroyByDevice(loopDevice); 1854 close(fd); 1855 return -1; 1856 } 1857 1858 close(fd); 1859 1860 if (setupDevMapperDevice(dmDevice, sizeof(loopDevice), loopDevice, img,key, idHash, nr_sec, &cleanupDm, mDebug)) { 1861 Loop::destroyByDevice(loopDevice); 1862 return -1; 1863 } 1864 1865 if (mkdir(mountPoint, 0755)) { 1866 if (errno != EEXIST) { 1867 SLOGE("Mountpoint creation failed (%s)", strerror(errno)); 1868 if (cleanupDm) { 1869 Devmapper::destroy(idHash); 1870 } 1871 Loop::destroyByDevice(loopDevice); 1872 return -1; 1873 } 1874 } 1875 1876 /* 1877 * Wait for the device mapper node to be created. 1878 */ 1879 waitForDevMapper(dmDevice); 1880 1881 if (android::vold::vfat::Mount(dmDevice, mountPoint, 1882 true, false, true, 0, ownerGid, 0227, false)) { 1883 SLOGE("Image mount failed (%s)", strerror(errno)); 1884 if (cleanupDm) { 1885 Devmapper::destroy(idHash); 1886 } 1887 Loop::destroyByDevice(loopDevice); 1888 return -1; 1889 } 1890 1891 mActiveContainers->push_back(new ContainerData(strdup(img), OBB)); 1892 if (mDebug) { 1893 SLOGD("Image %s mounted", img); 1894 } 1895 return 0; 1896 } 1897 1898 int VolumeManager::listMountedObbs(SocketClient* cli) { 1899 FILE *fp = setmntent("/proc/mounts", "r"); 1900 if (fp == NULL) { 1901 SLOGE("Error opening /proc/mounts (%s)", strerror(errno)); 1902 return -1; 1903 } 1904 1905 // Create a string to compare against that has a trailing slash 1906 int loopDirLen = strlen(VolumeManager::LOOPDIR); 1907 char loopDir[loopDirLen + 2]; 1908 strlcpy(loopDir, VolumeManager::LOOPDIR, sizeof(loopDir)); 1909 loopDir[loopDirLen++] = '/'; 1910 loopDir[loopDirLen] = '\0'; 1911 1912 mntent* mentry; 1913 while ((mentry = getmntent(fp)) != NULL) { 1914 if (!strncmp(mentry->mnt_dir, loopDir, loopDirLen)) { 1915 int fd = open(mentry->mnt_fsname, O_RDONLY | O_CLOEXEC); 1916 if (fd >= 0) { 1917 struct loop_info64 li; 1918 if (ioctl(fd, LOOP_GET_STATUS64, &li) >= 0) { 1919 cli->sendMsg(ResponseCode::AsecListResult, 1920 (const char*) li.lo_file_name, false); 1921 } 1922 close(fd); 1923 } 1924 } 1925 } 1926 endmntent(fp); 1927 return 0; 1928 } 1929 1930 extern "C" int vold_unmountAll(void) { 1931 VolumeManager *vm = VolumeManager::Instance(); 1932 return vm->unmountAll(); 1933 } 1934 1935 bool VolumeManager::isMountpointMounted(const char *mp) 1936 { 1937 FILE *fp = setmntent("/proc/mounts", "r"); 1938 if (fp == NULL) { 1939 SLOGE("Error opening /proc/mounts (%s)", strerror(errno)); 1940 return false; 1941 } 1942 1943 bool found_mp = false; 1944 mntent* mentry; 1945 while ((mentry = getmntent(fp)) != NULL) { 1946 if (strcmp(mentry->mnt_dir, mp) == 0) { 1947 found_mp = true; 1948 break; 1949 } 1950 } 1951 endmntent(fp); 1952 return found_mp; 1953 } 1954 1955 int VolumeManager::mkdirs(char* path) { 1956 // Only offer to create directories for paths managed by vold 1957 if (strncmp(path, "/storage/", 9) == 0) { 1958 // fs_mkdirs() does symlink checking and relative path enforcement 1959 return fs_mkdirs(path, 0700); 1960 } else { 1961 SLOGE("Failed to find mounted volume for %s", path); 1962 return -EINVAL; 1963 } 1964 } 1965