blob: a6bed03a65b5bd1de08ea959ffe1fff2f57056e7 [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
Yabin Cuid1104f72015-01-02 13:28:28 -080017#include <dirent.h>
San Mehatf1b736b2009-10-10 17:22:08 -070018#include <errno.h>
San Mehata2677e42009-12-13 10:40:18 -080019#include <fcntl.h>
Kenny Root344ca102012-04-03 17:23:01 -070020#include <fts.h>
Yabin Cuid1104f72015-01-02 13:28:28 -080021#include <mntent.h>
22#include <stdio.h>
23#include <stdlib.h>
24#include <string.h>
25#include <sys/ioctl.h>
26#include <sys/mount.h>
San Mehata19b2502010-01-06 10:33:53 -080027#include <sys/stat.h>
28#include <sys/types.h>
Elliott Hughes0e08e842017-05-18 09:08:24 -070029#include <sys/sysmacros.h>
Jeff Sharkey66270a22015-06-24 11:49:24 -070030#include <sys/wait.h>
Yabin Cuid1104f72015-01-02 13:28:28 -080031#include <unistd.h>
San Mehata19b2502010-01-06 10:33:53 -080032
San Mehata2677e42009-12-13 10:40:18 -080033#include <linux/kdev_t.h>
San Mehatf1b736b2009-10-10 17:22:08 -070034
35#define LOG_TAG "Vold"
36
Kenny Root7b18a7b2010-03-15 13:13:41 -070037#include <openssl/md5.h>
38
Elliott Hughes7e128fb2015-12-04 15:50:53 -080039#include <android-base/logging.h>
40#include <android-base/stringprintf.h>
Jeff Sharkey71ebe152013-09-17 17:24:38 -070041#include <cutils/fs.h>
San Mehatf1b736b2009-10-10 17:22:08 -070042#include <cutils/log.h>
43
Robert Craigb9e3ba52014-02-04 10:53:00 -050044#include <selinux/android.h>
45
San Mehatfd7f5872009-10-12 11:32:47 -070046#include <sysutils/NetlinkEvent.h>
47
Kenny Root344ca102012-04-03 17:23:01 -070048#include <private/android_filesystem_config.h>
49
Jeff Sharkey5a6bfca2015-05-14 20:33:55 -070050#include "Benchmark.h"
Jeff Sharkey36801cc2015-03-13 16:09:20 -070051#include "EmulatedVolume.h"
San Mehatf1b736b2009-10-10 17:22:08 -070052#include "VolumeManager.h"
Jeff Sharkey36801cc2015-03-13 16:09:20 -070053#include "NetlinkManager.h"
San Mehata2677e42009-12-13 10:40:18 -080054#include "ResponseCode.h"
San Mehata19b2502010-01-06 10:33:53 -080055#include "Loop.h"
Jeff Sharkeyd0640f62015-05-21 22:35:42 -070056#include "fs/Ext4.h"
57#include "fs/Vfat.h"
Jeff Sharkey36801cc2015-03-13 16:09:20 -070058#include "Utils.h"
San Mehatb78a32c2010-01-10 13:02:12 -080059#include "Devmapper.h"
San Mehat586536c2010-02-16 17:12:00 -080060#include "Process.h"
San Mehatfcf24fe2010-03-03 12:37:32 -080061#include "Asec.h"
Hiroaki Miyazawa14eab552015-02-04 13:29:15 +090062#include "VoldUtil.h"
Ken Sumrall29d8da82011-05-18 17:20:07 -070063#include "cryptfs.h"
San Mehat23969932010-01-09 07:08:06 -080064
Mike Lockwood97f2fc12011-06-07 10:51:38 -070065#define MASS_STORAGE_FILE_PATH "/sys/class/android_usb/android0/f_mass_storage/lun/file"
66
Chih-Hung Hsiehcc5d5802016-05-11 15:05:05 -070067#define ROUND_UP_POWER_OF_2(number, po2) (((!!((number) & ((1U << (po2)) - 1))) << (po2))\
68 + ((number) & (~((1U << (po2)) - 1))))
Daniel Rosenberg6a74dca2014-05-23 13:47:00 -070069
Jeff Sharkey36801cc2015-03-13 16:09:20 -070070using android::base::StringPrintf;
71
Jeff Sharkey9f18fe72015-04-01 23:32:18 -070072/*
73 * Path to external storage where *only* root can access ASEC image files
74 */
75const char *VolumeManager::SEC_ASECDIR_EXT = "/mnt/secure/asec";
76
77/*
78 * Path to internal storage where *only* root can access ASEC image files
79 */
80const char *VolumeManager::SEC_ASECDIR_INT = "/data/app-asec";
81
82/*
83 * Path to where secure containers are mounted
84 */
85const char *VolumeManager::ASECDIR = "/mnt/asec";
86
87/*
88 * Path to where OBBs are mounted
89 */
90const char *VolumeManager::LOOPDIR = "/mnt/obb";
91
Jeff Sharkey36801cc2015-03-13 16:09:20 -070092static const char* kUserMountPath = "/mnt/user";
93
Jeff Sharkey36801cc2015-03-13 16:09:20 -070094static const unsigned int kMajorBlockMmc = 179;
Yu Ning942d4e82016-01-08 17:36:47 +080095static const unsigned int kMajorBlockExperimentalMin = 240;
96static const unsigned int kMajorBlockExperimentalMax = 254;
Jeff Sharkey36801cc2015-03-13 16:09:20 -070097
Daniel Rosenbergfcd34a02014-05-22 11:23:56 -070098/* writes superblock at end of file or device given by name */
99static int writeSuperBlock(const char* name, struct asec_superblock *sb, unsigned int numImgSectors) {
Jeff Sharkeyce6a9132015-04-08 21:07:21 -0700100 int sbfd = open(name, O_RDWR | O_CLOEXEC);
Daniel Rosenbergfcd34a02014-05-22 11:23:56 -0700101 if (sbfd < 0) {
102 SLOGE("Failed to open %s for superblock write (%s)", name, strerror(errno));
103 return -1;
104 }
105
106 if (lseek(sbfd, (numImgSectors * 512), SEEK_SET) < 0) {
107 SLOGE("Failed to lseek for superblock (%s)", strerror(errno));
108 close(sbfd);
109 return -1;
110 }
111
112 if (write(sbfd, sb, sizeof(struct asec_superblock)) != sizeof(struct asec_superblock)) {
113 SLOGE("Failed to write superblock (%s)", strerror(errno));
114 close(sbfd);
115 return -1;
116 }
117 close(sbfd);
118 return 0;
119}
120
Mateusz Nowaka4f48d02015-08-03 18:06:39 +0200121static unsigned long adjustSectorNumExt4(unsigned long numSectors) {
Daniel Rosenberge9196fe2014-06-10 17:16:03 -0700122 // Ext4 started to reserve 2% or 4096 clusters, whichever is smaller for
123 // preventing costly operations or unexpected ENOSPC error.
124 // Ext4::format() uses default block size without clustering.
Mateusz Nowaka4f48d02015-08-03 18:06:39 +0200125 unsigned long clusterSectors = 4096 / 512;
126 unsigned long reservedSectors = (numSectors * 2)/100 + (numSectors % 50 > 0);
Daniel Rosenberge9196fe2014-06-10 17:16:03 -0700127 numSectors += reservedSectors > (4096 * clusterSectors) ? (4096 * clusterSectors) : reservedSectors;
Daniel Rosenbergfcd34a02014-05-22 11:23:56 -0700128 return ROUND_UP_POWER_OF_2(numSectors, 3);
129}
130
Mateusz Nowaka4f48d02015-08-03 18:06:39 +0200131static unsigned long adjustSectorNumFAT(unsigned long numSectors) {
Daniel Rosenbergfcd34a02014-05-22 11:23:56 -0700132 /*
133 * Add some headroom
134 */
Mateusz Nowaka4f48d02015-08-03 18:06:39 +0200135 unsigned long fatSize = (((numSectors * 4) / 512) + 1) * 2;
Daniel Rosenbergfcd34a02014-05-22 11:23:56 -0700136 numSectors += fatSize + 2;
137 /*
138 * FAT is aligned to 32 kb with 512b sectors.
139 */
140 return ROUND_UP_POWER_OF_2(numSectors, 6);
141}
142
143static int setupLoopDevice(char* buffer, size_t len, const char* asecFileName, const char* idHash, bool debug) {
144 if (Loop::lookupActive(idHash, buffer, len)) {
145 if (Loop::create(idHash, asecFileName, buffer, len)) {
146 SLOGE("ASEC loop device creation failed for %s (%s)", asecFileName, strerror(errno));
147 return -1;
148 }
149 if (debug) {
150 SLOGD("New loop device created at %s", buffer);
151 }
152 } else {
153 if (debug) {
154 SLOGD("Found active loopback for %s at %s", asecFileName, buffer);
155 }
156 }
157 return 0;
158}
159
Mateusz Nowaka4f48d02015-08-03 18:06:39 +0200160static int setupDevMapperDevice(char* buffer, size_t len, const char* loopDevice, const char* asecFileName, const char* key, const char* idHash , unsigned long numImgSectors, bool* createdDMDevice, bool debug) {
Daniel Rosenbergfcd34a02014-05-22 11:23:56 -0700161 if (strcmp(key, "none")) {
162 if (Devmapper::lookupActive(idHash, buffer, len)) {
163 if (Devmapper::create(idHash, loopDevice, key, numImgSectors,
164 buffer, len)) {
165 SLOGE("ASEC device mapping failed for %s (%s)", asecFileName, strerror(errno));
166 return -1;
167 }
168 if (debug) {
169 SLOGD("New devmapper instance created at %s", buffer);
170 }
171 } else {
172 if (debug) {
173 SLOGD("Found active devmapper for %s at %s", asecFileName, buffer);
174 }
175 }
176 *createdDMDevice = true;
177 } else {
178 strcpy(buffer, loopDevice);
179 *createdDMDevice = false;
180 }
181 return 0;
182}
183
184static void waitForDevMapper(const char *dmDevice) {
185 /*
186 * Wait for the device mapper node to be created. Sometimes it takes a
187 * while. Wait for up to 1 second. We could also inspect incoming uevents,
188 * but that would take more effort.
189 */
190 int tries = 25;
191 while (tries--) {
192 if (!access(dmDevice, F_OK) || errno != ENOENT) {
193 break;
194 }
195 usleep(40 * 1000);
196 }
197}
198
San Mehatf1b736b2009-10-10 17:22:08 -0700199VolumeManager *VolumeManager::sInstance = NULL;
200
201VolumeManager *VolumeManager::Instance() {
202 if (!sInstance)
203 sInstance = new VolumeManager();
204 return sInstance;
205}
206
207VolumeManager::VolumeManager() {
San Mehatd9a4e352010-03-12 13:32:47 -0800208 mDebug = false;
San Mehat88705162010-01-15 09:26:28 -0800209 mActiveContainers = new AsecIdCollection();
San Mehatf1b736b2009-10-10 17:22:08 -0700210 mBroadcaster = NULL;
Mike Lockwooda28056b2010-10-28 15:21:24 -0400211 mUmsSharingCount = 0;
212 mSavedDirtyRatio = -1;
213 // set dirty ratio to 0 when UMS is active
214 mUmsDirtyRatio = 0;
San Mehatf1b736b2009-10-10 17:22:08 -0700215}
216
217VolumeManager::~VolumeManager() {
San Mehat88705162010-01-15 09:26:28 -0800218 delete mActiveContainers;
San Mehatf1b736b2009-10-10 17:22:08 -0700219}
220
Kenny Root7b18a7b2010-03-15 13:13:41 -0700221char *VolumeManager::asecHash(const char *id, char *buffer, size_t len) {
Kenny Rootacc9e7d2010-06-18 19:06:50 -0700222 static const char* digits = "0123456789abcdef";
223
Kenny Root7b18a7b2010-03-15 13:13:41 -0700224 unsigned char sig[MD5_DIGEST_LENGTH];
225
Kenny Rootacc9e7d2010-06-18 19:06:50 -0700226 if (buffer == NULL) {
227 SLOGE("Destination buffer is NULL");
228 errno = ESPIPE;
229 return NULL;
230 } else if (id == NULL) {
231 SLOGE("Source buffer is NULL");
232 errno = ESPIPE;
233 return NULL;
234 } else if (len < MD5_ASCII_LENGTH_PLUS_NULL) {
Colin Cross59846b62014-02-06 20:34:29 -0800235 SLOGE("Target hash buffer size < %d bytes (%zu)",
Kenny Rootacc9e7d2010-06-18 19:06:50 -0700236 MD5_ASCII_LENGTH_PLUS_NULL, len);
San Mehatd9a4e352010-03-12 13:32:47 -0800237 errno = ESPIPE;
238 return NULL;
239 }
Kenny Root7b18a7b2010-03-15 13:13:41 -0700240
241 MD5(reinterpret_cast<const unsigned char*>(id), strlen(id), sig);
San Mehatd9a4e352010-03-12 13:32:47 -0800242
Kenny Rootacc9e7d2010-06-18 19:06:50 -0700243 char *p = buffer;
Kenny Root7b18a7b2010-03-15 13:13:41 -0700244 for (int i = 0; i < MD5_DIGEST_LENGTH; i++) {
Kenny Rootacc9e7d2010-06-18 19:06:50 -0700245 *p++ = digits[sig[i] >> 4];
246 *p++ = digits[sig[i] & 0x0F];
San Mehatd9a4e352010-03-12 13:32:47 -0800247 }
Kenny Rootacc9e7d2010-06-18 19:06:50 -0700248 *p = '\0';
San Mehatd9a4e352010-03-12 13:32:47 -0800249
250 return buffer;
251}
252
Jeff Sharkeyf1b996d2015-04-17 17:35:20 -0700253int VolumeManager::setDebug(bool enable) {
San Mehatd9a4e352010-03-12 13:32:47 -0800254 mDebug = enable;
Jeff Sharkeyf1b996d2015-04-17 17:35:20 -0700255 return 0;
San Mehatd9a4e352010-03-12 13:32:47 -0800256}
257
San Mehatf1b736b2009-10-10 17:22:08 -0700258int VolumeManager::start() {
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700259 // Always start from a clean slate by unmounting everything in
260 // directories that we own, in case we crashed.
Jeff Sharkey9c484982015-03-31 10:35:33 -0700261 unmountAll();
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700262
263 // Assume that we always have an emulated volume on internal
264 // storage; the framework will decide if it should be mounted.
Jeff Sharkeyc8e04c52015-04-21 12:14:17 -0700265 CHECK(mInternalEmulated == nullptr);
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700266 mInternalEmulated = std::shared_ptr<android::vold::VolumeBase>(
Jeff Sharkey3161fb32015-04-12 16:03:33 -0700267 new android::vold::EmulatedVolume("/data/media"));
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700268 mInternalEmulated->create();
269
San Mehatf1b736b2009-10-10 17:22:08 -0700270 return 0;
271}
272
273int VolumeManager::stop() {
Jeff Sharkeyc8e04c52015-04-21 12:14:17 -0700274 CHECK(mInternalEmulated != nullptr);
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700275 mInternalEmulated->destroy();
276 mInternalEmulated = nullptr;
San Mehatf1b736b2009-10-10 17:22:08 -0700277 return 0;
278}
279
San Mehatfd7f5872009-10-12 11:32:47 -0700280void VolumeManager::handleBlockEvent(NetlinkEvent *evt) {
Jeff Sharkeyc8e04c52015-04-21 12:14:17 -0700281 std::lock_guard<std::mutex> lock(mLock);
282
Jeff Sharkeyf1b996d2015-04-17 17:35:20 -0700283 if (mDebug) {
284 LOG(VERBOSE) << "----------------";
285 LOG(VERBOSE) << "handleBlockEvent with action " << (int) evt->getAction();
286 evt->dump();
287 }
San Mehatf1b736b2009-10-10 17:22:08 -0700288
Mateusz Nowak64403792015-08-03 16:39:19 +0200289 std::string eventPath(evt->findParam("DEVPATH")?evt->findParam("DEVPATH"):"");
290 std::string devType(evt->findParam("DEVTYPE")?evt->findParam("DEVTYPE"):"");
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700291
292 if (devType != "disk") return;
293
294 int major = atoi(evt->findParam("MAJOR"));
295 int minor = atoi(evt->findParam("MINOR"));
296 dev_t device = makedev(major, minor);
297
298 switch (evt->getAction()) {
299 case NetlinkEvent::Action::kAdd: {
Chih-Hung Hsieh11a2ce82016-07-27 14:11:02 -0700300 for (const auto& source : mDiskSources) {
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700301 if (source->matches(eventPath)) {
Yu Ning942d4e82016-01-08 17:36:47 +0800302 // For now, assume that MMC and virtio-blk (the latter is
303 // emulator-specific; see Disk.cpp for details) devices are SD,
304 // and that everything else is USB
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700305 int flags = source->getFlags();
Yu Ning942d4e82016-01-08 17:36:47 +0800306 if (major == kMajorBlockMmc
307 || (android::vold::IsRunningInEmulator()
308 && major >= (int) kMajorBlockExperimentalMin
309 && major <= (int) kMajorBlockExperimentalMax)) {
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700310 flags |= android::vold::Disk::Flags::kSd;
311 } else {
312 flags |= android::vold::Disk::Flags::kUsb;
313 }
314
315 auto disk = new android::vold::Disk(eventPath, device,
316 source->getNickname(), flags);
317 disk->create();
318 mDisks.push_back(std::shared_ptr<android::vold::Disk>(disk));
319 break;
320 }
321 }
322 break;
323 }
324 case NetlinkEvent::Action::kChange: {
Jeff Sharkey7d9d0112015-04-14 23:14:23 -0700325 LOG(DEBUG) << "Disk at " << major << ":" << minor << " changed";
Chih-Hung Hsieh11a2ce82016-07-27 14:11:02 -0700326 for (const auto& disk : mDisks) {
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700327 if (disk->getDevice() == device) {
328 disk->readMetadata();
329 disk->readPartitions();
330 }
331 }
332 break;
333 }
334 case NetlinkEvent::Action::kRemove: {
335 auto i = mDisks.begin();
336 while (i != mDisks.end()) {
337 if ((*i)->getDevice() == device) {
338 (*i)->destroy();
339 i = mDisks.erase(i);
340 } else {
341 ++i;
342 }
343 }
344 break;
345 }
346 default: {
347 LOG(WARNING) << "Unexpected block event action " << (int) evt->getAction();
348 break;
349 }
350 }
351}
352
353void VolumeManager::addDiskSource(const std::shared_ptr<DiskSource>& diskSource) {
Wei Wang6b455c22017-01-20 11:52:33 -0800354 std::lock_guard<std::mutex> lock(mLock);
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700355 mDiskSources.push_back(diskSource);
356}
357
358std::shared_ptr<android::vold::Disk> VolumeManager::findDisk(const std::string& id) {
359 for (auto disk : mDisks) {
360 if (disk->getId() == id) {
361 return disk;
San Mehatf1b736b2009-10-10 17:22:08 -0700362 }
363 }
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700364 return nullptr;
365}
San Mehatf1b736b2009-10-10 17:22:08 -0700366
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700367std::shared_ptr<android::vold::VolumeBase> VolumeManager::findVolume(const std::string& id) {
Gao Xiangd263da82017-08-14 11:32:13 +0800368 // Vold could receive "mount" after "shutdown" command in the extreme case.
369 // If this happens, mInternalEmulated will equal nullptr and
370 // we need to deal with it in order to avoid null pointer crash.
371 if (mInternalEmulated != nullptr && mInternalEmulated->getId() == id) {
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700372 return mInternalEmulated;
San Mehatf1b736b2009-10-10 17:22:08 -0700373 }
Chih-Hung Hsieh11a2ce82016-07-27 14:11:02 -0700374 for (const auto& disk : mDisks) {
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700375 auto vol = disk->findVolume(id);
376 if (vol != nullptr) {
377 return vol;
378 }
379 }
380 return nullptr;
381}
382
Jeff Sharkeyc86ab6f2015-06-26 14:02:09 -0700383void VolumeManager::listVolumes(android::vold::VolumeBase::Type type,
384 std::list<std::string>& list) {
385 list.clear();
Chih-Hung Hsieh11a2ce82016-07-27 14:11:02 -0700386 for (const auto& disk : mDisks) {
Jeff Sharkeyc86ab6f2015-06-26 14:02:09 -0700387 disk->listVolumes(type, list);
388 }
389}
390
391nsecs_t VolumeManager::benchmarkPrivate(const std::string& id) {
Jeff Sharkey5a6bfca2015-05-14 20:33:55 -0700392 std::string path;
Jeff Sharkeyc86ab6f2015-06-26 14:02:09 -0700393 if (id == "private" || id == "null") {
Jeff Sharkey5a6bfca2015-05-14 20:33:55 -0700394 path = "/data";
Jeff Sharkeyc86ab6f2015-06-26 14:02:09 -0700395 } else {
396 auto vol = findVolume(id);
397 if (vol != nullptr && vol->getState() == android::vold::VolumeBase::State::kMounted) {
398 path = vol->getPath();
399 }
Jeff Sharkey5a6bfca2015-05-14 20:33:55 -0700400 }
401
402 if (path.empty()) {
403 LOG(WARNING) << "Failed to find volume for " << id;
404 return -1;
405 }
406
Jeff Sharkeyc86ab6f2015-06-26 14:02:09 -0700407 return android::vold::BenchmarkPrivate(path);
Jeff Sharkey5a6bfca2015-05-14 20:33:55 -0700408}
409
Jeff Sharkeybc40cc82015-06-18 14:25:08 -0700410int VolumeManager::forgetPartition(const std::string& partGuid) {
411 std::string normalizedGuid;
412 if (android::vold::NormalizeHex(partGuid, normalizedGuid)) {
413 LOG(WARNING) << "Invalid GUID " << partGuid;
414 return -1;
415 }
416
417 std::string keyPath = android::vold::BuildKeyPath(normalizedGuid);
418 if (unlink(keyPath.c_str()) != 0) {
419 LOG(ERROR) << "Failed to unlink " << keyPath;
420 return -1;
421 }
422
423 return 0;
424}
425
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700426int VolumeManager::linkPrimary(userid_t userId) {
427 std::string source(mPrimary->getPath());
428 if (mPrimary->getType() == android::vold::VolumeBase::Type::kEmulated) {
429 source = StringPrintf("%s/%d", source.c_str(), userId);
Jeff Sharkey32679a82015-07-21 14:22:01 -0700430 fs_prepare_dir(source.c_str(), 0755, AID_ROOT, AID_ROOT);
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700431 }
432
433 std::string target(StringPrintf("/mnt/user/%d/primary", userId));
434 if (TEMP_FAILURE_RETRY(unlink(target.c_str()))) {
435 if (errno != ENOENT) {
436 SLOGW("Failed to unlink %s: %s", target.c_str(), strerror(errno));
437 }
438 }
Jeff Sharkey1bfb3752015-04-29 15:22:23 -0700439 LOG(DEBUG) << "Linking " << source << " to " << target;
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700440 if (TEMP_FAILURE_RETRY(symlink(source.c_str(), target.c_str()))) {
441 SLOGW("Failed to link %s to %s: %s", source.c_str(), target.c_str(),
442 strerror(errno));
443 return -errno;
444 }
445 return 0;
446}
447
Jeff Sharkeybd3038d2015-06-10 09:42:01 -0700448int VolumeManager::onUserAdded(userid_t userId, int userSerialNumber) {
449 mAddedUsers[userId] = userSerialNumber;
450 return 0;
451}
452
453int VolumeManager::onUserRemoved(userid_t userId) {
454 mAddedUsers.erase(userId);
455 return 0;
456}
457
458int VolumeManager::onUserStarted(userid_t userId) {
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700459 // Note that sometimes the system will spin up processes from Zygote
460 // before actually starting the user, so we're okay if Zygote
461 // already created this directory.
462 std::string path(StringPrintf("%s/%d", kUserMountPath, userId));
463 fs_prepare_dir(path.c_str(), 0755, AID_ROOT, AID_ROOT);
464
Jeff Sharkeybd3038d2015-06-10 09:42:01 -0700465 mStartedUsers.insert(userId);
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700466 if (mPrimary) {
467 linkPrimary(userId);
468 }
469 return 0;
470}
471
Jeff Sharkeybd3038d2015-06-10 09:42:01 -0700472int VolumeManager::onUserStopped(userid_t userId) {
473 mStartedUsers.erase(userId);
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700474 return 0;
475}
476
477int VolumeManager::setPrimary(const std::shared_ptr<android::vold::VolumeBase>& vol) {
478 mPrimary = vol;
Jeff Sharkeybd3038d2015-06-10 09:42:01 -0700479 for (userid_t userId : mStartedUsers) {
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700480 linkPrimary(userId);
481 }
482 return 0;
483}
484
Jeff Sharkeyc7b5b572015-06-30 15:54:17 -0700485static int unmount_tree(const char* path) {
486 size_t path_len = strlen(path);
487
488 FILE* fp = setmntent("/proc/mounts", "r");
489 if (fp == NULL) {
490 ALOGE("Error opening /proc/mounts: %s", strerror(errno));
491 return -errno;
492 }
493
494 // Some volumes can be stacked on each other, so force unmount in
495 // reverse order to give us the best chance of success.
496 std::list<std::string> toUnmount;
497 mntent* mentry;
498 while ((mentry = getmntent(fp)) != NULL) {
499 if (strncmp(mentry->mnt_dir, path, path_len) == 0) {
500 toUnmount.push_front(std::string(mentry->mnt_dir));
501 }
502 }
503 endmntent(fp);
504
Chih-Hung Hsieh11a2ce82016-07-27 14:11:02 -0700505 for (const auto& path : toUnmount) {
Jeff Sharkeyc7b5b572015-06-30 15:54:17 -0700506 if (umount2(path.c_str(), MNT_DETACH)) {
507 ALOGW("Failed to unmount %s: %s", path.c_str(), strerror(errno));
508 }
509 }
510 return 0;
511}
512
Jeff Sharkey66270a22015-06-24 11:49:24 -0700513int VolumeManager::remountUid(uid_t uid, const std::string& mode) {
514 LOG(DEBUG) << "Remounting " << uid << " as mode " << mode;
515
516 DIR* dir;
517 struct dirent* de;
518 char rootName[PATH_MAX];
519 char pidName[PATH_MAX];
520 int pidFd;
521 int nsFd;
522 struct stat sb;
523 pid_t child;
524
525 if (!(dir = opendir("/proc"))) {
526 PLOG(ERROR) << "Failed to opendir";
527 return -1;
528 }
529
530 // Figure out root namespace to compare against below
Daichi Hirono10d34882016-01-29 14:33:51 +0900531 if (android::vold::SaneReadLinkAt(dirfd(dir), "1/ns/mnt", rootName, PATH_MAX) == -1) {
Jeff Sharkey66270a22015-06-24 11:49:24 -0700532 PLOG(ERROR) << "Failed to readlink";
533 closedir(dir);
534 return -1;
535 }
536
537 // Poke through all running PIDs look for apps running as UID
538 while ((de = readdir(dir))) {
539 pidFd = -1;
540 nsFd = -1;
541
542 pidFd = openat(dirfd(dir), de->d_name, O_RDONLY | O_DIRECTORY | O_CLOEXEC);
543 if (pidFd < 0) {
544 goto next;
545 }
546 if (fstat(pidFd, &sb) != 0) {
547 PLOG(WARNING) << "Failed to stat " << de->d_name;
548 goto next;
549 }
550 if (sb.st_uid != uid) {
551 goto next;
552 }
553
554 // Matches so far, but refuse to touch if in root namespace
555 LOG(DEBUG) << "Found matching PID " << de->d_name;
Daichi Hirono10d34882016-01-29 14:33:51 +0900556 if (android::vold::SaneReadLinkAt(pidFd, "ns/mnt", pidName, PATH_MAX) == -1) {
Jeff Sharkey66270a22015-06-24 11:49:24 -0700557 PLOG(WARNING) << "Failed to read namespace for " << de->d_name;
558 goto next;
559 }
560 if (!strcmp(rootName, pidName)) {
561 LOG(WARNING) << "Skipping due to root namespace";
562 goto next;
563 }
564
565 // We purposefully leave the namespace open across the fork
566 nsFd = openat(pidFd, "ns/mnt", O_RDONLY);
567 if (nsFd < 0) {
Jeff Sharkeyc7b5b572015-06-30 15:54:17 -0700568 PLOG(WARNING) << "Failed to open namespace for " << de->d_name;
Jeff Sharkey66270a22015-06-24 11:49:24 -0700569 goto next;
570 }
571
572 if (!(child = fork())) {
573 if (setns(nsFd, CLONE_NEWNS) != 0) {
Jeff Sharkeyc7b5b572015-06-30 15:54:17 -0700574 PLOG(ERROR) << "Failed to setns for " << de->d_name;
Jeff Sharkey66270a22015-06-24 11:49:24 -0700575 _exit(1);
576 }
577
Jeff Sharkeyc7b5b572015-06-30 15:54:17 -0700578 unmount_tree("/storage");
Jeff Sharkey66270a22015-06-24 11:49:24 -0700579
580 std::string storageSource;
581 if (mode == "default") {
Jeff Sharkey1bd078f2015-08-06 11:40:00 -0700582 storageSource = "/mnt/runtime/default";
Jeff Sharkey66270a22015-06-24 11:49:24 -0700583 } else if (mode == "read") {
Jeff Sharkey1bd078f2015-08-06 11:40:00 -0700584 storageSource = "/mnt/runtime/read";
Jeff Sharkey66270a22015-06-24 11:49:24 -0700585 } else if (mode == "write") {
Jeff Sharkey1bd078f2015-08-06 11:40:00 -0700586 storageSource = "/mnt/runtime/write";
Jeff Sharkey66270a22015-06-24 11:49:24 -0700587 } else {
588 // Sane default of no storage visible
589 _exit(0);
590 }
591 if (TEMP_FAILURE_RETRY(mount(storageSource.c_str(), "/storage",
592 NULL, MS_BIND | MS_REC | MS_SLAVE, NULL)) == -1) {
Jeff Sharkeyc7b5b572015-06-30 15:54:17 -0700593 PLOG(ERROR) << "Failed to mount " << storageSource << " for "
594 << de->d_name;
595 _exit(1);
Jeff Sharkey66270a22015-06-24 11:49:24 -0700596 }
Jeff Sharkeyc7b5b572015-06-30 15:54:17 -0700597
598 // Mount user-specific symlink helper into place
599 userid_t user_id = multiuser_get_user_id(uid);
600 std::string userSource(StringPrintf("/mnt/user/%d", user_id));
601 if (TEMP_FAILURE_RETRY(mount(userSource.c_str(), "/storage/self",
602 NULL, MS_BIND, NULL)) == -1) {
603 PLOG(ERROR) << "Failed to mount " << userSource << " for "
604 << de->d_name;
605 _exit(1);
606 }
607
Jeff Sharkey66270a22015-06-24 11:49:24 -0700608 _exit(0);
609 }
610
611 if (child == -1) {
612 PLOG(ERROR) << "Failed to fork";
613 goto next;
614 } else {
615 TEMP_FAILURE_RETRY(waitpid(child, nullptr, 0));
616 }
617
618next:
619 close(nsFd);
620 close(pidFd);
621 }
622 closedir(dir);
623 return 0;
624}
625
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700626int VolumeManager::reset() {
627 // Tear down all existing disks/volumes and start from a blank slate so
628 // newly connected framework hears all events.
Gao Xiangd263da82017-08-14 11:32:13 +0800629 if (mInternalEmulated != nullptr) {
630 mInternalEmulated->destroy();
631 mInternalEmulated->create();
632 }
Chih-Hung Hsieh11a2ce82016-07-27 14:11:02 -0700633 for (const auto& disk : mDisks) {
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700634 disk->destroy();
635 disk->create();
636 }
Jeff Sharkeybd3038d2015-06-10 09:42:01 -0700637 mAddedUsers.clear();
638 mStartedUsers.clear();
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700639 return 0;
640}
641
Keun-young Parka5bbb5e2017-03-13 18:02:50 -0700642// Can be called twice (sequentially) during shutdown. should be safe for that.
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700643int VolumeManager::shutdown() {
Keun-young Parka5bbb5e2017-03-13 18:02:50 -0700644 if (mInternalEmulated == nullptr) {
645 return 0; // already shutdown
646 }
Jeff Sharkey9c484982015-03-31 10:35:33 -0700647 mInternalEmulated->destroy();
Keun-young Parka5bbb5e2017-03-13 18:02:50 -0700648 mInternalEmulated = nullptr;
Chih-Hung Hsieh11a2ce82016-07-27 14:11:02 -0700649 for (const auto& disk : mDisks) {
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700650 disk->destroy();
651 }
652 mDisks.clear();
653 return 0;
San Mehatf1b736b2009-10-10 17:22:08 -0700654}
655
Jeff Sharkey9c484982015-03-31 10:35:33 -0700656int VolumeManager::unmountAll() {
Jeff Sharkeyc8e04c52015-04-21 12:14:17 -0700657 std::lock_guard<std::mutex> lock(mLock);
658
Jeff Sharkey9c484982015-03-31 10:35:33 -0700659 // First, try gracefully unmounting all known devices
660 if (mInternalEmulated != nullptr) {
661 mInternalEmulated->unmount();
662 }
Chih-Hung Hsieh11a2ce82016-07-27 14:11:02 -0700663 for (const auto& disk : mDisks) {
Jeff Sharkey9c484982015-03-31 10:35:33 -0700664 disk->unmountAll();
665 }
666
667 // Worst case we might have some stale mounts lurking around, so
668 // force unmount those just to be safe.
669 FILE* fp = setmntent("/proc/mounts", "r");
670 if (fp == NULL) {
671 SLOGE("Error opening /proc/mounts: %s", strerror(errno));
672 return -errno;
673 }
674
675 // Some volumes can be stacked on each other, so force unmount in
676 // reverse order to give us the best chance of success.
677 std::list<std::string> toUnmount;
678 mntent* mentry;
679 while ((mentry = getmntent(fp)) != NULL) {
680 if (strncmp(mentry->mnt_dir, "/mnt/", 5) == 0
681 || strncmp(mentry->mnt_dir, "/storage/", 9) == 0) {
682 toUnmount.push_front(std::string(mentry->mnt_dir));
683 }
684 }
685 endmntent(fp);
686
Chih-Hung Hsieh11a2ce82016-07-27 14:11:02 -0700687 for (const auto& path : toUnmount) {
Jeff Sharkey9c484982015-03-31 10:35:33 -0700688 SLOGW("Tearing down stale mount %s", path.c_str());
689 android::vold::ForceUnmount(path);
690 }
691
692 return 0;
693}
694
Kenny Root508c0e12010-07-12 09:59:49 -0700695int VolumeManager::getObbMountPath(const char *sourceFile, char *mountPath, int mountPathLen) {
696 char idHash[33];
697 if (!asecHash(sourceFile, idHash, sizeof(idHash))) {
698 SLOGE("Hash of '%s' failed (%s)", sourceFile, strerror(errno));
699 return -1;
700 }
701
702 memset(mountPath, 0, mountPathLen);
Jeff Sharkey9f18fe72015-04-01 23:32:18 -0700703 int written = snprintf(mountPath, mountPathLen, "%s/%s", VolumeManager::LOOPDIR, idHash);
rpcraigd1c226f2012-10-09 06:58:16 -0400704 if ((written < 0) || (written >= mountPathLen)) {
705 errno = EINVAL;
706 return -1;
707 }
Kenny Root508c0e12010-07-12 09:59:49 -0700708
709 if (access(mountPath, F_OK)) {
710 errno = ENOENT;
711 return -1;
712 }
713
714 return 0;
715}
716
San Mehata19b2502010-01-06 10:33:53 -0800717int VolumeManager::getAsecMountPath(const char *id, char *buffer, int maxlen) {
San Mehat88ac2c02010-03-23 11:15:58 -0700718 char asecFileName[255];
Kenny Root344ca102012-04-03 17:23:01 -0700719
Nick Kralevich0de7c612014-01-27 14:58:06 -0800720 if (!isLegalAsecId(id)) {
721 SLOGE("getAsecMountPath: Invalid asec id \"%s\"", id);
722 errno = EINVAL;
723 return -1;
724 }
725
Kenny Root344ca102012-04-03 17:23:01 -0700726 if (findAsec(id, asecFileName, sizeof(asecFileName))) {
727 SLOGE("Couldn't find ASEC %s", id);
728 return -1;
729 }
San Mehat88ac2c02010-03-23 11:15:58 -0700730
731 memset(buffer, 0, maxlen);
732 if (access(asecFileName, F_OK)) {
733 errno = ENOENT;
734 return -1;
735 }
San Mehata19b2502010-01-06 10:33:53 -0800736
Jeff Sharkey9f18fe72015-04-01 23:32:18 -0700737 int written = snprintf(buffer, maxlen, "%s/%s", VolumeManager::ASECDIR, id);
rpcraigd1c226f2012-10-09 06:58:16 -0400738 if ((written < 0) || (written >= maxlen)) {
739 SLOGE("getAsecMountPath failed for %s: couldn't construct path in buffer", id);
740 errno = EINVAL;
741 return -1;
742 }
743
San Mehata19b2502010-01-06 10:33:53 -0800744 return 0;
745}
746
Dianne Hackborn736910c2011-06-27 13:37:07 -0700747int VolumeManager::getAsecFilesystemPath(const char *id, char *buffer, int maxlen) {
748 char asecFileName[255];
Kenny Root344ca102012-04-03 17:23:01 -0700749
Nick Kralevich0de7c612014-01-27 14:58:06 -0800750 if (!isLegalAsecId(id)) {
751 SLOGE("getAsecFilesystemPath: Invalid asec id \"%s\"", id);
752 errno = EINVAL;
753 return -1;
754 }
755
Kenny Root344ca102012-04-03 17:23:01 -0700756 if (findAsec(id, asecFileName, sizeof(asecFileName))) {
757 SLOGE("Couldn't find ASEC %s", id);
758 return -1;
759 }
Dianne Hackborn736910c2011-06-27 13:37:07 -0700760
761 memset(buffer, 0, maxlen);
762 if (access(asecFileName, F_OK)) {
763 errno = ENOENT;
764 return -1;
765 }
766
rpcraigd1c226f2012-10-09 06:58:16 -0400767 int written = snprintf(buffer, maxlen, "%s", asecFileName);
768 if ((written < 0) || (written >= maxlen)) {
769 errno = EINVAL;
770 return -1;
771 }
772
Dianne Hackborn736910c2011-06-27 13:37:07 -0700773 return 0;
774}
775
Mateusz Nowaka4f48d02015-08-03 18:06:39 +0200776int VolumeManager::createAsec(const char *id, unsigned long numSectors, const char *fstype,
Kenny Root344ca102012-04-03 17:23:01 -0700777 const char *key, const int ownerUid, bool isExternal) {
San Mehatfcf24fe2010-03-03 12:37:32 -0800778 struct asec_superblock sb;
779 memset(&sb, 0, sizeof(sb));
780
Nick Kralevich0de7c612014-01-27 14:58:06 -0800781 if (!isLegalAsecId(id)) {
782 SLOGE("createAsec: Invalid asec id \"%s\"", id);
783 errno = EINVAL;
784 return -1;
785 }
786
Kenny Root344ca102012-04-03 17:23:01 -0700787 const bool wantFilesystem = strcmp(fstype, "none");
788 bool usingExt4 = false;
789 if (wantFilesystem) {
790 usingExt4 = !strcmp(fstype, "ext4");
791 if (usingExt4) {
792 sb.c_opts |= ASEC_SB_C_OPTS_EXT4;
793 } else if (strcmp(fstype, "fat")) {
794 SLOGE("Invalid filesystem type %s", fstype);
795 errno = EINVAL;
796 return -1;
797 }
798 }
799
San Mehatfcf24fe2010-03-03 12:37:32 -0800800 sb.magic = ASEC_SB_MAGIC;
801 sb.ver = ASEC_SB_VER;
San Mehata19b2502010-01-06 10:33:53 -0800802
San Mehatd31e3802010-02-18 08:37:45 -0800803 if (numSectors < ((1024*1024)/512)) {
Mateusz Nowaka4f48d02015-08-03 18:06:39 +0200804 SLOGE("Invalid container size specified (%lu sectors)", numSectors);
San Mehatd31e3802010-02-18 08:37:45 -0800805 errno = EINVAL;
806 return -1;
807 }
808
San Mehata19b2502010-01-06 10:33:53 -0800809 char asecFileName[255];
Kenny Root344ca102012-04-03 17:23:01 -0700810
811 if (!findAsec(id, asecFileName, sizeof(asecFileName))) {
812 SLOGE("ASEC file '%s' currently exists - destroy it first! (%s)",
813 asecFileName, strerror(errno));
814 errno = EADDRINUSE;
815 return -1;
816 }
817
Jeff Sharkey9f18fe72015-04-01 23:32:18 -0700818 const char *asecDir = isExternal ? VolumeManager::SEC_ASECDIR_EXT : VolumeManager::SEC_ASECDIR_INT;
Kenny Root344ca102012-04-03 17:23:01 -0700819
rpcraigd1c226f2012-10-09 06:58:16 -0400820 int written = snprintf(asecFileName, sizeof(asecFileName), "%s/%s.asec", asecDir, id);
821 if ((written < 0) || (size_t(written) >= sizeof(asecFileName))) {
822 errno = EINVAL;
823 return -1;
824 }
San Mehata19b2502010-01-06 10:33:53 -0800825
826 if (!access(asecFileName, F_OK)) {
San Mehat97ac40e2010-03-24 10:24:19 -0700827 SLOGE("ASEC file '%s' currently exists - destroy it first! (%s)",
Kenny Root344ca102012-04-03 17:23:01 -0700828 asecFileName, strerror(errno));
San Mehata19b2502010-01-06 10:33:53 -0800829 errno = EADDRINUSE;
830 return -1;
831 }
832
Mateusz Nowaka4f48d02015-08-03 18:06:39 +0200833 unsigned long numImgSectors;
Daniel Rosenberg6a74dca2014-05-23 13:47:00 -0700834 if (usingExt4)
Daniel Rosenbergfcd34a02014-05-22 11:23:56 -0700835 numImgSectors = adjustSectorNumExt4(numSectors);
Daniel Rosenberg6a74dca2014-05-23 13:47:00 -0700836 else
Daniel Rosenbergfcd34a02014-05-22 11:23:56 -0700837 numImgSectors = adjustSectorNumFAT(numSectors);
San Mehatfcf24fe2010-03-03 12:37:32 -0800838
839 // Add +1 for our superblock which is at the end
840 if (Loop::createImageFile(asecFileName, numImgSectors + 1)) {
San Mehat97ac40e2010-03-24 10:24:19 -0700841 SLOGE("ASEC image file creation failed (%s)", strerror(errno));
San Mehata19b2502010-01-06 10:33:53 -0800842 return -1;
843 }
844
San Mehatd9a4e352010-03-12 13:32:47 -0800845 char idHash[33];
846 if (!asecHash(id, idHash, sizeof(idHash))) {
San Mehat97ac40e2010-03-24 10:24:19 -0700847 SLOGE("Hash of '%s' failed (%s)", id, strerror(errno));
San Mehatd9a4e352010-03-12 13:32:47 -0800848 unlink(asecFileName);
849 return -1;
850 }
851
San Mehata19b2502010-01-06 10:33:53 -0800852 char loopDevice[255];
San Mehatd9a4e352010-03-12 13:32:47 -0800853 if (Loop::create(idHash, asecFileName, loopDevice, sizeof(loopDevice))) {
San Mehat97ac40e2010-03-24 10:24:19 -0700854 SLOGE("ASEC loop device creation failed (%s)", strerror(errno));
San Mehata19b2502010-01-06 10:33:53 -0800855 unlink(asecFileName);
856 return -1;
857 }
858
San Mehatb78a32c2010-01-10 13:02:12 -0800859 char dmDevice[255];
860 bool cleanupDm = false;
San Mehata19b2502010-01-06 10:33:53 -0800861
San Mehatb78a32c2010-01-10 13:02:12 -0800862 if (strcmp(key, "none")) {
San Mehatfcf24fe2010-03-03 12:37:32 -0800863 // XXX: This is all we support for now
864 sb.c_cipher = ASEC_SB_C_CIPHER_TWOFISH;
San Mehatd9a4e352010-03-12 13:32:47 -0800865 if (Devmapper::create(idHash, loopDevice, key, numImgSectors, dmDevice,
San Mehatb78a32c2010-01-10 13:02:12 -0800866 sizeof(dmDevice))) {
San Mehat97ac40e2010-03-24 10:24:19 -0700867 SLOGE("ASEC device mapping failed (%s)", strerror(errno));
San Mehatb78a32c2010-01-10 13:02:12 -0800868 Loop::destroyByDevice(loopDevice);
869 unlink(asecFileName);
870 return -1;
871 }
872 cleanupDm = true;
873 } else {
San Mehatfcf24fe2010-03-03 12:37:32 -0800874 sb.c_cipher = ASEC_SB_C_CIPHER_NONE;
San Mehatb78a32c2010-01-10 13:02:12 -0800875 strcpy(dmDevice, loopDevice);
876 }
877
San Mehatfcf24fe2010-03-03 12:37:32 -0800878 /*
879 * Drop down the superblock at the end of the file
880 */
Daniel Rosenbergfcd34a02014-05-22 11:23:56 -0700881 if (writeSuperBlock(loopDevice, &sb, numImgSectors)) {
San Mehatfcf24fe2010-03-03 12:37:32 -0800882 if (cleanupDm) {
San Mehatd9a4e352010-03-12 13:32:47 -0800883 Devmapper::destroy(idHash);
San Mehatfcf24fe2010-03-03 12:37:32 -0800884 }
885 Loop::destroyByDevice(loopDevice);
886 unlink(asecFileName);
887 return -1;
888 }
889
Kenny Root344ca102012-04-03 17:23:01 -0700890 if (wantFilesystem) {
891 int formatStatus;
rpcraiga54e13a2012-09-21 14:17:08 -0400892 char mountPoint[255];
893
Jeff Sharkey9f18fe72015-04-01 23:32:18 -0700894 int written = snprintf(mountPoint, sizeof(mountPoint), "%s/%s", VolumeManager::ASECDIR, id);
rpcraigd1c226f2012-10-09 06:58:16 -0400895 if ((written < 0) || (size_t(written) >= sizeof(mountPoint))) {
896 SLOGE("ASEC fs format failed: couldn't construct mountPoint");
897 if (cleanupDm) {
898 Devmapper::destroy(idHash);
899 }
900 Loop::destroyByDevice(loopDevice);
901 unlink(asecFileName);
902 return -1;
903 }
rpcraiga54e13a2012-09-21 14:17:08 -0400904
Kenny Root344ca102012-04-03 17:23:01 -0700905 if (usingExt4) {
Jeff Sharkeyd0640f62015-05-21 22:35:42 -0700906 formatStatus = android::vold::ext4::Format(dmDevice, numImgSectors, mountPoint);
Kenny Root344ca102012-04-03 17:23:01 -0700907 } else {
Jeff Sharkeyd0640f62015-05-21 22:35:42 -0700908 formatStatus = android::vold::vfat::Format(dmDevice, numImgSectors);
San Mehatb78a32c2010-01-10 13:02:12 -0800909 }
San Mehata19b2502010-01-06 10:33:53 -0800910
Kenny Root344ca102012-04-03 17:23:01 -0700911 if (formatStatus < 0) {
912 SLOGE("ASEC fs format failed (%s)", strerror(errno));
San Mehatb78a32c2010-01-10 13:02:12 -0800913 if (cleanupDm) {
San Mehatd9a4e352010-03-12 13:32:47 -0800914 Devmapper::destroy(idHash);
San Mehatb78a32c2010-01-10 13:02:12 -0800915 }
San Mehateb13a902010-01-07 12:12:50 -0800916 Loop::destroyByDevice(loopDevice);
917 unlink(asecFileName);
918 return -1;
919 }
Kenny Root344ca102012-04-03 17:23:01 -0700920
Kenny Root344ca102012-04-03 17:23:01 -0700921 if (mkdir(mountPoint, 0000)) {
San Mehata1091cb2010-02-28 20:17:20 -0800922 if (errno != EEXIST) {
San Mehat97ac40e2010-03-24 10:24:19 -0700923 SLOGE("Mountpoint creation failed (%s)", strerror(errno));
San Mehata1091cb2010-02-28 20:17:20 -0800924 if (cleanupDm) {
San Mehatd9a4e352010-03-12 13:32:47 -0800925 Devmapper::destroy(idHash);
San Mehata1091cb2010-02-28 20:17:20 -0800926 }
927 Loop::destroyByDevice(loopDevice);
928 unlink(asecFileName);
929 return -1;
930 }
San Mehatb78a32c2010-01-10 13:02:12 -0800931 }
San Mehata1091cb2010-02-28 20:17:20 -0800932
Kenny Root344ca102012-04-03 17:23:01 -0700933 int mountStatus;
934 if (usingExt4) {
Jeff Sharkeyd0640f62015-05-21 22:35:42 -0700935 mountStatus = android::vold::ext4::Mount(dmDevice, mountPoint,
936 false, false, false);
Kenny Root344ca102012-04-03 17:23:01 -0700937 } else {
Jeff Sharkeyd0640f62015-05-21 22:35:42 -0700938 mountStatus = android::vold::vfat::Mount(dmDevice, mountPoint,
939 false, false, false, ownerUid, 0, 0000, false);
Kenny Root344ca102012-04-03 17:23:01 -0700940 }
941
942 if (mountStatus) {
San Mehat97ac40e2010-03-24 10:24:19 -0700943 SLOGE("ASEC FAT mount failed (%s)", strerror(errno));
San Mehata1091cb2010-02-28 20:17:20 -0800944 if (cleanupDm) {
San Mehatd9a4e352010-03-12 13:32:47 -0800945 Devmapper::destroy(idHash);
San Mehata1091cb2010-02-28 20:17:20 -0800946 }
947 Loop::destroyByDevice(loopDevice);
948 unlink(asecFileName);
949 return -1;
950 }
Kenny Root344ca102012-04-03 17:23:01 -0700951
952 if (usingExt4) {
Jeff Sharkeyce6a9132015-04-08 21:07:21 -0700953 int dirfd = open(mountPoint, O_DIRECTORY | O_CLOEXEC);
Kenny Root344ca102012-04-03 17:23:01 -0700954 if (dirfd >= 0) {
955 if (fchown(dirfd, ownerUid, AID_SYSTEM)
956 || fchmod(dirfd, S_IRUSR | S_IWUSR | S_IXUSR | S_ISGID | S_IRGRP | S_IXGRP)) {
957 SLOGI("Cannot chown/chmod new ASEC mount point %s", mountPoint);
958 }
959 close(dirfd);
960 }
961 }
San Mehata1091cb2010-02-28 20:17:20 -0800962 } else {
San Mehat97ac40e2010-03-24 10:24:19 -0700963 SLOGI("Created raw secure container %s (no filesystem)", id);
San Mehata19b2502010-01-06 10:33:53 -0800964 }
San Mehat88705162010-01-15 09:26:28 -0800965
Kenny Rootcbacf782010-09-24 15:11:48 -0700966 mActiveContainers->push_back(new ContainerData(strdup(id), ASEC));
San Mehata19b2502010-01-06 10:33:53 -0800967 return 0;
968}
969
Mateusz Nowaka4f48d02015-08-03 18:06:39 +0200970int VolumeManager::resizeAsec(const char *id, unsigned long numSectors, const char *key) {
Daniel Rosenbergfcd34a02014-05-22 11:23:56 -0700971 char asecFileName[255];
972 char mountPoint[255];
973 bool cleanupDm = false;
974
975 if (!isLegalAsecId(id)) {
976 SLOGE("resizeAsec: Invalid asec id \"%s\"", id);
977 errno = EINVAL;
978 return -1;
979 }
980
981 if (findAsec(id, asecFileName, sizeof(asecFileName))) {
982 SLOGE("Couldn't find ASEC %s", id);
983 return -1;
984 }
985
Jeff Sharkey9f18fe72015-04-01 23:32:18 -0700986 int written = snprintf(mountPoint, sizeof(mountPoint), "%s/%s", VolumeManager::ASECDIR, id);
Daniel Rosenbergfcd34a02014-05-22 11:23:56 -0700987 if ((written < 0) || (size_t(written) >= sizeof(mountPoint))) {
988 SLOGE("ASEC resize failed for %s: couldn't construct mountpoint", id);
989 return -1;
990 }
991
992 if (isMountpointMounted(mountPoint)) {
993 SLOGE("ASEC %s mounted. Unmount before resizing", id);
994 errno = EBUSY;
995 return -1;
996 }
997
998 struct asec_superblock sb;
999 int fd;
Mateusz Nowaka4f48d02015-08-03 18:06:39 +02001000 unsigned long oldNumSec = 0;
Daniel Rosenbergfcd34a02014-05-22 11:23:56 -07001001
Jeff Sharkeyce6a9132015-04-08 21:07:21 -07001002 if ((fd = open(asecFileName, O_RDONLY | O_CLOEXEC)) < 0) {
Daniel Rosenbergfcd34a02014-05-22 11:23:56 -07001003 SLOGE("Failed to open ASEC file (%s)", strerror(errno));
1004 return -1;
1005 }
1006
1007 struct stat info;
1008 if (fstat(fd, &info) < 0) {
1009 SLOGE("Failed to get file size (%s)", strerror(errno));
1010 close(fd);
1011 return -1;
1012 }
1013
1014 oldNumSec = info.st_size / 512;
1015
Mateusz Nowaka4f48d02015-08-03 18:06:39 +02001016 unsigned long numImgSectors;
Daniel Rosenbergfcd34a02014-05-22 11:23:56 -07001017 if (sb.c_opts & ASEC_SB_C_OPTS_EXT4)
1018 numImgSectors = adjustSectorNumExt4(numSectors);
1019 else
1020 numImgSectors = adjustSectorNumFAT(numSectors);
1021 /*
1022 * add one block for the superblock
1023 */
Mateusz Nowaka4f48d02015-08-03 18:06:39 +02001024 SLOGD("Resizing from %lu sectors to %lu sectors", oldNumSec, numImgSectors + 1);
Jeff Sharkey43ed1232014-08-22 12:29:05 -07001025 if (oldNumSec == numImgSectors + 1) {
1026 SLOGW("Size unchanged; ignoring resize request");
1027 return 0;
1028 } else if (oldNumSec > numImgSectors + 1) {
Daniel Rosenbergfcd34a02014-05-22 11:23:56 -07001029 SLOGE("Only growing is currently supported.");
1030 close(fd);
1031 return -1;
1032 }
1033
1034 /*
1035 * Try to read superblock.
1036 */
1037 memset(&sb, 0, sizeof(struct asec_superblock));
1038 if (lseek(fd, ((oldNumSec - 1) * 512), SEEK_SET) < 0) {
1039 SLOGE("lseek failed (%s)", strerror(errno));
1040 close(fd);
1041 return -1;
1042 }
1043 if (read(fd, &sb, sizeof(struct asec_superblock)) != sizeof(struct asec_superblock)) {
1044 SLOGE("superblock read failed (%s)", strerror(errno));
1045 close(fd);
1046 return -1;
1047 }
1048 close(fd);
1049
1050 if (mDebug) {
1051 SLOGD("Container sb magic/ver (%.8x/%.2x)", sb.magic, sb.ver);
1052 }
1053 if (sb.magic != ASEC_SB_MAGIC || sb.ver != ASEC_SB_VER) {
1054 SLOGE("Bad container magic/version (%.8x/%.2x)", sb.magic, sb.ver);
1055 errno = EMEDIUMTYPE;
1056 return -1;
1057 }
1058
1059 if (!(sb.c_opts & ASEC_SB_C_OPTS_EXT4)) {
1060 SLOGE("Only ext4 partitions are supported for resize");
1061 errno = EINVAL;
1062 return -1;
1063 }
1064
1065 if (Loop::resizeImageFile(asecFileName, numImgSectors + 1)) {
1066 SLOGE("Resize of ASEC image file failed. Could not resize %s", id);
1067 return -1;
1068 }
1069
1070 /*
1071 * Drop down a copy of the superblock at the end of the file
1072 */
1073 if (writeSuperBlock(asecFileName, &sb, numImgSectors))
1074 goto fail;
1075
1076 char idHash[33];
1077 if (!asecHash(id, idHash, sizeof(idHash))) {
1078 SLOGE("Hash of '%s' failed (%s)", id, strerror(errno));
1079 goto fail;
1080 }
1081
1082 char loopDevice[255];
1083 if (setupLoopDevice(loopDevice, sizeof(loopDevice), asecFileName, idHash, mDebug))
1084 goto fail;
1085
1086 char dmDevice[255];
1087
1088 if (setupDevMapperDevice(dmDevice, sizeof(dmDevice), loopDevice, asecFileName, key, idHash, numImgSectors, &cleanupDm, mDebug)) {
1089 Loop::destroyByDevice(loopDevice);
1090 goto fail;
1091 }
1092
1093 /*
1094 * Wait for the device mapper node to be created.
1095 */
1096 waitForDevMapper(dmDevice);
1097
Jeff Sharkeyd0640f62015-05-21 22:35:42 -07001098 if (android::vold::ext4::Resize(dmDevice, numImgSectors)) {
Daniel Rosenbergfcd34a02014-05-22 11:23:56 -07001099 SLOGE("Unable to resize %s (%s)", id, strerror(errno));
1100 if (cleanupDm) {
1101 Devmapper::destroy(idHash);
1102 }
1103 Loop::destroyByDevice(loopDevice);
1104 goto fail;
1105 }
1106
1107 return 0;
1108fail:
1109 Loop::resizeImageFile(asecFileName, oldNumSec);
1110 return -1;
1111}
1112
San Mehata19b2502010-01-06 10:33:53 -08001113int VolumeManager::finalizeAsec(const char *id) {
1114 char asecFileName[255];
1115 char loopDevice[255];
1116 char mountPoint[255];
1117
Nick Kralevich0de7c612014-01-27 14:58:06 -08001118 if (!isLegalAsecId(id)) {
1119 SLOGE("finalizeAsec: Invalid asec id \"%s\"", id);
1120 errno = EINVAL;
1121 return -1;
1122 }
1123
Kenny Root344ca102012-04-03 17:23:01 -07001124 if (findAsec(id, asecFileName, sizeof(asecFileName))) {
1125 SLOGE("Couldn't find ASEC %s", id);
1126 return -1;
1127 }
San Mehata19b2502010-01-06 10:33:53 -08001128
San Mehatd9a4e352010-03-12 13:32:47 -08001129 char idHash[33];
1130 if (!asecHash(id, idHash, sizeof(idHash))) {
San Mehat97ac40e2010-03-24 10:24:19 -07001131 SLOGE("Hash of '%s' failed (%s)", id, strerror(errno));
San Mehatd9a4e352010-03-12 13:32:47 -08001132 return -1;
1133 }
1134
1135 if (Loop::lookupActive(idHash, loopDevice, sizeof(loopDevice))) {
San Mehat97ac40e2010-03-24 10:24:19 -07001136 SLOGE("Unable to finalize %s (%s)", id, strerror(errno));
San Mehata19b2502010-01-06 10:33:53 -08001137 return -1;
1138 }
1139
Hiroaki Miyazawa14eab552015-02-04 13:29:15 +09001140 unsigned long nr_sec = 0;
Kenny Root344ca102012-04-03 17:23:01 -07001141 struct asec_superblock sb;
1142
1143 if (Loop::lookupInfo(loopDevice, &sb, &nr_sec)) {
1144 return -1;
1145 }
1146
Jeff Sharkey9f18fe72015-04-01 23:32:18 -07001147 int written = snprintf(mountPoint, sizeof(mountPoint), "%s/%s", VolumeManager::ASECDIR, id);
rpcraigd1c226f2012-10-09 06:58:16 -04001148 if ((written < 0) || (size_t(written) >= sizeof(mountPoint))) {
1149 SLOGE("ASEC finalize failed: couldn't construct mountPoint");
1150 return -1;
1151 }
Kenny Root344ca102012-04-03 17:23:01 -07001152
1153 int result = 0;
1154 if (sb.c_opts & ASEC_SB_C_OPTS_EXT4) {
Jeff Sharkeyd0640f62015-05-21 22:35:42 -07001155 result = android::vold::ext4::Mount(loopDevice, mountPoint,
1156 true, true, true);
Kenny Root344ca102012-04-03 17:23:01 -07001157 } else {
Jeff Sharkeyd0640f62015-05-21 22:35:42 -07001158 result = android::vold::vfat::Mount(loopDevice, mountPoint,
1159 true, true, true, 0, 0, 0227, false);
Kenny Root344ca102012-04-03 17:23:01 -07001160 }
1161
1162 if (result) {
San Mehat97ac40e2010-03-24 10:24:19 -07001163 SLOGE("ASEC finalize mount failed (%s)", strerror(errno));
San Mehata19b2502010-01-06 10:33:53 -08001164 return -1;
1165 }
1166
San Mehatd9a4e352010-03-12 13:32:47 -08001167 if (mDebug) {
San Mehat97ac40e2010-03-24 10:24:19 -07001168 SLOGD("ASEC %s finalized", id);
San Mehatd9a4e352010-03-12 13:32:47 -08001169 }
San Mehata19b2502010-01-06 10:33:53 -08001170 return 0;
1171}
1172
Kenny Root344ca102012-04-03 17:23:01 -07001173int VolumeManager::fixupAsecPermissions(const char *id, gid_t gid, const char* filename) {
1174 char asecFileName[255];
1175 char loopDevice[255];
1176 char mountPoint[255];
1177
1178 if (gid < AID_APP) {
1179 SLOGE("Group ID is not in application range");
1180 return -1;
1181 }
1182
Nick Kralevich0de7c612014-01-27 14:58:06 -08001183 if (!isLegalAsecId(id)) {
1184 SLOGE("fixupAsecPermissions: Invalid asec id \"%s\"", id);
1185 errno = EINVAL;
1186 return -1;
1187 }
1188
Kenny Root344ca102012-04-03 17:23:01 -07001189 if (findAsec(id, asecFileName, sizeof(asecFileName))) {
1190 SLOGE("Couldn't find ASEC %s", id);
1191 return -1;
1192 }
1193
1194 char idHash[33];
1195 if (!asecHash(id, idHash, sizeof(idHash))) {
1196 SLOGE("Hash of '%s' failed (%s)", id, strerror(errno));
1197 return -1;
1198 }
1199
1200 if (Loop::lookupActive(idHash, loopDevice, sizeof(loopDevice))) {
1201 SLOGE("Unable fix permissions during lookup on %s (%s)", id, strerror(errno));
1202 return -1;
1203 }
1204
Hiroaki Miyazawa14eab552015-02-04 13:29:15 +09001205 unsigned long nr_sec = 0;
Kenny Root344ca102012-04-03 17:23:01 -07001206 struct asec_superblock sb;
1207
1208 if (Loop::lookupInfo(loopDevice, &sb, &nr_sec)) {
1209 return -1;
1210 }
1211
Jeff Sharkey9f18fe72015-04-01 23:32:18 -07001212 int written = snprintf(mountPoint, sizeof(mountPoint), "%s/%s", VolumeManager::ASECDIR, id);
rpcraigd1c226f2012-10-09 06:58:16 -04001213 if ((written < 0) || (size_t(written) >= sizeof(mountPoint))) {
1214 SLOGE("Unable remount to fix permissions for %s: couldn't construct mountpoint", id);
1215 return -1;
1216 }
Kenny Root344ca102012-04-03 17:23:01 -07001217
1218 int result = 0;
1219 if ((sb.c_opts & ASEC_SB_C_OPTS_EXT4) == 0) {
1220 return 0;
1221 }
1222
Jeff Sharkeyd0640f62015-05-21 22:35:42 -07001223 int ret = android::vold::ext4::Mount(loopDevice, mountPoint,
Kenny Root344ca102012-04-03 17:23:01 -07001224 false /* read-only */,
1225 true /* remount */,
1226 false /* executable */);
1227 if (ret) {
1228 SLOGE("Unable remount to fix permissions for %s (%s)", id, strerror(errno));
1229 return -1;
1230 }
1231
1232 char *paths[] = { mountPoint, NULL };
1233
1234 FTS *fts = fts_open(paths, FTS_PHYSICAL | FTS_NOCHDIR | FTS_XDEV, NULL);
1235 if (fts) {
1236 // Traverse the entire hierarchy and chown to system UID.
1237 for (FTSENT *ftsent = fts_read(fts); ftsent != NULL; ftsent = fts_read(fts)) {
1238 // We don't care about the lost+found directory.
1239 if (!strcmp(ftsent->fts_name, "lost+found")) {
1240 continue;
1241 }
1242
1243 /*
1244 * There can only be one file marked as private right now.
1245 * This should be more robust, but it satisfies the requirements
1246 * we have for right now.
1247 */
1248 const bool privateFile = !strcmp(ftsent->fts_name, filename);
1249
Jeff Sharkeyce6a9132015-04-08 21:07:21 -07001250 int fd = open(ftsent->fts_accpath, O_NOFOLLOW | O_CLOEXEC);
Kenny Root344ca102012-04-03 17:23:01 -07001251 if (fd < 0) {
1252 SLOGE("Couldn't open file %s: %s", ftsent->fts_accpath, strerror(errno));
1253 result = -1;
1254 continue;
1255 }
1256
1257 result |= fchown(fd, AID_SYSTEM, privateFile? gid : AID_SYSTEM);
1258
1259 if (ftsent->fts_info & FTS_D) {
Kenny Root1a673c82012-05-10 16:45:29 -07001260 result |= fchmod(fd, 0755);
Kenny Root348c8ab2012-05-10 15:39:53 -07001261 } else if (ftsent->fts_info & FTS_F) {
Kenny Root344ca102012-04-03 17:23:01 -07001262 result |= fchmod(fd, privateFile ? 0640 : 0644);
1263 }
Robert Craigb9e3ba52014-02-04 10:53:00 -05001264
Stephen Smalley5093e612014-02-12 09:43:08 -05001265 if (selinux_android_restorecon(ftsent->fts_path, 0) < 0) {
Robert Craigb9e3ba52014-02-04 10:53:00 -05001266 SLOGE("restorecon failed for %s: %s\n", ftsent->fts_path, strerror(errno));
1267 result |= -1;
1268 }
1269
Kenny Root344ca102012-04-03 17:23:01 -07001270 close(fd);
1271 }
1272 fts_close(fts);
1273
1274 // Finally make the directory readable by everyone.
Jeff Sharkeyce6a9132015-04-08 21:07:21 -07001275 int dirfd = open(mountPoint, O_DIRECTORY | O_CLOEXEC);
Kenny Root344ca102012-04-03 17:23:01 -07001276 if (dirfd < 0 || fchmod(dirfd, 0755)) {
1277 SLOGE("Couldn't change owner of existing directory %s: %s", mountPoint, strerror(errno));
1278 result |= -1;
1279 }
1280 close(dirfd);
1281 } else {
1282 result |= -1;
1283 }
1284
Jeff Sharkeyd0640f62015-05-21 22:35:42 -07001285 result |= android::vold::ext4::Mount(loopDevice, mountPoint,
Kenny Root344ca102012-04-03 17:23:01 -07001286 true /* read-only */,
1287 true /* remount */,
1288 true /* execute */);
1289
1290 if (result) {
1291 SLOGE("ASEC fix permissions failed (%s)", strerror(errno));
1292 return -1;
1293 }
1294
1295 if (mDebug) {
1296 SLOGD("ASEC %s permissions fixed", id);
1297 }
1298 return 0;
1299}
1300
San Mehat048b0802010-01-23 08:17:06 -08001301int VolumeManager::renameAsec(const char *id1, const char *id2) {
Kenny Root344ca102012-04-03 17:23:01 -07001302 char asecFilename1[255];
San Mehat048b0802010-01-23 08:17:06 -08001303 char *asecFilename2;
1304 char mountPoint[255];
1305
Kenny Root344ca102012-04-03 17:23:01 -07001306 const char *dir;
1307
Nick Kralevich0de7c612014-01-27 14:58:06 -08001308 if (!isLegalAsecId(id1)) {
1309 SLOGE("renameAsec: Invalid asec id1 \"%s\"", id1);
1310 errno = EINVAL;
1311 return -1;
1312 }
1313
1314 if (!isLegalAsecId(id2)) {
1315 SLOGE("renameAsec: Invalid asec id2 \"%s\"", id2);
1316 errno = EINVAL;
1317 return -1;
1318 }
1319
Kenny Root344ca102012-04-03 17:23:01 -07001320 if (findAsec(id1, asecFilename1, sizeof(asecFilename1), &dir)) {
1321 SLOGE("Couldn't find ASEC %s", id1);
1322 return -1;
1323 }
1324
1325 asprintf(&asecFilename2, "%s/%s.asec", dir, id2);
San Mehat048b0802010-01-23 08:17:06 -08001326
Jeff Sharkey9f18fe72015-04-01 23:32:18 -07001327 int written = snprintf(mountPoint, sizeof(mountPoint), "%s/%s", VolumeManager::ASECDIR, id1);
rpcraigd1c226f2012-10-09 06:58:16 -04001328 if ((written < 0) || (size_t(written) >= sizeof(mountPoint))) {
1329 SLOGE("Rename failed: couldn't construct mountpoint");
1330 goto out_err;
1331 }
1332
San Mehat048b0802010-01-23 08:17:06 -08001333 if (isMountpointMounted(mountPoint)) {
San Mehat97ac40e2010-03-24 10:24:19 -07001334 SLOGW("Rename attempt when src mounted");
San Mehat048b0802010-01-23 08:17:06 -08001335 errno = EBUSY;
1336 goto out_err;
1337 }
1338
Jeff Sharkey9f18fe72015-04-01 23:32:18 -07001339 written = snprintf(mountPoint, sizeof(mountPoint), "%s/%s", VolumeManager::ASECDIR, id2);
rpcraigd1c226f2012-10-09 06:58:16 -04001340 if ((written < 0) || (size_t(written) >= sizeof(mountPoint))) {
1341 SLOGE("Rename failed: couldn't construct mountpoint2");
1342 goto out_err;
1343 }
1344
San Mehat96956ed2010-02-24 08:42:51 -08001345 if (isMountpointMounted(mountPoint)) {
San Mehat97ac40e2010-03-24 10:24:19 -07001346 SLOGW("Rename attempt when dst mounted");
San Mehat96956ed2010-02-24 08:42:51 -08001347 errno = EBUSY;
1348 goto out_err;
1349 }
1350
San Mehat048b0802010-01-23 08:17:06 -08001351 if (!access(asecFilename2, F_OK)) {
San Mehat97ac40e2010-03-24 10:24:19 -07001352 SLOGE("Rename attempt when dst exists");
San Mehat048b0802010-01-23 08:17:06 -08001353 errno = EADDRINUSE;
1354 goto out_err;
1355 }
1356
1357 if (rename(asecFilename1, asecFilename2)) {
San Mehat97ac40e2010-03-24 10:24:19 -07001358 SLOGE("Rename of '%s' to '%s' failed (%s)", asecFilename1, asecFilename2, strerror(errno));
San Mehat048b0802010-01-23 08:17:06 -08001359 goto out_err;
1360 }
1361
San Mehat048b0802010-01-23 08:17:06 -08001362 free(asecFilename2);
1363 return 0;
1364
1365out_err:
San Mehat048b0802010-01-23 08:17:06 -08001366 free(asecFilename2);
1367 return -1;
1368}
1369
Kenny Rootfb7c4d52010-06-30 18:48:41 -07001370#define UNMOUNT_RETRIES 5
1371#define UNMOUNT_SLEEP_BETWEEN_RETRY_MS (1000 * 1000)
San Mehat4ba89482010-02-18 09:00:18 -08001372int VolumeManager::unmountAsec(const char *id, bool force) {
San Mehata19b2502010-01-06 10:33:53 -08001373 char asecFileName[255];
1374 char mountPoint[255];
1375
Nick Kralevich0de7c612014-01-27 14:58:06 -08001376 if (!isLegalAsecId(id)) {
1377 SLOGE("unmountAsec: Invalid asec id \"%s\"", id);
1378 errno = EINVAL;
1379 return -1;
1380 }
1381
Kenny Root344ca102012-04-03 17:23:01 -07001382 if (findAsec(id, asecFileName, sizeof(asecFileName))) {
1383 SLOGE("Couldn't find ASEC %s", id);
1384 return -1;
1385 }
1386
Jeff Sharkey9f18fe72015-04-01 23:32:18 -07001387 int written = snprintf(mountPoint, sizeof(mountPoint), "%s/%s", VolumeManager::ASECDIR, id);
rpcraigd1c226f2012-10-09 06:58:16 -04001388 if ((written < 0) || (size_t(written) >= sizeof(mountPoint))) {
1389 SLOGE("ASEC unmount failed for %s: couldn't construct mountpoint", id);
1390 return -1;
1391 }
San Mehata19b2502010-01-06 10:33:53 -08001392
San Mehatd9a4e352010-03-12 13:32:47 -08001393 char idHash[33];
1394 if (!asecHash(id, idHash, sizeof(idHash))) {
San Mehat97ac40e2010-03-24 10:24:19 -07001395 SLOGE("Hash of '%s' failed (%s)", id, strerror(errno));
San Mehatd9a4e352010-03-12 13:32:47 -08001396 return -1;
1397 }
1398
Kenny Rootfb7c4d52010-06-30 18:48:41 -07001399 return unmountLoopImage(id, idHash, asecFileName, mountPoint, force);
1400}
1401
Kenny Root508c0e12010-07-12 09:59:49 -07001402int VolumeManager::unmountObb(const char *fileName, bool force) {
Kenny Rootfb7c4d52010-06-30 18:48:41 -07001403 char mountPoint[255];
1404
1405 char idHash[33];
1406 if (!asecHash(fileName, idHash, sizeof(idHash))) {
1407 SLOGE("Hash of '%s' failed (%s)", fileName, strerror(errno));
1408 return -1;
1409 }
1410
Jeff Sharkey9f18fe72015-04-01 23:32:18 -07001411 int written = snprintf(mountPoint, sizeof(mountPoint), "%s/%s", VolumeManager::LOOPDIR, idHash);
rpcraigd1c226f2012-10-09 06:58:16 -04001412 if ((written < 0) || (size_t(written) >= sizeof(mountPoint))) {
1413 SLOGE("OBB unmount failed for %s: couldn't construct mountpoint", fileName);
1414 return -1;
1415 }
Kenny Rootfb7c4d52010-06-30 18:48:41 -07001416
1417 return unmountLoopImage(fileName, idHash, fileName, mountPoint, force);
1418}
1419
1420int VolumeManager::unmountLoopImage(const char *id, const char *idHash,
1421 const char *fileName, const char *mountPoint, bool force) {
San Mehat0586d542010-01-12 15:38:59 -08001422 if (!isMountpointMounted(mountPoint)) {
Kenny Rootfb7c4d52010-06-30 18:48:41 -07001423 SLOGE("Unmount request for %s when not mounted", id);
Kenny Root918e5f92010-09-30 18:00:52 -07001424 errno = ENOENT;
San Mehatb78a32c2010-01-10 13:02:12 -08001425 return -1;
1426 }
San Mehat23969932010-01-09 07:08:06 -08001427
San Mehatb78a32c2010-01-10 13:02:12 -08001428 int i, rc;
Kenny Rootfb7c4d52010-06-30 18:48:41 -07001429 for (i = 1; i <= UNMOUNT_RETRIES; i++) {
San Mehatb78a32c2010-01-10 13:02:12 -08001430 rc = umount(mountPoint);
1431 if (!rc) {
1432 break;
San Mehata19b2502010-01-06 10:33:53 -08001433 }
San Mehatb78a32c2010-01-10 13:02:12 -08001434 if (rc && (errno == EINVAL || errno == ENOENT)) {
Kenny Rootfb7c4d52010-06-30 18:48:41 -07001435 SLOGI("Container %s unmounted OK", id);
San Mehatb78a32c2010-01-10 13:02:12 -08001436 rc = 0;
1437 break;
San Mehata19b2502010-01-06 10:33:53 -08001438 }
Kenny Rootfb7c4d52010-06-30 18:48:41 -07001439 SLOGW("%s unmount attempt %d failed (%s)",
San Mehat8c940ef2010-02-13 14:19:53 -08001440 id, i, strerror(errno));
San Mehatb78a32c2010-01-10 13:02:12 -08001441
Jeff Sharkey36801cc2015-03-13 16:09:20 -07001442 int signal = 0; // default is to just complain
San Mehat4ba89482010-02-18 09:00:18 -08001443
1444 if (force) {
Kenny Rootfb7c4d52010-06-30 18:48:41 -07001445 if (i > (UNMOUNT_RETRIES - 2))
Jeff Sharkey36801cc2015-03-13 16:09:20 -07001446 signal = SIGKILL;
Kenny Rootfb7c4d52010-06-30 18:48:41 -07001447 else if (i > (UNMOUNT_RETRIES - 3))
Jeff Sharkey36801cc2015-03-13 16:09:20 -07001448 signal = SIGTERM;
San Mehat4ba89482010-02-18 09:00:18 -08001449 }
San Mehat8c940ef2010-02-13 14:19:53 -08001450
Jeff Sharkey36801cc2015-03-13 16:09:20 -07001451 Process::killProcessesWithOpenFiles(mountPoint, signal);
Kenny Rootfb7c4d52010-06-30 18:48:41 -07001452 usleep(UNMOUNT_SLEEP_BETWEEN_RETRY_MS);
San Mehatb78a32c2010-01-10 13:02:12 -08001453 }
1454
1455 if (rc) {
San Mehat4ba89482010-02-18 09:00:18 -08001456 errno = EBUSY;
San Mehat97ac40e2010-03-24 10:24:19 -07001457 SLOGE("Failed to unmount container %s (%s)", id, strerror(errno));
San Mehatb78a32c2010-01-10 13:02:12 -08001458 return -1;
1459 }
1460
San Mehat12f4b892010-02-24 11:43:22 -08001461 int retries = 10;
1462
1463 while(retries--) {
1464 if (!rmdir(mountPoint)) {
1465 break;
1466 }
1467
San Mehat97ac40e2010-03-24 10:24:19 -07001468 SLOGW("Failed to rmdir %s (%s)", mountPoint, strerror(errno));
Kenny Rootfb7c4d52010-06-30 18:48:41 -07001469 usleep(UNMOUNT_SLEEP_BETWEEN_RETRY_MS);
San Mehat12f4b892010-02-24 11:43:22 -08001470 }
1471
1472 if (!retries) {
San Mehat97ac40e2010-03-24 10:24:19 -07001473 SLOGE("Timed out trying to rmdir %s (%s)", mountPoint, strerror(errno));
San Mehatf5c61982010-02-03 11:04:46 -08001474 }
San Mehat88705162010-01-15 09:26:28 -08001475
Paul Lawrence60dec162014-09-02 10:52:15 -07001476 for (i=1; i <= UNMOUNT_RETRIES; i++) {
1477 if (Devmapper::destroy(idHash) && errno != ENXIO) {
1478 SLOGE("Failed to destroy devmapper instance (%s)", strerror(errno));
1479 usleep(UNMOUNT_SLEEP_BETWEEN_RETRY_MS);
1480 continue;
1481 } else {
1482 break;
1483 }
San Mehata19b2502010-01-06 10:33:53 -08001484 }
1485
1486 char loopDevice[255];
San Mehatd9a4e352010-03-12 13:32:47 -08001487 if (!Loop::lookupActive(idHash, loopDevice, sizeof(loopDevice))) {
San Mehata19b2502010-01-06 10:33:53 -08001488 Loop::destroyByDevice(loopDevice);
San Mehatd9a4e352010-03-12 13:32:47 -08001489 } else {
Kenny Rootfb7c4d52010-06-30 18:48:41 -07001490 SLOGW("Failed to find loop device for {%s} (%s)", fileName, strerror(errno));
San Mehata19b2502010-01-06 10:33:53 -08001491 }
San Mehat88705162010-01-15 09:26:28 -08001492
1493 AsecIdCollection::iterator it;
1494 for (it = mActiveContainers->begin(); it != mActiveContainers->end(); ++it) {
Kenny Rootcbacf782010-09-24 15:11:48 -07001495 ContainerData* cd = *it;
1496 if (!strcmp(cd->id, id)) {
San Mehat88705162010-01-15 09:26:28 -08001497 free(*it);
1498 mActiveContainers->erase(it);
1499 break;
1500 }
1501 }
1502 if (it == mActiveContainers->end()) {
San Mehat97ac40e2010-03-24 10:24:19 -07001503 SLOGW("mActiveContainers is inconsistent!");
San Mehat88705162010-01-15 09:26:28 -08001504 }
San Mehatb78a32c2010-01-10 13:02:12 -08001505 return 0;
1506}
1507
San Mehat4ba89482010-02-18 09:00:18 -08001508int VolumeManager::destroyAsec(const char *id, bool force) {
San Mehatb78a32c2010-01-10 13:02:12 -08001509 char asecFileName[255];
1510 char mountPoint[255];
1511
Nick Kralevich0de7c612014-01-27 14:58:06 -08001512 if (!isLegalAsecId(id)) {
1513 SLOGE("destroyAsec: Invalid asec id \"%s\"", id);
1514 errno = EINVAL;
1515 return -1;
1516 }
1517
Kenny Root344ca102012-04-03 17:23:01 -07001518 if (findAsec(id, asecFileName, sizeof(asecFileName))) {
1519 SLOGE("Couldn't find ASEC %s", id);
1520 return -1;
1521 }
1522
Jeff Sharkey9f18fe72015-04-01 23:32:18 -07001523 int written = snprintf(mountPoint, sizeof(mountPoint), "%s/%s", VolumeManager::ASECDIR, id);
rpcraigd1c226f2012-10-09 06:58:16 -04001524 if ((written < 0) || (size_t(written) >= sizeof(mountPoint))) {
1525 SLOGE("ASEC destroy failed for %s: couldn't construct mountpoint", id);
1526 return -1;
1527 }
San Mehatb78a32c2010-01-10 13:02:12 -08001528
San Mehat0586d542010-01-12 15:38:59 -08001529 if (isMountpointMounted(mountPoint)) {
San Mehatd9a4e352010-03-12 13:32:47 -08001530 if (mDebug) {
San Mehat97ac40e2010-03-24 10:24:19 -07001531 SLOGD("Unmounting container before destroy");
San Mehatd9a4e352010-03-12 13:32:47 -08001532 }
San Mehat4ba89482010-02-18 09:00:18 -08001533 if (unmountAsec(id, force)) {
San Mehat97ac40e2010-03-24 10:24:19 -07001534 SLOGE("Failed to unmount asec %s for destroy (%s)", id, strerror(errno));
San Mehat0586d542010-01-12 15:38:59 -08001535 return -1;
1536 }
1537 }
San Mehata19b2502010-01-06 10:33:53 -08001538
San Mehat0586d542010-01-12 15:38:59 -08001539 if (unlink(asecFileName)) {
San Mehat97ac40e2010-03-24 10:24:19 -07001540 SLOGE("Failed to unlink asec '%s' (%s)", asecFileName, strerror(errno));
San Mehat0586d542010-01-12 15:38:59 -08001541 return -1;
1542 }
San Mehata19b2502010-01-06 10:33:53 -08001543
San Mehatd9a4e352010-03-12 13:32:47 -08001544 if (mDebug) {
San Mehat97ac40e2010-03-24 10:24:19 -07001545 SLOGD("ASEC %s destroyed", id);
San Mehatd9a4e352010-03-12 13:32:47 -08001546 }
San Mehata19b2502010-01-06 10:33:53 -08001547 return 0;
1548}
1549
Nick Kralevich0de7c612014-01-27 14:58:06 -08001550/*
1551 * Legal ASEC ids consist of alphanumeric characters, '-',
1552 * '_', or '.'. ".." is not allowed. The first or last character
1553 * of the ASEC id cannot be '.' (dot).
1554 */
1555bool VolumeManager::isLegalAsecId(const char *id) const {
1556 size_t i;
1557 size_t len = strlen(id);
1558
1559 if (len == 0) {
1560 return false;
1561 }
1562 if ((id[0] == '.') || (id[len - 1] == '.')) {
1563 return false;
1564 }
1565
1566 for (i = 0; i < len; i++) {
1567 if (id[i] == '.') {
1568 // i=0 is guaranteed never to have a dot. See above.
1569 if (id[i-1] == '.') return false;
1570 continue;
1571 }
1572 if (id[i] == '_' || id[i] == '-') continue;
1573 if (id[i] >= 'a' && id[i] <= 'z') continue;
1574 if (id[i] >= 'A' && id[i] <= 'Z') continue;
1575 if (id[i] >= '0' && id[i] <= '9') continue;
1576 return false;
1577 }
1578
1579 return true;
1580}
1581
Kenny Root344ca102012-04-03 17:23:01 -07001582bool VolumeManager::isAsecInDirectory(const char *dir, const char *asecName) const {
Jeff Sharkeyce6a9132015-04-08 21:07:21 -07001583 int dirfd = open(dir, O_DIRECTORY | O_CLOEXEC);
Kenny Root344ca102012-04-03 17:23:01 -07001584 if (dirfd < 0) {
1585 SLOGE("Couldn't open internal ASEC dir (%s)", strerror(errno));
Nick Kralevich25e581a2015-02-06 08:55:08 -08001586 return false;
Kenny Root344ca102012-04-03 17:23:01 -07001587 }
1588
Nick Kralevich25e581a2015-02-06 08:55:08 -08001589 struct stat sb;
1590 bool ret = (fstatat(dirfd, asecName, &sb, AT_SYMLINK_NOFOLLOW) == 0)
1591 && S_ISREG(sb.st_mode);
Kenny Root344ca102012-04-03 17:23:01 -07001592
1593 close(dirfd);
1594
1595 return ret;
1596}
1597
1598int VolumeManager::findAsec(const char *id, char *asecPath, size_t asecPathLen,
1599 const char **directory) const {
Kenny Root344ca102012-04-03 17:23:01 -07001600 char *asecName;
1601
Nick Kralevich0de7c612014-01-27 14:58:06 -08001602 if (!isLegalAsecId(id)) {
1603 SLOGE("findAsec: Invalid asec id \"%s\"", id);
1604 errno = EINVAL;
1605 return -1;
1606 }
1607
Kenny Root344ca102012-04-03 17:23:01 -07001608 if (asprintf(&asecName, "%s.asec", id) < 0) {
1609 SLOGE("Couldn't allocate string to write ASEC name");
1610 return -1;
1611 }
1612
1613 const char *dir;
Jeff Sharkey9f18fe72015-04-01 23:32:18 -07001614 if (isAsecInDirectory(VolumeManager::SEC_ASECDIR_INT, asecName)) {
1615 dir = VolumeManager::SEC_ASECDIR_INT;
1616 } else if (isAsecInDirectory(VolumeManager::SEC_ASECDIR_EXT, asecName)) {
1617 dir = VolumeManager::SEC_ASECDIR_EXT;
Kenny Root344ca102012-04-03 17:23:01 -07001618 } else {
1619 free(asecName);
1620 return -1;
1621 }
1622
1623 if (directory != NULL) {
1624 *directory = dir;
1625 }
1626
1627 if (asecPath != NULL) {
1628 int written = snprintf(asecPath, asecPathLen, "%s/%s", dir, asecName);
rpcraigd1c226f2012-10-09 06:58:16 -04001629 if ((written < 0) || (size_t(written) >= asecPathLen)) {
1630 SLOGE("findAsec failed for %s: couldn't construct ASEC path", id);
Kenny Root344ca102012-04-03 17:23:01 -07001631 free(asecName);
1632 return -1;
1633 }
1634 }
1635
1636 free(asecName);
1637 return 0;
1638}
1639
Jeff Sharkey43ed1232014-08-22 12:29:05 -07001640int VolumeManager::mountAsec(const char *id, const char *key, int ownerUid, bool readOnly) {
San Mehata19b2502010-01-06 10:33:53 -08001641 char asecFileName[255];
1642 char mountPoint[255];
1643
Nick Kralevich0de7c612014-01-27 14:58:06 -08001644 if (!isLegalAsecId(id)) {
1645 SLOGE("mountAsec: Invalid asec id \"%s\"", id);
1646 errno = EINVAL;
1647 return -1;
1648 }
1649
Kenny Root344ca102012-04-03 17:23:01 -07001650 if (findAsec(id, asecFileName, sizeof(asecFileName))) {
1651 SLOGE("Couldn't find ASEC %s", id);
1652 return -1;
1653 }
1654
Jeff Sharkey9f18fe72015-04-01 23:32:18 -07001655 int written = snprintf(mountPoint, sizeof(mountPoint), "%s/%s", VolumeManager::ASECDIR, id);
rpcraigd1c226f2012-10-09 06:58:16 -04001656 if ((written < 0) || (size_t(written) >= sizeof(mountPoint))) {
Colin Cross59846b62014-02-06 20:34:29 -08001657 SLOGE("ASEC mount failed for %s: couldn't construct mountpoint", id);
rpcraigd1c226f2012-10-09 06:58:16 -04001658 return -1;
1659 }
San Mehata19b2502010-01-06 10:33:53 -08001660
1661 if (isMountpointMounted(mountPoint)) {
San Mehat97ac40e2010-03-24 10:24:19 -07001662 SLOGE("ASEC %s already mounted", id);
San Mehata19b2502010-01-06 10:33:53 -08001663 errno = EBUSY;
1664 return -1;
1665 }
1666
San Mehatd9a4e352010-03-12 13:32:47 -08001667 char idHash[33];
1668 if (!asecHash(id, idHash, sizeof(idHash))) {
San Mehat97ac40e2010-03-24 10:24:19 -07001669 SLOGE("Hash of '%s' failed (%s)", id, strerror(errno));
San Mehatd9a4e352010-03-12 13:32:47 -08001670 return -1;
1671 }
Kenny Root7b18a7b2010-03-15 13:13:41 -07001672
San Mehata19b2502010-01-06 10:33:53 -08001673 char loopDevice[255];
Daniel Rosenbergfcd34a02014-05-22 11:23:56 -07001674 if (setupLoopDevice(loopDevice, sizeof(loopDevice), asecFileName, idHash, mDebug))
1675 return -1;
San Mehatb78a32c2010-01-10 13:02:12 -08001676
1677 char dmDevice[255];
1678 bool cleanupDm = false;
Tim Murray8439dc92014-12-15 11:56:11 -08001679
Hiroaki Miyazawa14eab552015-02-04 13:29:15 +09001680 unsigned long nr_sec = 0;
San Mehatfcf24fe2010-03-03 12:37:32 -08001681 struct asec_superblock sb;
San Mehatfcf24fe2010-03-03 12:37:32 -08001682
Kenny Root344ca102012-04-03 17:23:01 -07001683 if (Loop::lookupInfo(loopDevice, &sb, &nr_sec)) {
1684 return -1;
1685 }
San Mehatfcf24fe2010-03-03 12:37:32 -08001686
San Mehatd9a4e352010-03-12 13:32:47 -08001687 if (mDebug) {
San Mehat97ac40e2010-03-24 10:24:19 -07001688 SLOGD("Container sb magic/ver (%.8x/%.2x)", sb.magic, sb.ver);
San Mehatd9a4e352010-03-12 13:32:47 -08001689 }
San Mehatfcf24fe2010-03-03 12:37:32 -08001690 if (sb.magic != ASEC_SB_MAGIC || sb.ver != ASEC_SB_VER) {
San Mehat97ac40e2010-03-24 10:24:19 -07001691 SLOGE("Bad container magic/version (%.8x/%.2x)", sb.magic, sb.ver);
San Mehatfcf24fe2010-03-03 12:37:32 -08001692 Loop::destroyByDevice(loopDevice);
1693 errno = EMEDIUMTYPE;
1694 return -1;
1695 }
1696 nr_sec--; // We don't want the devmapping to extend onto our superblock
1697
Daniel Rosenbergfcd34a02014-05-22 11:23:56 -07001698 if (setupDevMapperDevice(dmDevice, sizeof(dmDevice), loopDevice, asecFileName, key, idHash , nr_sec, &cleanupDm, mDebug)) {
1699 Loop::destroyByDevice(loopDevice);
1700 return -1;
San Mehata19b2502010-01-06 10:33:53 -08001701 }
1702
Kenny Root344ca102012-04-03 17:23:01 -07001703 if (mkdir(mountPoint, 0000)) {
San Mehatb78a32c2010-01-10 13:02:12 -08001704 if (errno != EEXIST) {
San Mehat97ac40e2010-03-24 10:24:19 -07001705 SLOGE("Mountpoint creation failed (%s)", strerror(errno));
San Mehatb78a32c2010-01-10 13:02:12 -08001706 if (cleanupDm) {
San Mehatd9a4e352010-03-12 13:32:47 -08001707 Devmapper::destroy(idHash);
San Mehatb78a32c2010-01-10 13:02:12 -08001708 }
1709 Loop::destroyByDevice(loopDevice);
1710 return -1;
1711 }
San Mehata19b2502010-01-06 10:33:53 -08001712 }
1713
Kenny Rootcdc2a1c2012-05-03 13:49:46 -07001714 /*
Daniel Rosenbergfcd34a02014-05-22 11:23:56 -07001715 * Wait for the device mapper node to be created.
Kenny Rootcdc2a1c2012-05-03 13:49:46 -07001716 */
Daniel Rosenbergfcd34a02014-05-22 11:23:56 -07001717 waitForDevMapper(dmDevice);
Kenny Rootcdc2a1c2012-05-03 13:49:46 -07001718
Kenny Root344ca102012-04-03 17:23:01 -07001719 int result;
1720 if (sb.c_opts & ASEC_SB_C_OPTS_EXT4) {
Jeff Sharkeyd0640f62015-05-21 22:35:42 -07001721 result = android::vold::ext4::Mount(dmDevice, mountPoint,
1722 readOnly, false, readOnly);
Kenny Root344ca102012-04-03 17:23:01 -07001723 } else {
Jeff Sharkeyd0640f62015-05-21 22:35:42 -07001724 result = android::vold::vfat::Mount(dmDevice, mountPoint,
1725 readOnly, false, readOnly, ownerUid, 0, 0222, false);
Kenny Root344ca102012-04-03 17:23:01 -07001726 }
1727
1728 if (result) {
San Mehat97ac40e2010-03-24 10:24:19 -07001729 SLOGE("ASEC mount failed (%s)", strerror(errno));
San Mehatb78a32c2010-01-10 13:02:12 -08001730 if (cleanupDm) {
San Mehatd9a4e352010-03-12 13:32:47 -08001731 Devmapper::destroy(idHash);
San Mehatb78a32c2010-01-10 13:02:12 -08001732 }
1733 Loop::destroyByDevice(loopDevice);
San Mehata19b2502010-01-06 10:33:53 -08001734 return -1;
1735 }
1736
Kenny Rootcbacf782010-09-24 15:11:48 -07001737 mActiveContainers->push_back(new ContainerData(strdup(id), ASEC));
San Mehatd9a4e352010-03-12 13:32:47 -08001738 if (mDebug) {
San Mehat97ac40e2010-03-24 10:24:19 -07001739 SLOGD("ASEC %s mounted", id);
San Mehatd9a4e352010-03-12 13:32:47 -08001740 }
San Mehata19b2502010-01-06 10:33:53 -08001741 return 0;
1742}
1743
Kenny Rootfb7c4d52010-06-30 18:48:41 -07001744/**
1745 * Mounts an image file <code>img</code>.
1746 */
Jeff Sharkey69479042012-09-25 16:14:57 -07001747int VolumeManager::mountObb(const char *img, const char *key, int ownerGid) {
Kenny Rootfb7c4d52010-06-30 18:48:41 -07001748 char mountPoint[255];
1749
Kenny Rootfb7c4d52010-06-30 18:48:41 -07001750 char idHash[33];
1751 if (!asecHash(img, idHash, sizeof(idHash))) {
1752 SLOGE("Hash of '%s' failed (%s)", img, strerror(errno));
1753 return -1;
1754 }
1755
Jeff Sharkey9f18fe72015-04-01 23:32:18 -07001756 int written = snprintf(mountPoint, sizeof(mountPoint), "%s/%s", VolumeManager::LOOPDIR, idHash);
rpcraigd1c226f2012-10-09 06:58:16 -04001757 if ((written < 0) || (size_t(written) >= sizeof(mountPoint))) {
Colin Cross59846b62014-02-06 20:34:29 -08001758 SLOGE("OBB mount failed for %s: couldn't construct mountpoint", img);
rpcraigd1c226f2012-10-09 06:58:16 -04001759 return -1;
1760 }
Kenny Rootfb7c4d52010-06-30 18:48:41 -07001761
1762 if (isMountpointMounted(mountPoint)) {
1763 SLOGE("Image %s already mounted", img);
1764 errno = EBUSY;
1765 return -1;
1766 }
1767
1768 char loopDevice[255];
Daniel Rosenbergfcd34a02014-05-22 11:23:56 -07001769 if (setupLoopDevice(loopDevice, sizeof(loopDevice), img, idHash, mDebug))
1770 return -1;
Kenny Rootfb7c4d52010-06-30 18:48:41 -07001771
1772 char dmDevice[255];
1773 bool cleanupDm = false;
1774 int fd;
Hiroaki Miyazawa14eab552015-02-04 13:29:15 +09001775 unsigned long nr_sec = 0;
Kenny Rootfb7c4d52010-06-30 18:48:41 -07001776
Jeff Sharkeyce6a9132015-04-08 21:07:21 -07001777 if ((fd = open(loopDevice, O_RDWR | O_CLOEXEC)) < 0) {
Kenny Rootfb7c4d52010-06-30 18:48:41 -07001778 SLOGE("Failed to open loopdevice (%s)", strerror(errno));
1779 Loop::destroyByDevice(loopDevice);
1780 return -1;
1781 }
1782
Hiroaki Miyazawa14eab552015-02-04 13:29:15 +09001783 get_blkdev_size(fd, &nr_sec);
1784 if (nr_sec == 0) {
Kenny Rootfb7c4d52010-06-30 18:48:41 -07001785 SLOGE("Failed to get loop size (%s)", strerror(errno));
1786 Loop::destroyByDevice(loopDevice);
1787 close(fd);
1788 return -1;
1789 }
1790
1791 close(fd);
1792
Hiroaki Miyazawa14eab552015-02-04 13:29:15 +09001793 if (setupDevMapperDevice(dmDevice, sizeof(loopDevice), loopDevice, img,key, idHash, nr_sec, &cleanupDm, mDebug)) {
Daniel Rosenbergfcd34a02014-05-22 11:23:56 -07001794 Loop::destroyByDevice(loopDevice);
1795 return -1;
Kenny Rootfb7c4d52010-06-30 18:48:41 -07001796 }
1797
1798 if (mkdir(mountPoint, 0755)) {
1799 if (errno != EEXIST) {
1800 SLOGE("Mountpoint creation failed (%s)", strerror(errno));
1801 if (cleanupDm) {
1802 Devmapper::destroy(idHash);
1803 }
1804 Loop::destroyByDevice(loopDevice);
1805 return -1;
1806 }
1807 }
1808
yoshiyuki hama476a6272015-01-28 16:37:23 +09001809 /*
1810 * Wait for the device mapper node to be created.
1811 */
1812 waitForDevMapper(dmDevice);
1813
Jeff Sharkeyd0640f62015-05-21 22:35:42 -07001814 if (android::vold::vfat::Mount(dmDevice, mountPoint,
1815 true, false, true, 0, ownerGid, 0227, false)) {
Kenny Rootfb7c4d52010-06-30 18:48:41 -07001816 SLOGE("Image mount failed (%s)", strerror(errno));
1817 if (cleanupDm) {
1818 Devmapper::destroy(idHash);
1819 }
1820 Loop::destroyByDevice(loopDevice);
1821 return -1;
1822 }
1823
Kenny Rootcbacf782010-09-24 15:11:48 -07001824 mActiveContainers->push_back(new ContainerData(strdup(img), OBB));
Kenny Rootfb7c4d52010-06-30 18:48:41 -07001825 if (mDebug) {
1826 SLOGD("Image %s mounted", img);
1827 }
1828 return 0;
1829}
1830
Kenny Root508c0e12010-07-12 09:59:49 -07001831int VolumeManager::listMountedObbs(SocketClient* cli) {
Yabin Cuid1104f72015-01-02 13:28:28 -08001832 FILE *fp = setmntent("/proc/mounts", "r");
1833 if (fp == NULL) {
Kenny Root508c0e12010-07-12 09:59:49 -07001834 SLOGE("Error opening /proc/mounts (%s)", strerror(errno));
1835 return -1;
1836 }
1837
1838 // Create a string to compare against that has a trailing slash
Jeff Sharkey9f18fe72015-04-01 23:32:18 -07001839 int loopDirLen = strlen(VolumeManager::LOOPDIR);
Kenny Root508c0e12010-07-12 09:59:49 -07001840 char loopDir[loopDirLen + 2];
Jeff Sharkey9f18fe72015-04-01 23:32:18 -07001841 strcpy(loopDir, VolumeManager::LOOPDIR);
Kenny Root508c0e12010-07-12 09:59:49 -07001842 loopDir[loopDirLen++] = '/';
1843 loopDir[loopDirLen] = '\0';
1844
Yabin Cuid1104f72015-01-02 13:28:28 -08001845 mntent* mentry;
1846 while ((mentry = getmntent(fp)) != NULL) {
1847 if (!strncmp(mentry->mnt_dir, loopDir, loopDirLen)) {
Jeff Sharkeyce6a9132015-04-08 21:07:21 -07001848 int fd = open(mentry->mnt_fsname, O_RDONLY | O_CLOEXEC);
Kenny Root508c0e12010-07-12 09:59:49 -07001849 if (fd >= 0) {
1850 struct loop_info64 li;
1851 if (ioctl(fd, LOOP_GET_STATUS64, &li) >= 0) {
1852 cli->sendMsg(ResponseCode::AsecListResult,
1853 (const char*) li.lo_file_name, false);
1854 }
1855 close(fd);
1856 }
1857 }
1858 }
Yabin Cuid1104f72015-01-02 13:28:28 -08001859 endmntent(fp);
Kenny Root508c0e12010-07-12 09:59:49 -07001860 return 0;
1861}
1862
Jeff Sharkey9c484982015-03-31 10:35:33 -07001863extern "C" int vold_unmountAll(void) {
Ken Sumrall425524d2012-06-14 20:55:28 -07001864 VolumeManager *vm = VolumeManager::Instance();
Jeff Sharkey9c484982015-03-31 10:35:33 -07001865 return vm->unmountAll();
Ken Sumrall425524d2012-06-14 20:55:28 -07001866}
1867
San Mehata19b2502010-01-06 10:33:53 -08001868bool VolumeManager::isMountpointMounted(const char *mp)
1869{
Yabin Cuid1104f72015-01-02 13:28:28 -08001870 FILE *fp = setmntent("/proc/mounts", "r");
1871 if (fp == NULL) {
San Mehat97ac40e2010-03-24 10:24:19 -07001872 SLOGE("Error opening /proc/mounts (%s)", strerror(errno));
San Mehata19b2502010-01-06 10:33:53 -08001873 return false;
1874 }
1875
Yabin Cuid1104f72015-01-02 13:28:28 -08001876 bool found_mp = false;
1877 mntent* mentry;
1878 while ((mentry = getmntent(fp)) != NULL) {
1879 if (strcmp(mentry->mnt_dir, mp) == 0) {
1880 found_mp = true;
1881 break;
San Mehata19b2502010-01-06 10:33:53 -08001882 }
San Mehata19b2502010-01-06 10:33:53 -08001883 }
Yabin Cuid1104f72015-01-02 13:28:28 -08001884 endmntent(fp);
1885 return found_mp;
San Mehata19b2502010-01-06 10:33:53 -08001886}
1887
Jeff Sharkey71ebe152013-09-17 17:24:38 -07001888int VolumeManager::mkdirs(char* path) {
Jeff Sharkey36801cc2015-03-13 16:09:20 -07001889 // Only offer to create directories for paths managed by vold
1890 if (strncmp(path, "/storage/", 9) == 0) {
1891 // fs_mkdirs() does symlink checking and relative path enforcement
1892 return fs_mkdirs(path, 0700);
Jeff Sharkey71ebe152013-09-17 17:24:38 -07001893 } else {
Cylen Yao27cfee32014-05-02 19:23:42 +08001894 SLOGE("Failed to find mounted volume for %s", path);
Jeff Sharkey71ebe152013-09-17 17:24:38 -07001895 return -EINVAL;
1896 }
Jeff Sharkey71ebe152013-09-17 17:24:38 -07001897}