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#define ATRACE_TAG ATRACE_TAG_PACKAGE_MANAGER 18 19#include <dirent.h> 20#include <errno.h> 21#include <fcntl.h> 22#include <mntent.h> 23#include <stdio.h> 24#include <stdlib.h> 25#include <string.h> 26#include <sys/ioctl.h> 27#include <sys/mount.h> 28#include <sys/stat.h> 29#include <sys/types.h> 30#include <sys/sysmacros.h> 31#include <sys/wait.h> 32#include <unistd.h> 33 34#include <linux/kdev_t.h> 35 36#include <android-base/logging.h> 37#include <android-base/parseint.h> 38#include <android-base/properties.h> 39#include <android-base/stringprintf.h> 40#include <android-base/strings.h> 41 42#include <cutils/fs.h> 43#include <utils/Trace.h> 44 45#include <selinux/android.h> 46 47#include <sysutils/NetlinkEvent.h> 48 49#include <private/android_filesystem_config.h> 50 51#include <ext4_utils/ext4_crypt.h> 52 53#include "Devmapper.h" 54#include "Ext4Crypt.h" 55#include "Loop.h" 56#include "NetlinkManager.h" 57#include "Process.h" 58#include "Utils.h" 59#include "VoldUtil.h" 60#include "VolumeManager.h" 61#include "cryptfs.h" 62#include "fs/Ext4.h" 63#include "fs/Vfat.h" 64#include "model/EmulatedVolume.h" 65#include "model/ObbVolume.h" 66 67using android::base::StringPrintf; 68using android::base::unique_fd; 69 70static const char* kPathUserMount = "/mnt/user"; 71static const char* kPathVirtualDisk = "/data/misc/vold/virtual_disk"; 72 73static const char* kPropVirtualDisk = "persist.sys.virtual_disk"; 74 75/* 512MiB is large enough for testing purposes */ 76static const unsigned int kSizeVirtualDisk = 536870912; 77 78static const unsigned int kMajorBlockMmc = 179; 79static const unsigned int kMajorBlockExperimentalMin = 240; 80static const unsigned int kMajorBlockExperimentalMax = 254; 81 82VolumeManager *VolumeManager::sInstance = NULL; 83 84VolumeManager *VolumeManager::Instance() { 85 if (!sInstance) 86 sInstance = new VolumeManager(); 87 return sInstance; 88} 89 90VolumeManager::VolumeManager() { 91 mDebug = false; 92 mNextObbId = 0; 93 // For security reasons, assume that a secure keyguard is 94 // showing until we hear otherwise 95 mSecureKeyguardShowing = true; 96} 97 98VolumeManager::~VolumeManager() { 99} 100 101int VolumeManager::updateVirtualDisk() { 102 ATRACE_NAME("VolumeManager::updateVirtualDisk"); 103 if (android::base::GetBoolProperty(kPropVirtualDisk, false)) { 104 if (access(kPathVirtualDisk, F_OK) != 0) { 105 Loop::createImageFile(kPathVirtualDisk, kSizeVirtualDisk / 512); 106 } 107 108 if (mVirtualDisk == nullptr) { 109 if (Loop::create(kPathVirtualDisk, mVirtualDiskPath) != 0) { 110 LOG(ERROR) << "Failed to create virtual disk"; 111 return -1; 112 } 113 114 struct stat buf; 115 if (stat(mVirtualDiskPath.c_str(), &buf) < 0) { 116 PLOG(ERROR) << "Failed to stat " << mVirtualDiskPath; 117 return -1; 118 } 119 120 auto disk = new android::vold::Disk("virtual", buf.st_rdev, "virtual", 121 android::vold::Disk::Flags::kAdoptable | android::vold::Disk::Flags::kSd); 122 mVirtualDisk = std::shared_ptr<android::vold::Disk>(disk); 123 handleDiskAdded(mVirtualDisk); 124 } 125 } else { 126 if (mVirtualDisk != nullptr) { 127 dev_t device = mVirtualDisk->getDevice(); 128 handleDiskRemoved(device); 129 130 Loop::destroyByDevice(mVirtualDiskPath.c_str()); 131 mVirtualDisk = nullptr; 132 } 133 134 if (access(kPathVirtualDisk, F_OK) == 0) { 135 unlink(kPathVirtualDisk); 136 } 137 } 138 return 0; 139} 140 141int VolumeManager::setDebug(bool enable) { 142 mDebug = enable; 143 return 0; 144} 145 146int VolumeManager::start() { 147 ATRACE_NAME("VolumeManager::start"); 148 149 // Always start from a clean slate by unmounting everything in 150 // directories that we own, in case we crashed. 151 unmountAll(); 152 153 Devmapper::destroyAll(); 154 Loop::destroyAll(); 155 156 // Assume that we always have an emulated volume on internal 157 // storage; the framework will decide if it should be mounted. 158 CHECK(mInternalEmulated == nullptr); 159 mInternalEmulated = std::shared_ptr<android::vold::VolumeBase>( 160 new android::vold::EmulatedVolume("/data/media")); 161 mInternalEmulated->create(); 162 163 // Consider creating a virtual disk 164 updateVirtualDisk(); 165 166 return 0; 167} 168 169int VolumeManager::stop() { 170 CHECK(mInternalEmulated != nullptr); 171 mInternalEmulated->destroy(); 172 mInternalEmulated = nullptr; 173 return 0; 174} 175 176void VolumeManager::handleBlockEvent(NetlinkEvent *evt) { 177 std::lock_guard<std::mutex> lock(mLock); 178 179 if (mDebug) { 180 LOG(VERBOSE) << "----------------"; 181 LOG(VERBOSE) << "handleBlockEvent with action " << (int) evt->getAction(); 182 evt->dump(); 183 } 184 185 std::string eventPath(evt->findParam("DEVPATH")?evt->findParam("DEVPATH"):""); 186 std::string devType(evt->findParam("DEVTYPE")?evt->findParam("DEVTYPE"):""); 187 188 if (devType != "disk") return; 189 190 int major = std::stoi(evt->findParam("MAJOR")); 191 int minor = std::stoi(evt->findParam("MINOR")); 192 dev_t device = makedev(major, minor); 193 194 switch (evt->getAction()) { 195 case NetlinkEvent::Action::kAdd: { 196 for (const auto& source : mDiskSources) { 197 if (source->matches(eventPath)) { 198 // For now, assume that MMC and virtio-blk (the latter is 199 // emulator-specific; see Disk.cpp for details) devices are SD, 200 // and that everything else is USB 201 int flags = source->getFlags(); 202 if (major == kMajorBlockMmc 203 || (android::vold::IsRunningInEmulator() 204 && major >= (int) kMajorBlockExperimentalMin 205 && major <= (int) kMajorBlockExperimentalMax)) { 206 flags |= android::vold::Disk::Flags::kSd; 207 } else { 208 flags |= android::vold::Disk::Flags::kUsb; 209 } 210 211 auto disk = new android::vold::Disk(eventPath, device, 212 source->getNickname(), flags); 213 handleDiskAdded(std::shared_ptr<android::vold::Disk>(disk)); 214 break; 215 } 216 } 217 break; 218 } 219 case NetlinkEvent::Action::kChange: { 220 LOG(DEBUG) << "Disk at " << major << ":" << minor << " changed"; 221 handleDiskChanged(device); 222 break; 223 } 224 case NetlinkEvent::Action::kRemove: { 225 handleDiskRemoved(device); 226 break; 227 } 228 default: { 229 LOG(WARNING) << "Unexpected block event action " << (int) evt->getAction(); 230 break; 231 } 232 } 233} 234 235void VolumeManager::handleDiskAdded(const std::shared_ptr<android::vold::Disk>& disk) { 236 // For security reasons, if secure keyguard is showing, wait 237 // until the user unlocks the device to actually touch it 238 if (mSecureKeyguardShowing) { 239 LOG(INFO) << "Found disk at " << disk->getEventPath() 240 << " but delaying scan due to secure keyguard"; 241 mPendingDisks.push_back(disk); 242 } else { 243 disk->create(); 244 mDisks.push_back(disk); 245 } 246} 247 248void VolumeManager::handleDiskChanged(dev_t device) { 249 for (const auto& disk : mDisks) { 250 if (disk->getDevice() == device) { 251 disk->readMetadata(); 252 disk->readPartitions(); 253 } 254 } 255 256 // For security reasons, we ignore all pending disks, since 257 // we'll scan them once the device is unlocked 258} 259 260void VolumeManager::handleDiskRemoved(dev_t device) { 261 auto i = mDisks.begin(); 262 while (i != mDisks.end()) { 263 if ((*i)->getDevice() == device) { 264 (*i)->destroy(); 265 i = mDisks.erase(i); 266 } else { 267 ++i; 268 } 269 } 270 auto j = mPendingDisks.begin(); 271 while (j != mPendingDisks.end()) { 272 if ((*j)->getDevice() == device) { 273 j = mPendingDisks.erase(j); 274 } else { 275 ++j; 276 } 277 } 278} 279 280void VolumeManager::addDiskSource(const std::shared_ptr<DiskSource>& diskSource) { 281 std::lock_guard<std::mutex> lock(mLock); 282 mDiskSources.push_back(diskSource); 283} 284 285std::shared_ptr<android::vold::Disk> VolumeManager::findDisk(const std::string& id) { 286 for (auto disk : mDisks) { 287 if (disk->getId() == id) { 288 return disk; 289 } 290 } 291 return nullptr; 292} 293 294std::shared_ptr<android::vold::VolumeBase> VolumeManager::findVolume(const std::string& id) { 295 // Vold could receive "mount" after "shutdown" command in the extreme case. 296 // If this happens, mInternalEmulated will equal nullptr and 297 // we need to deal with it in order to avoid null pointer crash. 298 if (mInternalEmulated != nullptr && mInternalEmulated->getId() == id) { 299 return mInternalEmulated; 300 } 301 for (const auto& disk : mDisks) { 302 auto vol = disk->findVolume(id); 303 if (vol != nullptr) { 304 return vol; 305 } 306 } 307 for (const auto& vol : mObbVolumes) { 308 if (vol->getId() == id) { 309 return vol; 310 } 311 } 312 return nullptr; 313} 314 315void VolumeManager::listVolumes(android::vold::VolumeBase::Type type, 316 std::list<std::string>& list) { 317 list.clear(); 318 for (const auto& disk : mDisks) { 319 disk->listVolumes(type, list); 320 } 321} 322 323int VolumeManager::forgetPartition(const std::string& partGuid, const std::string& fsUuid) { 324 std::string normalizedGuid; 325 if (android::vold::NormalizeHex(partGuid, normalizedGuid)) { 326 LOG(WARNING) << "Invalid GUID " << partGuid; 327 return -1; 328 } 329 330 bool success = true; 331 std::string keyPath = android::vold::BuildKeyPath(normalizedGuid); 332 if (unlink(keyPath.c_str()) != 0) { 333 LOG(ERROR) << "Failed to unlink " << keyPath; 334 success = false; 335 } 336 if (e4crypt_is_native()) { 337 if (!e4crypt_destroy_volume_keys(fsUuid)) { 338 success = false; 339 } 340 } 341 return success ? 0 : -1; 342} 343 344int VolumeManager::linkPrimary(userid_t userId) { 345 std::string source(mPrimary->getPath()); 346 if (mPrimary->getType() == android::vold::VolumeBase::Type::kEmulated) { 347 source = StringPrintf("%s/%d", source.c_str(), userId); 348 fs_prepare_dir(source.c_str(), 0755, AID_ROOT, AID_ROOT); 349 } 350 351 std::string target(StringPrintf("/mnt/user/%d/primary", userId)); 352 if (TEMP_FAILURE_RETRY(unlink(target.c_str()))) { 353 if (errno != ENOENT) { 354 PLOG(WARNING) << "Failed to unlink " << target; 355 } 356 } 357 LOG(DEBUG) << "Linking " << source << " to " << target; 358 if (TEMP_FAILURE_RETRY(symlink(source.c_str(), target.c_str()))) { 359 PLOG(WARNING) << "Failed to link"; 360 return -errno; 361 } 362 return 0; 363} 364 365int VolumeManager::onUserAdded(userid_t userId, int userSerialNumber) { 366 mAddedUsers[userId] = userSerialNumber; 367 return 0; 368} 369 370int VolumeManager::onUserRemoved(userid_t userId) { 371 mAddedUsers.erase(userId); 372 return 0; 373} 374 375int VolumeManager::onUserStarted(userid_t userId) { 376 // Note that sometimes the system will spin up processes from Zygote 377 // before actually starting the user, so we're okay if Zygote 378 // already created this directory. 379 std::string path(StringPrintf("%s/%d", kPathUserMount, userId)); 380 fs_prepare_dir(path.c_str(), 0755, AID_ROOT, AID_ROOT); 381 382 mStartedUsers.insert(userId); 383 if (mPrimary) { 384 linkPrimary(userId); 385 } 386 return 0; 387} 388 389int VolumeManager::onUserStopped(userid_t userId) { 390 mStartedUsers.erase(userId); 391 return 0; 392} 393 394int VolumeManager::onSecureKeyguardStateChanged(bool isShowing) { 395 mSecureKeyguardShowing = isShowing; 396 if (!mSecureKeyguardShowing) { 397 // Now that secure keyguard has been dismissed, process 398 // any pending disks 399 for (const auto& disk : mPendingDisks) { 400 disk->create(); 401 mDisks.push_back(disk); 402 } 403 mPendingDisks.clear(); 404 } 405 return 0; 406} 407 408int VolumeManager::setPrimary(const std::shared_ptr<android::vold::VolumeBase>& vol) { 409 mPrimary = vol; 410 for (userid_t userId : mStartedUsers) { 411 linkPrimary(userId); 412 } 413 return 0; 414} 415 416static int unmount_tree(const std::string& prefix) { 417 FILE* fp = setmntent("/proc/mounts", "r"); 418 if (fp == NULL) { 419 PLOG(ERROR) << "Failed to open /proc/mounts"; 420 return -errno; 421 } 422 423 // Some volumes can be stacked on each other, so force unmount in 424 // reverse order to give us the best chance of success. 425 std::list<std::string> toUnmount; 426 mntent* mentry; 427 while ((mentry = getmntent(fp)) != NULL) { 428 auto test = std::string(mentry->mnt_dir) + "/"; 429 if (android::base::StartsWith(test, prefix)) { 430 toUnmount.push_front(test); 431 } 432 } 433 endmntent(fp); 434 435 for (const auto& path : toUnmount) { 436 if (umount2(path.c_str(), MNT_DETACH)) { 437 PLOG(ERROR) << "Failed to unmount " << path; 438 } 439 } 440 return 0; 441} 442 443int VolumeManager::remountUid(uid_t uid, const std::string& mode) { 444 LOG(DEBUG) << "Remounting " << uid << " as mode " << mode; 445 446 DIR* dir; 447 struct dirent* de; 448 std::string rootName; 449 std::string pidName; 450 int pidFd; 451 int nsFd; 452 struct stat sb; 453 pid_t child; 454 455 if (!(dir = opendir("/proc"))) { 456 PLOG(ERROR) << "Failed to opendir"; 457 return -1; 458 } 459 460 // Figure out root namespace to compare against below 461 if (!android::vold::Readlinkat(dirfd(dir), "1/ns/mnt", &rootName)) { 462 PLOG(ERROR) << "Failed to read root namespace"; 463 closedir(dir); 464 return -1; 465 } 466 467 // Poke through all running PIDs look for apps running as UID 468 while ((de = readdir(dir))) { 469 pid_t pid; 470 if (de->d_type != DT_DIR) continue; 471 if (!android::base::ParseInt(de->d_name, &pid)) continue; 472 473 pidFd = -1; 474 nsFd = -1; 475 476 pidFd = openat(dirfd(dir), de->d_name, O_RDONLY | O_DIRECTORY | O_CLOEXEC); 477 if (pidFd < 0) { 478 goto next; 479 } 480 if (fstat(pidFd, &sb) != 0) { 481 PLOG(WARNING) << "Failed to stat " << de->d_name; 482 goto next; 483 } 484 if (sb.st_uid != uid) { 485 goto next; 486 } 487 488 // Matches so far, but refuse to touch if in root namespace 489 LOG(DEBUG) << "Found matching PID " << de->d_name; 490 if (!android::vold::Readlinkat(pidFd, "ns/mnt", &pidName)) { 491 PLOG(WARNING) << "Failed to read namespace for " << de->d_name; 492 goto next; 493 } 494 if (rootName == pidName) { 495 LOG(WARNING) << "Skipping due to root namespace"; 496 goto next; 497 } 498 499 // We purposefully leave the namespace open across the fork 500 nsFd = openat(pidFd, "ns/mnt", O_RDONLY); // not O_CLOEXEC 501 if (nsFd < 0) { 502 PLOG(WARNING) << "Failed to open namespace for " << de->d_name; 503 goto next; 504 } 505 506 if (!(child = fork())) { 507 if (setns(nsFd, CLONE_NEWNS) != 0) { 508 PLOG(ERROR) << "Failed to setns for " << de->d_name; 509 _exit(1); 510 } 511 512 unmount_tree("/storage/"); 513 514 std::string storageSource; 515 if (mode == "default") { 516 storageSource = "/mnt/runtime/default"; 517 } else if (mode == "read") { 518 storageSource = "/mnt/runtime/read"; 519 } else if (mode == "write") { 520 storageSource = "/mnt/runtime/write"; 521 } else { 522 // Sane default of no storage visible 523 _exit(0); 524 } 525 if (TEMP_FAILURE_RETRY(mount(storageSource.c_str(), "/storage", 526 NULL, MS_BIND | MS_REC, NULL)) == -1) { 527 PLOG(ERROR) << "Failed to mount " << storageSource << " for " 528 << de->d_name; 529 _exit(1); 530 } 531 if (TEMP_FAILURE_RETRY(mount(NULL, "/storage", NULL, 532 MS_REC | MS_SLAVE, NULL)) == -1) { 533 PLOG(ERROR) << "Failed to set MS_SLAVE to /storage for " 534 << de->d_name; 535 _exit(1); 536 } 537 538 // Mount user-specific symlink helper into place 539 userid_t user_id = multiuser_get_user_id(uid); 540 std::string userSource(StringPrintf("/mnt/user/%d", user_id)); 541 if (TEMP_FAILURE_RETRY(mount(userSource.c_str(), "/storage/self", 542 NULL, MS_BIND, NULL)) == -1) { 543 PLOG(ERROR) << "Failed to mount " << userSource << " for " 544 << de->d_name; 545 _exit(1); 546 } 547 548 _exit(0); 549 } 550 551 if (child == -1) { 552 PLOG(ERROR) << "Failed to fork"; 553 goto next; 554 } else { 555 TEMP_FAILURE_RETRY(waitpid(child, nullptr, 0)); 556 } 557 558next: 559 close(nsFd); 560 close(pidFd); 561 } 562 closedir(dir); 563 return 0; 564} 565 566int VolumeManager::reset() { 567 // Tear down all existing disks/volumes and start from a blank slate so 568 // newly connected framework hears all events. 569 if (mInternalEmulated != nullptr) { 570 mInternalEmulated->destroy(); 571 mInternalEmulated->create(); 572 } 573 for (const auto& disk : mDisks) { 574 disk->destroy(); 575 disk->create(); 576 } 577 updateVirtualDisk(); 578 mAddedUsers.clear(); 579 mStartedUsers.clear(); 580 return 0; 581} 582 583// Can be called twice (sequentially) during shutdown. should be safe for that. 584int VolumeManager::shutdown() { 585 if (mInternalEmulated == nullptr) { 586 return 0; // already shutdown 587 } 588 android::vold::sSleepOnUnmount = false; 589 mInternalEmulated->destroy(); 590 mInternalEmulated = nullptr; 591 for (const auto& disk : mDisks) { 592 disk->destroy(); 593 } 594 mDisks.clear(); 595 mPendingDisks.clear(); 596 android::vold::sSleepOnUnmount = true; 597 return 0; 598} 599 600int VolumeManager::unmountAll() { 601 std::lock_guard<std::mutex> lock(mLock); 602 ATRACE_NAME("VolumeManager::unmountAll()"); 603 604 // First, try gracefully unmounting all known devices 605 if (mInternalEmulated != nullptr) { 606 mInternalEmulated->unmount(); 607 } 608 for (const auto& disk : mDisks) { 609 disk->unmountAll(); 610 } 611 612 // Worst case we might have some stale mounts lurking around, so 613 // force unmount those just to be safe. 614 FILE* fp = setmntent("/proc/mounts", "r"); 615 if (fp == NULL) { 616 PLOG(ERROR) << "Failed to open /proc/mounts"; 617 return -errno; 618 } 619 620 // Some volumes can be stacked on each other, so force unmount in 621 // reverse order to give us the best chance of success. 622 std::list<std::string> toUnmount; 623 mntent* mentry; 624 while ((mentry = getmntent(fp)) != NULL) { 625 auto test = std::string(mentry->mnt_dir); 626 if ((android::base::StartsWith(test, "/mnt/") && 627 !android::base::StartsWith(test, "/mnt/vendor")) || 628 android::base::StartsWith(test, "/storage/")) { 629 toUnmount.push_front(test); 630 } 631 } 632 endmntent(fp); 633 634 for (const auto& path : toUnmount) { 635 LOG(DEBUG) << "Tearing down stale mount " << path; 636 android::vold::ForceUnmount(path); 637 } 638 639 return 0; 640} 641 642int VolumeManager::mkdirs(const std::string& path) { 643 // Only offer to create directories for paths managed by vold 644 if (android::base::StartsWith(path, "/storage/")) { 645 // fs_mkdirs() does symlink checking and relative path enforcement 646 return fs_mkdirs(path.c_str(), 0700); 647 } else { 648 LOG(ERROR) << "Failed to find mounted volume for " << path; 649 return -EINVAL; 650 } 651} 652 653static size_t kAppFuseMaxMountPointName = 32; 654 655static android::status_t getMountPath(uid_t uid, const std::string& name, std::string* path) { 656 if (name.size() > kAppFuseMaxMountPointName) { 657 LOG(ERROR) << "AppFuse mount name is too long."; 658 return -EINVAL; 659 } 660 for (size_t i = 0; i < name.size(); i++) { 661 if (!isalnum(name[i])) { 662 LOG(ERROR) << "AppFuse mount name contains invalid character."; 663 return -EINVAL; 664 } 665 } 666 *path = android::base::StringPrintf("/mnt/appfuse/%d_%s", uid, name.c_str()); 667 return android::OK; 668} 669 670static android::status_t mountInNamespace(uid_t uid, int device_fd, const std::string& path) { 671 // Remove existing mount. 672 android::vold::ForceUnmount(path); 673 674 const auto opts = android::base::StringPrintf( 675 "fd=%i," 676 "rootmode=40000," 677 "default_permissions," 678 "allow_other," 679 "user_id=%d,group_id=%d," 680 "context=\"u:object_r:app_fuse_file:s0\"," 681 "fscontext=u:object_r:app_fusefs:s0", 682 device_fd, 683 uid, 684 uid); 685 686 const int result = TEMP_FAILURE_RETRY(mount( 687 "/dev/fuse", path.c_str(), "fuse", 688 MS_NOSUID | MS_NODEV | MS_NOEXEC | MS_NOATIME, opts.c_str())); 689 if (result != 0) { 690 PLOG(ERROR) << "Failed to mount " << path; 691 return -errno; 692 } 693 694 return android::OK; 695} 696 697static android::status_t runCommandInNamespace(const std::string& command, 698 uid_t uid, 699 pid_t pid, 700 const std::string& path, 701 int device_fd) { 702 if (DEBUG_APPFUSE) { 703 LOG(DEBUG) << "Run app fuse command " << command << " for the path " << path 704 << " in namespace " << uid; 705 } 706 707 unique_fd dir(open("/proc", O_RDONLY | O_DIRECTORY | O_CLOEXEC)); 708 if (dir.get() == -1) { 709 PLOG(ERROR) << "Failed to open /proc"; 710 return -errno; 711 } 712 713 // Obtains process file descriptor. 714 const std::string pid_str = android::base::StringPrintf("%d", pid); 715 const unique_fd pid_fd( 716 openat(dir.get(), pid_str.c_str(), O_RDONLY | O_DIRECTORY | O_CLOEXEC)); 717 if (pid_fd.get() == -1) { 718 PLOG(ERROR) << "Failed to open /proc/" << pid; 719 return -errno; 720 } 721 722 // Check UID of process. 723 { 724 struct stat sb; 725 const int result = fstat(pid_fd.get(), &sb); 726 if (result == -1) { 727 PLOG(ERROR) << "Failed to stat /proc/" << pid; 728 return -errno; 729 } 730 if (sb.st_uid != AID_SYSTEM) { 731 LOG(ERROR) << "Only system can mount appfuse. UID expected=" << AID_SYSTEM 732 << ", actual=" << sb.st_uid; 733 return -EPERM; 734 } 735 } 736 737 // Matches so far, but refuse to touch if in root namespace 738 { 739 std::string rootName; 740 std::string pidName; 741 if (!android::vold::Readlinkat(dir.get(), "1/ns/mnt", &rootName) 742 || !android::vold::Readlinkat(pid_fd.get(), "ns/mnt", &pidName)) { 743 PLOG(ERROR) << "Failed to read namespaces"; 744 return -EPERM; 745 } 746 if (rootName == pidName) { 747 LOG(ERROR) << "Don't mount appfuse in root namespace"; 748 return -EPERM; 749 } 750 } 751 752 // We purposefully leave the namespace open across the fork 753 unique_fd ns_fd(openat(pid_fd.get(), "ns/mnt", O_RDONLY)); // not O_CLOEXEC 754 if (ns_fd.get() < 0) { 755 PLOG(ERROR) << "Failed to open namespace for /proc/" << pid << "/ns/mnt"; 756 return -errno; 757 } 758 759 int child = fork(); 760 if (child == 0) { 761 if (setns(ns_fd.get(), CLONE_NEWNS) != 0) { 762 PLOG(ERROR) << "Failed to setns"; 763 _exit(-errno); 764 } 765 766 if (command == "mount") { 767 _exit(mountInNamespace(uid, device_fd, path)); 768 } else if (command == "unmount") { 769 // If it's just after all FD opened on mount point are closed, umount2 can fail with 770 // EBUSY. To avoid the case, specify MNT_DETACH. 771 if (umount2(path.c_str(), UMOUNT_NOFOLLOW | MNT_DETACH) != 0 && 772 errno != EINVAL && errno != ENOENT) { 773 PLOG(ERROR) << "Failed to unmount directory."; 774 _exit(-errno); 775 } 776 if (rmdir(path.c_str()) != 0) { 777 PLOG(ERROR) << "Failed to remove the mount directory."; 778 _exit(-errno); 779 } 780 _exit(android::OK); 781 } else { 782 LOG(ERROR) << "Unknown appfuse command " << command; 783 _exit(-EPERM); 784 } 785 } 786 787 if (child == -1) { 788 PLOG(ERROR) << "Failed to folk child process"; 789 return -errno; 790 } 791 792 android::status_t status; 793 TEMP_FAILURE_RETRY(waitpid(child, &status, 0)); 794 795 return status; 796} 797 798int VolumeManager::createObb(const std::string& sourcePath, const std::string& sourceKey, 799 int32_t ownerGid, std::string* outVolId) { 800 int id = mNextObbId++; 801 802 auto vol = std::shared_ptr<android::vold::VolumeBase>( 803 new android::vold::ObbVolume(id, sourcePath, sourceKey, ownerGid)); 804 vol->create(); 805 806 mObbVolumes.push_back(vol); 807 *outVolId = vol->getId(); 808 return android::OK; 809} 810 811int VolumeManager::destroyObb(const std::string& volId) { 812 auto i = mObbVolumes.begin(); 813 while (i != mObbVolumes.end()) { 814 if ((*i)->getId() == volId) { 815 (*i)->destroy(); 816 i = mObbVolumes.erase(i); 817 } else { 818 ++i; 819 } 820 } 821 return android::OK; 822} 823 824int VolumeManager::mountAppFuse(uid_t uid, pid_t pid, int mountId, 825 android::base::unique_fd* device_fd) { 826 std::string name = std::to_string(mountId); 827 828 // Check mount point name. 829 std::string path; 830 if (getMountPath(uid, name, &path) != android::OK) { 831 LOG(ERROR) << "Invalid mount point name"; 832 return -1; 833 } 834 835 // Create directories. 836 const android::status_t result = android::vold::PrepareDir(path, 0700, 0, 0); 837 if (result != android::OK) { 838 PLOG(ERROR) << "Failed to prepare directory " << path; 839 return -1; 840 } 841 842 // Open device FD. 843 device_fd->reset(open("/dev/fuse", O_RDWR)); // not O_CLOEXEC 844 if (device_fd->get() == -1) { 845 PLOG(ERROR) << "Failed to open /dev/fuse"; 846 return -1; 847 } 848 849 // Mount. 850 return runCommandInNamespace("mount", uid, pid, path, device_fd->get()); 851} 852 853int VolumeManager::unmountAppFuse(uid_t uid, pid_t pid, int mountId) { 854 std::string name = std::to_string(mountId); 855 856 // Check mount point name. 857 std::string path; 858 if (getMountPath(uid, name, &path) != android::OK) { 859 LOG(ERROR) << "Invalid mount point name"; 860 return -1; 861 } 862 863 return runCommandInNamespace("unmount", uid, pid, path, -1 /* device_fd */); 864} 865