OSDN Git Service

Add rc file for wait_for_keymaster
[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 #define ATRACE_TAG ATRACE_TAG_PACKAGE_MANAGER
18
19 #include <dirent.h>
20 #include <errno.h>
21 #include <fcntl.h>
22 #include <mntent.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <sys/ioctl.h>
27 #include <sys/mount.h>
28 #include <sys/stat.h>
29 #include <sys/types.h>
30 #include <sys/sysmacros.h>
31 #include <sys/wait.h>
32 #include <unistd.h>
33
34 #include <linux/kdev_t.h>
35
36 #include <android-base/logging.h>
37 #include <android-base/parseint.h>
38 #include <android-base/properties.h>
39 #include <android-base/stringprintf.h>
40 #include <android-base/strings.h>
41
42 #include <cutils/fs.h>
43 #include <utils/Trace.h>
44
45 #include <selinux/android.h>
46
47 #include <sysutils/NetlinkEvent.h>
48
49 #include <private/android_filesystem_config.h>
50
51 #include <ext4_utils/ext4_crypt.h>
52
53 #include "Devmapper.h"
54 #include "Ext4Crypt.h"
55 #include "Loop.h"
56 #include "NetlinkManager.h"
57 #include "Process.h"
58 #include "Utils.h"
59 #include "VoldUtil.h"
60 #include "VolumeManager.h"
61 #include "cryptfs.h"
62 #include "fs/Ext4.h"
63 #include "fs/Vfat.h"
64 #include "model/EmulatedVolume.h"
65 #include "model/ObbVolume.h"
66
67 using android::base::StringPrintf;
68 using android::base::unique_fd;
69
70 static const char* kPathUserMount = "/mnt/user";
71 static const char* kPathVirtualDisk = "/data/misc/vold/virtual_disk";
72
73 static const char* kPropVirtualDisk = "persist.sys.virtual_disk";
74
75 /* 512MiB is large enough for testing purposes */
76 static const unsigned int kSizeVirtualDisk = 536870912;
77
78 static const unsigned int kMajorBlockMmc = 179;
79 static const unsigned int kMajorBlockExperimentalMin = 240;
80 static const unsigned int kMajorBlockExperimentalMax = 254;
81
82 VolumeManager *VolumeManager::sInstance = NULL;
83
84 VolumeManager *VolumeManager::Instance() {
85     if (!sInstance)
86         sInstance = new VolumeManager();
87     return sInstance;
88 }
89
90 VolumeManager::VolumeManager() {
91     mDebug = false;
92     mNextObbId = 0;
93     // For security reasons, assume that a secure keyguard is
94     // showing until we hear otherwise
95     mSecureKeyguardShowing = true;
96 }
97
98 VolumeManager::~VolumeManager() {
99 }
100
101 int VolumeManager::updateVirtualDisk() {
102     ATRACE_NAME("VolumeManager::updateVirtualDisk");
103     if (android::base::GetBoolProperty(kPropVirtualDisk, false)) {
104         if (access(kPathVirtualDisk, F_OK) != 0) {
105             Loop::createImageFile(kPathVirtualDisk, kSizeVirtualDisk / 512);
106         }
107
108         if (mVirtualDisk == nullptr) {
109             if (Loop::create(kPathVirtualDisk, mVirtualDiskPath) != 0) {
110                 LOG(ERROR) << "Failed to create virtual disk";
111                 return -1;
112             }
113
114             struct stat buf;
115             if (stat(mVirtualDiskPath.c_str(), &buf) < 0) {
116                 PLOG(ERROR) << "Failed to stat " << mVirtualDiskPath;
117                 return -1;
118             }
119
120             auto disk = new android::vold::Disk("virtual", buf.st_rdev, "virtual",
121                     android::vold::Disk::Flags::kAdoptable | android::vold::Disk::Flags::kSd);
122             mVirtualDisk = std::shared_ptr<android::vold::Disk>(disk);
123             handleDiskAdded(mVirtualDisk);
124         }
125     } else {
126         if (mVirtualDisk != nullptr) {
127             dev_t device = mVirtualDisk->getDevice();
128             handleDiskRemoved(device);
129
130             Loop::destroyByDevice(mVirtualDiskPath.c_str());
131             mVirtualDisk = nullptr;
132         }
133
134         if (access(kPathVirtualDisk, F_OK) == 0) {
135             unlink(kPathVirtualDisk);
136         }
137     }
138     return 0;
139 }
140
141 int VolumeManager::setDebug(bool enable) {
142     mDebug = enable;
143     return 0;
144 }
145
146 int VolumeManager::start() {
147     ATRACE_NAME("VolumeManager::start");
148
149     // Always start from a clean slate by unmounting everything in
150     // directories that we own, in case we crashed.
151     unmountAll();
152
153     Devmapper::destroyAll();
154     Loop::destroyAll();
155
156     // Assume that we always have an emulated volume on internal
157     // storage; the framework will decide if it should be mounted.
158     CHECK(mInternalEmulated == nullptr);
159     mInternalEmulated = std::shared_ptr<android::vold::VolumeBase>(
160             new android::vold::EmulatedVolume("/data/media"));
161     mInternalEmulated->create();
162
163     // Consider creating a virtual disk
164     updateVirtualDisk();
165
166     return 0;
167 }
168
169 int VolumeManager::stop() {
170     CHECK(mInternalEmulated != nullptr);
171     mInternalEmulated->destroy();
172     mInternalEmulated = nullptr;
173     return 0;
174 }
175
176 void VolumeManager::handleBlockEvent(NetlinkEvent *evt) {
177     std::lock_guard<std::mutex> lock(mLock);
178
179     if (mDebug) {
180         LOG(VERBOSE) << "----------------";
181         LOG(VERBOSE) << "handleBlockEvent with action " << (int) evt->getAction();
182         evt->dump();
183     }
184
185     std::string eventPath(evt->findParam("DEVPATH")?evt->findParam("DEVPATH"):"");
186     std::string devType(evt->findParam("DEVTYPE")?evt->findParam("DEVTYPE"):"");
187
188     if (devType != "disk") return;
189
190     int major = std::stoi(evt->findParam("MAJOR"));
191     int minor = std::stoi(evt->findParam("MINOR"));
192     dev_t device = makedev(major, minor);
193
194     switch (evt->getAction()) {
195     case NetlinkEvent::Action::kAdd: {
196         for (const auto& source : mDiskSources) {
197             if (source->matches(eventPath)) {
198                 // For now, assume that MMC and virtio-blk (the latter is
199                 // emulator-specific; see Disk.cpp for details) devices are SD,
200                 // and that everything else is USB
201                 int flags = source->getFlags();
202                 if (major == kMajorBlockMmc
203                     || (android::vold::IsRunningInEmulator()
204                     && major >= (int) kMajorBlockExperimentalMin
205                     && major <= (int) kMajorBlockExperimentalMax)) {
206                     flags |= android::vold::Disk::Flags::kSd;
207                 } else {
208                     flags |= android::vold::Disk::Flags::kUsb;
209                 }
210
211                 auto disk = new android::vold::Disk(eventPath, device,
212                         source->getNickname(), flags);
213                 handleDiskAdded(std::shared_ptr<android::vold::Disk>(disk));
214                 break;
215             }
216         }
217         break;
218     }
219     case NetlinkEvent::Action::kChange: {
220         LOG(DEBUG) << "Disk at " << major << ":" << minor << " changed";
221         handleDiskChanged(device);
222         break;
223     }
224     case NetlinkEvent::Action::kRemove: {
225         handleDiskRemoved(device);
226         break;
227     }
228     default: {
229         LOG(WARNING) << "Unexpected block event action " << (int) evt->getAction();
230         break;
231     }
232     }
233 }
234
235 void VolumeManager::handleDiskAdded(const std::shared_ptr<android::vold::Disk>& disk) {
236     // For security reasons, if secure keyguard is showing, wait
237     // until the user unlocks the device to actually touch it
238     if (mSecureKeyguardShowing) {
239         LOG(INFO) << "Found disk at " << disk->getEventPath()
240                 << " but delaying scan due to secure keyguard";
241         mPendingDisks.push_back(disk);
242     } else {
243         disk->create();
244         mDisks.push_back(disk);
245     }
246 }
247
248 void VolumeManager::handleDiskChanged(dev_t device) {
249     for (const auto& disk : mDisks) {
250         if (disk->getDevice() == device) {
251             disk->readMetadata();
252             disk->readPartitions();
253         }
254     }
255
256     // For security reasons, we ignore all pending disks, since
257     // we'll scan them once the device is unlocked
258 }
259
260 void VolumeManager::handleDiskRemoved(dev_t device) {
261     auto i = mDisks.begin();
262     while (i != mDisks.end()) {
263         if ((*i)->getDevice() == device) {
264             (*i)->destroy();
265             i = mDisks.erase(i);
266         } else {
267             ++i;
268         }
269     }
270     auto j = mPendingDisks.begin();
271     while (j != mPendingDisks.end()) {
272         if ((*j)->getDevice() == device) {
273             j = mPendingDisks.erase(j);
274         } else {
275             ++j;
276         }
277     }
278 }
279
280 void VolumeManager::addDiskSource(const std::shared_ptr<DiskSource>& diskSource) {
281     std::lock_guard<std::mutex> lock(mLock);
282     mDiskSources.push_back(diskSource);
283 }
284
285 std::shared_ptr<android::vold::Disk> VolumeManager::findDisk(const std::string& id) {
286     for (auto disk : mDisks) {
287         if (disk->getId() == id) {
288             return disk;
289         }
290     }
291     return nullptr;
292 }
293
294 std::shared_ptr<android::vold::VolumeBase> VolumeManager::findVolume(const std::string& id) {
295     // Vold could receive "mount" after "shutdown" command in the extreme case.
296     // If this happens, mInternalEmulated will equal nullptr and
297     // we need to deal with it in order to avoid null pointer crash.
298     if (mInternalEmulated != nullptr && mInternalEmulated->getId() == id) {
299         return mInternalEmulated;
300     }
301     for (const auto& disk : mDisks) {
302         auto vol = disk->findVolume(id);
303         if (vol != nullptr) {
304             return vol;
305         }
306     }
307     for (const auto& vol : mObbVolumes) {
308         if (vol->getId() == id) {
309             return vol;
310         }
311     }
312     return nullptr;
313 }
314
315 void VolumeManager::listVolumes(android::vold::VolumeBase::Type type,
316         std::list<std::string>& list) {
317     list.clear();
318     for (const auto& disk : mDisks) {
319         disk->listVolumes(type, list);
320     }
321 }
322
323 int VolumeManager::forgetPartition(const std::string& partGuid, const std::string& fsUuid) {
324     std::string normalizedGuid;
325     if (android::vold::NormalizeHex(partGuid, normalizedGuid)) {
326         LOG(WARNING) << "Invalid GUID " << partGuid;
327         return -1;
328     }
329
330     bool success = true;
331     std::string keyPath = android::vold::BuildKeyPath(normalizedGuid);
332     if (unlink(keyPath.c_str()) != 0) {
333         LOG(ERROR) << "Failed to unlink " << keyPath;
334         success = false;
335     }
336     if (e4crypt_is_native()) {
337         if (!e4crypt_destroy_volume_keys(fsUuid)) {
338             success = false;
339         }
340     }
341     return success ? 0 : -1;
342 }
343
344 int VolumeManager::linkPrimary(userid_t userId) {
345     std::string source(mPrimary->getPath());
346     if (mPrimary->getType() == android::vold::VolumeBase::Type::kEmulated) {
347         source = StringPrintf("%s/%d", source.c_str(), userId);
348         fs_prepare_dir(source.c_str(), 0755, AID_ROOT, AID_ROOT);
349     }
350
351     std::string target(StringPrintf("/mnt/user/%d/primary", userId));
352     if (TEMP_FAILURE_RETRY(unlink(target.c_str()))) {
353         if (errno != ENOENT) {
354             PLOG(WARNING) << "Failed to unlink " << target;
355         }
356     }
357     LOG(DEBUG) << "Linking " << source << " to " << target;
358     if (TEMP_FAILURE_RETRY(symlink(source.c_str(), target.c_str()))) {
359         PLOG(WARNING) << "Failed to link";
360         return -errno;
361     }
362     return 0;
363 }
364
365 int VolumeManager::onUserAdded(userid_t userId, int userSerialNumber) {
366     mAddedUsers[userId] = userSerialNumber;
367     return 0;
368 }
369
370 int VolumeManager::onUserRemoved(userid_t userId) {
371     mAddedUsers.erase(userId);
372     return 0;
373 }
374
375 int VolumeManager::onUserStarted(userid_t userId) {
376     // Note that sometimes the system will spin up processes from Zygote
377     // before actually starting the user, so we're okay if Zygote
378     // already created this directory.
379     std::string path(StringPrintf("%s/%d", kPathUserMount, userId));
380     fs_prepare_dir(path.c_str(), 0755, AID_ROOT, AID_ROOT);
381
382     mStartedUsers.insert(userId);
383     if (mPrimary) {
384         linkPrimary(userId);
385     }
386     return 0;
387 }
388
389 int VolumeManager::onUserStopped(userid_t userId) {
390     mStartedUsers.erase(userId);
391     return 0;
392 }
393
394 int VolumeManager::onSecureKeyguardStateChanged(bool isShowing) {
395     mSecureKeyguardShowing = isShowing;
396     if (!mSecureKeyguardShowing) {
397         // Now that secure keyguard has been dismissed, process
398         // any pending disks
399         for (const auto& disk : mPendingDisks) {
400             disk->create();
401             mDisks.push_back(disk);
402         }
403         mPendingDisks.clear();
404     }
405     return 0;
406 }
407
408 int VolumeManager::setPrimary(const std::shared_ptr<android::vold::VolumeBase>& vol) {
409     mPrimary = vol;
410     for (userid_t userId : mStartedUsers) {
411         linkPrimary(userId);
412     }
413     return 0;
414 }
415
416 static int unmount_tree(const std::string& prefix) {
417     FILE* fp = setmntent("/proc/mounts", "r");
418     if (fp == NULL) {
419         PLOG(ERROR) << "Failed to open /proc/mounts";
420         return -errno;
421     }
422
423     // Some volumes can be stacked on each other, so force unmount in
424     // reverse order to give us the best chance of success.
425     std::list<std::string> toUnmount;
426     mntent* mentry;
427     while ((mentry = getmntent(fp)) != NULL) {
428         auto test = std::string(mentry->mnt_dir) + "/";
429         if (android::base::StartsWith(test, prefix)) {
430             toUnmount.push_front(test);
431         }
432     }
433     endmntent(fp);
434
435     for (const auto& path : toUnmount) {
436         if (umount2(path.c_str(), MNT_DETACH)) {
437             PLOG(ERROR) << "Failed to unmount " << path;
438         }
439     }
440     return 0;
441 }
442
443 int VolumeManager::remountUid(uid_t uid, const std::string& mode) {
444     LOG(DEBUG) << "Remounting " << uid << " as mode " << mode;
445
446     DIR* dir;
447     struct dirent* de;
448     std::string rootName;
449     std::string pidName;
450     int pidFd;
451     int nsFd;
452     struct stat sb;
453     pid_t child;
454
455     if (!(dir = opendir("/proc"))) {
456         PLOG(ERROR) << "Failed to opendir";
457         return -1;
458     }
459
460     // Figure out root namespace to compare against below
461     if (!android::vold::Readlinkat(dirfd(dir), "1/ns/mnt", &rootName)) {
462         PLOG(ERROR) << "Failed to read root namespace";
463         closedir(dir);
464         return -1;
465     }
466
467     // Poke through all running PIDs look for apps running as UID
468     while ((de = readdir(dir))) {
469         pid_t pid;
470         if (de->d_type != DT_DIR) continue;
471         if (!android::base::ParseInt(de->d_name, &pid)) continue;
472
473         pidFd = -1;
474         nsFd = -1;
475
476         pidFd = openat(dirfd(dir), de->d_name, O_RDONLY | O_DIRECTORY | O_CLOEXEC);
477         if (pidFd < 0) {
478             goto next;
479         }
480         if (fstat(pidFd, &sb) != 0) {
481             PLOG(WARNING) << "Failed to stat " << de->d_name;
482             goto next;
483         }
484         if (sb.st_uid != uid) {
485             goto next;
486         }
487
488         // Matches so far, but refuse to touch if in root namespace
489         LOG(DEBUG) << "Found matching PID " << de->d_name;
490         if (!android::vold::Readlinkat(pidFd, "ns/mnt", &pidName)) {
491             PLOG(WARNING) << "Failed to read namespace for " << de->d_name;
492             goto next;
493         }
494         if (rootName == pidName) {
495             LOG(WARNING) << "Skipping due to root namespace";
496             goto next;
497         }
498
499         // We purposefully leave the namespace open across the fork
500         nsFd = openat(pidFd, "ns/mnt", O_RDONLY); // not O_CLOEXEC
501         if (nsFd < 0) {
502             PLOG(WARNING) << "Failed to open namespace for " << de->d_name;
503             goto next;
504         }
505
506         if (!(child = fork())) {
507             if (setns(nsFd, CLONE_NEWNS) != 0) {
508                 PLOG(ERROR) << "Failed to setns for " << de->d_name;
509                 _exit(1);
510             }
511
512             unmount_tree("/storage/");
513
514             std::string storageSource;
515             if (mode == "default") {
516                 storageSource = "/mnt/runtime/default";
517             } else if (mode == "read") {
518                 storageSource = "/mnt/runtime/read";
519             } else if (mode == "write") {
520                 storageSource = "/mnt/runtime/write";
521             } else {
522                 // Sane default of no storage visible
523                 _exit(0);
524             }
525             if (TEMP_FAILURE_RETRY(mount(storageSource.c_str(), "/storage",
526                     NULL, MS_BIND | MS_REC, NULL)) == -1) {
527                 PLOG(ERROR) << "Failed to mount " << storageSource << " for "
528                         << de->d_name;
529                 _exit(1);
530             }
531             if (TEMP_FAILURE_RETRY(mount(NULL, "/storage", NULL,
532                     MS_REC | MS_SLAVE, NULL)) == -1) {
533                 PLOG(ERROR) << "Failed to set MS_SLAVE to /storage for "
534                         << de->d_name;
535                 _exit(1);
536             }
537
538             // Mount user-specific symlink helper into place
539             userid_t user_id = multiuser_get_user_id(uid);
540             std::string userSource(StringPrintf("/mnt/user/%d", user_id));
541             if (TEMP_FAILURE_RETRY(mount(userSource.c_str(), "/storage/self",
542                     NULL, MS_BIND, NULL)) == -1) {
543                 PLOG(ERROR) << "Failed to mount " << userSource << " for "
544                         << de->d_name;
545                 _exit(1);
546             }
547
548             _exit(0);
549         }
550
551         if (child == -1) {
552             PLOG(ERROR) << "Failed to fork";
553             goto next;
554         } else {
555             TEMP_FAILURE_RETRY(waitpid(child, nullptr, 0));
556         }
557
558 next:
559         close(nsFd);
560         close(pidFd);
561     }
562     closedir(dir);
563     return 0;
564 }
565
566 int VolumeManager::reset() {
567     // Tear down all existing disks/volumes and start from a blank slate so
568     // newly connected framework hears all events.
569     if (mInternalEmulated != nullptr) {
570         mInternalEmulated->destroy();
571         mInternalEmulated->create();
572     }
573     for (const auto& disk : mDisks) {
574         disk->destroy();
575         disk->create();
576     }
577     updateVirtualDisk();
578     mAddedUsers.clear();
579     mStartedUsers.clear();
580     return 0;
581 }
582
583 // Can be called twice (sequentially) during shutdown. should be safe for that.
584 int VolumeManager::shutdown() {
585     if (mInternalEmulated == nullptr) {
586         return 0; // already shutdown
587     }
588     android::vold::sSleepOnUnmount = false;
589     mInternalEmulated->destroy();
590     mInternalEmulated = nullptr;
591     for (const auto& disk : mDisks) {
592         disk->destroy();
593     }
594     mDisks.clear();
595     mPendingDisks.clear();
596     android::vold::sSleepOnUnmount = true;
597     return 0;
598 }
599
600 int VolumeManager::unmountAll() {
601     std::lock_guard<std::mutex> lock(mLock);
602     ATRACE_NAME("VolumeManager::unmountAll()");
603
604     // First, try gracefully unmounting all known devices
605     if (mInternalEmulated != nullptr) {
606         mInternalEmulated->unmount();
607     }
608     for (const auto& disk : mDisks) {
609         disk->unmountAll();
610     }
611
612     // Worst case we might have some stale mounts lurking around, so
613     // force unmount those just to be safe.
614     FILE* fp = setmntent("/proc/mounts", "r");
615     if (fp == NULL) {
616         PLOG(ERROR) << "Failed to open /proc/mounts";
617         return -errno;
618     }
619
620     // Some volumes can be stacked on each other, so force unmount in
621     // reverse order to give us the best chance of success.
622     std::list<std::string> toUnmount;
623     mntent* mentry;
624     while ((mentry = getmntent(fp)) != NULL) {
625         auto test = std::string(mentry->mnt_dir);
626         if ((android::base::StartsWith(test, "/mnt/") &&
627              !android::base::StartsWith(test, "/mnt/vendor")) ||
628             android::base::StartsWith(test, "/storage/")) {
629             toUnmount.push_front(test);
630         }
631     }
632     endmntent(fp);
633
634     for (const auto& path : toUnmount) {
635         LOG(DEBUG) << "Tearing down stale mount " << path;
636         android::vold::ForceUnmount(path);
637     }
638
639     return 0;
640 }
641
642 int VolumeManager::mkdirs(const std::string& path) {
643     // Only offer to create directories for paths managed by vold
644     if (android::base::StartsWith(path, "/storage/")) {
645         // fs_mkdirs() does symlink checking and relative path enforcement
646         return fs_mkdirs(path.c_str(), 0700);
647     } else {
648         LOG(ERROR) << "Failed to find mounted volume for " << path;
649         return -EINVAL;
650     }
651 }
652
653 static size_t kAppFuseMaxMountPointName = 32;
654
655 static android::status_t getMountPath(uid_t uid, const std::string& name, std::string* path) {
656     if (name.size() > kAppFuseMaxMountPointName) {
657         LOG(ERROR) << "AppFuse mount name is too long.";
658         return -EINVAL;
659     }
660     for (size_t i = 0; i < name.size(); i++) {
661         if (!isalnum(name[i])) {
662             LOG(ERROR) << "AppFuse mount name contains invalid character.";
663             return -EINVAL;
664         }
665     }
666     *path = android::base::StringPrintf("/mnt/appfuse/%d_%s", uid, name.c_str());
667     return android::OK;
668 }
669
670 static android::status_t mountInNamespace(uid_t uid, int device_fd, const std::string& path) {
671     // Remove existing mount.
672     android::vold::ForceUnmount(path);
673
674     const auto opts = android::base::StringPrintf(
675             "fd=%i,"
676             "rootmode=40000,"
677             "default_permissions,"
678             "allow_other,"
679             "user_id=%d,group_id=%d,"
680             "context=\"u:object_r:app_fuse_file:s0\","
681             "fscontext=u:object_r:app_fusefs:s0",
682             device_fd,
683             uid,
684             uid);
685
686     const int result = TEMP_FAILURE_RETRY(mount(
687             "/dev/fuse", path.c_str(), "fuse",
688             MS_NOSUID | MS_NODEV | MS_NOEXEC | MS_NOATIME, opts.c_str()));
689     if (result != 0) {
690         PLOG(ERROR) << "Failed to mount " << path;
691         return -errno;
692     }
693
694     return android::OK;
695 }
696
697 static android::status_t runCommandInNamespace(const std::string& command,
698                                                uid_t uid,
699                                                pid_t pid,
700                                                const std::string& path,
701                                                int device_fd) {
702     if (DEBUG_APPFUSE) {
703         LOG(DEBUG) << "Run app fuse command " << command << " for the path " << path
704                    << " in namespace " << uid;
705     }
706
707     unique_fd dir(open("/proc", O_RDONLY | O_DIRECTORY | O_CLOEXEC));
708     if (dir.get() == -1) {
709         PLOG(ERROR) << "Failed to open /proc";
710         return -errno;
711     }
712
713     // Obtains process file descriptor.
714     const std::string pid_str = android::base::StringPrintf("%d", pid);
715     const unique_fd pid_fd(
716             openat(dir.get(), pid_str.c_str(), O_RDONLY | O_DIRECTORY | O_CLOEXEC));
717     if (pid_fd.get() == -1) {
718         PLOG(ERROR) << "Failed to open /proc/" << pid;
719         return -errno;
720     }
721
722     // Check UID of process.
723     {
724         struct stat sb;
725         const int result = fstat(pid_fd.get(), &sb);
726         if (result == -1) {
727             PLOG(ERROR) << "Failed to stat /proc/" << pid;
728             return -errno;
729         }
730         if (sb.st_uid != AID_SYSTEM) {
731             LOG(ERROR) << "Only system can mount appfuse. UID expected=" << AID_SYSTEM
732                     << ", actual=" << sb.st_uid;
733             return -EPERM;
734         }
735     }
736
737     // Matches so far, but refuse to touch if in root namespace
738     {
739         std::string rootName;
740         std::string pidName;
741         if (!android::vold::Readlinkat(dir.get(), "1/ns/mnt", &rootName)
742                 || !android::vold::Readlinkat(pid_fd.get(), "ns/mnt", &pidName)) {
743             PLOG(ERROR) << "Failed to read namespaces";
744             return -EPERM;
745         }
746         if (rootName == pidName) {
747             LOG(ERROR) << "Don't mount appfuse in root namespace";
748             return -EPERM;
749         }
750     }
751
752     // We purposefully leave the namespace open across the fork
753     unique_fd ns_fd(openat(pid_fd.get(), "ns/mnt", O_RDONLY)); // not O_CLOEXEC
754     if (ns_fd.get() < 0) {
755         PLOG(ERROR) << "Failed to open namespace for /proc/" << pid << "/ns/mnt";
756         return -errno;
757     }
758
759     int child = fork();
760     if (child == 0) {
761         if (setns(ns_fd.get(), CLONE_NEWNS) != 0) {
762             PLOG(ERROR) << "Failed to setns";
763             _exit(-errno);
764         }
765
766         if (command == "mount") {
767             _exit(mountInNamespace(uid, device_fd, path));
768         } else if (command == "unmount") {
769             // If it's just after all FD opened on mount point are closed, umount2 can fail with
770             // EBUSY. To avoid the case, specify MNT_DETACH.
771             if (umount2(path.c_str(), UMOUNT_NOFOLLOW | MNT_DETACH) != 0 &&
772                     errno != EINVAL && errno != ENOENT) {
773                 PLOG(ERROR) << "Failed to unmount directory.";
774                 _exit(-errno);
775             }
776             if (rmdir(path.c_str()) != 0) {
777                 PLOG(ERROR) << "Failed to remove the mount directory.";
778                 _exit(-errno);
779             }
780             _exit(android::OK);
781         } else {
782             LOG(ERROR) << "Unknown appfuse command " << command;
783             _exit(-EPERM);
784         }
785     }
786
787     if (child == -1) {
788         PLOG(ERROR) << "Failed to folk child process";
789         return -errno;
790     }
791
792     android::status_t status;
793     TEMP_FAILURE_RETRY(waitpid(child, &status, 0));
794
795     return status;
796 }
797
798 int VolumeManager::createObb(const std::string& sourcePath, const std::string& sourceKey,
799         int32_t ownerGid, std::string* outVolId) {
800     int id = mNextObbId++;
801
802     auto vol = std::shared_ptr<android::vold::VolumeBase>(
803             new android::vold::ObbVolume(id, sourcePath, sourceKey, ownerGid));
804     vol->create();
805
806     mObbVolumes.push_back(vol);
807     *outVolId = vol->getId();
808     return android::OK;
809 }
810
811 int VolumeManager::destroyObb(const std::string& volId) {
812     auto i = mObbVolumes.begin();
813     while (i != mObbVolumes.end()) {
814         if ((*i)->getId() == volId) {
815             (*i)->destroy();
816             i = mObbVolumes.erase(i);
817         } else {
818             ++i;
819         }
820     }
821     return android::OK;
822 }
823
824 int VolumeManager::mountAppFuse(uid_t uid, pid_t pid, int mountId,
825         android::base::unique_fd* device_fd) {
826     std::string name = std::to_string(mountId);
827
828     // Check mount point name.
829     std::string path;
830     if (getMountPath(uid, name, &path) != android::OK) {
831         LOG(ERROR) << "Invalid mount point name";
832         return -1;
833     }
834
835     // Create directories.
836     const android::status_t result = android::vold::PrepareDir(path, 0700, 0, 0);
837     if (result != android::OK) {
838         PLOG(ERROR) << "Failed to prepare directory " << path;
839         return -1;
840     }
841
842     // Open device FD.
843     device_fd->reset(open("/dev/fuse", O_RDWR)); // not O_CLOEXEC
844     if (device_fd->get() == -1) {
845         PLOG(ERROR) << "Failed to open /dev/fuse";
846         return -1;
847     }
848
849     // Mount.
850     return runCommandInNamespace("mount", uid, pid, path, device_fd->get());
851 }
852
853 int VolumeManager::unmountAppFuse(uid_t uid, pid_t pid, int mountId) {
854     std::string name = std::to_string(mountId);
855
856     // Check mount point name.
857     std::string path;
858     if (getMountPath(uid, name, &path) != android::OK) {
859         LOG(ERROR) << "Invalid mount point name";
860         return -1;
861     }
862
863     return runCommandInNamespace("unmount", uid, pid, path, -1 /* device_fd */);
864 }