blob: f1cd232db5df69b18d1ecbf2b951754c5bd94ff7 [file] [log] [blame]
San Mehatf1b736b2009-10-10 17:22:08 -07001/*
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 Sharkey67b8c492017-09-21 17:08:43 -060017#define ATRACE_TAG ATRACE_TAG_PACKAGE_MANAGER
18
Yabin Cuid1104f72015-01-02 13:28:28 -080019#include <dirent.h>
San Mehatf1b736b2009-10-10 17:22:08 -070020#include <errno.h>
San Mehata2677e42009-12-13 10:40:18 -080021#include <fcntl.h>
Yabin Cuid1104f72015-01-02 13:28:28 -080022#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 Mehata19b2502010-01-06 10:33:53 -080028#include <sys/stat.h>
Elliott Hughes0e08e842017-05-18 09:08:24 -070029#include <sys/sysmacros.h>
Paul Crowleyedf7a4e2018-09-18 15:14:18 -070030#include <sys/types.h>
Jeff Sharkey66270a22015-06-24 11:49:24 -070031#include <sys/wait.h>
Yabin Cuid1104f72015-01-02 13:28:28 -080032#include <unistd.h>
Sudheer Shanka40ab6742018-09-18 13:07:45 -070033#include <array>
San Mehata19b2502010-01-06 10:33:53 -080034
San Mehata2677e42009-12-13 10:40:18 -080035#include <linux/kdev_t.h>
San Mehatf1b736b2009-10-10 17:22:08 -070036
Jiyong Park8d21c922019-01-04 13:35:25 +090037#include <ApexProperties.sysprop.h>
Elliott Hughes7e128fb2015-12-04 15:50:53 -080038#include <android-base/logging.h>
Jeff Vander Stoep58890832017-10-23 17:12:31 -070039#include <android-base/parseint.h>
Jeff Sharkey3472e522017-10-06 18:02:53 -060040#include <android-base/properties.h>
Elliott Hughes7e128fb2015-12-04 15:50:53 -080041#include <android-base/stringprintf.h>
Jeff Vander Stoep58890832017-10-23 17:12:31 -070042#include <android-base/strings.h>
Narayan Kamath02efdf52019-11-27 10:53:51 +000043#include <async_safe/log.h>
Jeff Vander Stoep58890832017-10-23 17:12:31 -070044
Jeff Sharkey71ebe152013-09-17 17:24:38 -070045#include <cutils/fs.h>
Jeff Sharkey67b8c492017-09-21 17:08:43 -060046#include <utils/Trace.h>
San Mehatf1b736b2009-10-10 17:22:08 -070047
Robert Craigb9e3ba52014-02-04 10:53:00 -050048#include <selinux/android.h>
49
San Mehatfd7f5872009-10-12 11:32:47 -070050#include <sysutils/NetlinkEvent.h>
51
Kenny Root344ca102012-04-03 17:23:01 -070052#include <private/android_filesystem_config.h>
53
Eric Biggersa701c452018-10-23 13:06:55 -070054#include <fscrypt/fscrypt.h>
Paul Crowleyc6433a22017-10-24 14:54:43 -070055
Risanac02a482018-10-31 21:59:47 -060056#include "AppFuseUtil.h"
Paul Crowleyc6433a22017-10-24 14:54:43 -070057#include "Devmapper.h"
Eric Biggersa701c452018-10-23 13:06:55 -070058#include "FsCrypt.h"
San Mehata19b2502010-01-06 10:33:53 -080059#include "Loop.h"
Paul Crowleyc6433a22017-10-24 14:54:43 -070060#include "NetlinkManager.h"
61#include "Process.h"
62#include "Utils.h"
Sudheer Shanka40ab6742018-09-18 13:07:45 -070063#include "VoldNativeService.h"
Paul Crowleyc6433a22017-10-24 14:54:43 -070064#include "VoldUtil.h"
65#include "VolumeManager.h"
66#include "cryptfs.h"
Jeff Sharkeyd0640f62015-05-21 22:35:42 -070067#include "fs/Ext4.h"
68#include "fs/Vfat.h"
Paul Crowleyc6433a22017-10-24 14:54:43 -070069#include "model/EmulatedVolume.h"
70#include "model/ObbVolume.h"
Zima438b242019-09-25 14:37:38 +010071#include "model/PrivateVolume.h"
Risan8c9f3322018-10-29 08:52:56 +090072#include "model/StubVolume.h"
San Mehat23969932010-01-09 07:08:06 -080073
Sudheer Shankaf9b38a52019-02-14 19:09:51 +000074using android::OK;
Sudheer Shanka53947a32018-08-01 10:24:13 -070075using android::base::GetBoolProperty;
Mark Salyzyn86e81e72018-09-20 10:09:27 -070076using android::base::StartsWith;
Sudheer Shanka53947a32018-08-01 10:24:13 -070077using android::base::StringAppendF;
Jeff Sharkey36801cc2015-03-13 16:09:20 -070078using android::base::StringPrintf;
Jeff Sharkey11c2d382017-09-11 10:32:01 -060079using android::base::unique_fd;
Sudheer Shanka023b5392019-02-06 12:39:19 -080080using android::vold::BindMount;
Sudheer Shankaf9b38a52019-02-14 19:09:51 +000081using android::vold::CreateDir;
Sudheer Shanka30df1c62019-02-22 17:03:02 -080082using android::vold::DeleteDirContents;
Sudheer Shanka023b5392019-02-06 12:39:19 -080083using android::vold::DeleteDirContentsAndDir;
Zima438b242019-09-25 14:37:38 +010084using android::vold::PrivateVolume;
Sudheer Shanka023b5392019-02-06 12:39:19 -080085using android::vold::Symlink;
86using android::vold::Unlink;
87using android::vold::UnmountTree;
Sudheer Shanka03992e32018-12-12 12:43:38 -080088using android::vold::VoldNativeService;
Zima438b242019-09-25 14:37:38 +010089using android::vold::VolumeBase;
Jeff Sharkey36801cc2015-03-13 16:09:20 -070090
Jeff Sharkeyfa1c6772017-03-25 22:49:13 -060091static const char* kPathUserMount = "/mnt/user";
92static const char* kPathVirtualDisk = "/data/misc/vold/virtual_disk";
93
94static const char* kPropVirtualDisk = "persist.sys.virtual_disk";
95
Sudheer Shanka53947a32018-08-01 10:24:13 -070096static const std::string kEmptyString("");
97
Jeff Sharkeyfa1c6772017-03-25 22:49:13 -060098/* 512MiB is large enough for testing purposes */
99static const unsigned int kSizeVirtualDisk = 536870912;
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700100
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700101static const unsigned int kMajorBlockMmc = 179;
Yu Ning942d4e82016-01-08 17:36:47 +0800102static const unsigned int kMajorBlockExperimentalMin = 240;
103static const unsigned int kMajorBlockExperimentalMax = 254;
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700104
Paul Crowleyedf7a4e2018-09-18 15:14:18 -0700105VolumeManager* VolumeManager::sInstance = NULL;
San Mehatf1b736b2009-10-10 17:22:08 -0700106
Paul Crowleyedf7a4e2018-09-18 15:14:18 -0700107VolumeManager* VolumeManager::Instance() {
108 if (!sInstance) sInstance = new VolumeManager();
San Mehatf1b736b2009-10-10 17:22:08 -0700109 return sInstance;
110}
111
112VolumeManager::VolumeManager() {
San Mehatd9a4e352010-03-12 13:32:47 -0800113 mDebug = false;
Jeff Sharkey11c2d382017-09-11 10:32:01 -0600114 mNextObbId = 0;
Risan8c9f3322018-10-29 08:52:56 +0900115 mNextStubVolumeId = 0;
Jeff Sharkey401b2602017-12-14 22:15:20 -0700116 // For security reasons, assume that a secure keyguard is
117 // showing until we hear otherwise
118 mSecureKeyguardShowing = true;
San Mehatf1b736b2009-10-10 17:22:08 -0700119}
120
Paul Crowleyedf7a4e2018-09-18 15:14:18 -0700121VolumeManager::~VolumeManager() {}
San Mehatd9a4e352010-03-12 13:32:47 -0800122
Jeff Sharkeyfa1c6772017-03-25 22:49:13 -0600123int VolumeManager::updateVirtualDisk() {
Jeff Sharkey67b8c492017-09-21 17:08:43 -0600124 ATRACE_NAME("VolumeManager::updateVirtualDisk");
Mark Salyzyn86e81e72018-09-20 10:09:27 -0700125 if (GetBoolProperty(kPropVirtualDisk, false)) {
Jeff Sharkeyfa1c6772017-03-25 22:49:13 -0600126 if (access(kPathVirtualDisk, F_OK) != 0) {
127 Loop::createImageFile(kPathVirtualDisk, kSizeVirtualDisk / 512);
128 }
129
130 if (mVirtualDisk == nullptr) {
131 if (Loop::create(kPathVirtualDisk, mVirtualDiskPath) != 0) {
132 LOG(ERROR) << "Failed to create virtual disk";
133 return -1;
134 }
135
136 struct stat buf;
137 if (stat(mVirtualDiskPath.c_str(), &buf) < 0) {
138 PLOG(ERROR) << "Failed to stat " << mVirtualDiskPath;
139 return -1;
140 }
141
Paul Crowleyedf7a4e2018-09-18 15:14:18 -0700142 auto disk = new android::vold::Disk(
143 "virtual", buf.st_rdev, "virtual",
144 android::vold::Disk::Flags::kAdoptable | android::vold::Disk::Flags::kSd);
Jeff Sharkeyfa1c6772017-03-25 22:49:13 -0600145 mVirtualDisk = std::shared_ptr<android::vold::Disk>(disk);
Jeff Sharkey401b2602017-12-14 22:15:20 -0700146 handleDiskAdded(mVirtualDisk);
Jeff Sharkeyfa1c6772017-03-25 22:49:13 -0600147 }
148 } else {
149 if (mVirtualDisk != nullptr) {
150 dev_t device = mVirtualDisk->getDevice();
Jeff Sharkey401b2602017-12-14 22:15:20 -0700151 handleDiskRemoved(device);
Jeff Sharkeyfa1c6772017-03-25 22:49:13 -0600152
153 Loop::destroyByDevice(mVirtualDiskPath.c_str());
154 mVirtualDisk = nullptr;
155 }
156
157 if (access(kPathVirtualDisk, F_OK) == 0) {
158 unlink(kPathVirtualDisk);
159 }
160 }
161 return 0;
162}
163
Jeff Sharkeyf1b996d2015-04-17 17:35:20 -0700164int VolumeManager::setDebug(bool enable) {
San Mehatd9a4e352010-03-12 13:32:47 -0800165 mDebug = enable;
Jeff Sharkeyf1b996d2015-04-17 17:35:20 -0700166 return 0;
San Mehatd9a4e352010-03-12 13:32:47 -0800167}
168
San Mehatf1b736b2009-10-10 17:22:08 -0700169int VolumeManager::start() {
Jeff Sharkey67b8c492017-09-21 17:08:43 -0600170 ATRACE_NAME("VolumeManager::start");
171
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700172 // Always start from a clean slate by unmounting everything in
173 // directories that we own, in case we crashed.
Jeff Sharkey9c484982015-03-31 10:35:33 -0700174 unmountAll();
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700175
Jeff Sharkey11c2d382017-09-11 10:32:01 -0600176 Devmapper::destroyAll();
177 Loop::destroyAll();
178
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700179 // Assume that we always have an emulated volume on internal
180 // storage; the framework will decide if it should be mounted.
Zima438b242019-09-25 14:37:38 +0100181 CHECK(mInternalEmulatedVolumes.empty());
182
183 auto vol = std::shared_ptr<android::vold::VolumeBase>(
184 new android::vold::EmulatedVolume("/data/media", 0));
185 vol->setMountUserId(0);
186 vol->create();
187 mInternalEmulatedVolumes.push_back(vol);
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700188
Jeff Sharkeyfa1c6772017-03-25 22:49:13 -0600189 // Consider creating a virtual disk
190 updateVirtualDisk();
191
San Mehatf1b736b2009-10-10 17:22:08 -0700192 return 0;
193}
194
195int VolumeManager::stop() {
Zima438b242019-09-25 14:37:38 +0100196 CHECK(!mInternalEmulatedVolumes.empty());
197 for (const auto& vol : mInternalEmulatedVolumes) {
198 vol->destroy();
199 }
200 mInternalEmulatedVolumes.clear();
201
San Mehatf1b736b2009-10-10 17:22:08 -0700202 return 0;
203}
204
Paul Crowleyedf7a4e2018-09-18 15:14:18 -0700205void VolumeManager::handleBlockEvent(NetlinkEvent* evt) {
Jeff Sharkeyc8e04c52015-04-21 12:14:17 -0700206 std::lock_guard<std::mutex> lock(mLock);
207
Jeff Sharkeyf1b996d2015-04-17 17:35:20 -0700208 if (mDebug) {
Sudheer Shanka4b6ca4e2018-09-21 10:54:54 -0700209 LOG(DEBUG) << "----------------";
210 LOG(DEBUG) << "handleBlockEvent with action " << (int)evt->getAction();
Jeff Sharkeyf1b996d2015-04-17 17:35:20 -0700211 evt->dump();
212 }
San Mehatf1b736b2009-10-10 17:22:08 -0700213
Paul Crowleyedf7a4e2018-09-18 15:14:18 -0700214 std::string eventPath(evt->findParam("DEVPATH") ? evt->findParam("DEVPATH") : "");
215 std::string devType(evt->findParam("DEVTYPE") ? evt->findParam("DEVTYPE") : "");
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700216
217 if (devType != "disk") return;
218
Jeff Sharkey95440eb2017-09-18 18:19:28 -0600219 int major = std::stoi(evt->findParam("MAJOR"));
220 int minor = std::stoi(evt->findParam("MINOR"));
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700221 dev_t device = makedev(major, minor);
222
223 switch (evt->getAction()) {
Paul Crowleyedf7a4e2018-09-18 15:14:18 -0700224 case NetlinkEvent::Action::kAdd: {
225 for (const auto& source : mDiskSources) {
226 if (source->matches(eventPath)) {
227 // For now, assume that MMC and virtio-blk (the latter is
228 // emulator-specific; see Disk.cpp for details) devices are SD,
229 // and that everything else is USB
230 int flags = source->getFlags();
231 if (major == kMajorBlockMmc || (android::vold::IsRunningInEmulator() &&
232 major >= (int)kMajorBlockExperimentalMin &&
233 major <= (int)kMajorBlockExperimentalMax)) {
234 flags |= android::vold::Disk::Flags::kSd;
235 } else {
236 flags |= android::vold::Disk::Flags::kUsb;
237 }
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700238
Paul Crowleyedf7a4e2018-09-18 15:14:18 -0700239 auto disk =
240 new android::vold::Disk(eventPath, device, source->getNickname(), flags);
241 handleDiskAdded(std::shared_ptr<android::vold::Disk>(disk));
242 break;
243 }
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700244 }
Paul Crowleyedf7a4e2018-09-18 15:14:18 -0700245 break;
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700246 }
Paul Crowleyedf7a4e2018-09-18 15:14:18 -0700247 case NetlinkEvent::Action::kChange: {
248 LOG(DEBUG) << "Disk at " << major << ":" << minor << " changed";
249 handleDiskChanged(device);
250 break;
251 }
252 case NetlinkEvent::Action::kRemove: {
253 handleDiskRemoved(device);
254 break;
255 }
256 default: {
257 LOG(WARNING) << "Unexpected block event action " << (int)evt->getAction();
258 break;
259 }
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700260 }
261}
262
Jeff Sharkey401b2602017-12-14 22:15:20 -0700263void VolumeManager::handleDiskAdded(const std::shared_ptr<android::vold::Disk>& disk) {
264 // For security reasons, if secure keyguard is showing, wait
265 // until the user unlocks the device to actually touch it
266 if (mSecureKeyguardShowing) {
267 LOG(INFO) << "Found disk at " << disk->getEventPath()
Paul Crowleyedf7a4e2018-09-18 15:14:18 -0700268 << " but delaying scan due to secure keyguard";
Jeff Sharkey401b2602017-12-14 22:15:20 -0700269 mPendingDisks.push_back(disk);
270 } else {
271 disk->create();
272 mDisks.push_back(disk);
273 }
274}
275
276void VolumeManager::handleDiskChanged(dev_t device) {
277 for (const auto& disk : mDisks) {
278 if (disk->getDevice() == device) {
279 disk->readMetadata();
280 disk->readPartitions();
281 }
282 }
283
284 // For security reasons, we ignore all pending disks, since
285 // we'll scan them once the device is unlocked
286}
287
288void VolumeManager::handleDiskRemoved(dev_t device) {
289 auto i = mDisks.begin();
290 while (i != mDisks.end()) {
291 if ((*i)->getDevice() == device) {
292 (*i)->destroy();
293 i = mDisks.erase(i);
294 } else {
295 ++i;
296 }
297 }
298 auto j = mPendingDisks.begin();
299 while (j != mPendingDisks.end()) {
300 if ((*j)->getDevice() == device) {
301 j = mPendingDisks.erase(j);
302 } else {
303 ++j;
304 }
305 }
306}
307
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700308void VolumeManager::addDiskSource(const std::shared_ptr<DiskSource>& diskSource) {
Wei Wang6b455c22017-01-20 11:52:33 -0800309 std::lock_guard<std::mutex> lock(mLock);
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700310 mDiskSources.push_back(diskSource);
311}
312
313std::shared_ptr<android::vold::Disk> VolumeManager::findDisk(const std::string& id) {
314 for (auto disk : mDisks) {
315 if (disk->getId() == id) {
316 return disk;
San Mehatf1b736b2009-10-10 17:22:08 -0700317 }
318 }
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700319 return nullptr;
320}
San Mehatf1b736b2009-10-10 17:22:08 -0700321
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700322std::shared_ptr<android::vold::VolumeBase> VolumeManager::findVolume(const std::string& id) {
Zima438b242019-09-25 14:37:38 +0100323 for (const auto& vol : mInternalEmulatedVolumes) {
324 if (vol->getId() == id) {
325 return vol;
326 }
San Mehatf1b736b2009-10-10 17:22:08 -0700327 }
Chih-Hung Hsieh11a2ce82016-07-27 14:11:02 -0700328 for (const auto& disk : mDisks) {
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700329 auto vol = disk->findVolume(id);
330 if (vol != nullptr) {
331 return vol;
332 }
333 }
Risan8c9f3322018-10-29 08:52:56 +0900334 for (const auto& vol : mStubVolumes) {
335 if (vol->getId() == id) {
336 return vol;
337 }
338 }
Jeff Sharkey11c2d382017-09-11 10:32:01 -0600339 for (const auto& vol : mObbVolumes) {
340 if (vol->getId() == id) {
341 return vol;
342 }
343 }
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700344 return nullptr;
345}
346
Greg Kaiser2bc201e2018-12-18 08:42:08 -0800347void VolumeManager::listVolumes(android::vold::VolumeBase::Type type,
348 std::list<std::string>& list) const {
Jeff Sharkeyc86ab6f2015-06-26 14:02:09 -0700349 list.clear();
Chih-Hung Hsieh11a2ce82016-07-27 14:11:02 -0700350 for (const auto& disk : mDisks) {
Jeff Sharkeyc86ab6f2015-06-26 14:02:09 -0700351 disk->listVolumes(type, list);
352 }
353}
354
Jeff Sharkey3ce18252017-10-24 11:08:45 -0600355int VolumeManager::forgetPartition(const std::string& partGuid, const std::string& fsUuid) {
Jeff Sharkeybc40cc82015-06-18 14:25:08 -0700356 std::string normalizedGuid;
357 if (android::vold::NormalizeHex(partGuid, normalizedGuid)) {
358 LOG(WARNING) << "Invalid GUID " << partGuid;
359 return -1;
360 }
361
Paul Crowleyc6433a22017-10-24 14:54:43 -0700362 bool success = true;
Jeff Sharkeybc40cc82015-06-18 14:25:08 -0700363 std::string keyPath = android::vold::BuildKeyPath(normalizedGuid);
364 if (unlink(keyPath.c_str()) != 0) {
365 LOG(ERROR) << "Failed to unlink " << keyPath;
Paul Crowleyc6433a22017-10-24 14:54:43 -0700366 success = false;
Jeff Sharkeybc40cc82015-06-18 14:25:08 -0700367 }
Eric Biggersa701c452018-10-23 13:06:55 -0700368 if (fscrypt_is_native()) {
369 if (!fscrypt_destroy_volume_keys(fsUuid)) {
Paul Crowleyc6433a22017-10-24 14:54:43 -0700370 success = false;
371 }
372 }
373 return success ? 0 : -1;
Jeff Sharkeybc40cc82015-06-18 14:25:08 -0700374}
375
Sudheer Shanka40ab6742018-09-18 13:07:45 -0700376int VolumeManager::linkPrimary(userid_t userId) {
Zima438b242019-09-25 14:37:38 +0100377 if (!GetBoolProperty(android::vold::kPropFuseSnapshot, false)) {
378 std::string source(mPrimary->getPath());
379 if (mPrimary->isEmulated()) {
380 source = StringPrintf("%s/%d", source.c_str(), userId);
381 fs_prepare_dir(source.c_str(), 0755, AID_ROOT, AID_ROOT);
382 }
Zim3623a212019-07-19 16:46:53 +0100383
Zima438b242019-09-25 14:37:38 +0100384 std::string target(StringPrintf("/mnt/user/%d/primary", userId));
385 LOG(DEBUG) << "Linking " << source << " to " << target;
386 Symlink(source, target);
Zim3623a212019-07-19 16:46:53 +0100387 }
Sudheer Shanka40ab6742018-09-18 13:07:45 -0700388 return 0;
389}
390
Zima438b242019-09-25 14:37:38 +0100391void VolumeManager::destroyEmulatedVolumesForUser(userid_t userId) {
392 // Destroy and remove all unstacked EmulatedVolumes for the user
393 auto i = mInternalEmulatedVolumes.begin();
394 while (i != mInternalEmulatedVolumes.end()) {
395 auto vol = *i;
396 if (vol->getMountUserId() == userId) {
397 vol->destroy();
398 i = mInternalEmulatedVolumes.erase(i);
399 } else {
400 i++;
401 }
402 }
403
404 // Destroy and remove all stacked EmulatedVolumes for the user on each mounted private volume
405 std::list<std::string> private_vols;
406 listVolumes(VolumeBase::Type::kPrivate, private_vols);
407 for (const std::string& id : private_vols) {
408 PrivateVolume* pvol = static_cast<PrivateVolume*>(findVolume(id).get());
409 std::list<std::shared_ptr<VolumeBase>> vols_to_remove;
410 if (pvol->getState() == VolumeBase::State::kMounted) {
411 for (const auto& vol : pvol->getVolumes()) {
412 if (vol->getMountUserId() == userId) {
413 vols_to_remove.push_back(vol);
414 }
415 }
416 for (const auto& vol : vols_to_remove) {
417 vol->destroy();
418 pvol->removeVolume(vol);
419 }
420 } // else EmulatedVolumes will be destroyed on VolumeBase#unmount
421 }
422}
423
424void VolumeManager::createEmulatedVolumesForUser(userid_t userId) {
425 // Create unstacked EmulatedVolumes for the user
426 auto vol = std::shared_ptr<android::vold::VolumeBase>(
427 new android::vold::EmulatedVolume("/data/media", userId));
428 vol->setMountUserId(userId);
429 mInternalEmulatedVolumes.push_back(vol);
430 vol->create();
431
432 // Create stacked EmulatedVolumes for the user on each PrivateVolume
433 std::list<std::string> private_vols;
434 listVolumes(VolumeBase::Type::kPrivate, private_vols);
435 for (const std::string& id : private_vols) {
436 PrivateVolume* pvol = static_cast<PrivateVolume*>(findVolume(id).get());
437 if (pvol->getState() == VolumeBase::State::kMounted) {
438 auto evol =
439 std::shared_ptr<android::vold::VolumeBase>(new android::vold::EmulatedVolume(
440 pvol->getPath() + "/media", pvol->getRawDevice(), pvol->getFsUuid(),
441 userId));
442 evol->setMountUserId(userId);
443 pvol->addVolume(evol);
444 evol->create();
445 } // else EmulatedVolumes will be created per user when on PrivateVolume#doMount
446 }
447}
448
Jeff Sharkeybd3038d2015-06-10 09:42:01 -0700449int VolumeManager::onUserAdded(userid_t userId, int userSerialNumber) {
Zima438b242019-09-25 14:37:38 +0100450 LOG(INFO) << "onUserAdded: " << userId;
451
Jeff Sharkeybd3038d2015-06-10 09:42:01 -0700452 mAddedUsers[userId] = userSerialNumber;
453 return 0;
454}
455
456int VolumeManager::onUserRemoved(userid_t userId) {
Zima438b242019-09-25 14:37:38 +0100457 LOG(INFO) << "onUserRemoved: " << userId;
458
Zim2d45d9b2019-11-14 16:19:05 +0000459 onUserStopped(userId);
Jeff Sharkeybd3038d2015-06-10 09:42:01 -0700460 mAddedUsers.erase(userId);
461 return 0;
462}
463
Sudheer Shankaebce4cc2019-04-29 10:46:35 -0700464int VolumeManager::onUserStarted(userid_t userId) {
Zima438b242019-09-25 14:37:38 +0100465 LOG(INFO) << "onUserStarted: " << userId;
466
Zim2d45d9b2019-11-14 16:19:05 +0000467 if (mStartedUsers.find(userId) == mStartedUsers.end()) {
468 createEmulatedVolumesForUser(userId);
469 }
470
471 if (!GetBoolProperty(android::vold::kPropFuseSnapshot, false)) {
Zima438b242019-09-25 14:37:38 +0100472 // Note that sometimes the system will spin up processes from Zygote
473 // before actually starting the user, so we're okay if Zygote
474 // already created this directory.
475 std::string path(StringPrintf("%s/%d", kPathUserMount, userId));
476 fs_prepare_dir(path.c_str(), 0755, AID_ROOT, AID_ROOT);
477
478 if (mPrimary) {
479 linkPrimary(userId);
480 }
481 }
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700482
Jeff Sharkeybd3038d2015-06-10 09:42:01 -0700483 mStartedUsers.insert(userId);
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700484 return 0;
485}
486
Jeff Sharkeybd3038d2015-06-10 09:42:01 -0700487int VolumeManager::onUserStopped(userid_t userId) {
Sudheer Shanka40ab6742018-09-18 13:07:45 -0700488 LOG(VERBOSE) << "onUserStopped: " << userId;
Zima438b242019-09-25 14:37:38 +0100489
Zim2d45d9b2019-11-14 16:19:05 +0000490 if (mStartedUsers.find(userId) != mStartedUsers.end()) {
Zima438b242019-09-25 14:37:38 +0100491 destroyEmulatedVolumesForUser(userId);
492 }
493
Jeff Sharkeybd3038d2015-06-10 09:42:01 -0700494 mStartedUsers.erase(userId);
Sudheer Shankafa6a1742018-10-04 16:26:22 -0700495 return 0;
496}
497
Jeff Sharkey401b2602017-12-14 22:15:20 -0700498int VolumeManager::onSecureKeyguardStateChanged(bool isShowing) {
499 mSecureKeyguardShowing = isShowing;
500 if (!mSecureKeyguardShowing) {
501 // Now that secure keyguard has been dismissed, process
502 // any pending disks
503 for (const auto& disk : mPendingDisks) {
504 disk->create();
505 mDisks.push_back(disk);
506 }
507 mPendingDisks.clear();
508 }
509 return 0;
510}
511
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700512int VolumeManager::setPrimary(const std::shared_ptr<android::vold::VolumeBase>& vol) {
513 mPrimary = vol;
Jeff Sharkeybd3038d2015-06-10 09:42:01 -0700514 for (userid_t userId : mStartedUsers) {
Sudheer Shanka40ab6742018-09-18 13:07:45 -0700515 linkPrimary(userId);
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700516 }
517 return 0;
518}
519
Narayan Kamath02efdf52019-11-27 10:53:51 +0000520// This code is executed after a fork so it's very important that the set of
521// methods we call here is strictly limited.
522//
523// TODO: Get rid of this guesswork altogether and instead exec a process
524// immediately after fork to do our bindding for us.
525static bool childProcess(const char* storageSource, const char* userSource, int nsFd,
526 struct dirent* de) {
527 if (setns(nsFd, CLONE_NEWNS) != 0) {
528 async_safe_format_log(ANDROID_LOG_ERROR, "vold", "Failed to setns for %s :%s", de->d_name,
529 strerror(errno));
530 return false;
531 }
532
533 // NOTE: Inlined from vold::UnmountTree here to avoid using PLOG methods and
534 // to also protect against future changes that may cause issues across a
535 // fork.
536 if (TEMP_FAILURE_RETRY(umount2("/storage/", MNT_DETACH)) < 0 && errno != EINVAL &&
537 errno != ENOENT) {
538 async_safe_format_log(ANDROID_LOG_ERROR, "vold", "Failed to unmount /storage/ :%s",
539 strerror(errno));
540 return false;
541 }
542
543 if (TEMP_FAILURE_RETRY(mount(storageSource, "/storage", NULL, MS_BIND | MS_REC, NULL)) == -1) {
544 async_safe_format_log(ANDROID_LOG_ERROR, "vold", "Failed to mount %s for %s :%s",
545 storageSource, de->d_name, strerror(errno));
546 return false;
547 }
548
549 if (TEMP_FAILURE_RETRY(mount(NULL, "/storage", NULL, MS_REC | MS_SLAVE, NULL)) == -1) {
550 async_safe_format_log(ANDROID_LOG_ERROR, "vold",
551 "Failed to set MS_SLAVE to /storage for %s :%s", de->d_name,
552 strerror(errno));
553 return false;
554 }
555
556 if (TEMP_FAILURE_RETRY(mount(userSource, "/storage/self", NULL, MS_BIND, NULL)) == -1) {
557 async_safe_format_log(ANDROID_LOG_ERROR, "vold", "Failed to mount %s for %s :%s",
558 userSource, de->d_name, strerror(errno));
559 return false;
560 }
561
562 return true;
563}
564
Sudheer Shanka817b9112018-12-13 17:40:28 -0800565int VolumeManager::remountUid(uid_t uid, int32_t mountMode) {
shafik5cf32b52019-09-25 13:56:01 +0100566 if (GetBoolProperty(android::vold::kPropFuseSnapshot, false)) {
Zim3623a212019-07-19 16:46:53 +0100567 // TODO(135341433): Implement fuse specific logic.
568 return 0;
569 }
Sudheer Shanka817b9112018-12-13 17:40:28 -0800570 std::string mode;
571 switch (mountMode) {
572 case VoldNativeService::REMOUNT_MODE_NONE:
573 mode = "none";
574 break;
575 case VoldNativeService::REMOUNT_MODE_DEFAULT:
576 mode = "default";
577 break;
578 case VoldNativeService::REMOUNT_MODE_READ:
579 mode = "read";
580 break;
581 case VoldNativeService::REMOUNT_MODE_WRITE:
Sudheer Shankaa05ea742019-04-12 13:55:28 -0700582 case VoldNativeService::REMOUNT_MODE_LEGACY:
583 case VoldNativeService::REMOUNT_MODE_INSTALLER:
Sudheer Shanka817b9112018-12-13 17:40:28 -0800584 mode = "write";
585 break;
Sudheer Shanka36bdf7a2019-04-18 15:18:30 -0700586 case VoldNativeService::REMOUNT_MODE_FULL:
587 mode = "full";
588 break;
Zim981222f2019-09-09 10:24:44 +0100589 case VoldNativeService::REMOUNT_MODE_PASS_THROUGH:
590 mode = "pass_through";
591 break;
Sudheer Shanka817b9112018-12-13 17:40:28 -0800592 default:
593 PLOG(ERROR) << "Unknown mode " << std::to_string(mountMode);
594 return -1;
595 }
Jeff Sharkey66270a22015-06-24 11:49:24 -0700596 LOG(DEBUG) << "Remounting " << uid << " as mode " << mode;
597
598 DIR* dir;
599 struct dirent* de;
Jeff Sharkey3472e522017-10-06 18:02:53 -0600600 std::string rootName;
601 std::string pidName;
Jeff Sharkey66270a22015-06-24 11:49:24 -0700602 int pidFd;
603 int nsFd;
604 struct stat sb;
605 pid_t child;
Narayan Kamath02efdf52019-11-27 10:53:51 +0000606 std::string userSource;
607 std::string storageSource;
Jeff Sharkey66270a22015-06-24 11:49:24 -0700608
Jiyong Park8d21c922019-01-04 13:35:25 +0900609 static bool apexUpdatable = android::sysprop::ApexProperties::updatable().value_or(false);
610
Jeff Sharkey66270a22015-06-24 11:49:24 -0700611 if (!(dir = opendir("/proc"))) {
612 PLOG(ERROR) << "Failed to opendir";
613 return -1;
614 }
615
616 // Figure out root namespace to compare against below
Jeff Sharkey3472e522017-10-06 18:02:53 -0600617 if (!android::vold::Readlinkat(dirfd(dir), "1/ns/mnt", &rootName)) {
618 PLOG(ERROR) << "Failed to read root namespace";
Jeff Sharkey66270a22015-06-24 11:49:24 -0700619 closedir(dir);
620 return -1;
621 }
622
623 // Poke through all running PIDs look for apps running as UID
624 while ((de = readdir(dir))) {
Jeff Vander Stoep58890832017-10-23 17:12:31 -0700625 pid_t pid;
626 if (de->d_type != DT_DIR) continue;
627 if (!android::base::ParseInt(de->d_name, &pid)) continue;
628
Jeff Sharkey66270a22015-06-24 11:49:24 -0700629 pidFd = -1;
630 nsFd = -1;
631
632 pidFd = openat(dirfd(dir), de->d_name, O_RDONLY | O_DIRECTORY | O_CLOEXEC);
633 if (pidFd < 0) {
634 goto next;
635 }
636 if (fstat(pidFd, &sb) != 0) {
637 PLOG(WARNING) << "Failed to stat " << de->d_name;
638 goto next;
639 }
640 if (sb.st_uid != uid) {
641 goto next;
642 }
643
644 // Matches so far, but refuse to touch if in root namespace
645 LOG(DEBUG) << "Found matching PID " << de->d_name;
Jeff Sharkey3472e522017-10-06 18:02:53 -0600646 if (!android::vold::Readlinkat(pidFd, "ns/mnt", &pidName)) {
Jeff Sharkey66270a22015-06-24 11:49:24 -0700647 PLOG(WARNING) << "Failed to read namespace for " << de->d_name;
648 goto next;
649 }
Jeff Sharkey3472e522017-10-06 18:02:53 -0600650 if (rootName == pidName) {
Jeff Sharkey66270a22015-06-24 11:49:24 -0700651 LOG(WARNING) << "Skipping due to root namespace";
652 goto next;
653 }
654
Jiyong Park8d21c922019-01-04 13:35:25 +0900655 if (apexUpdatable) {
656 std::string exeName;
657 // When ro.apex.bionic_updatable is set to true,
658 // some early native processes have mount namespaces that are different
659 // from that of the init. Therefore, above check can't filter them out.
660 // Since the propagation type of / is 'shared', unmounting /storage
661 // for the early native processes affects other processes including
662 // init. Filter out such processes by skipping if a process is a
663 // non-Java process whose UID is < AID_APP_START. (The UID condition
664 // is required to not filter out child processes spawned by apps.)
665 if (!android::vold::Readlinkat(pidFd, "exe", &exeName)) {
666 PLOG(WARNING) << "Failed to read exe name for " << de->d_name;
667 goto next;
668 }
669 if (!StartsWith(exeName, "/system/bin/app_process") && sb.st_uid < AID_APP_START) {
670 LOG(WARNING) << "Skipping due to native system process";
671 goto next;
672 }
673 }
674
Jeff Sharkey66270a22015-06-24 11:49:24 -0700675 // We purposefully leave the namespace open across the fork
Nick Kraleviche7e89ac2019-03-29 16:03:51 -0700676 // NOLINTNEXTLINE(android-cloexec-open): Deliberately not O_CLOEXEC
677 nsFd = openat(pidFd, "ns/mnt", O_RDONLY);
Jeff Sharkey66270a22015-06-24 11:49:24 -0700678 if (nsFd < 0) {
Jeff Sharkeyc7b5b572015-06-30 15:54:17 -0700679 PLOG(WARNING) << "Failed to open namespace for " << de->d_name;
Jeff Sharkey66270a22015-06-24 11:49:24 -0700680 goto next;
681 }
682
Narayan Kamath02efdf52019-11-27 10:53:51 +0000683 if (mode == "default") {
684 storageSource = "/mnt/runtime/default";
685 } else if (mode == "read") {
686 storageSource = "/mnt/runtime/read";
687 } else if (mode == "write") {
688 storageSource = "/mnt/runtime/write";
689 } else if (mode == "full") {
690 storageSource = "/mnt/runtime/full";
691 } else {
692 // Sane default of no storage visible. No need to fork a child
693 // to remount uid.
694 goto next;
695 }
696
697 // Mount user-specific symlink helper into place
698 userSource = StringPrintf("/mnt/user/%d", multiuser_get_user_id(uid));
Jeff Sharkey66270a22015-06-24 11:49:24 -0700699 if (!(child = fork())) {
Narayan Kamath02efdf52019-11-27 10:53:51 +0000700 if (childProcess(storageSource.c_str(), userSource.c_str(), nsFd, de)) {
Jeff Sharkey66270a22015-06-24 11:49:24 -0700701 _exit(0);
Narayan Kamath02efdf52019-11-27 10:53:51 +0000702 } else {
Jeff Sharkeyc7b5b572015-06-30 15:54:17 -0700703 _exit(1);
Jeff Sharkey66270a22015-06-24 11:49:24 -0700704 }
Jeff Sharkey66270a22015-06-24 11:49:24 -0700705 }
706
707 if (child == -1) {
708 PLOG(ERROR) << "Failed to fork";
709 goto next;
710 } else {
711 TEMP_FAILURE_RETRY(waitpid(child, nullptr, 0));
712 }
713
Paul Crowleyedf7a4e2018-09-18 15:14:18 -0700714 next:
Jeff Sharkey66270a22015-06-24 11:49:24 -0700715 close(nsFd);
716 close(pidFd);
717 }
718 closedir(dir);
719 return 0;
720}
721
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700722int VolumeManager::reset() {
723 // Tear down all existing disks/volumes and start from a blank slate so
724 // newly connected framework hears all events.
Zima438b242019-09-25 14:37:38 +0100725 for (const auto& vol : mInternalEmulatedVolumes) {
726 vol->destroy();
Gao Xiangd263da82017-08-14 11:32:13 +0800727 }
Zima438b242019-09-25 14:37:38 +0100728 mInternalEmulatedVolumes.clear();
Zima438b242019-09-25 14:37:38 +0100729
Chih-Hung Hsieh11a2ce82016-07-27 14:11:02 -0700730 for (const auto& disk : mDisks) {
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700731 disk->destroy();
732 disk->create();
733 }
Jeff Sharkeyfa1c6772017-03-25 22:49:13 -0600734 updateVirtualDisk();
Jeff Sharkeybd3038d2015-06-10 09:42:01 -0700735 mAddedUsers.clear();
Sudheer Shanka023b5392019-02-06 12:39:19 -0800736 mStartedUsers.clear();
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700737 return 0;
738}
739
Keun-young Parka5bbb5e2017-03-13 18:02:50 -0700740// Can be called twice (sequentially) during shutdown. should be safe for that.
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700741int VolumeManager::shutdown() {
Zima438b242019-09-25 14:37:38 +0100742 if (mInternalEmulatedVolumes.empty()) {
Paul Crowleyedf7a4e2018-09-18 15:14:18 -0700743 return 0; // already shutdown
Keun-young Parka5bbb5e2017-03-13 18:02:50 -0700744 }
Paul Crowley56292ef2017-10-20 08:07:53 -0700745 android::vold::sSleepOnUnmount = false;
Zima438b242019-09-25 14:37:38 +0100746 for (const auto& vol : mInternalEmulatedVolumes) {
747 vol->destroy();
748 }
Chih-Hung Hsieh11a2ce82016-07-27 14:11:02 -0700749 for (const auto& disk : mDisks) {
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700750 disk->destroy();
751 }
Zima438b242019-09-25 14:37:38 +0100752
753 mInternalEmulatedVolumes.clear();
Risan8c9f3322018-10-29 08:52:56 +0900754 mStubVolumes.clear();
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700755 mDisks.clear();
Jeff Sharkey401b2602017-12-14 22:15:20 -0700756 mPendingDisks.clear();
Paul Crowley56292ef2017-10-20 08:07:53 -0700757 android::vold::sSleepOnUnmount = true;
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700758 return 0;
San Mehatf1b736b2009-10-10 17:22:08 -0700759}
760
Jeff Sharkey9c484982015-03-31 10:35:33 -0700761int VolumeManager::unmountAll() {
Jeff Sharkeyc8e04c52015-04-21 12:14:17 -0700762 std::lock_guard<std::mutex> lock(mLock);
Jeff Sharkey67b8c492017-09-21 17:08:43 -0600763 ATRACE_NAME("VolumeManager::unmountAll()");
Jeff Sharkeyc8e04c52015-04-21 12:14:17 -0700764
Jeff Sharkey9c484982015-03-31 10:35:33 -0700765 // First, try gracefully unmounting all known devices
Zima438b242019-09-25 14:37:38 +0100766 for (const auto& vol : mInternalEmulatedVolumes) {
767 vol->unmount();
Jeff Sharkey9c484982015-03-31 10:35:33 -0700768 }
Risan8c9f3322018-10-29 08:52:56 +0900769 for (const auto& stub : mStubVolumes) {
770 stub->unmount();
771 }
Chih-Hung Hsieh11a2ce82016-07-27 14:11:02 -0700772 for (const auto& disk : mDisks) {
Jeff Sharkey9c484982015-03-31 10:35:33 -0700773 disk->unmountAll();
774 }
775
776 // Worst case we might have some stale mounts lurking around, so
777 // force unmount those just to be safe.
LongPing.WEI4f046062018-11-23 19:27:35 +0800778 FILE* fp = setmntent("/proc/mounts", "re");
Jeff Sharkey9c484982015-03-31 10:35:33 -0700779 if (fp == NULL) {
Jeff Sharkey3472e522017-10-06 18:02:53 -0600780 PLOG(ERROR) << "Failed to open /proc/mounts";
Jeff Sharkey9c484982015-03-31 10:35:33 -0700781 return -errno;
782 }
783
784 // Some volumes can be stacked on each other, so force unmount in
785 // reverse order to give us the best chance of success.
786 std::list<std::string> toUnmount;
787 mntent* mentry;
788 while ((mentry = getmntent(fp)) != NULL) {
Jeff Sharkey3472e522017-10-06 18:02:53 -0600789 auto test = std::string(mentry->mnt_dir);
Mark Salyzyn86e81e72018-09-20 10:09:27 -0700790 if ((StartsWith(test, "/mnt/") &&
791#ifdef __ANDROID_DEBUGGABLE__
792 !StartsWith(test, "/mnt/scratch") &&
793#endif
794 !StartsWith(test, "/mnt/vendor") && !StartsWith(test, "/mnt/product")) ||
795 StartsWith(test, "/storage/")) {
Jeff Sharkey3472e522017-10-06 18:02:53 -0600796 toUnmount.push_front(test);
Jeff Sharkey9c484982015-03-31 10:35:33 -0700797 }
798 }
799 endmntent(fp);
800
Chih-Hung Hsieh11a2ce82016-07-27 14:11:02 -0700801 for (const auto& path : toUnmount) {
Jeff Sharkey11c2d382017-09-11 10:32:01 -0600802 LOG(DEBUG) << "Tearing down stale mount " << path;
Jeff Sharkey9c484982015-03-31 10:35:33 -0700803 android::vold::ForceUnmount(path);
804 }
805
806 return 0;
807}
808
Jeff Sharkey3472e522017-10-06 18:02:53 -0600809int VolumeManager::mkdirs(const std::string& path) {
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700810 // Only offer to create directories for paths managed by vold
Mark Salyzyn86e81e72018-09-20 10:09:27 -0700811 if (StartsWith(path, "/storage/")) {
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700812 // fs_mkdirs() does symlink checking and relative path enforcement
Jeff Sharkey3472e522017-10-06 18:02:53 -0600813 return fs_mkdirs(path.c_str(), 0700);
Jeff Sharkey71ebe152013-09-17 17:24:38 -0700814 } else {
Jeff Sharkey3472e522017-10-06 18:02:53 -0600815 LOG(ERROR) << "Failed to find mounted volume for " << path;
Jeff Sharkey71ebe152013-09-17 17:24:38 -0700816 return -EINVAL;
817 }
Jeff Sharkey71ebe152013-09-17 17:24:38 -0700818}
Jeff Sharkey11c2d382017-09-11 10:32:01 -0600819
Jeff Sharkey11c2d382017-09-11 10:32:01 -0600820int VolumeManager::createObb(const std::string& sourcePath, const std::string& sourceKey,
Paul Crowleyedf7a4e2018-09-18 15:14:18 -0700821 int32_t ownerGid, std::string* outVolId) {
Jeff Sharkey11c2d382017-09-11 10:32:01 -0600822 int id = mNextObbId++;
823
824 auto vol = std::shared_ptr<android::vold::VolumeBase>(
Paul Crowleyedf7a4e2018-09-18 15:14:18 -0700825 new android::vold::ObbVolume(id, sourcePath, sourceKey, ownerGid));
Jeff Sharkey11c2d382017-09-11 10:32:01 -0600826 vol->create();
827
828 mObbVolumes.push_back(vol);
829 *outVolId = vol->getId();
830 return android::OK;
831}
832
833int VolumeManager::destroyObb(const std::string& volId) {
834 auto i = mObbVolumes.begin();
835 while (i != mObbVolumes.end()) {
836 if ((*i)->getId() == volId) {
837 (*i)->destroy();
838 i = mObbVolumes.erase(i);
839 } else {
840 ++i;
841 }
842 }
843 return android::OK;
844}
845
Risan8c9f3322018-10-29 08:52:56 +0900846int VolumeManager::createStubVolume(const std::string& sourcePath, const std::string& mountPath,
847 const std::string& fsType, const std::string& fsUuid,
848 const std::string& fsLabel, std::string* outVolId) {
849 int id = mNextStubVolumeId++;
850 auto vol = std::shared_ptr<android::vold::VolumeBase>(
851 new android::vold::StubVolume(id, sourcePath, mountPath, fsType, fsUuid, fsLabel));
852 vol->create();
853
854 mStubVolumes.push_back(vol);
855 *outVolId = vol->getId();
856 return android::OK;
857}
858
859int VolumeManager::destroyStubVolume(const std::string& volId) {
860 auto i = mStubVolumes.begin();
861 while (i != mStubVolumes.end()) {
862 if ((*i)->getId() == volId) {
863 (*i)->destroy();
864 i = mStubVolumes.erase(i);
865 } else {
866 ++i;
867 }
868 }
869 return android::OK;
870}
871
Risan8f6198d2018-10-26 20:56:45 -0600872int VolumeManager::mountAppFuse(uid_t uid, int mountId, unique_fd* device_fd) {
Risanac02a482018-10-31 21:59:47 -0600873 return android::vold::MountAppFuse(uid, mountId, device_fd);
Jeff Sharkey11c2d382017-09-11 10:32:01 -0600874}
875
Risan8f6198d2018-10-26 20:56:45 -0600876int VolumeManager::unmountAppFuse(uid_t uid, int mountId) {
Risanac02a482018-10-31 21:59:47 -0600877 return android::vold::UnmountAppFuse(uid, mountId);
Risan8f6198d2018-10-26 20:56:45 -0600878}
879
880int VolumeManager::openAppFuseFile(uid_t uid, int mountId, int fileId, int flags) {
Risanac02a482018-10-31 21:59:47 -0600881 return android::vold::OpenAppFuseFile(uid, mountId, fileId, flags);
Jeff Sharkey11c2d382017-09-11 10:32:01 -0600882}