blob: 4a649bb50fd0411890f2f99b88db61d2f254bbab [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>
Jeff Sharkey66270a22015-06-24 11:49:24 -070029#include <sys/wait.h>
Yabin Cuid1104f72015-01-02 13:28:28 -080030#include <unistd.h>
San Mehata19b2502010-01-06 10:33:53 -080031
San Mehata2677e42009-12-13 10:40:18 -080032#include <linux/kdev_t.h>
San Mehatf1b736b2009-10-10 17:22:08 -070033
34#define LOG_TAG "Vold"
35
Kenny Root7b18a7b2010-03-15 13:13:41 -070036#include <openssl/md5.h>
37
Elliott Hughes7e128fb2015-12-04 15:50:53 -080038#include <android-base/logging.h>
39#include <android-base/stringprintf.h>
Jeff Sharkey71ebe152013-09-17 17:24:38 -070040#include <cutils/fs.h>
San Mehatf1b736b2009-10-10 17:22:08 -070041#include <cutils/log.h>
42
Robert Craigb9e3ba52014-02-04 10:53:00 -050043#include <selinux/android.h>
44
San Mehatfd7f5872009-10-12 11:32:47 -070045#include <sysutils/NetlinkEvent.h>
46
Kenny Root344ca102012-04-03 17:23:01 -070047#include <private/android_filesystem_config.h>
48
Jeff Sharkey5a6bfca2015-05-14 20:33:55 -070049#include "Benchmark.h"
Jeff Sharkey36801cc2015-03-13 16:09:20 -070050#include "EmulatedVolume.h"
San Mehatf1b736b2009-10-10 17:22:08 -070051#include "VolumeManager.h"
Jeff Sharkey36801cc2015-03-13 16:09:20 -070052#include "NetlinkManager.h"
San Mehata2677e42009-12-13 10:40:18 -080053#include "ResponseCode.h"
San Mehata19b2502010-01-06 10:33:53 -080054#include "Loop.h"
Jeff Sharkeyd0640f62015-05-21 22:35:42 -070055#include "fs/Ext4.h"
56#include "fs/Vfat.h"
Jeff Sharkey36801cc2015-03-13 16:09:20 -070057#include "Utils.h"
San Mehatb78a32c2010-01-10 13:02:12 -080058#include "Devmapper.h"
San Mehat586536c2010-02-16 17:12:00 -080059#include "Process.h"
San Mehatfcf24fe2010-03-03 12:37:32 -080060#include "Asec.h"
Hiroaki Miyazawa14eab552015-02-04 13:29:15 +090061#include "VoldUtil.h"
Ken Sumrall29d8da82011-05-18 17:20:07 -070062#include "cryptfs.h"
San Mehat23969932010-01-09 07:08:06 -080063
Mike Lockwood97f2fc12011-06-07 10:51:38 -070064#define MASS_STORAGE_FILE_PATH "/sys/class/android_usb/android0/f_mass_storage/lun/file"
65
Chih-Hung Hsiehcc5d5802016-05-11 15:05:05 -070066#define ROUND_UP_POWER_OF_2(number, po2) (((!!((number) & ((1U << (po2)) - 1))) << (po2))\
67 + ((number) & (~((1U << (po2)) - 1))))
Daniel Rosenberg6a74dca2014-05-23 13:47:00 -070068
Jeff Sharkey36801cc2015-03-13 16:09:20 -070069using android::base::StringPrintf;
70
Jeff Sharkey9f18fe72015-04-01 23:32:18 -070071/*
72 * Path to external storage where *only* root can access ASEC image files
73 */
74const char *VolumeManager::SEC_ASECDIR_EXT = "/mnt/secure/asec";
75
76/*
77 * Path to internal storage where *only* root can access ASEC image files
78 */
79const char *VolumeManager::SEC_ASECDIR_INT = "/data/app-asec";
80
81/*
82 * Path to where secure containers are mounted
83 */
84const char *VolumeManager::ASECDIR = "/mnt/asec";
85
86/*
87 * Path to where OBBs are mounted
88 */
89const char *VolumeManager::LOOPDIR = "/mnt/obb";
90
Jeff Sharkey36801cc2015-03-13 16:09:20 -070091static const char* kUserMountPath = "/mnt/user";
92
Jeff Sharkey36801cc2015-03-13 16:09:20 -070093static const unsigned int kMajorBlockMmc = 179;
Yu Ning942d4e82016-01-08 17:36:47 +080094static const unsigned int kMajorBlockExperimentalMin = 240;
95static const unsigned int kMajorBlockExperimentalMax = 254;
Jeff Sharkey36801cc2015-03-13 16:09:20 -070096
Daniel Rosenbergfcd34a02014-05-22 11:23:56 -070097/* writes superblock at end of file or device given by name */
98static int writeSuperBlock(const char* name, struct asec_superblock *sb, unsigned int numImgSectors) {
Jeff Sharkeyce6a9132015-04-08 21:07:21 -070099 int sbfd = open(name, O_RDWR | O_CLOEXEC);
Daniel Rosenbergfcd34a02014-05-22 11:23:56 -0700100 if (sbfd < 0) {
101 SLOGE("Failed to open %s for superblock write (%s)", name, strerror(errno));
102 return -1;
103 }
104
105 if (lseek(sbfd, (numImgSectors * 512), SEEK_SET) < 0) {
106 SLOGE("Failed to lseek for superblock (%s)", strerror(errno));
107 close(sbfd);
108 return -1;
109 }
110
111 if (write(sbfd, sb, sizeof(struct asec_superblock)) != sizeof(struct asec_superblock)) {
112 SLOGE("Failed to write superblock (%s)", strerror(errno));
113 close(sbfd);
114 return -1;
115 }
116 close(sbfd);
117 return 0;
118}
119
Mateusz Nowaka4f48d02015-08-03 18:06:39 +0200120static unsigned long adjustSectorNumExt4(unsigned long numSectors) {
Daniel Rosenberge9196fe2014-06-10 17:16:03 -0700121 // Ext4 started to reserve 2% or 4096 clusters, whichever is smaller for
122 // preventing costly operations or unexpected ENOSPC error.
123 // Ext4::format() uses default block size without clustering.
Mateusz Nowaka4f48d02015-08-03 18:06:39 +0200124 unsigned long clusterSectors = 4096 / 512;
125 unsigned long reservedSectors = (numSectors * 2)/100 + (numSectors % 50 > 0);
Daniel Rosenberge9196fe2014-06-10 17:16:03 -0700126 numSectors += reservedSectors > (4096 * clusterSectors) ? (4096 * clusterSectors) : reservedSectors;
Daniel Rosenbergfcd34a02014-05-22 11:23:56 -0700127 return ROUND_UP_POWER_OF_2(numSectors, 3);
128}
129
Mateusz Nowaka4f48d02015-08-03 18:06:39 +0200130static unsigned long adjustSectorNumFAT(unsigned long numSectors) {
Daniel Rosenbergfcd34a02014-05-22 11:23:56 -0700131 /*
132 * Add some headroom
133 */
Mateusz Nowaka4f48d02015-08-03 18:06:39 +0200134 unsigned long fatSize = (((numSectors * 4) / 512) + 1) * 2;
Daniel Rosenbergfcd34a02014-05-22 11:23:56 -0700135 numSectors += fatSize + 2;
136 /*
137 * FAT is aligned to 32 kb with 512b sectors.
138 */
139 return ROUND_UP_POWER_OF_2(numSectors, 6);
140}
141
142static int setupLoopDevice(char* buffer, size_t len, const char* asecFileName, const char* idHash, bool debug) {
143 if (Loop::lookupActive(idHash, buffer, len)) {
144 if (Loop::create(idHash, asecFileName, buffer, len)) {
145 SLOGE("ASEC loop device creation failed for %s (%s)", asecFileName, strerror(errno));
146 return -1;
147 }
148 if (debug) {
149 SLOGD("New loop device created at %s", buffer);
150 }
151 } else {
152 if (debug) {
153 SLOGD("Found active loopback for %s at %s", asecFileName, buffer);
154 }
155 }
156 return 0;
157}
158
Mateusz Nowaka4f48d02015-08-03 18:06:39 +0200159static 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 -0700160 if (strcmp(key, "none")) {
161 if (Devmapper::lookupActive(idHash, buffer, len)) {
162 if (Devmapper::create(idHash, loopDevice, key, numImgSectors,
163 buffer, len)) {
164 SLOGE("ASEC device mapping failed for %s (%s)", asecFileName, strerror(errno));
165 return -1;
166 }
167 if (debug) {
168 SLOGD("New devmapper instance created at %s", buffer);
169 }
170 } else {
171 if (debug) {
172 SLOGD("Found active devmapper for %s at %s", asecFileName, buffer);
173 }
174 }
175 *createdDMDevice = true;
176 } else {
177 strcpy(buffer, loopDevice);
178 *createdDMDevice = false;
179 }
180 return 0;
181}
182
183static void waitForDevMapper(const char *dmDevice) {
184 /*
185 * Wait for the device mapper node to be created. Sometimes it takes a
186 * while. Wait for up to 1 second. We could also inspect incoming uevents,
187 * but that would take more effort.
188 */
189 int tries = 25;
190 while (tries--) {
191 if (!access(dmDevice, F_OK) || errno != ENOENT) {
192 break;
193 }
194 usleep(40 * 1000);
195 }
196}
197
San Mehatf1b736b2009-10-10 17:22:08 -0700198VolumeManager *VolumeManager::sInstance = NULL;
199
200VolumeManager *VolumeManager::Instance() {
201 if (!sInstance)
202 sInstance = new VolumeManager();
203 return sInstance;
204}
205
206VolumeManager::VolumeManager() {
San Mehatd9a4e352010-03-12 13:32:47 -0800207 mDebug = false;
San Mehat88705162010-01-15 09:26:28 -0800208 mActiveContainers = new AsecIdCollection();
San Mehatf1b736b2009-10-10 17:22:08 -0700209 mBroadcaster = NULL;
Mike Lockwooda28056b2010-10-28 15:21:24 -0400210 mUmsSharingCount = 0;
211 mSavedDirtyRatio = -1;
212 // set dirty ratio to 0 when UMS is active
213 mUmsDirtyRatio = 0;
San Mehatf1b736b2009-10-10 17:22:08 -0700214}
215
216VolumeManager::~VolumeManager() {
San Mehat88705162010-01-15 09:26:28 -0800217 delete mActiveContainers;
San Mehatf1b736b2009-10-10 17:22:08 -0700218}
219
Kenny Root7b18a7b2010-03-15 13:13:41 -0700220char *VolumeManager::asecHash(const char *id, char *buffer, size_t len) {
Kenny Rootacc9e7d2010-06-18 19:06:50 -0700221 static const char* digits = "0123456789abcdef";
222
Kenny Root7b18a7b2010-03-15 13:13:41 -0700223 unsigned char sig[MD5_DIGEST_LENGTH];
224
Kenny Rootacc9e7d2010-06-18 19:06:50 -0700225 if (buffer == NULL) {
226 SLOGE("Destination buffer is NULL");
227 errno = ESPIPE;
228 return NULL;
229 } else if (id == NULL) {
230 SLOGE("Source buffer is NULL");
231 errno = ESPIPE;
232 return NULL;
233 } else if (len < MD5_ASCII_LENGTH_PLUS_NULL) {
Colin Cross59846b62014-02-06 20:34:29 -0800234 SLOGE("Target hash buffer size < %d bytes (%zu)",
Kenny Rootacc9e7d2010-06-18 19:06:50 -0700235 MD5_ASCII_LENGTH_PLUS_NULL, len);
San Mehatd9a4e352010-03-12 13:32:47 -0800236 errno = ESPIPE;
237 return NULL;
238 }
Kenny Root7b18a7b2010-03-15 13:13:41 -0700239
240 MD5(reinterpret_cast<const unsigned char*>(id), strlen(id), sig);
San Mehatd9a4e352010-03-12 13:32:47 -0800241
Kenny Rootacc9e7d2010-06-18 19:06:50 -0700242 char *p = buffer;
Kenny Root7b18a7b2010-03-15 13:13:41 -0700243 for (int i = 0; i < MD5_DIGEST_LENGTH; i++) {
Kenny Rootacc9e7d2010-06-18 19:06:50 -0700244 *p++ = digits[sig[i] >> 4];
245 *p++ = digits[sig[i] & 0x0F];
San Mehatd9a4e352010-03-12 13:32:47 -0800246 }
Kenny Rootacc9e7d2010-06-18 19:06:50 -0700247 *p = '\0';
San Mehatd9a4e352010-03-12 13:32:47 -0800248
249 return buffer;
250}
251
Jeff Sharkeyf1b996d2015-04-17 17:35:20 -0700252int VolumeManager::setDebug(bool enable) {
San Mehatd9a4e352010-03-12 13:32:47 -0800253 mDebug = enable;
Jeff Sharkeyf1b996d2015-04-17 17:35:20 -0700254 return 0;
San Mehatd9a4e352010-03-12 13:32:47 -0800255}
256
San Mehatf1b736b2009-10-10 17:22:08 -0700257int VolumeManager::start() {
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700258 // Always start from a clean slate by unmounting everything in
259 // directories that we own, in case we crashed.
Jeff Sharkey9c484982015-03-31 10:35:33 -0700260 unmountAll();
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700261
262 // Assume that we always have an emulated volume on internal
263 // storage; the framework will decide if it should be mounted.
Jeff Sharkeyc8e04c52015-04-21 12:14:17 -0700264 CHECK(mInternalEmulated == nullptr);
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700265 mInternalEmulated = std::shared_ptr<android::vold::VolumeBase>(
Jeff Sharkey3161fb32015-04-12 16:03:33 -0700266 new android::vold::EmulatedVolume("/data/media"));
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700267 mInternalEmulated->create();
268
San Mehatf1b736b2009-10-10 17:22:08 -0700269 return 0;
270}
271
272int VolumeManager::stop() {
Jeff Sharkeyc8e04c52015-04-21 12:14:17 -0700273 CHECK(mInternalEmulated != nullptr);
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700274 mInternalEmulated->destroy();
275 mInternalEmulated = nullptr;
San Mehatf1b736b2009-10-10 17:22:08 -0700276 return 0;
277}
278
San Mehatfd7f5872009-10-12 11:32:47 -0700279void VolumeManager::handleBlockEvent(NetlinkEvent *evt) {
Jeff Sharkeyc8e04c52015-04-21 12:14:17 -0700280 std::lock_guard<std::mutex> lock(mLock);
281
Jeff Sharkeyf1b996d2015-04-17 17:35:20 -0700282 if (mDebug) {
283 LOG(VERBOSE) << "----------------";
284 LOG(VERBOSE) << "handleBlockEvent with action " << (int) evt->getAction();
285 evt->dump();
286 }
San Mehatf1b736b2009-10-10 17:22:08 -0700287
Mateusz Nowak64403792015-08-03 16:39:19 +0200288 std::string eventPath(evt->findParam("DEVPATH")?evt->findParam("DEVPATH"):"");
289 std::string devType(evt->findParam("DEVTYPE")?evt->findParam("DEVTYPE"):"");
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700290
291 if (devType != "disk") return;
292
293 int major = atoi(evt->findParam("MAJOR"));
294 int minor = atoi(evt->findParam("MINOR"));
295 dev_t device = makedev(major, minor);
296
297 switch (evt->getAction()) {
298 case NetlinkEvent::Action::kAdd: {
Chih-Hung Hsieh11a2ce82016-07-27 14:11:02 -0700299 for (const auto& source : mDiskSources) {
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700300 if (source->matches(eventPath)) {
Yu Ning942d4e82016-01-08 17:36:47 +0800301 // For now, assume that MMC and virtio-blk (the latter is
302 // emulator-specific; see Disk.cpp for details) devices are SD,
303 // and that everything else is USB
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700304 int flags = source->getFlags();
Yu Ning942d4e82016-01-08 17:36:47 +0800305 if (major == kMajorBlockMmc
306 || (android::vold::IsRunningInEmulator()
307 && major >= (int) kMajorBlockExperimentalMin
308 && major <= (int) kMajorBlockExperimentalMax)) {
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700309 flags |= android::vold::Disk::Flags::kSd;
310 } else {
311 flags |= android::vold::Disk::Flags::kUsb;
312 }
313
314 auto disk = new android::vold::Disk(eventPath, device,
315 source->getNickname(), flags);
316 disk->create();
317 mDisks.push_back(std::shared_ptr<android::vold::Disk>(disk));
318 break;
319 }
320 }
321 break;
322 }
323 case NetlinkEvent::Action::kChange: {
Jeff Sharkey7d9d0112015-04-14 23:14:23 -0700324 LOG(DEBUG) << "Disk at " << major << ":" << minor << " changed";
Chih-Hung Hsieh11a2ce82016-07-27 14:11:02 -0700325 for (const auto& disk : mDisks) {
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700326 if (disk->getDevice() == device) {
327 disk->readMetadata();
328 disk->readPartitions();
329 }
330 }
331 break;
332 }
333 case NetlinkEvent::Action::kRemove: {
334 auto i = mDisks.begin();
335 while (i != mDisks.end()) {
336 if ((*i)->getDevice() == device) {
337 (*i)->destroy();
338 i = mDisks.erase(i);
339 } else {
340 ++i;
341 }
342 }
343 break;
344 }
345 default: {
346 LOG(WARNING) << "Unexpected block event action " << (int) evt->getAction();
347 break;
348 }
349 }
350}
351
352void VolumeManager::addDiskSource(const std::shared_ptr<DiskSource>& diskSource) {
Wei Wang6b455c22017-01-20 11:52:33 -0800353 std::lock_guard<std::mutex> lock(mLock);
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700354 mDiskSources.push_back(diskSource);
355}
356
357std::shared_ptr<android::vold::Disk> VolumeManager::findDisk(const std::string& id) {
358 for (auto disk : mDisks) {
359 if (disk->getId() == id) {
360 return disk;
San Mehatf1b736b2009-10-10 17:22:08 -0700361 }
362 }
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700363 return nullptr;
364}
San Mehatf1b736b2009-10-10 17:22:08 -0700365
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700366std::shared_ptr<android::vold::VolumeBase> VolumeManager::findVolume(const std::string& id) {
367 if (mInternalEmulated->getId() == id) {
368 return mInternalEmulated;
San Mehatf1b736b2009-10-10 17:22:08 -0700369 }
Chih-Hung Hsieh11a2ce82016-07-27 14:11:02 -0700370 for (const auto& disk : mDisks) {
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700371 auto vol = disk->findVolume(id);
372 if (vol != nullptr) {
373 return vol;
374 }
375 }
376 return nullptr;
377}
378
Jeff Sharkeyc86ab6f2015-06-26 14:02:09 -0700379void VolumeManager::listVolumes(android::vold::VolumeBase::Type type,
380 std::list<std::string>& list) {
381 list.clear();
Chih-Hung Hsieh11a2ce82016-07-27 14:11:02 -0700382 for (const auto& disk : mDisks) {
Jeff Sharkeyc86ab6f2015-06-26 14:02:09 -0700383 disk->listVolumes(type, list);
384 }
385}
386
387nsecs_t VolumeManager::benchmarkPrivate(const std::string& id) {
Jeff Sharkey5a6bfca2015-05-14 20:33:55 -0700388 std::string path;
Jeff Sharkeyc86ab6f2015-06-26 14:02:09 -0700389 if (id == "private" || id == "null") {
Jeff Sharkey5a6bfca2015-05-14 20:33:55 -0700390 path = "/data";
Jeff Sharkeyc86ab6f2015-06-26 14:02:09 -0700391 } else {
392 auto vol = findVolume(id);
393 if (vol != nullptr && vol->getState() == android::vold::VolumeBase::State::kMounted) {
394 path = vol->getPath();
395 }
Jeff Sharkey5a6bfca2015-05-14 20:33:55 -0700396 }
397
398 if (path.empty()) {
399 LOG(WARNING) << "Failed to find volume for " << id;
400 return -1;
401 }
402
Jeff Sharkeyc86ab6f2015-06-26 14:02:09 -0700403 return android::vold::BenchmarkPrivate(path);
Jeff Sharkey5a6bfca2015-05-14 20:33:55 -0700404}
405
Jeff Sharkeybc40cc82015-06-18 14:25:08 -0700406int VolumeManager::forgetPartition(const std::string& partGuid) {
407 std::string normalizedGuid;
408 if (android::vold::NormalizeHex(partGuid, normalizedGuid)) {
409 LOG(WARNING) << "Invalid GUID " << partGuid;
410 return -1;
411 }
412
413 std::string keyPath = android::vold::BuildKeyPath(normalizedGuid);
414 if (unlink(keyPath.c_str()) != 0) {
415 LOG(ERROR) << "Failed to unlink " << keyPath;
416 return -1;
417 }
418
419 return 0;
420}
421
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700422int VolumeManager::linkPrimary(userid_t userId) {
423 std::string source(mPrimary->getPath());
424 if (mPrimary->getType() == android::vold::VolumeBase::Type::kEmulated) {
425 source = StringPrintf("%s/%d", source.c_str(), userId);
Jeff Sharkey32679a82015-07-21 14:22:01 -0700426 fs_prepare_dir(source.c_str(), 0755, AID_ROOT, AID_ROOT);
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700427 }
428
429 std::string target(StringPrintf("/mnt/user/%d/primary", userId));
430 if (TEMP_FAILURE_RETRY(unlink(target.c_str()))) {
431 if (errno != ENOENT) {
432 SLOGW("Failed to unlink %s: %s", target.c_str(), strerror(errno));
433 }
434 }
Jeff Sharkey1bfb3752015-04-29 15:22:23 -0700435 LOG(DEBUG) << "Linking " << source << " to " << target;
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700436 if (TEMP_FAILURE_RETRY(symlink(source.c_str(), target.c_str()))) {
437 SLOGW("Failed to link %s to %s: %s", source.c_str(), target.c_str(),
438 strerror(errno));
439 return -errno;
440 }
441 return 0;
442}
443
Jeff Sharkeybd3038d2015-06-10 09:42:01 -0700444int VolumeManager::onUserAdded(userid_t userId, int userSerialNumber) {
445 mAddedUsers[userId] = userSerialNumber;
446 return 0;
447}
448
449int VolumeManager::onUserRemoved(userid_t userId) {
450 mAddedUsers.erase(userId);
451 return 0;
452}
453
454int VolumeManager::onUserStarted(userid_t userId) {
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700455 // Note that sometimes the system will spin up processes from Zygote
456 // before actually starting the user, so we're okay if Zygote
457 // already created this directory.
458 std::string path(StringPrintf("%s/%d", kUserMountPath, userId));
459 fs_prepare_dir(path.c_str(), 0755, AID_ROOT, AID_ROOT);
460
Jeff Sharkeybd3038d2015-06-10 09:42:01 -0700461 mStartedUsers.insert(userId);
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700462 if (mPrimary) {
463 linkPrimary(userId);
464 }
465 return 0;
466}
467
Jeff Sharkeybd3038d2015-06-10 09:42:01 -0700468int VolumeManager::onUserStopped(userid_t userId) {
469 mStartedUsers.erase(userId);
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700470 return 0;
471}
472
473int VolumeManager::setPrimary(const std::shared_ptr<android::vold::VolumeBase>& vol) {
474 mPrimary = vol;
Jeff Sharkeybd3038d2015-06-10 09:42:01 -0700475 for (userid_t userId : mStartedUsers) {
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700476 linkPrimary(userId);
477 }
478 return 0;
479}
480
Jeff Sharkeyc7b5b572015-06-30 15:54:17 -0700481static int unmount_tree(const char* path) {
482 size_t path_len = strlen(path);
483
484 FILE* fp = setmntent("/proc/mounts", "r");
485 if (fp == NULL) {
486 ALOGE("Error opening /proc/mounts: %s", strerror(errno));
487 return -errno;
488 }
489
490 // Some volumes can be stacked on each other, so force unmount in
491 // reverse order to give us the best chance of success.
492 std::list<std::string> toUnmount;
493 mntent* mentry;
494 while ((mentry = getmntent(fp)) != NULL) {
495 if (strncmp(mentry->mnt_dir, path, path_len) == 0) {
496 toUnmount.push_front(std::string(mentry->mnt_dir));
497 }
498 }
499 endmntent(fp);
500
Chih-Hung Hsieh11a2ce82016-07-27 14:11:02 -0700501 for (const auto& path : toUnmount) {
Jeff Sharkeyc7b5b572015-06-30 15:54:17 -0700502 if (umount2(path.c_str(), MNT_DETACH)) {
503 ALOGW("Failed to unmount %s: %s", path.c_str(), strerror(errno));
504 }
505 }
506 return 0;
507}
508
Jeff Sharkey66270a22015-06-24 11:49:24 -0700509int VolumeManager::remountUid(uid_t uid, const std::string& mode) {
510 LOG(DEBUG) << "Remounting " << uid << " as mode " << mode;
511
512 DIR* dir;
513 struct dirent* de;
514 char rootName[PATH_MAX];
515 char pidName[PATH_MAX];
516 int pidFd;
517 int nsFd;
518 struct stat sb;
519 pid_t child;
520
521 if (!(dir = opendir("/proc"))) {
522 PLOG(ERROR) << "Failed to opendir";
523 return -1;
524 }
525
526 // Figure out root namespace to compare against below
Daichi Hirono10d34882016-01-29 14:33:51 +0900527 if (android::vold::SaneReadLinkAt(dirfd(dir), "1/ns/mnt", rootName, PATH_MAX) == -1) {
Jeff Sharkey66270a22015-06-24 11:49:24 -0700528 PLOG(ERROR) << "Failed to readlink";
529 closedir(dir);
530 return -1;
531 }
532
533 // Poke through all running PIDs look for apps running as UID
534 while ((de = readdir(dir))) {
535 pidFd = -1;
536 nsFd = -1;
537
538 pidFd = openat(dirfd(dir), de->d_name, O_RDONLY | O_DIRECTORY | O_CLOEXEC);
539 if (pidFd < 0) {
540 goto next;
541 }
542 if (fstat(pidFd, &sb) != 0) {
543 PLOG(WARNING) << "Failed to stat " << de->d_name;
544 goto next;
545 }
546 if (sb.st_uid != uid) {
547 goto next;
548 }
549
550 // Matches so far, but refuse to touch if in root namespace
551 LOG(DEBUG) << "Found matching PID " << de->d_name;
Daichi Hirono10d34882016-01-29 14:33:51 +0900552 if (android::vold::SaneReadLinkAt(pidFd, "ns/mnt", pidName, PATH_MAX) == -1) {
Jeff Sharkey66270a22015-06-24 11:49:24 -0700553 PLOG(WARNING) << "Failed to read namespace for " << de->d_name;
554 goto next;
555 }
556 if (!strcmp(rootName, pidName)) {
557 LOG(WARNING) << "Skipping due to root namespace";
558 goto next;
559 }
560
561 // We purposefully leave the namespace open across the fork
562 nsFd = openat(pidFd, "ns/mnt", O_RDONLY);
563 if (nsFd < 0) {
Jeff Sharkeyc7b5b572015-06-30 15:54:17 -0700564 PLOG(WARNING) << "Failed to open namespace for " << de->d_name;
Jeff Sharkey66270a22015-06-24 11:49:24 -0700565 goto next;
566 }
567
568 if (!(child = fork())) {
569 if (setns(nsFd, CLONE_NEWNS) != 0) {
Jeff Sharkeyc7b5b572015-06-30 15:54:17 -0700570 PLOG(ERROR) << "Failed to setns for " << de->d_name;
Jeff Sharkey66270a22015-06-24 11:49:24 -0700571 _exit(1);
572 }
573
Jeff Sharkeyc7b5b572015-06-30 15:54:17 -0700574 unmount_tree("/storage");
Jeff Sharkey66270a22015-06-24 11:49:24 -0700575
576 std::string storageSource;
577 if (mode == "default") {
Jeff Sharkey1bd078f2015-08-06 11:40:00 -0700578 storageSource = "/mnt/runtime/default";
Jeff Sharkey66270a22015-06-24 11:49:24 -0700579 } else if (mode == "read") {
Jeff Sharkey1bd078f2015-08-06 11:40:00 -0700580 storageSource = "/mnt/runtime/read";
Jeff Sharkey66270a22015-06-24 11:49:24 -0700581 } else if (mode == "write") {
Jeff Sharkey1bd078f2015-08-06 11:40:00 -0700582 storageSource = "/mnt/runtime/write";
Jeff Sharkey66270a22015-06-24 11:49:24 -0700583 } else {
584 // Sane default of no storage visible
585 _exit(0);
586 }
587 if (TEMP_FAILURE_RETRY(mount(storageSource.c_str(), "/storage",
588 NULL, MS_BIND | MS_REC | MS_SLAVE, NULL)) == -1) {
Jeff Sharkeyc7b5b572015-06-30 15:54:17 -0700589 PLOG(ERROR) << "Failed to mount " << storageSource << " for "
590 << de->d_name;
591 _exit(1);
Jeff Sharkey66270a22015-06-24 11:49:24 -0700592 }
Jeff Sharkeyc7b5b572015-06-30 15:54:17 -0700593
594 // Mount user-specific symlink helper into place
595 userid_t user_id = multiuser_get_user_id(uid);
596 std::string userSource(StringPrintf("/mnt/user/%d", user_id));
597 if (TEMP_FAILURE_RETRY(mount(userSource.c_str(), "/storage/self",
598 NULL, MS_BIND, NULL)) == -1) {
599 PLOG(ERROR) << "Failed to mount " << userSource << " for "
600 << de->d_name;
601 _exit(1);
602 }
603
Jeff Sharkey66270a22015-06-24 11:49:24 -0700604 _exit(0);
605 }
606
607 if (child == -1) {
608 PLOG(ERROR) << "Failed to fork";
609 goto next;
610 } else {
611 TEMP_FAILURE_RETRY(waitpid(child, nullptr, 0));
612 }
613
614next:
615 close(nsFd);
616 close(pidFd);
617 }
618 closedir(dir);
619 return 0;
620}
621
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700622int VolumeManager::reset() {
623 // Tear down all existing disks/volumes and start from a blank slate so
624 // newly connected framework hears all events.
625 mInternalEmulated->destroy();
626 mInternalEmulated->create();
Chih-Hung Hsieh11a2ce82016-07-27 14:11:02 -0700627 for (const auto& disk : mDisks) {
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700628 disk->destroy();
629 disk->create();
630 }
Jeff Sharkeybd3038d2015-06-10 09:42:01 -0700631 mAddedUsers.clear();
632 mStartedUsers.clear();
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700633 return 0;
634}
635
636int VolumeManager::shutdown() {
Jeff Sharkey9c484982015-03-31 10:35:33 -0700637 mInternalEmulated->destroy();
Chih-Hung Hsieh11a2ce82016-07-27 14:11:02 -0700638 for (const auto& disk : mDisks) {
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700639 disk->destroy();
640 }
641 mDisks.clear();
642 return 0;
San Mehatf1b736b2009-10-10 17:22:08 -0700643}
644
Jeff Sharkey9c484982015-03-31 10:35:33 -0700645int VolumeManager::unmountAll() {
Jeff Sharkeyc8e04c52015-04-21 12:14:17 -0700646 std::lock_guard<std::mutex> lock(mLock);
647
Jeff Sharkey9c484982015-03-31 10:35:33 -0700648 // First, try gracefully unmounting all known devices
649 if (mInternalEmulated != nullptr) {
650 mInternalEmulated->unmount();
651 }
Chih-Hung Hsieh11a2ce82016-07-27 14:11:02 -0700652 for (const auto& disk : mDisks) {
Jeff Sharkey9c484982015-03-31 10:35:33 -0700653 disk->unmountAll();
654 }
655
656 // Worst case we might have some stale mounts lurking around, so
657 // force unmount those just to be safe.
658 FILE* fp = setmntent("/proc/mounts", "r");
659 if (fp == NULL) {
660 SLOGE("Error opening /proc/mounts: %s", strerror(errno));
661 return -errno;
662 }
663
664 // Some volumes can be stacked on each other, so force unmount in
665 // reverse order to give us the best chance of success.
666 std::list<std::string> toUnmount;
667 mntent* mentry;
668 while ((mentry = getmntent(fp)) != NULL) {
669 if (strncmp(mentry->mnt_dir, "/mnt/", 5) == 0
670 || strncmp(mentry->mnt_dir, "/storage/", 9) == 0) {
671 toUnmount.push_front(std::string(mentry->mnt_dir));
672 }
673 }
674 endmntent(fp);
675
Chih-Hung Hsieh11a2ce82016-07-27 14:11:02 -0700676 for (const auto& path : toUnmount) {
Jeff Sharkey9c484982015-03-31 10:35:33 -0700677 SLOGW("Tearing down stale mount %s", path.c_str());
678 android::vold::ForceUnmount(path);
679 }
680
681 return 0;
682}
683
Kenny Root508c0e12010-07-12 09:59:49 -0700684int VolumeManager::getObbMountPath(const char *sourceFile, char *mountPath, int mountPathLen) {
685 char idHash[33];
686 if (!asecHash(sourceFile, idHash, sizeof(idHash))) {
687 SLOGE("Hash of '%s' failed (%s)", sourceFile, strerror(errno));
688 return -1;
689 }
690
691 memset(mountPath, 0, mountPathLen);
Jeff Sharkey9f18fe72015-04-01 23:32:18 -0700692 int written = snprintf(mountPath, mountPathLen, "%s/%s", VolumeManager::LOOPDIR, idHash);
rpcraigd1c226f2012-10-09 06:58:16 -0400693 if ((written < 0) || (written >= mountPathLen)) {
694 errno = EINVAL;
695 return -1;
696 }
Kenny Root508c0e12010-07-12 09:59:49 -0700697
698 if (access(mountPath, F_OK)) {
699 errno = ENOENT;
700 return -1;
701 }
702
703 return 0;
704}
705
San Mehata19b2502010-01-06 10:33:53 -0800706int VolumeManager::getAsecMountPath(const char *id, char *buffer, int maxlen) {
San Mehat88ac2c02010-03-23 11:15:58 -0700707 char asecFileName[255];
Kenny Root344ca102012-04-03 17:23:01 -0700708
Nick Kralevich0de7c612014-01-27 14:58:06 -0800709 if (!isLegalAsecId(id)) {
710 SLOGE("getAsecMountPath: Invalid asec id \"%s\"", id);
711 errno = EINVAL;
712 return -1;
713 }
714
Kenny Root344ca102012-04-03 17:23:01 -0700715 if (findAsec(id, asecFileName, sizeof(asecFileName))) {
716 SLOGE("Couldn't find ASEC %s", id);
717 return -1;
718 }
San Mehat88ac2c02010-03-23 11:15:58 -0700719
720 memset(buffer, 0, maxlen);
721 if (access(asecFileName, F_OK)) {
722 errno = ENOENT;
723 return -1;
724 }
San Mehata19b2502010-01-06 10:33:53 -0800725
Jeff Sharkey9f18fe72015-04-01 23:32:18 -0700726 int written = snprintf(buffer, maxlen, "%s/%s", VolumeManager::ASECDIR, id);
rpcraigd1c226f2012-10-09 06:58:16 -0400727 if ((written < 0) || (written >= maxlen)) {
728 SLOGE("getAsecMountPath failed for %s: couldn't construct path in buffer", id);
729 errno = EINVAL;
730 return -1;
731 }
732
San Mehata19b2502010-01-06 10:33:53 -0800733 return 0;
734}
735
Dianne Hackborn736910c2011-06-27 13:37:07 -0700736int VolumeManager::getAsecFilesystemPath(const char *id, char *buffer, int maxlen) {
737 char asecFileName[255];
Kenny Root344ca102012-04-03 17:23:01 -0700738
Nick Kralevich0de7c612014-01-27 14:58:06 -0800739 if (!isLegalAsecId(id)) {
740 SLOGE("getAsecFilesystemPath: Invalid asec id \"%s\"", id);
741 errno = EINVAL;
742 return -1;
743 }
744
Kenny Root344ca102012-04-03 17:23:01 -0700745 if (findAsec(id, asecFileName, sizeof(asecFileName))) {
746 SLOGE("Couldn't find ASEC %s", id);
747 return -1;
748 }
Dianne Hackborn736910c2011-06-27 13:37:07 -0700749
750 memset(buffer, 0, maxlen);
751 if (access(asecFileName, F_OK)) {
752 errno = ENOENT;
753 return -1;
754 }
755
rpcraigd1c226f2012-10-09 06:58:16 -0400756 int written = snprintf(buffer, maxlen, "%s", asecFileName);
757 if ((written < 0) || (written >= maxlen)) {
758 errno = EINVAL;
759 return -1;
760 }
761
Dianne Hackborn736910c2011-06-27 13:37:07 -0700762 return 0;
763}
764
Mateusz Nowaka4f48d02015-08-03 18:06:39 +0200765int VolumeManager::createAsec(const char *id, unsigned long numSectors, const char *fstype,
Kenny Root344ca102012-04-03 17:23:01 -0700766 const char *key, const int ownerUid, bool isExternal) {
San Mehatfcf24fe2010-03-03 12:37:32 -0800767 struct asec_superblock sb;
768 memset(&sb, 0, sizeof(sb));
769
Nick Kralevich0de7c612014-01-27 14:58:06 -0800770 if (!isLegalAsecId(id)) {
771 SLOGE("createAsec: Invalid asec id \"%s\"", id);
772 errno = EINVAL;
773 return -1;
774 }
775
Kenny Root344ca102012-04-03 17:23:01 -0700776 const bool wantFilesystem = strcmp(fstype, "none");
777 bool usingExt4 = false;
778 if (wantFilesystem) {
779 usingExt4 = !strcmp(fstype, "ext4");
780 if (usingExt4) {
781 sb.c_opts |= ASEC_SB_C_OPTS_EXT4;
782 } else if (strcmp(fstype, "fat")) {
783 SLOGE("Invalid filesystem type %s", fstype);
784 errno = EINVAL;
785 return -1;
786 }
787 }
788
San Mehatfcf24fe2010-03-03 12:37:32 -0800789 sb.magic = ASEC_SB_MAGIC;
790 sb.ver = ASEC_SB_VER;
San Mehata19b2502010-01-06 10:33:53 -0800791
San Mehatd31e3802010-02-18 08:37:45 -0800792 if (numSectors < ((1024*1024)/512)) {
Mateusz Nowaka4f48d02015-08-03 18:06:39 +0200793 SLOGE("Invalid container size specified (%lu sectors)", numSectors);
San Mehatd31e3802010-02-18 08:37:45 -0800794 errno = EINVAL;
795 return -1;
796 }
797
San Mehata19b2502010-01-06 10:33:53 -0800798 char asecFileName[255];
Kenny Root344ca102012-04-03 17:23:01 -0700799
800 if (!findAsec(id, asecFileName, sizeof(asecFileName))) {
801 SLOGE("ASEC file '%s' currently exists - destroy it first! (%s)",
802 asecFileName, strerror(errno));
803 errno = EADDRINUSE;
804 return -1;
805 }
806
Jeff Sharkey9f18fe72015-04-01 23:32:18 -0700807 const char *asecDir = isExternal ? VolumeManager::SEC_ASECDIR_EXT : VolumeManager::SEC_ASECDIR_INT;
Kenny Root344ca102012-04-03 17:23:01 -0700808
rpcraigd1c226f2012-10-09 06:58:16 -0400809 int written = snprintf(asecFileName, sizeof(asecFileName), "%s/%s.asec", asecDir, id);
810 if ((written < 0) || (size_t(written) >= sizeof(asecFileName))) {
811 errno = EINVAL;
812 return -1;
813 }
San Mehata19b2502010-01-06 10:33:53 -0800814
815 if (!access(asecFileName, F_OK)) {
San Mehat97ac40e2010-03-24 10:24:19 -0700816 SLOGE("ASEC file '%s' currently exists - destroy it first! (%s)",
Kenny Root344ca102012-04-03 17:23:01 -0700817 asecFileName, strerror(errno));
San Mehata19b2502010-01-06 10:33:53 -0800818 errno = EADDRINUSE;
819 return -1;
820 }
821
Mateusz Nowaka4f48d02015-08-03 18:06:39 +0200822 unsigned long numImgSectors;
Daniel Rosenberg6a74dca2014-05-23 13:47:00 -0700823 if (usingExt4)
Daniel Rosenbergfcd34a02014-05-22 11:23:56 -0700824 numImgSectors = adjustSectorNumExt4(numSectors);
Daniel Rosenberg6a74dca2014-05-23 13:47:00 -0700825 else
Daniel Rosenbergfcd34a02014-05-22 11:23:56 -0700826 numImgSectors = adjustSectorNumFAT(numSectors);
San Mehatfcf24fe2010-03-03 12:37:32 -0800827
828 // Add +1 for our superblock which is at the end
829 if (Loop::createImageFile(asecFileName, numImgSectors + 1)) {
San Mehat97ac40e2010-03-24 10:24:19 -0700830 SLOGE("ASEC image file creation failed (%s)", strerror(errno));
San Mehata19b2502010-01-06 10:33:53 -0800831 return -1;
832 }
833
San Mehatd9a4e352010-03-12 13:32:47 -0800834 char idHash[33];
835 if (!asecHash(id, idHash, sizeof(idHash))) {
San Mehat97ac40e2010-03-24 10:24:19 -0700836 SLOGE("Hash of '%s' failed (%s)", id, strerror(errno));
San Mehatd9a4e352010-03-12 13:32:47 -0800837 unlink(asecFileName);
838 return -1;
839 }
840
San Mehata19b2502010-01-06 10:33:53 -0800841 char loopDevice[255];
San Mehatd9a4e352010-03-12 13:32:47 -0800842 if (Loop::create(idHash, asecFileName, loopDevice, sizeof(loopDevice))) {
San Mehat97ac40e2010-03-24 10:24:19 -0700843 SLOGE("ASEC loop device creation failed (%s)", strerror(errno));
San Mehata19b2502010-01-06 10:33:53 -0800844 unlink(asecFileName);
845 return -1;
846 }
847
San Mehatb78a32c2010-01-10 13:02:12 -0800848 char dmDevice[255];
849 bool cleanupDm = false;
San Mehata19b2502010-01-06 10:33:53 -0800850
San Mehatb78a32c2010-01-10 13:02:12 -0800851 if (strcmp(key, "none")) {
San Mehatfcf24fe2010-03-03 12:37:32 -0800852 // XXX: This is all we support for now
853 sb.c_cipher = ASEC_SB_C_CIPHER_TWOFISH;
San Mehatd9a4e352010-03-12 13:32:47 -0800854 if (Devmapper::create(idHash, loopDevice, key, numImgSectors, dmDevice,
San Mehatb78a32c2010-01-10 13:02:12 -0800855 sizeof(dmDevice))) {
San Mehat97ac40e2010-03-24 10:24:19 -0700856 SLOGE("ASEC device mapping failed (%s)", strerror(errno));
San Mehatb78a32c2010-01-10 13:02:12 -0800857 Loop::destroyByDevice(loopDevice);
858 unlink(asecFileName);
859 return -1;
860 }
861 cleanupDm = true;
862 } else {
San Mehatfcf24fe2010-03-03 12:37:32 -0800863 sb.c_cipher = ASEC_SB_C_CIPHER_NONE;
San Mehatb78a32c2010-01-10 13:02:12 -0800864 strcpy(dmDevice, loopDevice);
865 }
866
San Mehatfcf24fe2010-03-03 12:37:32 -0800867 /*
868 * Drop down the superblock at the end of the file
869 */
Daniel Rosenbergfcd34a02014-05-22 11:23:56 -0700870 if (writeSuperBlock(loopDevice, &sb, numImgSectors)) {
San Mehatfcf24fe2010-03-03 12:37:32 -0800871 if (cleanupDm) {
San Mehatd9a4e352010-03-12 13:32:47 -0800872 Devmapper::destroy(idHash);
San Mehatfcf24fe2010-03-03 12:37:32 -0800873 }
874 Loop::destroyByDevice(loopDevice);
875 unlink(asecFileName);
876 return -1;
877 }
878
Kenny Root344ca102012-04-03 17:23:01 -0700879 if (wantFilesystem) {
880 int formatStatus;
rpcraiga54e13a2012-09-21 14:17:08 -0400881 char mountPoint[255];
882
Jeff Sharkey9f18fe72015-04-01 23:32:18 -0700883 int written = snprintf(mountPoint, sizeof(mountPoint), "%s/%s", VolumeManager::ASECDIR, id);
rpcraigd1c226f2012-10-09 06:58:16 -0400884 if ((written < 0) || (size_t(written) >= sizeof(mountPoint))) {
885 SLOGE("ASEC fs format failed: couldn't construct mountPoint");
886 if (cleanupDm) {
887 Devmapper::destroy(idHash);
888 }
889 Loop::destroyByDevice(loopDevice);
890 unlink(asecFileName);
891 return -1;
892 }
rpcraiga54e13a2012-09-21 14:17:08 -0400893
Kenny Root344ca102012-04-03 17:23:01 -0700894 if (usingExt4) {
Jeff Sharkeyd0640f62015-05-21 22:35:42 -0700895 formatStatus = android::vold::ext4::Format(dmDevice, numImgSectors, mountPoint);
Kenny Root344ca102012-04-03 17:23:01 -0700896 } else {
Jeff Sharkeyd0640f62015-05-21 22:35:42 -0700897 formatStatus = android::vold::vfat::Format(dmDevice, numImgSectors);
San Mehatb78a32c2010-01-10 13:02:12 -0800898 }
San Mehata19b2502010-01-06 10:33:53 -0800899
Kenny Root344ca102012-04-03 17:23:01 -0700900 if (formatStatus < 0) {
901 SLOGE("ASEC fs format failed (%s)", strerror(errno));
San Mehatb78a32c2010-01-10 13:02:12 -0800902 if (cleanupDm) {
San Mehatd9a4e352010-03-12 13:32:47 -0800903 Devmapper::destroy(idHash);
San Mehatb78a32c2010-01-10 13:02:12 -0800904 }
San Mehateb13a902010-01-07 12:12:50 -0800905 Loop::destroyByDevice(loopDevice);
906 unlink(asecFileName);
907 return -1;
908 }
Kenny Root344ca102012-04-03 17:23:01 -0700909
Kenny Root344ca102012-04-03 17:23:01 -0700910 if (mkdir(mountPoint, 0000)) {
San Mehata1091cb2010-02-28 20:17:20 -0800911 if (errno != EEXIST) {
San Mehat97ac40e2010-03-24 10:24:19 -0700912 SLOGE("Mountpoint creation failed (%s)", strerror(errno));
San Mehata1091cb2010-02-28 20:17:20 -0800913 if (cleanupDm) {
San Mehatd9a4e352010-03-12 13:32:47 -0800914 Devmapper::destroy(idHash);
San Mehata1091cb2010-02-28 20:17:20 -0800915 }
916 Loop::destroyByDevice(loopDevice);
917 unlink(asecFileName);
918 return -1;
919 }
San Mehatb78a32c2010-01-10 13:02:12 -0800920 }
San Mehata1091cb2010-02-28 20:17:20 -0800921
Kenny Root344ca102012-04-03 17:23:01 -0700922 int mountStatus;
923 if (usingExt4) {
Jeff Sharkeyd0640f62015-05-21 22:35:42 -0700924 mountStatus = android::vold::ext4::Mount(dmDevice, mountPoint,
925 false, false, false);
Kenny Root344ca102012-04-03 17:23:01 -0700926 } else {
Jeff Sharkeyd0640f62015-05-21 22:35:42 -0700927 mountStatus = android::vold::vfat::Mount(dmDevice, mountPoint,
928 false, false, false, ownerUid, 0, 0000, false);
Kenny Root344ca102012-04-03 17:23:01 -0700929 }
930
931 if (mountStatus) {
San Mehat97ac40e2010-03-24 10:24:19 -0700932 SLOGE("ASEC FAT mount failed (%s)", strerror(errno));
San Mehata1091cb2010-02-28 20:17:20 -0800933 if (cleanupDm) {
San Mehatd9a4e352010-03-12 13:32:47 -0800934 Devmapper::destroy(idHash);
San Mehata1091cb2010-02-28 20:17:20 -0800935 }
936 Loop::destroyByDevice(loopDevice);
937 unlink(asecFileName);
938 return -1;
939 }
Kenny Root344ca102012-04-03 17:23:01 -0700940
941 if (usingExt4) {
Jeff Sharkeyce6a9132015-04-08 21:07:21 -0700942 int dirfd = open(mountPoint, O_DIRECTORY | O_CLOEXEC);
Kenny Root344ca102012-04-03 17:23:01 -0700943 if (dirfd >= 0) {
944 if (fchown(dirfd, ownerUid, AID_SYSTEM)
945 || fchmod(dirfd, S_IRUSR | S_IWUSR | S_IXUSR | S_ISGID | S_IRGRP | S_IXGRP)) {
946 SLOGI("Cannot chown/chmod new ASEC mount point %s", mountPoint);
947 }
948 close(dirfd);
949 }
950 }
San Mehata1091cb2010-02-28 20:17:20 -0800951 } else {
San Mehat97ac40e2010-03-24 10:24:19 -0700952 SLOGI("Created raw secure container %s (no filesystem)", id);
San Mehata19b2502010-01-06 10:33:53 -0800953 }
San Mehat88705162010-01-15 09:26:28 -0800954
Kenny Rootcbacf782010-09-24 15:11:48 -0700955 mActiveContainers->push_back(new ContainerData(strdup(id), ASEC));
San Mehata19b2502010-01-06 10:33:53 -0800956 return 0;
957}
958
Mateusz Nowaka4f48d02015-08-03 18:06:39 +0200959int VolumeManager::resizeAsec(const char *id, unsigned long numSectors, const char *key) {
Daniel Rosenbergfcd34a02014-05-22 11:23:56 -0700960 char asecFileName[255];
961 char mountPoint[255];
962 bool cleanupDm = false;
963
964 if (!isLegalAsecId(id)) {
965 SLOGE("resizeAsec: Invalid asec id \"%s\"", id);
966 errno = EINVAL;
967 return -1;
968 }
969
970 if (findAsec(id, asecFileName, sizeof(asecFileName))) {
971 SLOGE("Couldn't find ASEC %s", id);
972 return -1;
973 }
974
Jeff Sharkey9f18fe72015-04-01 23:32:18 -0700975 int written = snprintf(mountPoint, sizeof(mountPoint), "%s/%s", VolumeManager::ASECDIR, id);
Daniel Rosenbergfcd34a02014-05-22 11:23:56 -0700976 if ((written < 0) || (size_t(written) >= sizeof(mountPoint))) {
977 SLOGE("ASEC resize failed for %s: couldn't construct mountpoint", id);
978 return -1;
979 }
980
981 if (isMountpointMounted(mountPoint)) {
982 SLOGE("ASEC %s mounted. Unmount before resizing", id);
983 errno = EBUSY;
984 return -1;
985 }
986
987 struct asec_superblock sb;
988 int fd;
Mateusz Nowaka4f48d02015-08-03 18:06:39 +0200989 unsigned long oldNumSec = 0;
Daniel Rosenbergfcd34a02014-05-22 11:23:56 -0700990
Jeff Sharkeyce6a9132015-04-08 21:07:21 -0700991 if ((fd = open(asecFileName, O_RDONLY | O_CLOEXEC)) < 0) {
Daniel Rosenbergfcd34a02014-05-22 11:23:56 -0700992 SLOGE("Failed to open ASEC file (%s)", strerror(errno));
993 return -1;
994 }
995
996 struct stat info;
997 if (fstat(fd, &info) < 0) {
998 SLOGE("Failed to get file size (%s)", strerror(errno));
999 close(fd);
1000 return -1;
1001 }
1002
1003 oldNumSec = info.st_size / 512;
1004
Mateusz Nowaka4f48d02015-08-03 18:06:39 +02001005 unsigned long numImgSectors;
Daniel Rosenbergfcd34a02014-05-22 11:23:56 -07001006 if (sb.c_opts & ASEC_SB_C_OPTS_EXT4)
1007 numImgSectors = adjustSectorNumExt4(numSectors);
1008 else
1009 numImgSectors = adjustSectorNumFAT(numSectors);
1010 /*
1011 * add one block for the superblock
1012 */
Mateusz Nowaka4f48d02015-08-03 18:06:39 +02001013 SLOGD("Resizing from %lu sectors to %lu sectors", oldNumSec, numImgSectors + 1);
Jeff Sharkey43ed1232014-08-22 12:29:05 -07001014 if (oldNumSec == numImgSectors + 1) {
1015 SLOGW("Size unchanged; ignoring resize request");
1016 return 0;
1017 } else if (oldNumSec > numImgSectors + 1) {
Daniel Rosenbergfcd34a02014-05-22 11:23:56 -07001018 SLOGE("Only growing is currently supported.");
1019 close(fd);
1020 return -1;
1021 }
1022
1023 /*
1024 * Try to read superblock.
1025 */
1026 memset(&sb, 0, sizeof(struct asec_superblock));
1027 if (lseek(fd, ((oldNumSec - 1) * 512), SEEK_SET) < 0) {
1028 SLOGE("lseek failed (%s)", strerror(errno));
1029 close(fd);
1030 return -1;
1031 }
1032 if (read(fd, &sb, sizeof(struct asec_superblock)) != sizeof(struct asec_superblock)) {
1033 SLOGE("superblock read failed (%s)", strerror(errno));
1034 close(fd);
1035 return -1;
1036 }
1037 close(fd);
1038
1039 if (mDebug) {
1040 SLOGD("Container sb magic/ver (%.8x/%.2x)", sb.magic, sb.ver);
1041 }
1042 if (sb.magic != ASEC_SB_MAGIC || sb.ver != ASEC_SB_VER) {
1043 SLOGE("Bad container magic/version (%.8x/%.2x)", sb.magic, sb.ver);
1044 errno = EMEDIUMTYPE;
1045 return -1;
1046 }
1047
1048 if (!(sb.c_opts & ASEC_SB_C_OPTS_EXT4)) {
1049 SLOGE("Only ext4 partitions are supported for resize");
1050 errno = EINVAL;
1051 return -1;
1052 }
1053
1054 if (Loop::resizeImageFile(asecFileName, numImgSectors + 1)) {
1055 SLOGE("Resize of ASEC image file failed. Could not resize %s", id);
1056 return -1;
1057 }
1058
1059 /*
1060 * Drop down a copy of the superblock at the end of the file
1061 */
1062 if (writeSuperBlock(asecFileName, &sb, numImgSectors))
1063 goto fail;
1064
1065 char idHash[33];
1066 if (!asecHash(id, idHash, sizeof(idHash))) {
1067 SLOGE("Hash of '%s' failed (%s)", id, strerror(errno));
1068 goto fail;
1069 }
1070
1071 char loopDevice[255];
1072 if (setupLoopDevice(loopDevice, sizeof(loopDevice), asecFileName, idHash, mDebug))
1073 goto fail;
1074
1075 char dmDevice[255];
1076
1077 if (setupDevMapperDevice(dmDevice, sizeof(dmDevice), loopDevice, asecFileName, key, idHash, numImgSectors, &cleanupDm, mDebug)) {
1078 Loop::destroyByDevice(loopDevice);
1079 goto fail;
1080 }
1081
1082 /*
1083 * Wait for the device mapper node to be created.
1084 */
1085 waitForDevMapper(dmDevice);
1086
Jeff Sharkeyd0640f62015-05-21 22:35:42 -07001087 if (android::vold::ext4::Resize(dmDevice, numImgSectors)) {
Daniel Rosenbergfcd34a02014-05-22 11:23:56 -07001088 SLOGE("Unable to resize %s (%s)", id, strerror(errno));
1089 if (cleanupDm) {
1090 Devmapper::destroy(idHash);
1091 }
1092 Loop::destroyByDevice(loopDevice);
1093 goto fail;
1094 }
1095
1096 return 0;
1097fail:
1098 Loop::resizeImageFile(asecFileName, oldNumSec);
1099 return -1;
1100}
1101
San Mehata19b2502010-01-06 10:33:53 -08001102int VolumeManager::finalizeAsec(const char *id) {
1103 char asecFileName[255];
1104 char loopDevice[255];
1105 char mountPoint[255];
1106
Nick Kralevich0de7c612014-01-27 14:58:06 -08001107 if (!isLegalAsecId(id)) {
1108 SLOGE("finalizeAsec: Invalid asec id \"%s\"", id);
1109 errno = EINVAL;
1110 return -1;
1111 }
1112
Kenny Root344ca102012-04-03 17:23:01 -07001113 if (findAsec(id, asecFileName, sizeof(asecFileName))) {
1114 SLOGE("Couldn't find ASEC %s", id);
1115 return -1;
1116 }
San Mehata19b2502010-01-06 10:33:53 -08001117
San Mehatd9a4e352010-03-12 13:32:47 -08001118 char idHash[33];
1119 if (!asecHash(id, idHash, sizeof(idHash))) {
San Mehat97ac40e2010-03-24 10:24:19 -07001120 SLOGE("Hash of '%s' failed (%s)", id, strerror(errno));
San Mehatd9a4e352010-03-12 13:32:47 -08001121 return -1;
1122 }
1123
1124 if (Loop::lookupActive(idHash, loopDevice, sizeof(loopDevice))) {
San Mehat97ac40e2010-03-24 10:24:19 -07001125 SLOGE("Unable to finalize %s (%s)", id, strerror(errno));
San Mehata19b2502010-01-06 10:33:53 -08001126 return -1;
1127 }
1128
Hiroaki Miyazawa14eab552015-02-04 13:29:15 +09001129 unsigned long nr_sec = 0;
Kenny Root344ca102012-04-03 17:23:01 -07001130 struct asec_superblock sb;
1131
1132 if (Loop::lookupInfo(loopDevice, &sb, &nr_sec)) {
1133 return -1;
1134 }
1135
Jeff Sharkey9f18fe72015-04-01 23:32:18 -07001136 int written = snprintf(mountPoint, sizeof(mountPoint), "%s/%s", VolumeManager::ASECDIR, id);
rpcraigd1c226f2012-10-09 06:58:16 -04001137 if ((written < 0) || (size_t(written) >= sizeof(mountPoint))) {
1138 SLOGE("ASEC finalize failed: couldn't construct mountPoint");
1139 return -1;
1140 }
Kenny Root344ca102012-04-03 17:23:01 -07001141
1142 int result = 0;
1143 if (sb.c_opts & ASEC_SB_C_OPTS_EXT4) {
Jeff Sharkeyd0640f62015-05-21 22:35:42 -07001144 result = android::vold::ext4::Mount(loopDevice, mountPoint,
1145 true, true, true);
Kenny Root344ca102012-04-03 17:23:01 -07001146 } else {
Jeff Sharkeyd0640f62015-05-21 22:35:42 -07001147 result = android::vold::vfat::Mount(loopDevice, mountPoint,
1148 true, true, true, 0, 0, 0227, false);
Kenny Root344ca102012-04-03 17:23:01 -07001149 }
1150
1151 if (result) {
San Mehat97ac40e2010-03-24 10:24:19 -07001152 SLOGE("ASEC finalize mount failed (%s)", strerror(errno));
San Mehata19b2502010-01-06 10:33:53 -08001153 return -1;
1154 }
1155
San Mehatd9a4e352010-03-12 13:32:47 -08001156 if (mDebug) {
San Mehat97ac40e2010-03-24 10:24:19 -07001157 SLOGD("ASEC %s finalized", id);
San Mehatd9a4e352010-03-12 13:32:47 -08001158 }
San Mehata19b2502010-01-06 10:33:53 -08001159 return 0;
1160}
1161
Kenny Root344ca102012-04-03 17:23:01 -07001162int VolumeManager::fixupAsecPermissions(const char *id, gid_t gid, const char* filename) {
1163 char asecFileName[255];
1164 char loopDevice[255];
1165 char mountPoint[255];
1166
1167 if (gid < AID_APP) {
1168 SLOGE("Group ID is not in application range");
1169 return -1;
1170 }
1171
Nick Kralevich0de7c612014-01-27 14:58:06 -08001172 if (!isLegalAsecId(id)) {
1173 SLOGE("fixupAsecPermissions: Invalid asec id \"%s\"", id);
1174 errno = EINVAL;
1175 return -1;
1176 }
1177
Kenny Root344ca102012-04-03 17:23:01 -07001178 if (findAsec(id, asecFileName, sizeof(asecFileName))) {
1179 SLOGE("Couldn't find ASEC %s", id);
1180 return -1;
1181 }
1182
1183 char idHash[33];
1184 if (!asecHash(id, idHash, sizeof(idHash))) {
1185 SLOGE("Hash of '%s' failed (%s)", id, strerror(errno));
1186 return -1;
1187 }
1188
1189 if (Loop::lookupActive(idHash, loopDevice, sizeof(loopDevice))) {
1190 SLOGE("Unable fix permissions during lookup on %s (%s)", id, strerror(errno));
1191 return -1;
1192 }
1193
Hiroaki Miyazawa14eab552015-02-04 13:29:15 +09001194 unsigned long nr_sec = 0;
Kenny Root344ca102012-04-03 17:23:01 -07001195 struct asec_superblock sb;
1196
1197 if (Loop::lookupInfo(loopDevice, &sb, &nr_sec)) {
1198 return -1;
1199 }
1200
Jeff Sharkey9f18fe72015-04-01 23:32:18 -07001201 int written = snprintf(mountPoint, sizeof(mountPoint), "%s/%s", VolumeManager::ASECDIR, id);
rpcraigd1c226f2012-10-09 06:58:16 -04001202 if ((written < 0) || (size_t(written) >= sizeof(mountPoint))) {
1203 SLOGE("Unable remount to fix permissions for %s: couldn't construct mountpoint", id);
1204 return -1;
1205 }
Kenny Root344ca102012-04-03 17:23:01 -07001206
1207 int result = 0;
1208 if ((sb.c_opts & ASEC_SB_C_OPTS_EXT4) == 0) {
1209 return 0;
1210 }
1211
Jeff Sharkeyd0640f62015-05-21 22:35:42 -07001212 int ret = android::vold::ext4::Mount(loopDevice, mountPoint,
Kenny Root344ca102012-04-03 17:23:01 -07001213 false /* read-only */,
1214 true /* remount */,
1215 false /* executable */);
1216 if (ret) {
1217 SLOGE("Unable remount to fix permissions for %s (%s)", id, strerror(errno));
1218 return -1;
1219 }
1220
1221 char *paths[] = { mountPoint, NULL };
1222
1223 FTS *fts = fts_open(paths, FTS_PHYSICAL | FTS_NOCHDIR | FTS_XDEV, NULL);
1224 if (fts) {
1225 // Traverse the entire hierarchy and chown to system UID.
1226 for (FTSENT *ftsent = fts_read(fts); ftsent != NULL; ftsent = fts_read(fts)) {
1227 // We don't care about the lost+found directory.
1228 if (!strcmp(ftsent->fts_name, "lost+found")) {
1229 continue;
1230 }
1231
1232 /*
1233 * There can only be one file marked as private right now.
1234 * This should be more robust, but it satisfies the requirements
1235 * we have for right now.
1236 */
1237 const bool privateFile = !strcmp(ftsent->fts_name, filename);
1238
Jeff Sharkeyce6a9132015-04-08 21:07:21 -07001239 int fd = open(ftsent->fts_accpath, O_NOFOLLOW | O_CLOEXEC);
Kenny Root344ca102012-04-03 17:23:01 -07001240 if (fd < 0) {
1241 SLOGE("Couldn't open file %s: %s", ftsent->fts_accpath, strerror(errno));
1242 result = -1;
1243 continue;
1244 }
1245
1246 result |= fchown(fd, AID_SYSTEM, privateFile? gid : AID_SYSTEM);
1247
1248 if (ftsent->fts_info & FTS_D) {
Kenny Root1a673c82012-05-10 16:45:29 -07001249 result |= fchmod(fd, 0755);
Kenny Root348c8ab2012-05-10 15:39:53 -07001250 } else if (ftsent->fts_info & FTS_F) {
Kenny Root344ca102012-04-03 17:23:01 -07001251 result |= fchmod(fd, privateFile ? 0640 : 0644);
1252 }
Robert Craigb9e3ba52014-02-04 10:53:00 -05001253
Stephen Smalley5093e612014-02-12 09:43:08 -05001254 if (selinux_android_restorecon(ftsent->fts_path, 0) < 0) {
Robert Craigb9e3ba52014-02-04 10:53:00 -05001255 SLOGE("restorecon failed for %s: %s\n", ftsent->fts_path, strerror(errno));
1256 result |= -1;
1257 }
1258
Kenny Root344ca102012-04-03 17:23:01 -07001259 close(fd);
1260 }
1261 fts_close(fts);
1262
1263 // Finally make the directory readable by everyone.
Jeff Sharkeyce6a9132015-04-08 21:07:21 -07001264 int dirfd = open(mountPoint, O_DIRECTORY | O_CLOEXEC);
Kenny Root344ca102012-04-03 17:23:01 -07001265 if (dirfd < 0 || fchmod(dirfd, 0755)) {
1266 SLOGE("Couldn't change owner of existing directory %s: %s", mountPoint, strerror(errno));
1267 result |= -1;
1268 }
1269 close(dirfd);
1270 } else {
1271 result |= -1;
1272 }
1273
Jeff Sharkeyd0640f62015-05-21 22:35:42 -07001274 result |= android::vold::ext4::Mount(loopDevice, mountPoint,
Kenny Root344ca102012-04-03 17:23:01 -07001275 true /* read-only */,
1276 true /* remount */,
1277 true /* execute */);
1278
1279 if (result) {
1280 SLOGE("ASEC fix permissions failed (%s)", strerror(errno));
1281 return -1;
1282 }
1283
1284 if (mDebug) {
1285 SLOGD("ASEC %s permissions fixed", id);
1286 }
1287 return 0;
1288}
1289
San Mehat048b0802010-01-23 08:17:06 -08001290int VolumeManager::renameAsec(const char *id1, const char *id2) {
Kenny Root344ca102012-04-03 17:23:01 -07001291 char asecFilename1[255];
San Mehat048b0802010-01-23 08:17:06 -08001292 char *asecFilename2;
1293 char mountPoint[255];
1294
Kenny Root344ca102012-04-03 17:23:01 -07001295 const char *dir;
1296
Nick Kralevich0de7c612014-01-27 14:58:06 -08001297 if (!isLegalAsecId(id1)) {
1298 SLOGE("renameAsec: Invalid asec id1 \"%s\"", id1);
1299 errno = EINVAL;
1300 return -1;
1301 }
1302
1303 if (!isLegalAsecId(id2)) {
1304 SLOGE("renameAsec: Invalid asec id2 \"%s\"", id2);
1305 errno = EINVAL;
1306 return -1;
1307 }
1308
Kenny Root344ca102012-04-03 17:23:01 -07001309 if (findAsec(id1, asecFilename1, sizeof(asecFilename1), &dir)) {
1310 SLOGE("Couldn't find ASEC %s", id1);
1311 return -1;
1312 }
1313
1314 asprintf(&asecFilename2, "%s/%s.asec", dir, id2);
San Mehat048b0802010-01-23 08:17:06 -08001315
Jeff Sharkey9f18fe72015-04-01 23:32:18 -07001316 int written = snprintf(mountPoint, sizeof(mountPoint), "%s/%s", VolumeManager::ASECDIR, id1);
rpcraigd1c226f2012-10-09 06:58:16 -04001317 if ((written < 0) || (size_t(written) >= sizeof(mountPoint))) {
1318 SLOGE("Rename failed: couldn't construct mountpoint");
1319 goto out_err;
1320 }
1321
San Mehat048b0802010-01-23 08:17:06 -08001322 if (isMountpointMounted(mountPoint)) {
San Mehat97ac40e2010-03-24 10:24:19 -07001323 SLOGW("Rename attempt when src mounted");
San Mehat048b0802010-01-23 08:17:06 -08001324 errno = EBUSY;
1325 goto out_err;
1326 }
1327
Jeff Sharkey9f18fe72015-04-01 23:32:18 -07001328 written = snprintf(mountPoint, sizeof(mountPoint), "%s/%s", VolumeManager::ASECDIR, id2);
rpcraigd1c226f2012-10-09 06:58:16 -04001329 if ((written < 0) || (size_t(written) >= sizeof(mountPoint))) {
1330 SLOGE("Rename failed: couldn't construct mountpoint2");
1331 goto out_err;
1332 }
1333
San Mehat96956ed2010-02-24 08:42:51 -08001334 if (isMountpointMounted(mountPoint)) {
San Mehat97ac40e2010-03-24 10:24:19 -07001335 SLOGW("Rename attempt when dst mounted");
San Mehat96956ed2010-02-24 08:42:51 -08001336 errno = EBUSY;
1337 goto out_err;
1338 }
1339
San Mehat048b0802010-01-23 08:17:06 -08001340 if (!access(asecFilename2, F_OK)) {
San Mehat97ac40e2010-03-24 10:24:19 -07001341 SLOGE("Rename attempt when dst exists");
San Mehat048b0802010-01-23 08:17:06 -08001342 errno = EADDRINUSE;
1343 goto out_err;
1344 }
1345
1346 if (rename(asecFilename1, asecFilename2)) {
San Mehat97ac40e2010-03-24 10:24:19 -07001347 SLOGE("Rename of '%s' to '%s' failed (%s)", asecFilename1, asecFilename2, strerror(errno));
San Mehat048b0802010-01-23 08:17:06 -08001348 goto out_err;
1349 }
1350
San Mehat048b0802010-01-23 08:17:06 -08001351 free(asecFilename2);
1352 return 0;
1353
1354out_err:
San Mehat048b0802010-01-23 08:17:06 -08001355 free(asecFilename2);
1356 return -1;
1357}
1358
Kenny Rootfb7c4d52010-06-30 18:48:41 -07001359#define UNMOUNT_RETRIES 5
1360#define UNMOUNT_SLEEP_BETWEEN_RETRY_MS (1000 * 1000)
San Mehat4ba89482010-02-18 09:00:18 -08001361int VolumeManager::unmountAsec(const char *id, bool force) {
San Mehata19b2502010-01-06 10:33:53 -08001362 char asecFileName[255];
1363 char mountPoint[255];
1364
Nick Kralevich0de7c612014-01-27 14:58:06 -08001365 if (!isLegalAsecId(id)) {
1366 SLOGE("unmountAsec: Invalid asec id \"%s\"", id);
1367 errno = EINVAL;
1368 return -1;
1369 }
1370
Kenny Root344ca102012-04-03 17:23:01 -07001371 if (findAsec(id, asecFileName, sizeof(asecFileName))) {
1372 SLOGE("Couldn't find ASEC %s", id);
1373 return -1;
1374 }
1375
Jeff Sharkey9f18fe72015-04-01 23:32:18 -07001376 int written = snprintf(mountPoint, sizeof(mountPoint), "%s/%s", VolumeManager::ASECDIR, id);
rpcraigd1c226f2012-10-09 06:58:16 -04001377 if ((written < 0) || (size_t(written) >= sizeof(mountPoint))) {
1378 SLOGE("ASEC unmount failed for %s: couldn't construct mountpoint", id);
1379 return -1;
1380 }
San Mehata19b2502010-01-06 10:33:53 -08001381
San Mehatd9a4e352010-03-12 13:32:47 -08001382 char idHash[33];
1383 if (!asecHash(id, idHash, sizeof(idHash))) {
San Mehat97ac40e2010-03-24 10:24:19 -07001384 SLOGE("Hash of '%s' failed (%s)", id, strerror(errno));
San Mehatd9a4e352010-03-12 13:32:47 -08001385 return -1;
1386 }
1387
Kenny Rootfb7c4d52010-06-30 18:48:41 -07001388 return unmountLoopImage(id, idHash, asecFileName, mountPoint, force);
1389}
1390
Kenny Root508c0e12010-07-12 09:59:49 -07001391int VolumeManager::unmountObb(const char *fileName, bool force) {
Kenny Rootfb7c4d52010-06-30 18:48:41 -07001392 char mountPoint[255];
1393
1394 char idHash[33];
1395 if (!asecHash(fileName, idHash, sizeof(idHash))) {
1396 SLOGE("Hash of '%s' failed (%s)", fileName, strerror(errno));
1397 return -1;
1398 }
1399
Jeff Sharkey9f18fe72015-04-01 23:32:18 -07001400 int written = snprintf(mountPoint, sizeof(mountPoint), "%s/%s", VolumeManager::LOOPDIR, idHash);
rpcraigd1c226f2012-10-09 06:58:16 -04001401 if ((written < 0) || (size_t(written) >= sizeof(mountPoint))) {
1402 SLOGE("OBB unmount failed for %s: couldn't construct mountpoint", fileName);
1403 return -1;
1404 }
Kenny Rootfb7c4d52010-06-30 18:48:41 -07001405
1406 return unmountLoopImage(fileName, idHash, fileName, mountPoint, force);
1407}
1408
1409int VolumeManager::unmountLoopImage(const char *id, const char *idHash,
1410 const char *fileName, const char *mountPoint, bool force) {
San Mehat0586d542010-01-12 15:38:59 -08001411 if (!isMountpointMounted(mountPoint)) {
Kenny Rootfb7c4d52010-06-30 18:48:41 -07001412 SLOGE("Unmount request for %s when not mounted", id);
Kenny Root918e5f92010-09-30 18:00:52 -07001413 errno = ENOENT;
San Mehatb78a32c2010-01-10 13:02:12 -08001414 return -1;
1415 }
San Mehat23969932010-01-09 07:08:06 -08001416
San Mehatb78a32c2010-01-10 13:02:12 -08001417 int i, rc;
Kenny Rootfb7c4d52010-06-30 18:48:41 -07001418 for (i = 1; i <= UNMOUNT_RETRIES; i++) {
San Mehatb78a32c2010-01-10 13:02:12 -08001419 rc = umount(mountPoint);
1420 if (!rc) {
1421 break;
San Mehata19b2502010-01-06 10:33:53 -08001422 }
San Mehatb78a32c2010-01-10 13:02:12 -08001423 if (rc && (errno == EINVAL || errno == ENOENT)) {
Kenny Rootfb7c4d52010-06-30 18:48:41 -07001424 SLOGI("Container %s unmounted OK", id);
San Mehatb78a32c2010-01-10 13:02:12 -08001425 rc = 0;
1426 break;
San Mehata19b2502010-01-06 10:33:53 -08001427 }
Kenny Rootfb7c4d52010-06-30 18:48:41 -07001428 SLOGW("%s unmount attempt %d failed (%s)",
San Mehat8c940ef2010-02-13 14:19:53 -08001429 id, i, strerror(errno));
San Mehatb78a32c2010-01-10 13:02:12 -08001430
Jeff Sharkey36801cc2015-03-13 16:09:20 -07001431 int signal = 0; // default is to just complain
San Mehat4ba89482010-02-18 09:00:18 -08001432
1433 if (force) {
Kenny Rootfb7c4d52010-06-30 18:48:41 -07001434 if (i > (UNMOUNT_RETRIES - 2))
Jeff Sharkey36801cc2015-03-13 16:09:20 -07001435 signal = SIGKILL;
Kenny Rootfb7c4d52010-06-30 18:48:41 -07001436 else if (i > (UNMOUNT_RETRIES - 3))
Jeff Sharkey36801cc2015-03-13 16:09:20 -07001437 signal = SIGTERM;
San Mehat4ba89482010-02-18 09:00:18 -08001438 }
San Mehat8c940ef2010-02-13 14:19:53 -08001439
Jeff Sharkey36801cc2015-03-13 16:09:20 -07001440 Process::killProcessesWithOpenFiles(mountPoint, signal);
Kenny Rootfb7c4d52010-06-30 18:48:41 -07001441 usleep(UNMOUNT_SLEEP_BETWEEN_RETRY_MS);
San Mehatb78a32c2010-01-10 13:02:12 -08001442 }
1443
1444 if (rc) {
San Mehat4ba89482010-02-18 09:00:18 -08001445 errno = EBUSY;
San Mehat97ac40e2010-03-24 10:24:19 -07001446 SLOGE("Failed to unmount container %s (%s)", id, strerror(errno));
San Mehatb78a32c2010-01-10 13:02:12 -08001447 return -1;
1448 }
1449
San Mehat12f4b892010-02-24 11:43:22 -08001450 int retries = 10;
1451
1452 while(retries--) {
1453 if (!rmdir(mountPoint)) {
1454 break;
1455 }
1456
San Mehat97ac40e2010-03-24 10:24:19 -07001457 SLOGW("Failed to rmdir %s (%s)", mountPoint, strerror(errno));
Kenny Rootfb7c4d52010-06-30 18:48:41 -07001458 usleep(UNMOUNT_SLEEP_BETWEEN_RETRY_MS);
San Mehat12f4b892010-02-24 11:43:22 -08001459 }
1460
1461 if (!retries) {
San Mehat97ac40e2010-03-24 10:24:19 -07001462 SLOGE("Timed out trying to rmdir %s (%s)", mountPoint, strerror(errno));
San Mehatf5c61982010-02-03 11:04:46 -08001463 }
San Mehat88705162010-01-15 09:26:28 -08001464
Paul Lawrence60dec162014-09-02 10:52:15 -07001465 for (i=1; i <= UNMOUNT_RETRIES; i++) {
1466 if (Devmapper::destroy(idHash) && errno != ENXIO) {
1467 SLOGE("Failed to destroy devmapper instance (%s)", strerror(errno));
1468 usleep(UNMOUNT_SLEEP_BETWEEN_RETRY_MS);
1469 continue;
1470 } else {
1471 break;
1472 }
San Mehata19b2502010-01-06 10:33:53 -08001473 }
1474
1475 char loopDevice[255];
San Mehatd9a4e352010-03-12 13:32:47 -08001476 if (!Loop::lookupActive(idHash, loopDevice, sizeof(loopDevice))) {
San Mehata19b2502010-01-06 10:33:53 -08001477 Loop::destroyByDevice(loopDevice);
San Mehatd9a4e352010-03-12 13:32:47 -08001478 } else {
Kenny Rootfb7c4d52010-06-30 18:48:41 -07001479 SLOGW("Failed to find loop device for {%s} (%s)", fileName, strerror(errno));
San Mehata19b2502010-01-06 10:33:53 -08001480 }
San Mehat88705162010-01-15 09:26:28 -08001481
1482 AsecIdCollection::iterator it;
1483 for (it = mActiveContainers->begin(); it != mActiveContainers->end(); ++it) {
Kenny Rootcbacf782010-09-24 15:11:48 -07001484 ContainerData* cd = *it;
1485 if (!strcmp(cd->id, id)) {
San Mehat88705162010-01-15 09:26:28 -08001486 free(*it);
1487 mActiveContainers->erase(it);
1488 break;
1489 }
1490 }
1491 if (it == mActiveContainers->end()) {
San Mehat97ac40e2010-03-24 10:24:19 -07001492 SLOGW("mActiveContainers is inconsistent!");
San Mehat88705162010-01-15 09:26:28 -08001493 }
San Mehatb78a32c2010-01-10 13:02:12 -08001494 return 0;
1495}
1496
San Mehat4ba89482010-02-18 09:00:18 -08001497int VolumeManager::destroyAsec(const char *id, bool force) {
San Mehatb78a32c2010-01-10 13:02:12 -08001498 char asecFileName[255];
1499 char mountPoint[255];
1500
Nick Kralevich0de7c612014-01-27 14:58:06 -08001501 if (!isLegalAsecId(id)) {
1502 SLOGE("destroyAsec: Invalid asec id \"%s\"", id);
1503 errno = EINVAL;
1504 return -1;
1505 }
1506
Kenny Root344ca102012-04-03 17:23:01 -07001507 if (findAsec(id, asecFileName, sizeof(asecFileName))) {
1508 SLOGE("Couldn't find ASEC %s", id);
1509 return -1;
1510 }
1511
Jeff Sharkey9f18fe72015-04-01 23:32:18 -07001512 int written = snprintf(mountPoint, sizeof(mountPoint), "%s/%s", VolumeManager::ASECDIR, id);
rpcraigd1c226f2012-10-09 06:58:16 -04001513 if ((written < 0) || (size_t(written) >= sizeof(mountPoint))) {
1514 SLOGE("ASEC destroy failed for %s: couldn't construct mountpoint", id);
1515 return -1;
1516 }
San Mehatb78a32c2010-01-10 13:02:12 -08001517
San Mehat0586d542010-01-12 15:38:59 -08001518 if (isMountpointMounted(mountPoint)) {
San Mehatd9a4e352010-03-12 13:32:47 -08001519 if (mDebug) {
San Mehat97ac40e2010-03-24 10:24:19 -07001520 SLOGD("Unmounting container before destroy");
San Mehatd9a4e352010-03-12 13:32:47 -08001521 }
San Mehat4ba89482010-02-18 09:00:18 -08001522 if (unmountAsec(id, force)) {
San Mehat97ac40e2010-03-24 10:24:19 -07001523 SLOGE("Failed to unmount asec %s for destroy (%s)", id, strerror(errno));
San Mehat0586d542010-01-12 15:38:59 -08001524 return -1;
1525 }
1526 }
San Mehata19b2502010-01-06 10:33:53 -08001527
San Mehat0586d542010-01-12 15:38:59 -08001528 if (unlink(asecFileName)) {
San Mehat97ac40e2010-03-24 10:24:19 -07001529 SLOGE("Failed to unlink asec '%s' (%s)", asecFileName, strerror(errno));
San Mehat0586d542010-01-12 15:38:59 -08001530 return -1;
1531 }
San Mehata19b2502010-01-06 10:33:53 -08001532
San Mehatd9a4e352010-03-12 13:32:47 -08001533 if (mDebug) {
San Mehat97ac40e2010-03-24 10:24:19 -07001534 SLOGD("ASEC %s destroyed", id);
San Mehatd9a4e352010-03-12 13:32:47 -08001535 }
San Mehata19b2502010-01-06 10:33:53 -08001536 return 0;
1537}
1538
Nick Kralevich0de7c612014-01-27 14:58:06 -08001539/*
1540 * Legal ASEC ids consist of alphanumeric characters, '-',
1541 * '_', or '.'. ".." is not allowed. The first or last character
1542 * of the ASEC id cannot be '.' (dot).
1543 */
1544bool VolumeManager::isLegalAsecId(const char *id) const {
1545 size_t i;
1546 size_t len = strlen(id);
1547
1548 if (len == 0) {
1549 return false;
1550 }
1551 if ((id[0] == '.') || (id[len - 1] == '.')) {
1552 return false;
1553 }
1554
1555 for (i = 0; i < len; i++) {
1556 if (id[i] == '.') {
1557 // i=0 is guaranteed never to have a dot. See above.
1558 if (id[i-1] == '.') return false;
1559 continue;
1560 }
1561 if (id[i] == '_' || id[i] == '-') continue;
1562 if (id[i] >= 'a' && id[i] <= 'z') continue;
1563 if (id[i] >= 'A' && id[i] <= 'Z') continue;
1564 if (id[i] >= '0' && id[i] <= '9') continue;
1565 return false;
1566 }
1567
1568 return true;
1569}
1570
Kenny Root344ca102012-04-03 17:23:01 -07001571bool VolumeManager::isAsecInDirectory(const char *dir, const char *asecName) const {
Jeff Sharkeyce6a9132015-04-08 21:07:21 -07001572 int dirfd = open(dir, O_DIRECTORY | O_CLOEXEC);
Kenny Root344ca102012-04-03 17:23:01 -07001573 if (dirfd < 0) {
1574 SLOGE("Couldn't open internal ASEC dir (%s)", strerror(errno));
Nick Kralevich25e581a2015-02-06 08:55:08 -08001575 return false;
Kenny Root344ca102012-04-03 17:23:01 -07001576 }
1577
Nick Kralevich25e581a2015-02-06 08:55:08 -08001578 struct stat sb;
1579 bool ret = (fstatat(dirfd, asecName, &sb, AT_SYMLINK_NOFOLLOW) == 0)
1580 && S_ISREG(sb.st_mode);
Kenny Root344ca102012-04-03 17:23:01 -07001581
1582 close(dirfd);
1583
1584 return ret;
1585}
1586
1587int VolumeManager::findAsec(const char *id, char *asecPath, size_t asecPathLen,
1588 const char **directory) const {
Kenny Root344ca102012-04-03 17:23:01 -07001589 char *asecName;
1590
Nick Kralevich0de7c612014-01-27 14:58:06 -08001591 if (!isLegalAsecId(id)) {
1592 SLOGE("findAsec: Invalid asec id \"%s\"", id);
1593 errno = EINVAL;
1594 return -1;
1595 }
1596
Kenny Root344ca102012-04-03 17:23:01 -07001597 if (asprintf(&asecName, "%s.asec", id) < 0) {
1598 SLOGE("Couldn't allocate string to write ASEC name");
1599 return -1;
1600 }
1601
1602 const char *dir;
Jeff Sharkey9f18fe72015-04-01 23:32:18 -07001603 if (isAsecInDirectory(VolumeManager::SEC_ASECDIR_INT, asecName)) {
1604 dir = VolumeManager::SEC_ASECDIR_INT;
1605 } else if (isAsecInDirectory(VolumeManager::SEC_ASECDIR_EXT, asecName)) {
1606 dir = VolumeManager::SEC_ASECDIR_EXT;
Kenny Root344ca102012-04-03 17:23:01 -07001607 } else {
1608 free(asecName);
1609 return -1;
1610 }
1611
1612 if (directory != NULL) {
1613 *directory = dir;
1614 }
1615
1616 if (asecPath != NULL) {
1617 int written = snprintf(asecPath, asecPathLen, "%s/%s", dir, asecName);
rpcraigd1c226f2012-10-09 06:58:16 -04001618 if ((written < 0) || (size_t(written) >= asecPathLen)) {
1619 SLOGE("findAsec failed for %s: couldn't construct ASEC path", id);
Kenny Root344ca102012-04-03 17:23:01 -07001620 free(asecName);
1621 return -1;
1622 }
1623 }
1624
1625 free(asecName);
1626 return 0;
1627}
1628
Jeff Sharkey43ed1232014-08-22 12:29:05 -07001629int VolumeManager::mountAsec(const char *id, const char *key, int ownerUid, bool readOnly) {
San Mehata19b2502010-01-06 10:33:53 -08001630 char asecFileName[255];
1631 char mountPoint[255];
1632
Nick Kralevich0de7c612014-01-27 14:58:06 -08001633 if (!isLegalAsecId(id)) {
1634 SLOGE("mountAsec: Invalid asec id \"%s\"", id);
1635 errno = EINVAL;
1636 return -1;
1637 }
1638
Kenny Root344ca102012-04-03 17:23:01 -07001639 if (findAsec(id, asecFileName, sizeof(asecFileName))) {
1640 SLOGE("Couldn't find ASEC %s", id);
1641 return -1;
1642 }
1643
Jeff Sharkey9f18fe72015-04-01 23:32:18 -07001644 int written = snprintf(mountPoint, sizeof(mountPoint), "%s/%s", VolumeManager::ASECDIR, id);
rpcraigd1c226f2012-10-09 06:58:16 -04001645 if ((written < 0) || (size_t(written) >= sizeof(mountPoint))) {
Colin Cross59846b62014-02-06 20:34:29 -08001646 SLOGE("ASEC mount failed for %s: couldn't construct mountpoint", id);
rpcraigd1c226f2012-10-09 06:58:16 -04001647 return -1;
1648 }
San Mehata19b2502010-01-06 10:33:53 -08001649
1650 if (isMountpointMounted(mountPoint)) {
San Mehat97ac40e2010-03-24 10:24:19 -07001651 SLOGE("ASEC %s already mounted", id);
San Mehata19b2502010-01-06 10:33:53 -08001652 errno = EBUSY;
1653 return -1;
1654 }
1655
San Mehatd9a4e352010-03-12 13:32:47 -08001656 char idHash[33];
1657 if (!asecHash(id, idHash, sizeof(idHash))) {
San Mehat97ac40e2010-03-24 10:24:19 -07001658 SLOGE("Hash of '%s' failed (%s)", id, strerror(errno));
San Mehatd9a4e352010-03-12 13:32:47 -08001659 return -1;
1660 }
Kenny Root7b18a7b2010-03-15 13:13:41 -07001661
San Mehata19b2502010-01-06 10:33:53 -08001662 char loopDevice[255];
Daniel Rosenbergfcd34a02014-05-22 11:23:56 -07001663 if (setupLoopDevice(loopDevice, sizeof(loopDevice), asecFileName, idHash, mDebug))
1664 return -1;
San Mehatb78a32c2010-01-10 13:02:12 -08001665
1666 char dmDevice[255];
1667 bool cleanupDm = false;
Tim Murray8439dc92014-12-15 11:56:11 -08001668
Hiroaki Miyazawa14eab552015-02-04 13:29:15 +09001669 unsigned long nr_sec = 0;
San Mehatfcf24fe2010-03-03 12:37:32 -08001670 struct asec_superblock sb;
San Mehatfcf24fe2010-03-03 12:37:32 -08001671
Kenny Root344ca102012-04-03 17:23:01 -07001672 if (Loop::lookupInfo(loopDevice, &sb, &nr_sec)) {
1673 return -1;
1674 }
San Mehatfcf24fe2010-03-03 12:37:32 -08001675
San Mehatd9a4e352010-03-12 13:32:47 -08001676 if (mDebug) {
San Mehat97ac40e2010-03-24 10:24:19 -07001677 SLOGD("Container sb magic/ver (%.8x/%.2x)", sb.magic, sb.ver);
San Mehatd9a4e352010-03-12 13:32:47 -08001678 }
San Mehatfcf24fe2010-03-03 12:37:32 -08001679 if (sb.magic != ASEC_SB_MAGIC || sb.ver != ASEC_SB_VER) {
San Mehat97ac40e2010-03-24 10:24:19 -07001680 SLOGE("Bad container magic/version (%.8x/%.2x)", sb.magic, sb.ver);
San Mehatfcf24fe2010-03-03 12:37:32 -08001681 Loop::destroyByDevice(loopDevice);
1682 errno = EMEDIUMTYPE;
1683 return -1;
1684 }
1685 nr_sec--; // We don't want the devmapping to extend onto our superblock
1686
Daniel Rosenbergfcd34a02014-05-22 11:23:56 -07001687 if (setupDevMapperDevice(dmDevice, sizeof(dmDevice), loopDevice, asecFileName, key, idHash , nr_sec, &cleanupDm, mDebug)) {
1688 Loop::destroyByDevice(loopDevice);
1689 return -1;
San Mehata19b2502010-01-06 10:33:53 -08001690 }
1691
Kenny Root344ca102012-04-03 17:23:01 -07001692 if (mkdir(mountPoint, 0000)) {
San Mehatb78a32c2010-01-10 13:02:12 -08001693 if (errno != EEXIST) {
San Mehat97ac40e2010-03-24 10:24:19 -07001694 SLOGE("Mountpoint creation failed (%s)", strerror(errno));
San Mehatb78a32c2010-01-10 13:02:12 -08001695 if (cleanupDm) {
San Mehatd9a4e352010-03-12 13:32:47 -08001696 Devmapper::destroy(idHash);
San Mehatb78a32c2010-01-10 13:02:12 -08001697 }
1698 Loop::destroyByDevice(loopDevice);
1699 return -1;
1700 }
San Mehata19b2502010-01-06 10:33:53 -08001701 }
1702
Kenny Rootcdc2a1c2012-05-03 13:49:46 -07001703 /*
Daniel Rosenbergfcd34a02014-05-22 11:23:56 -07001704 * Wait for the device mapper node to be created.
Kenny Rootcdc2a1c2012-05-03 13:49:46 -07001705 */
Daniel Rosenbergfcd34a02014-05-22 11:23:56 -07001706 waitForDevMapper(dmDevice);
Kenny Rootcdc2a1c2012-05-03 13:49:46 -07001707
Kenny Root344ca102012-04-03 17:23:01 -07001708 int result;
1709 if (sb.c_opts & ASEC_SB_C_OPTS_EXT4) {
Jeff Sharkeyd0640f62015-05-21 22:35:42 -07001710 result = android::vold::ext4::Mount(dmDevice, mountPoint,
1711 readOnly, false, readOnly);
Kenny Root344ca102012-04-03 17:23:01 -07001712 } else {
Jeff Sharkeyd0640f62015-05-21 22:35:42 -07001713 result = android::vold::vfat::Mount(dmDevice, mountPoint,
1714 readOnly, false, readOnly, ownerUid, 0, 0222, false);
Kenny Root344ca102012-04-03 17:23:01 -07001715 }
1716
1717 if (result) {
San Mehat97ac40e2010-03-24 10:24:19 -07001718 SLOGE("ASEC mount failed (%s)", strerror(errno));
San Mehatb78a32c2010-01-10 13:02:12 -08001719 if (cleanupDm) {
San Mehatd9a4e352010-03-12 13:32:47 -08001720 Devmapper::destroy(idHash);
San Mehatb78a32c2010-01-10 13:02:12 -08001721 }
1722 Loop::destroyByDevice(loopDevice);
San Mehata19b2502010-01-06 10:33:53 -08001723 return -1;
1724 }
1725
Kenny Rootcbacf782010-09-24 15:11:48 -07001726 mActiveContainers->push_back(new ContainerData(strdup(id), ASEC));
San Mehatd9a4e352010-03-12 13:32:47 -08001727 if (mDebug) {
San Mehat97ac40e2010-03-24 10:24:19 -07001728 SLOGD("ASEC %s mounted", id);
San Mehatd9a4e352010-03-12 13:32:47 -08001729 }
San Mehata19b2502010-01-06 10:33:53 -08001730 return 0;
1731}
1732
Kenny Rootfb7c4d52010-06-30 18:48:41 -07001733/**
1734 * Mounts an image file <code>img</code>.
1735 */
Jeff Sharkey69479042012-09-25 16:14:57 -07001736int VolumeManager::mountObb(const char *img, const char *key, int ownerGid) {
Kenny Rootfb7c4d52010-06-30 18:48:41 -07001737 char mountPoint[255];
1738
Kenny Rootfb7c4d52010-06-30 18:48:41 -07001739 char idHash[33];
1740 if (!asecHash(img, idHash, sizeof(idHash))) {
1741 SLOGE("Hash of '%s' failed (%s)", img, strerror(errno));
1742 return -1;
1743 }
1744
Jeff Sharkey9f18fe72015-04-01 23:32:18 -07001745 int written = snprintf(mountPoint, sizeof(mountPoint), "%s/%s", VolumeManager::LOOPDIR, idHash);
rpcraigd1c226f2012-10-09 06:58:16 -04001746 if ((written < 0) || (size_t(written) >= sizeof(mountPoint))) {
Colin Cross59846b62014-02-06 20:34:29 -08001747 SLOGE("OBB mount failed for %s: couldn't construct mountpoint", img);
rpcraigd1c226f2012-10-09 06:58:16 -04001748 return -1;
1749 }
Kenny Rootfb7c4d52010-06-30 18:48:41 -07001750
1751 if (isMountpointMounted(mountPoint)) {
1752 SLOGE("Image %s already mounted", img);
1753 errno = EBUSY;
1754 return -1;
1755 }
1756
1757 char loopDevice[255];
Daniel Rosenbergfcd34a02014-05-22 11:23:56 -07001758 if (setupLoopDevice(loopDevice, sizeof(loopDevice), img, idHash, mDebug))
1759 return -1;
Kenny Rootfb7c4d52010-06-30 18:48:41 -07001760
1761 char dmDevice[255];
1762 bool cleanupDm = false;
1763 int fd;
Hiroaki Miyazawa14eab552015-02-04 13:29:15 +09001764 unsigned long nr_sec = 0;
Kenny Rootfb7c4d52010-06-30 18:48:41 -07001765
Jeff Sharkeyce6a9132015-04-08 21:07:21 -07001766 if ((fd = open(loopDevice, O_RDWR | O_CLOEXEC)) < 0) {
Kenny Rootfb7c4d52010-06-30 18:48:41 -07001767 SLOGE("Failed to open loopdevice (%s)", strerror(errno));
1768 Loop::destroyByDevice(loopDevice);
1769 return -1;
1770 }
1771
Hiroaki Miyazawa14eab552015-02-04 13:29:15 +09001772 get_blkdev_size(fd, &nr_sec);
1773 if (nr_sec == 0) {
Kenny Rootfb7c4d52010-06-30 18:48:41 -07001774 SLOGE("Failed to get loop size (%s)", strerror(errno));
1775 Loop::destroyByDevice(loopDevice);
1776 close(fd);
1777 return -1;
1778 }
1779
1780 close(fd);
1781
Hiroaki Miyazawa14eab552015-02-04 13:29:15 +09001782 if (setupDevMapperDevice(dmDevice, sizeof(loopDevice), loopDevice, img,key, idHash, nr_sec, &cleanupDm, mDebug)) {
Daniel Rosenbergfcd34a02014-05-22 11:23:56 -07001783 Loop::destroyByDevice(loopDevice);
1784 return -1;
Kenny Rootfb7c4d52010-06-30 18:48:41 -07001785 }
1786
1787 if (mkdir(mountPoint, 0755)) {
1788 if (errno != EEXIST) {
1789 SLOGE("Mountpoint creation failed (%s)", strerror(errno));
1790 if (cleanupDm) {
1791 Devmapper::destroy(idHash);
1792 }
1793 Loop::destroyByDevice(loopDevice);
1794 return -1;
1795 }
1796 }
1797
yoshiyuki hama476a6272015-01-28 16:37:23 +09001798 /*
1799 * Wait for the device mapper node to be created.
1800 */
1801 waitForDevMapper(dmDevice);
1802
Jeff Sharkeyd0640f62015-05-21 22:35:42 -07001803 if (android::vold::vfat::Mount(dmDevice, mountPoint,
1804 true, false, true, 0, ownerGid, 0227, false)) {
Kenny Rootfb7c4d52010-06-30 18:48:41 -07001805 SLOGE("Image mount failed (%s)", strerror(errno));
1806 if (cleanupDm) {
1807 Devmapper::destroy(idHash);
1808 }
1809 Loop::destroyByDevice(loopDevice);
1810 return -1;
1811 }
1812
Kenny Rootcbacf782010-09-24 15:11:48 -07001813 mActiveContainers->push_back(new ContainerData(strdup(img), OBB));
Kenny Rootfb7c4d52010-06-30 18:48:41 -07001814 if (mDebug) {
1815 SLOGD("Image %s mounted", img);
1816 }
1817 return 0;
1818}
1819
Kenny Root508c0e12010-07-12 09:59:49 -07001820int VolumeManager::listMountedObbs(SocketClient* cli) {
Yabin Cuid1104f72015-01-02 13:28:28 -08001821 FILE *fp = setmntent("/proc/mounts", "r");
1822 if (fp == NULL) {
Kenny Root508c0e12010-07-12 09:59:49 -07001823 SLOGE("Error opening /proc/mounts (%s)", strerror(errno));
1824 return -1;
1825 }
1826
1827 // Create a string to compare against that has a trailing slash
Jeff Sharkey9f18fe72015-04-01 23:32:18 -07001828 int loopDirLen = strlen(VolumeManager::LOOPDIR);
Kenny Root508c0e12010-07-12 09:59:49 -07001829 char loopDir[loopDirLen + 2];
Jeff Sharkey9f18fe72015-04-01 23:32:18 -07001830 strcpy(loopDir, VolumeManager::LOOPDIR);
Kenny Root508c0e12010-07-12 09:59:49 -07001831 loopDir[loopDirLen++] = '/';
1832 loopDir[loopDirLen] = '\0';
1833
Yabin Cuid1104f72015-01-02 13:28:28 -08001834 mntent* mentry;
1835 while ((mentry = getmntent(fp)) != NULL) {
1836 if (!strncmp(mentry->mnt_dir, loopDir, loopDirLen)) {
Jeff Sharkeyce6a9132015-04-08 21:07:21 -07001837 int fd = open(mentry->mnt_fsname, O_RDONLY | O_CLOEXEC);
Kenny Root508c0e12010-07-12 09:59:49 -07001838 if (fd >= 0) {
1839 struct loop_info64 li;
1840 if (ioctl(fd, LOOP_GET_STATUS64, &li) >= 0) {
1841 cli->sendMsg(ResponseCode::AsecListResult,
1842 (const char*) li.lo_file_name, false);
1843 }
1844 close(fd);
1845 }
1846 }
1847 }
Yabin Cuid1104f72015-01-02 13:28:28 -08001848 endmntent(fp);
Kenny Root508c0e12010-07-12 09:59:49 -07001849 return 0;
1850}
1851
Jeff Sharkey9c484982015-03-31 10:35:33 -07001852extern "C" int vold_unmountAll(void) {
Ken Sumrall425524d2012-06-14 20:55:28 -07001853 VolumeManager *vm = VolumeManager::Instance();
Jeff Sharkey9c484982015-03-31 10:35:33 -07001854 return vm->unmountAll();
Ken Sumrall425524d2012-06-14 20:55:28 -07001855}
1856
San Mehata19b2502010-01-06 10:33:53 -08001857bool VolumeManager::isMountpointMounted(const char *mp)
1858{
Yabin Cuid1104f72015-01-02 13:28:28 -08001859 FILE *fp = setmntent("/proc/mounts", "r");
1860 if (fp == NULL) {
San Mehat97ac40e2010-03-24 10:24:19 -07001861 SLOGE("Error opening /proc/mounts (%s)", strerror(errno));
San Mehata19b2502010-01-06 10:33:53 -08001862 return false;
1863 }
1864
Yabin Cuid1104f72015-01-02 13:28:28 -08001865 bool found_mp = false;
1866 mntent* mentry;
1867 while ((mentry = getmntent(fp)) != NULL) {
1868 if (strcmp(mentry->mnt_dir, mp) == 0) {
1869 found_mp = true;
1870 break;
San Mehata19b2502010-01-06 10:33:53 -08001871 }
San Mehata19b2502010-01-06 10:33:53 -08001872 }
Yabin Cuid1104f72015-01-02 13:28:28 -08001873 endmntent(fp);
1874 return found_mp;
San Mehata19b2502010-01-06 10:33:53 -08001875}
1876
Jeff Sharkey71ebe152013-09-17 17:24:38 -07001877int VolumeManager::mkdirs(char* path) {
Jeff Sharkey36801cc2015-03-13 16:09:20 -07001878 // Only offer to create directories for paths managed by vold
1879 if (strncmp(path, "/storage/", 9) == 0) {
1880 // fs_mkdirs() does symlink checking and relative path enforcement
1881 return fs_mkdirs(path, 0700);
Jeff Sharkey71ebe152013-09-17 17:24:38 -07001882 } else {
Cylen Yao27cfee32014-05-02 19:23:42 +08001883 SLOGE("Failed to find mounted volume for %s", path);
Jeff Sharkey71ebe152013-09-17 17:24:38 -07001884 return -EINVAL;
1885 }
Jeff Sharkey71ebe152013-09-17 17:24:38 -07001886}