OSDN Git Service

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