OSDN Git Service

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