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
Instance()84 VolumeManager *VolumeManager::Instance() {
85 if (!sInstance)
86 sInstance = new VolumeManager();
87 return sInstance;
88 }
89
VolumeManager()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
~VolumeManager()98 VolumeManager::~VolumeManager() {
99 }
100
updateVirtualDisk()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
setDebug(bool enable)141 int VolumeManager::setDebug(bool enable) {
142 mDebug = enable;
143 return 0;
144 }
145
start()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
stop()169 int VolumeManager::stop() {
170 CHECK(mInternalEmulated != nullptr);
171 mInternalEmulated->destroy();
172 mInternalEmulated = nullptr;
173 return 0;
174 }
175
handleBlockEvent(NetlinkEvent * evt)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
handleDiskAdded(const std::shared_ptr<android::vold::Disk> & disk)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
handleDiskChanged(dev_t device)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
handleDiskRemoved(dev_t device)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
addDiskSource(const std::shared_ptr<DiskSource> & diskSource)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
findDisk(const std::string & id)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
findVolume(const std::string & id)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
listVolumes(android::vold::VolumeBase::Type type,std::list<std::string> & list)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
forgetPartition(const std::string & partGuid,const std::string & fsUuid)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
linkPrimary(userid_t userId)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
onUserAdded(userid_t userId,int userSerialNumber)365 int VolumeManager::onUserAdded(userid_t userId, int userSerialNumber) {
366 mAddedUsers[userId] = userSerialNumber;
367 return 0;
368 }
369
onUserRemoved(userid_t userId)370 int VolumeManager::onUserRemoved(userid_t userId) {
371 mAddedUsers.erase(userId);
372 return 0;
373 }
374
onUserStarted(userid_t userId)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
onUserStopped(userid_t userId)389 int VolumeManager::onUserStopped(userid_t userId) {
390 mStartedUsers.erase(userId);
391 return 0;
392 }
393
onSecureKeyguardStateChanged(bool isShowing)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
setPrimary(const std::shared_ptr<android::vold::VolumeBase> & vol)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
unmount_tree(const std::string & prefix)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
remountUid(uid_t uid,const std::string & mode)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
reset()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.
shutdown()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
unmountAll()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
mkdirs(const std::string & path)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
getMountPath(uid_t uid,const std::string & name,std::string * path)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
mountInNamespace(uid_t uid,int device_fd,const std::string & path)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
runCommandInNamespace(const std::string & command,uid_t uid,pid_t pid,const std::string & path,int device_fd)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
createObb(const std::string & sourcePath,const std::string & sourceKey,int32_t ownerGid,std::string * outVolId)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
destroyObb(const std::string & volId)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
mountAppFuse(uid_t uid,pid_t pid,int mountId,android::base::unique_fd * device_fd)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
unmountAppFuse(uid_t uid,pid_t pid,int mountId)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 }
865