OSDN Git Service

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