Home | History | Annotate | Download | only in vold
      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 
     67 using android::base::StringPrintf;
     68 using android::base::unique_fd;
     69 
     70 static const char* kPathUserMount = "/mnt/user";
     71 static const char* kPathVirtualDisk = "/data/misc/vold/virtual_disk";
     72 
     73 static const char* kPropVirtualDisk = "persist.sys.virtual_disk";
     74 
     75 /* 512MiB is large enough for testing purposes */
     76 static const unsigned int kSizeVirtualDisk = 536870912;
     77 
     78 static const unsigned int kMajorBlockMmc = 179;
     79 static const unsigned int kMajorBlockExperimentalMin = 240;
     80 static const unsigned int kMajorBlockExperimentalMax = 254;
     81 
     82 VolumeManager *VolumeManager::sInstance = NULL;
     83 
     84 VolumeManager *VolumeManager::Instance() {
     85     if (!sInstance)
     86         sInstance = new VolumeManager();
     87     return sInstance;
     88 }
     89 
     90 VolumeManager::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 
     98 VolumeManager::~VolumeManager() {
     99 }
    100 
    101 int 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 
    141 int VolumeManager::setDebug(bool enable) {
    142     mDebug = enable;
    143     return 0;
    144 }
    145 
    146 int 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 
    169 int VolumeManager::stop() {
    170     CHECK(mInternalEmulated != nullptr);
    171     mInternalEmulated->destroy();
    172     mInternalEmulated = nullptr;
    173     return 0;
    174 }
    175 
    176 void 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 
    235 void 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 
    248 void 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 
    260 void 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 
    280 void VolumeManager::addDiskSource(const std::shared_ptr<DiskSource>& diskSource) {
    281     std::lock_guard<std::mutex> lock(mLock);
    282     mDiskSources.push_back(diskSource);
    283 }
    284 
    285 std::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 
    294 std::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 
    315 void 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 
    323 int 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 
    344 int 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 
    365 int VolumeManager::onUserAdded(userid_t userId, int userSerialNumber) {
    366     mAddedUsers[userId] = userSerialNumber;
    367     return 0;
    368 }
    369 
    370 int VolumeManager::onUserRemoved(userid_t userId) {
    371     mAddedUsers.erase(userId);
    372     return 0;
    373 }
    374 
    375 int 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 
    389 int VolumeManager::onUserStopped(userid_t userId) {
    390     mStartedUsers.erase(userId);
    391     return 0;
    392 }
    393 
    394 int 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 
    408 int 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 
    416 static 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 
    443 int 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 
    558 next:
    559         close(nsFd);
    560         close(pidFd);
    561     }
    562     closedir(dir);
    563     return 0;
    564 }
    565 
    566 int 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.
    584 int 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 
    600 int 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 
    642 int 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 
    653 static size_t kAppFuseMaxMountPointName = 32;
    654 
    655 static 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 
    670 static 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 
    697 static 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 
    798 int 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 
    811 int 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 
    824 int 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 
    853 int 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