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