OSDN Git Service

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