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
67using android::base::StringPrintf;
68using android::base::unique_fd;
69
70static const char* kPathUserMount = "/mnt/user";
71static const char* kPathVirtualDisk = "/data/misc/vold/virtual_disk";
72
73static const char* kPropVirtualDisk = "persist.sys.virtual_disk";
74
75/* 512MiB is large enough for testing purposes */
76static const unsigned int kSizeVirtualDisk = 536870912;
77
78static const unsigned int kMajorBlockMmc = 179;
79static const unsigned int kMajorBlockExperimentalMin = 240;
80static const unsigned int kMajorBlockExperimentalMax = 254;
81
82VolumeManager *VolumeManager::sInstance = NULL;
83
84VolumeManager *VolumeManager::Instance() {
85    if (!sInstance)
86        sInstance = new VolumeManager();
87    return sInstance;
88}
89
90VolumeManager::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
98VolumeManager::~VolumeManager() {
99}
100
101int 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
141int VolumeManager::setDebug(bool enable) {
142    mDebug = enable;
143    return 0;
144}
145
146int 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
169int VolumeManager::stop() {
170    CHECK(mInternalEmulated != nullptr);
171    mInternalEmulated->destroy();
172    mInternalEmulated = nullptr;
173    return 0;
174}
175
176void 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
235void 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
248void 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
260void 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
280void VolumeManager::addDiskSource(const std::shared_ptr<DiskSource>& diskSource) {
281    std::lock_guard<std::mutex> lock(mLock);
282    mDiskSources.push_back(diskSource);
283}
284
285std::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
294std::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
315void 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
323int 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
344int 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
365int VolumeManager::onUserAdded(userid_t userId, int userSerialNumber) {
366    mAddedUsers[userId] = userSerialNumber;
367    return 0;
368}
369
370int VolumeManager::onUserRemoved(userid_t userId) {
371    mAddedUsers.erase(userId);
372    return 0;
373}
374
375int 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
389int VolumeManager::onUserStopped(userid_t userId) {
390    mStartedUsers.erase(userId);
391    return 0;
392}
393
394int 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
408int 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
416static 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
443int 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
558next:
559        close(nsFd);
560        close(pidFd);
561    }
562    closedir(dir);
563    return 0;
564}
565
566int 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.
584int 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
600int 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
642int 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
653static size_t kAppFuseMaxMountPointName = 32;
654
655static 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
670static 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
697static 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
798int 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
811int 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
824int 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
853int 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}
865