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