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