blob: 022cafffa4a850682acb031157a719c397d10b7f [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 Sharkey11c2d382017-09-11 10:32:01 -060051#include "model/EmulatedVolume.h"
52#include "model/ObbVolume.h"
San Mehatf1b736b2009-10-10 17:22:08 -070053#include "VolumeManager.h"
Jeff Sharkey36801cc2015-03-13 16:09:20 -070054#include "NetlinkManager.h"
San Mehata2677e42009-12-13 10:40:18 -080055#include "ResponseCode.h"
San Mehata19b2502010-01-06 10:33:53 -080056#include "Loop.h"
Jeff Sharkeyd0640f62015-05-21 22:35:42 -070057#include "fs/Ext4.h"
58#include "fs/Vfat.h"
Jeff Sharkey36801cc2015-03-13 16:09:20 -070059#include "Utils.h"
San Mehatb78a32c2010-01-10 13:02:12 -080060#include "Devmapper.h"
San Mehat586536c2010-02-16 17:12:00 -080061#include "Process.h"
San Mehatfcf24fe2010-03-03 12:37:32 -080062#include "Asec.h"
Hiroaki Miyazawa14eab552015-02-04 13:29:15 +090063#include "VoldUtil.h"
Ken Sumrall29d8da82011-05-18 17:20:07 -070064#include "cryptfs.h"
San Mehat23969932010-01-09 07:08:06 -080065
Mike Lockwood97f2fc12011-06-07 10:51:38 -070066#define MASS_STORAGE_FILE_PATH "/sys/class/android_usb/android0/f_mass_storage/lun/file"
67
Chih-Hung Hsiehcc5d5802016-05-11 15:05:05 -070068#define ROUND_UP_POWER_OF_2(number, po2) (((!!((number) & ((1U << (po2)) - 1))) << (po2))\
69 + ((number) & (~((1U << (po2)) - 1))))
Daniel Rosenberg6a74dca2014-05-23 13:47:00 -070070
Jeff Sharkey36801cc2015-03-13 16:09:20 -070071using android::base::StringPrintf;
Jeff Sharkey11c2d382017-09-11 10:32:01 -060072using android::base::unique_fd;
Jeff Sharkey36801cc2015-03-13 16:09:20 -070073
Jeff Sharkey9f18fe72015-04-01 23:32:18 -070074/*
75 * Path to external storage where *only* root can access ASEC image files
76 */
77const char *VolumeManager::SEC_ASECDIR_EXT = "/mnt/secure/asec";
78
79/*
80 * Path to internal storage where *only* root can access ASEC image files
81 */
82const char *VolumeManager::SEC_ASECDIR_INT = "/data/app-asec";
83
84/*
85 * Path to where secure containers are mounted
86 */
87const char *VolumeManager::ASECDIR = "/mnt/asec";
88
89/*
90 * Path to where OBBs are mounted
91 */
92const char *VolumeManager::LOOPDIR = "/mnt/obb";
93
Keun-young Park375ac252017-08-02 17:45:48 -070094bool VolumeManager::shutting_down = false;
95
Jeff Sharkeyfa1c6772017-03-25 22:49:13 -060096static const char* kPathUserMount = "/mnt/user";
97static const char* kPathVirtualDisk = "/data/misc/vold/virtual_disk";
98
99static const char* kPropVirtualDisk = "persist.sys.virtual_disk";
100
101/* 512MiB is large enough for testing purposes */
102static const unsigned int kSizeVirtualDisk = 536870912;
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700103
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700104static const unsigned int kMajorBlockMmc = 179;
Yu Ning942d4e82016-01-08 17:36:47 +0800105static const unsigned int kMajorBlockExperimentalMin = 240;
106static const unsigned int kMajorBlockExperimentalMax = 254;
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700107
Daniel Rosenbergfcd34a02014-05-22 11:23:56 -0700108/* writes superblock at end of file or device given by name */
109static int writeSuperBlock(const char* name, struct asec_superblock *sb, unsigned int numImgSectors) {
Jeff Sharkeyce6a9132015-04-08 21:07:21 -0700110 int sbfd = open(name, O_RDWR | O_CLOEXEC);
Daniel Rosenbergfcd34a02014-05-22 11:23:56 -0700111 if (sbfd < 0) {
112 SLOGE("Failed to open %s for superblock write (%s)", name, strerror(errno));
113 return -1;
114 }
115
116 if (lseek(sbfd, (numImgSectors * 512), SEEK_SET) < 0) {
117 SLOGE("Failed to lseek for superblock (%s)", strerror(errno));
118 close(sbfd);
119 return -1;
120 }
121
122 if (write(sbfd, sb, sizeof(struct asec_superblock)) != sizeof(struct asec_superblock)) {
123 SLOGE("Failed to write superblock (%s)", strerror(errno));
124 close(sbfd);
125 return -1;
126 }
127 close(sbfd);
128 return 0;
129}
130
Mateusz Nowaka4f48d02015-08-03 18:06:39 +0200131static unsigned long adjustSectorNumExt4(unsigned long numSectors) {
Daniel Rosenberge9196fe2014-06-10 17:16:03 -0700132 // Ext4 started to reserve 2% or 4096 clusters, whichever is smaller for
133 // preventing costly operations or unexpected ENOSPC error.
134 // Ext4::format() uses default block size without clustering.
Mateusz Nowaka4f48d02015-08-03 18:06:39 +0200135 unsigned long clusterSectors = 4096 / 512;
136 unsigned long reservedSectors = (numSectors * 2)/100 + (numSectors % 50 > 0);
Daniel Rosenberge9196fe2014-06-10 17:16:03 -0700137 numSectors += reservedSectors > (4096 * clusterSectors) ? (4096 * clusterSectors) : reservedSectors;
Daniel Rosenbergfcd34a02014-05-22 11:23:56 -0700138 return ROUND_UP_POWER_OF_2(numSectors, 3);
139}
140
Mateusz Nowaka4f48d02015-08-03 18:06:39 +0200141static unsigned long adjustSectorNumFAT(unsigned long numSectors) {
Daniel Rosenbergfcd34a02014-05-22 11:23:56 -0700142 /*
143 * Add some headroom
144 */
Mateusz Nowaka4f48d02015-08-03 18:06:39 +0200145 unsigned long fatSize = (((numSectors * 4) / 512) + 1) * 2;
Daniel Rosenbergfcd34a02014-05-22 11:23:56 -0700146 numSectors += fatSize + 2;
147 /*
148 * FAT is aligned to 32 kb with 512b sectors.
149 */
150 return ROUND_UP_POWER_OF_2(numSectors, 6);
151}
152
153static int setupLoopDevice(char* buffer, size_t len, const char* asecFileName, const char* idHash, bool debug) {
154 if (Loop::lookupActive(idHash, buffer, len)) {
155 if (Loop::create(idHash, asecFileName, buffer, len)) {
156 SLOGE("ASEC loop device creation failed for %s (%s)", asecFileName, strerror(errno));
157 return -1;
158 }
159 if (debug) {
160 SLOGD("New loop device created at %s", buffer);
161 }
162 } else {
163 if (debug) {
164 SLOGD("Found active loopback for %s at %s", asecFileName, buffer);
165 }
166 }
167 return 0;
168}
169
Mateusz Nowaka4f48d02015-08-03 18:06:39 +0200170static 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 -0700171 if (strcmp(key, "none")) {
172 if (Devmapper::lookupActive(idHash, buffer, len)) {
173 if (Devmapper::create(idHash, loopDevice, key, numImgSectors,
174 buffer, len)) {
175 SLOGE("ASEC device mapping failed for %s (%s)", asecFileName, strerror(errno));
176 return -1;
177 }
178 if (debug) {
179 SLOGD("New devmapper instance created at %s", buffer);
180 }
181 } else {
182 if (debug) {
183 SLOGD("Found active devmapper for %s at %s", asecFileName, buffer);
184 }
185 }
186 *createdDMDevice = true;
187 } else {
Jeff Sharkey32ebb732017-03-27 16:18:50 -0600188 strlcpy(buffer, loopDevice, len);
Daniel Rosenbergfcd34a02014-05-22 11:23:56 -0700189 *createdDMDevice = false;
190 }
191 return 0;
192}
193
194static void waitForDevMapper(const char *dmDevice) {
195 /*
196 * Wait for the device mapper node to be created. Sometimes it takes a
197 * while. Wait for up to 1 second. We could also inspect incoming uevents,
198 * but that would take more effort.
199 */
200 int tries = 25;
201 while (tries--) {
202 if (!access(dmDevice, F_OK) || errno != ENOENT) {
203 break;
204 }
205 usleep(40 * 1000);
206 }
207}
208
San Mehatf1b736b2009-10-10 17:22:08 -0700209VolumeManager *VolumeManager::sInstance = NULL;
210
211VolumeManager *VolumeManager::Instance() {
212 if (!sInstance)
213 sInstance = new VolumeManager();
214 return sInstance;
215}
216
217VolumeManager::VolumeManager() {
San Mehatd9a4e352010-03-12 13:32:47 -0800218 mDebug = false;
San Mehat88705162010-01-15 09:26:28 -0800219 mActiveContainers = new AsecIdCollection();
San Mehatf1b736b2009-10-10 17:22:08 -0700220 mBroadcaster = NULL;
Mike Lockwooda28056b2010-10-28 15:21:24 -0400221 mUmsSharingCount = 0;
222 mSavedDirtyRatio = -1;
223 // set dirty ratio to 0 when UMS is active
224 mUmsDirtyRatio = 0;
Jeff Sharkey11c2d382017-09-11 10:32:01 -0600225 mNextObbId = 0;
San Mehatf1b736b2009-10-10 17:22:08 -0700226}
227
228VolumeManager::~VolumeManager() {
San Mehat88705162010-01-15 09:26:28 -0800229 delete mActiveContainers;
San Mehatf1b736b2009-10-10 17:22:08 -0700230}
231
Kenny Root7b18a7b2010-03-15 13:13:41 -0700232char *VolumeManager::asecHash(const char *id, char *buffer, size_t len) {
Kenny Rootacc9e7d2010-06-18 19:06:50 -0700233 static const char* digits = "0123456789abcdef";
234
Kenny Root7b18a7b2010-03-15 13:13:41 -0700235 unsigned char sig[MD5_DIGEST_LENGTH];
236
Kenny Rootacc9e7d2010-06-18 19:06:50 -0700237 if (buffer == NULL) {
238 SLOGE("Destination buffer is NULL");
239 errno = ESPIPE;
240 return NULL;
241 } else if (id == NULL) {
242 SLOGE("Source buffer is NULL");
243 errno = ESPIPE;
244 return NULL;
245 } else if (len < MD5_ASCII_LENGTH_PLUS_NULL) {
Colin Cross59846b62014-02-06 20:34:29 -0800246 SLOGE("Target hash buffer size < %d bytes (%zu)",
Kenny Rootacc9e7d2010-06-18 19:06:50 -0700247 MD5_ASCII_LENGTH_PLUS_NULL, len);
San Mehatd9a4e352010-03-12 13:32:47 -0800248 errno = ESPIPE;
249 return NULL;
250 }
Kenny Root7b18a7b2010-03-15 13:13:41 -0700251
252 MD5(reinterpret_cast<const unsigned char*>(id), strlen(id), sig);
San Mehatd9a4e352010-03-12 13:32:47 -0800253
Kenny Rootacc9e7d2010-06-18 19:06:50 -0700254 char *p = buffer;
Kenny Root7b18a7b2010-03-15 13:13:41 -0700255 for (int i = 0; i < MD5_DIGEST_LENGTH; i++) {
Kenny Rootacc9e7d2010-06-18 19:06:50 -0700256 *p++ = digits[sig[i] >> 4];
257 *p++ = digits[sig[i] & 0x0F];
San Mehatd9a4e352010-03-12 13:32:47 -0800258 }
Kenny Rootacc9e7d2010-06-18 19:06:50 -0700259 *p = '\0';
San Mehatd9a4e352010-03-12 13:32:47 -0800260
261 return buffer;
262}
263
Jeff Sharkeyfa1c6772017-03-25 22:49:13 -0600264int VolumeManager::updateVirtualDisk() {
265 if (property_get_bool(kPropVirtualDisk, false)) {
266 if (access(kPathVirtualDisk, F_OK) != 0) {
267 Loop::createImageFile(kPathVirtualDisk, kSizeVirtualDisk / 512);
268 }
269
270 if (mVirtualDisk == nullptr) {
271 if (Loop::create(kPathVirtualDisk, mVirtualDiskPath) != 0) {
272 LOG(ERROR) << "Failed to create virtual disk";
273 return -1;
274 }
275
276 struct stat buf;
277 if (stat(mVirtualDiskPath.c_str(), &buf) < 0) {
278 PLOG(ERROR) << "Failed to stat " << mVirtualDiskPath;
279 return -1;
280 }
281
282 auto disk = new android::vold::Disk("virtual", buf.st_rdev, "virtual",
283 android::vold::Disk::Flags::kAdoptable | android::vold::Disk::Flags::kSd);
284 disk->create();
285 mVirtualDisk = std::shared_ptr<android::vold::Disk>(disk);
286 mDisks.push_back(mVirtualDisk);
287 }
288 } else {
289 if (mVirtualDisk != nullptr) {
290 dev_t device = mVirtualDisk->getDevice();
291
292 auto i = mDisks.begin();
293 while (i != mDisks.end()) {
294 if ((*i)->getDevice() == device) {
295 (*i)->destroy();
296 i = mDisks.erase(i);
297 } else {
298 ++i;
299 }
300 }
301
302 Loop::destroyByDevice(mVirtualDiskPath.c_str());
303 mVirtualDisk = nullptr;
304 }
305
306 if (access(kPathVirtualDisk, F_OK) == 0) {
307 unlink(kPathVirtualDisk);
308 }
309 }
310 return 0;
311}
312
Jeff Sharkeyf1b996d2015-04-17 17:35:20 -0700313int VolumeManager::setDebug(bool enable) {
San Mehatd9a4e352010-03-12 13:32:47 -0800314 mDebug = enable;
Jeff Sharkeyf1b996d2015-04-17 17:35:20 -0700315 return 0;
San Mehatd9a4e352010-03-12 13:32:47 -0800316}
317
San Mehatf1b736b2009-10-10 17:22:08 -0700318int VolumeManager::start() {
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700319 // Always start from a clean slate by unmounting everything in
320 // directories that we own, in case we crashed.
Jeff Sharkey9c484982015-03-31 10:35:33 -0700321 unmountAll();
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700322
Jeff Sharkey11c2d382017-09-11 10:32:01 -0600323 Devmapper::destroyAll();
324 Loop::destroyAll();
325
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700326 // Assume that we always have an emulated volume on internal
327 // storage; the framework will decide if it should be mounted.
Jeff Sharkeyc8e04c52015-04-21 12:14:17 -0700328 CHECK(mInternalEmulated == nullptr);
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700329 mInternalEmulated = std::shared_ptr<android::vold::VolumeBase>(
Jeff Sharkey3161fb32015-04-12 16:03:33 -0700330 new android::vold::EmulatedVolume("/data/media"));
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700331 mInternalEmulated->create();
332
Jeff Sharkeyfa1c6772017-03-25 22:49:13 -0600333 // Consider creating a virtual disk
334 updateVirtualDisk();
335
San Mehatf1b736b2009-10-10 17:22:08 -0700336 return 0;
337}
338
339int VolumeManager::stop() {
Jeff Sharkeyc8e04c52015-04-21 12:14:17 -0700340 CHECK(mInternalEmulated != nullptr);
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700341 mInternalEmulated->destroy();
342 mInternalEmulated = nullptr;
San Mehatf1b736b2009-10-10 17:22:08 -0700343 return 0;
344}
345
San Mehatfd7f5872009-10-12 11:32:47 -0700346void VolumeManager::handleBlockEvent(NetlinkEvent *evt) {
Jeff Sharkeyc8e04c52015-04-21 12:14:17 -0700347 std::lock_guard<std::mutex> lock(mLock);
348
Jeff Sharkeyf1b996d2015-04-17 17:35:20 -0700349 if (mDebug) {
350 LOG(VERBOSE) << "----------------";
351 LOG(VERBOSE) << "handleBlockEvent with action " << (int) evt->getAction();
352 evt->dump();
353 }
San Mehatf1b736b2009-10-10 17:22:08 -0700354
Mateusz Nowak64403792015-08-03 16:39:19 +0200355 std::string eventPath(evt->findParam("DEVPATH")?evt->findParam("DEVPATH"):"");
356 std::string devType(evt->findParam("DEVTYPE")?evt->findParam("DEVTYPE"):"");
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700357
358 if (devType != "disk") return;
359
360 int major = atoi(evt->findParam("MAJOR"));
361 int minor = atoi(evt->findParam("MINOR"));
362 dev_t device = makedev(major, minor);
363
364 switch (evt->getAction()) {
365 case NetlinkEvent::Action::kAdd: {
Chih-Hung Hsieh11a2ce82016-07-27 14:11:02 -0700366 for (const auto& source : mDiskSources) {
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700367 if (source->matches(eventPath)) {
Yu Ning942d4e82016-01-08 17:36:47 +0800368 // For now, assume that MMC and virtio-blk (the latter is
369 // emulator-specific; see Disk.cpp for details) devices are SD,
370 // and that everything else is USB
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700371 int flags = source->getFlags();
Yu Ning942d4e82016-01-08 17:36:47 +0800372 if (major == kMajorBlockMmc
373 || (android::vold::IsRunningInEmulator()
374 && major >= (int) kMajorBlockExperimentalMin
375 && major <= (int) kMajorBlockExperimentalMax)) {
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700376 flags |= android::vold::Disk::Flags::kSd;
377 } else {
378 flags |= android::vold::Disk::Flags::kUsb;
379 }
380
381 auto disk = new android::vold::Disk(eventPath, device,
382 source->getNickname(), flags);
383 disk->create();
384 mDisks.push_back(std::shared_ptr<android::vold::Disk>(disk));
385 break;
386 }
387 }
388 break;
389 }
390 case NetlinkEvent::Action::kChange: {
Jeff Sharkey7d9d0112015-04-14 23:14:23 -0700391 LOG(DEBUG) << "Disk at " << major << ":" << minor << " changed";
Chih-Hung Hsieh11a2ce82016-07-27 14:11:02 -0700392 for (const auto& disk : mDisks) {
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700393 if (disk->getDevice() == device) {
394 disk->readMetadata();
395 disk->readPartitions();
396 }
397 }
398 break;
399 }
400 case NetlinkEvent::Action::kRemove: {
401 auto i = mDisks.begin();
402 while (i != mDisks.end()) {
403 if ((*i)->getDevice() == device) {
404 (*i)->destroy();
405 i = mDisks.erase(i);
406 } else {
407 ++i;
408 }
409 }
410 break;
411 }
412 default: {
413 LOG(WARNING) << "Unexpected block event action " << (int) evt->getAction();
414 break;
415 }
416 }
417}
418
419void VolumeManager::addDiskSource(const std::shared_ptr<DiskSource>& diskSource) {
Wei Wang6b455c22017-01-20 11:52:33 -0800420 std::lock_guard<std::mutex> lock(mLock);
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700421 mDiskSources.push_back(diskSource);
422}
423
424std::shared_ptr<android::vold::Disk> VolumeManager::findDisk(const std::string& id) {
425 for (auto disk : mDisks) {
426 if (disk->getId() == id) {
427 return disk;
San Mehatf1b736b2009-10-10 17:22:08 -0700428 }
429 }
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700430 return nullptr;
431}
San Mehatf1b736b2009-10-10 17:22:08 -0700432
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700433std::shared_ptr<android::vold::VolumeBase> VolumeManager::findVolume(const std::string& id) {
Gao Xiangd263da82017-08-14 11:32:13 +0800434 // Vold could receive "mount" after "shutdown" command in the extreme case.
435 // If this happens, mInternalEmulated will equal nullptr and
436 // we need to deal with it in order to avoid null pointer crash.
437 if (mInternalEmulated != nullptr && mInternalEmulated->getId() == id) {
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700438 return mInternalEmulated;
San Mehatf1b736b2009-10-10 17:22:08 -0700439 }
Chih-Hung Hsieh11a2ce82016-07-27 14:11:02 -0700440 for (const auto& disk : mDisks) {
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700441 auto vol = disk->findVolume(id);
442 if (vol != nullptr) {
443 return vol;
444 }
445 }
Jeff Sharkey11c2d382017-09-11 10:32:01 -0600446 for (const auto& vol : mObbVolumes) {
447 if (vol->getId() == id) {
448 return vol;
449 }
450 }
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700451 return nullptr;
452}
453
Jeff Sharkeyc86ab6f2015-06-26 14:02:09 -0700454void VolumeManager::listVolumes(android::vold::VolumeBase::Type type,
455 std::list<std::string>& list) {
456 list.clear();
Chih-Hung Hsieh11a2ce82016-07-27 14:11:02 -0700457 for (const auto& disk : mDisks) {
Jeff Sharkeyc86ab6f2015-06-26 14:02:09 -0700458 disk->listVolumes(type, list);
459 }
460}
461
462nsecs_t VolumeManager::benchmarkPrivate(const std::string& id) {
Jeff Sharkey5a6bfca2015-05-14 20:33:55 -0700463 std::string path;
Jeff Sharkeyc86ab6f2015-06-26 14:02:09 -0700464 if (id == "private" || id == "null") {
Jeff Sharkey5a6bfca2015-05-14 20:33:55 -0700465 path = "/data";
Jeff Sharkeyc86ab6f2015-06-26 14:02:09 -0700466 } else {
467 auto vol = findVolume(id);
468 if (vol != nullptr && vol->getState() == android::vold::VolumeBase::State::kMounted) {
469 path = vol->getPath();
470 }
Jeff Sharkey5a6bfca2015-05-14 20:33:55 -0700471 }
472
473 if (path.empty()) {
474 LOG(WARNING) << "Failed to find volume for " << id;
475 return -1;
476 }
477
Jeff Sharkeyc86ab6f2015-06-26 14:02:09 -0700478 return android::vold::BenchmarkPrivate(path);
Jeff Sharkey5a6bfca2015-05-14 20:33:55 -0700479}
480
Jeff Sharkeybc40cc82015-06-18 14:25:08 -0700481int VolumeManager::forgetPartition(const std::string& partGuid) {
482 std::string normalizedGuid;
483 if (android::vold::NormalizeHex(partGuid, normalizedGuid)) {
484 LOG(WARNING) << "Invalid GUID " << partGuid;
485 return -1;
486 }
487
488 std::string keyPath = android::vold::BuildKeyPath(normalizedGuid);
489 if (unlink(keyPath.c_str()) != 0) {
490 LOG(ERROR) << "Failed to unlink " << keyPath;
491 return -1;
492 }
493
494 return 0;
495}
496
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700497int VolumeManager::linkPrimary(userid_t userId) {
498 std::string source(mPrimary->getPath());
499 if (mPrimary->getType() == android::vold::VolumeBase::Type::kEmulated) {
500 source = StringPrintf("%s/%d", source.c_str(), userId);
Jeff Sharkey32679a82015-07-21 14:22:01 -0700501 fs_prepare_dir(source.c_str(), 0755, AID_ROOT, AID_ROOT);
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700502 }
503
504 std::string target(StringPrintf("/mnt/user/%d/primary", userId));
505 if (TEMP_FAILURE_RETRY(unlink(target.c_str()))) {
506 if (errno != ENOENT) {
507 SLOGW("Failed to unlink %s: %s", target.c_str(), strerror(errno));
508 }
509 }
Jeff Sharkey1bfb3752015-04-29 15:22:23 -0700510 LOG(DEBUG) << "Linking " << source << " to " << target;
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700511 if (TEMP_FAILURE_RETRY(symlink(source.c_str(), target.c_str()))) {
512 SLOGW("Failed to link %s to %s: %s", source.c_str(), target.c_str(),
513 strerror(errno));
514 return -errno;
515 }
516 return 0;
517}
518
Jeff Sharkeybd3038d2015-06-10 09:42:01 -0700519int VolumeManager::onUserAdded(userid_t userId, int userSerialNumber) {
520 mAddedUsers[userId] = userSerialNumber;
521 return 0;
522}
523
524int VolumeManager::onUserRemoved(userid_t userId) {
525 mAddedUsers.erase(userId);
526 return 0;
527}
528
529int VolumeManager::onUserStarted(userid_t userId) {
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700530 // Note that sometimes the system will spin up processes from Zygote
531 // before actually starting the user, so we're okay if Zygote
532 // already created this directory.
Jeff Sharkeyfa1c6772017-03-25 22:49:13 -0600533 std::string path(StringPrintf("%s/%d", kPathUserMount, userId));
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700534 fs_prepare_dir(path.c_str(), 0755, AID_ROOT, AID_ROOT);
535
Jeff Sharkeybd3038d2015-06-10 09:42:01 -0700536 mStartedUsers.insert(userId);
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700537 if (mPrimary) {
538 linkPrimary(userId);
539 }
540 return 0;
541}
542
Jeff Sharkeybd3038d2015-06-10 09:42:01 -0700543int VolumeManager::onUserStopped(userid_t userId) {
544 mStartedUsers.erase(userId);
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700545 return 0;
546}
547
548int VolumeManager::setPrimary(const std::shared_ptr<android::vold::VolumeBase>& vol) {
549 mPrimary = vol;
Jeff Sharkeybd3038d2015-06-10 09:42:01 -0700550 for (userid_t userId : mStartedUsers) {
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700551 linkPrimary(userId);
552 }
553 return 0;
554}
555
Jeff Sharkeyc7b5b572015-06-30 15:54:17 -0700556static int unmount_tree(const char* path) {
557 size_t path_len = strlen(path);
558
559 FILE* fp = setmntent("/proc/mounts", "r");
560 if (fp == NULL) {
561 ALOGE("Error opening /proc/mounts: %s", strerror(errno));
562 return -errno;
563 }
564
565 // Some volumes can be stacked on each other, so force unmount in
566 // reverse order to give us the best chance of success.
567 std::list<std::string> toUnmount;
568 mntent* mentry;
569 while ((mentry = getmntent(fp)) != NULL) {
570 if (strncmp(mentry->mnt_dir, path, path_len) == 0) {
571 toUnmount.push_front(std::string(mentry->mnt_dir));
572 }
573 }
574 endmntent(fp);
575
Chih-Hung Hsieh11a2ce82016-07-27 14:11:02 -0700576 for (const auto& path : toUnmount) {
Jeff Sharkeyc7b5b572015-06-30 15:54:17 -0700577 if (umount2(path.c_str(), MNT_DETACH)) {
578 ALOGW("Failed to unmount %s: %s", path.c_str(), strerror(errno));
579 }
580 }
581 return 0;
582}
583
Jeff Sharkey66270a22015-06-24 11:49:24 -0700584int VolumeManager::remountUid(uid_t uid, const std::string& mode) {
585 LOG(DEBUG) << "Remounting " << uid << " as mode " << mode;
586
587 DIR* dir;
588 struct dirent* de;
589 char rootName[PATH_MAX];
590 char pidName[PATH_MAX];
591 int pidFd;
592 int nsFd;
593 struct stat sb;
594 pid_t child;
595
596 if (!(dir = opendir("/proc"))) {
597 PLOG(ERROR) << "Failed to opendir";
598 return -1;
599 }
600
601 // Figure out root namespace to compare against below
Daichi Hirono10d34882016-01-29 14:33:51 +0900602 if (android::vold::SaneReadLinkAt(dirfd(dir), "1/ns/mnt", rootName, PATH_MAX) == -1) {
Jeff Sharkey66270a22015-06-24 11:49:24 -0700603 PLOG(ERROR) << "Failed to readlink";
604 closedir(dir);
605 return -1;
606 }
607
608 // Poke through all running PIDs look for apps running as UID
609 while ((de = readdir(dir))) {
610 pidFd = -1;
611 nsFd = -1;
612
613 pidFd = openat(dirfd(dir), de->d_name, O_RDONLY | O_DIRECTORY | O_CLOEXEC);
614 if (pidFd < 0) {
615 goto next;
616 }
617 if (fstat(pidFd, &sb) != 0) {
618 PLOG(WARNING) << "Failed to stat " << de->d_name;
619 goto next;
620 }
621 if (sb.st_uid != uid) {
622 goto next;
623 }
624
625 // Matches so far, but refuse to touch if in root namespace
626 LOG(DEBUG) << "Found matching PID " << de->d_name;
Daichi Hirono10d34882016-01-29 14:33:51 +0900627 if (android::vold::SaneReadLinkAt(pidFd, "ns/mnt", pidName, PATH_MAX) == -1) {
Jeff Sharkey66270a22015-06-24 11:49:24 -0700628 PLOG(WARNING) << "Failed to read namespace for " << de->d_name;
629 goto next;
630 }
631 if (!strcmp(rootName, pidName)) {
632 LOG(WARNING) << "Skipping due to root namespace";
633 goto next;
634 }
635
636 // We purposefully leave the namespace open across the fork
Jeff Sharkeyfd3dc3c2017-03-27 10:49:21 -0600637 nsFd = openat(pidFd, "ns/mnt", O_RDONLY); // not O_CLOEXEC
Jeff Sharkey66270a22015-06-24 11:49:24 -0700638 if (nsFd < 0) {
Jeff Sharkeyc7b5b572015-06-30 15:54:17 -0700639 PLOG(WARNING) << "Failed to open namespace for " << de->d_name;
Jeff Sharkey66270a22015-06-24 11:49:24 -0700640 goto next;
641 }
642
643 if (!(child = fork())) {
644 if (setns(nsFd, CLONE_NEWNS) != 0) {
Jeff Sharkeyc7b5b572015-06-30 15:54:17 -0700645 PLOG(ERROR) << "Failed to setns for " << de->d_name;
Jeff Sharkey66270a22015-06-24 11:49:24 -0700646 _exit(1);
647 }
648
Jeff Sharkeyc7b5b572015-06-30 15:54:17 -0700649 unmount_tree("/storage");
Jeff Sharkey66270a22015-06-24 11:49:24 -0700650
651 std::string storageSource;
652 if (mode == "default") {
Jeff Sharkey1bd078f2015-08-06 11:40:00 -0700653 storageSource = "/mnt/runtime/default";
Jeff Sharkey66270a22015-06-24 11:49:24 -0700654 } else if (mode == "read") {
Jeff Sharkey1bd078f2015-08-06 11:40:00 -0700655 storageSource = "/mnt/runtime/read";
Jeff Sharkey66270a22015-06-24 11:49:24 -0700656 } else if (mode == "write") {
Jeff Sharkey1bd078f2015-08-06 11:40:00 -0700657 storageSource = "/mnt/runtime/write";
Jeff Sharkey66270a22015-06-24 11:49:24 -0700658 } else {
659 // Sane default of no storage visible
660 _exit(0);
661 }
662 if (TEMP_FAILURE_RETRY(mount(storageSource.c_str(), "/storage",
Hidehiko Abe674bed12016-03-09 16:42:10 +0900663 NULL, MS_BIND | MS_REC, NULL)) == -1) {
Jeff Sharkeyc7b5b572015-06-30 15:54:17 -0700664 PLOG(ERROR) << "Failed to mount " << storageSource << " for "
665 << de->d_name;
666 _exit(1);
Jeff Sharkey66270a22015-06-24 11:49:24 -0700667 }
Hidehiko Abe674bed12016-03-09 16:42:10 +0900668 if (TEMP_FAILURE_RETRY(mount(NULL, "/storage", NULL,
669 MS_REC | MS_SLAVE, NULL)) == -1) {
670 PLOG(ERROR) << "Failed to set MS_SLAVE to /storage for "
671 << de->d_name;
672 _exit(1);
673 }
Jeff Sharkeyc7b5b572015-06-30 15:54:17 -0700674
675 // Mount user-specific symlink helper into place
676 userid_t user_id = multiuser_get_user_id(uid);
677 std::string userSource(StringPrintf("/mnt/user/%d", user_id));
678 if (TEMP_FAILURE_RETRY(mount(userSource.c_str(), "/storage/self",
679 NULL, MS_BIND, NULL)) == -1) {
680 PLOG(ERROR) << "Failed to mount " << userSource << " for "
681 << de->d_name;
682 _exit(1);
683 }
684
Jeff Sharkey66270a22015-06-24 11:49:24 -0700685 _exit(0);
686 }
687
688 if (child == -1) {
689 PLOG(ERROR) << "Failed to fork";
690 goto next;
691 } else {
692 TEMP_FAILURE_RETRY(waitpid(child, nullptr, 0));
693 }
694
695next:
696 close(nsFd);
697 close(pidFd);
698 }
699 closedir(dir);
700 return 0;
701}
702
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700703int VolumeManager::reset() {
704 // Tear down all existing disks/volumes and start from a blank slate so
705 // newly connected framework hears all events.
Gao Xiangd263da82017-08-14 11:32:13 +0800706 if (mInternalEmulated != nullptr) {
707 mInternalEmulated->destroy();
708 mInternalEmulated->create();
709 }
Chih-Hung Hsieh11a2ce82016-07-27 14:11:02 -0700710 for (const auto& disk : mDisks) {
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700711 disk->destroy();
712 disk->create();
713 }
Jeff Sharkeyfa1c6772017-03-25 22:49:13 -0600714 updateVirtualDisk();
Jeff Sharkeybd3038d2015-06-10 09:42:01 -0700715 mAddedUsers.clear();
716 mStartedUsers.clear();
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700717 return 0;
718}
719
Keun-young Parka5bbb5e2017-03-13 18:02:50 -0700720// Can be called twice (sequentially) during shutdown. should be safe for that.
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700721int VolumeManager::shutdown() {
Keun-young Parka5bbb5e2017-03-13 18:02:50 -0700722 if (mInternalEmulated == nullptr) {
723 return 0; // already shutdown
724 }
Keun-young Park375ac252017-08-02 17:45:48 -0700725 shutting_down = true;
Jeff Sharkey9c484982015-03-31 10:35:33 -0700726 mInternalEmulated->destroy();
Keun-young Parka5bbb5e2017-03-13 18:02:50 -0700727 mInternalEmulated = nullptr;
Chih-Hung Hsieh11a2ce82016-07-27 14:11:02 -0700728 for (const auto& disk : mDisks) {
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700729 disk->destroy();
730 }
731 mDisks.clear();
Keun-young Park375ac252017-08-02 17:45:48 -0700732 shutting_down = false;
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700733 return 0;
San Mehatf1b736b2009-10-10 17:22:08 -0700734}
735
Jeff Sharkey9c484982015-03-31 10:35:33 -0700736int VolumeManager::unmountAll() {
Jeff Sharkeyc8e04c52015-04-21 12:14:17 -0700737 std::lock_guard<std::mutex> lock(mLock);
738
Jeff Sharkey9c484982015-03-31 10:35:33 -0700739 // First, try gracefully unmounting all known devices
740 if (mInternalEmulated != nullptr) {
741 mInternalEmulated->unmount();
742 }
Chih-Hung Hsieh11a2ce82016-07-27 14:11:02 -0700743 for (const auto& disk : mDisks) {
Jeff Sharkey9c484982015-03-31 10:35:33 -0700744 disk->unmountAll();
745 }
746
747 // Worst case we might have some stale mounts lurking around, so
748 // force unmount those just to be safe.
749 FILE* fp = setmntent("/proc/mounts", "r");
750 if (fp == NULL) {
751 SLOGE("Error opening /proc/mounts: %s", strerror(errno));
752 return -errno;
753 }
754
755 // Some volumes can be stacked on each other, so force unmount in
756 // reverse order to give us the best chance of success.
757 std::list<std::string> toUnmount;
758 mntent* mentry;
759 while ((mentry = getmntent(fp)) != NULL) {
760 if (strncmp(mentry->mnt_dir, "/mnt/", 5) == 0
761 || strncmp(mentry->mnt_dir, "/storage/", 9) == 0) {
762 toUnmount.push_front(std::string(mentry->mnt_dir));
763 }
764 }
765 endmntent(fp);
766
Chih-Hung Hsieh11a2ce82016-07-27 14:11:02 -0700767 for (const auto& path : toUnmount) {
Jeff Sharkey11c2d382017-09-11 10:32:01 -0600768 LOG(DEBUG) << "Tearing down stale mount " << path;
Jeff Sharkey9c484982015-03-31 10:35:33 -0700769 android::vold::ForceUnmount(path);
770 }
771
772 return 0;
773}
774
Kenny Root508c0e12010-07-12 09:59:49 -0700775int VolumeManager::getObbMountPath(const char *sourceFile, char *mountPath, int mountPathLen) {
776 char idHash[33];
777 if (!asecHash(sourceFile, idHash, sizeof(idHash))) {
778 SLOGE("Hash of '%s' failed (%s)", sourceFile, strerror(errno));
779 return -1;
780 }
781
782 memset(mountPath, 0, mountPathLen);
Jeff Sharkey9f18fe72015-04-01 23:32:18 -0700783 int written = snprintf(mountPath, mountPathLen, "%s/%s", VolumeManager::LOOPDIR, idHash);
rpcraigd1c226f2012-10-09 06:58:16 -0400784 if ((written < 0) || (written >= mountPathLen)) {
785 errno = EINVAL;
786 return -1;
787 }
Kenny Root508c0e12010-07-12 09:59:49 -0700788
789 if (access(mountPath, F_OK)) {
790 errno = ENOENT;
791 return -1;
792 }
793
794 return 0;
795}
796
San Mehata19b2502010-01-06 10:33:53 -0800797int VolumeManager::getAsecMountPath(const char *id, char *buffer, int maxlen) {
San Mehat88ac2c02010-03-23 11:15:58 -0700798 char asecFileName[255];
Kenny Root344ca102012-04-03 17:23:01 -0700799
Nick Kralevich0de7c612014-01-27 14:58:06 -0800800 if (!isLegalAsecId(id)) {
801 SLOGE("getAsecMountPath: Invalid asec id \"%s\"", id);
802 errno = EINVAL;
803 return -1;
804 }
805
Kenny Root344ca102012-04-03 17:23:01 -0700806 if (findAsec(id, asecFileName, sizeof(asecFileName))) {
807 SLOGE("Couldn't find ASEC %s", id);
808 return -1;
809 }
San Mehat88ac2c02010-03-23 11:15:58 -0700810
811 memset(buffer, 0, maxlen);
812 if (access(asecFileName, F_OK)) {
813 errno = ENOENT;
814 return -1;
815 }
San Mehata19b2502010-01-06 10:33:53 -0800816
Jeff Sharkey9f18fe72015-04-01 23:32:18 -0700817 int written = snprintf(buffer, maxlen, "%s/%s", VolumeManager::ASECDIR, id);
rpcraigd1c226f2012-10-09 06:58:16 -0400818 if ((written < 0) || (written >= maxlen)) {
819 SLOGE("getAsecMountPath failed for %s: couldn't construct path in buffer", id);
820 errno = EINVAL;
821 return -1;
822 }
823
San Mehata19b2502010-01-06 10:33:53 -0800824 return 0;
825}
826
Dianne Hackborn736910c2011-06-27 13:37:07 -0700827int VolumeManager::getAsecFilesystemPath(const char *id, char *buffer, int maxlen) {
828 char asecFileName[255];
Kenny Root344ca102012-04-03 17:23:01 -0700829
Nick Kralevich0de7c612014-01-27 14:58:06 -0800830 if (!isLegalAsecId(id)) {
831 SLOGE("getAsecFilesystemPath: Invalid asec id \"%s\"", id);
832 errno = EINVAL;
833 return -1;
834 }
835
Kenny Root344ca102012-04-03 17:23:01 -0700836 if (findAsec(id, asecFileName, sizeof(asecFileName))) {
837 SLOGE("Couldn't find ASEC %s", id);
838 return -1;
839 }
Dianne Hackborn736910c2011-06-27 13:37:07 -0700840
841 memset(buffer, 0, maxlen);
842 if (access(asecFileName, F_OK)) {
843 errno = ENOENT;
844 return -1;
845 }
846
rpcraigd1c226f2012-10-09 06:58:16 -0400847 int written = snprintf(buffer, maxlen, "%s", asecFileName);
848 if ((written < 0) || (written >= maxlen)) {
849 errno = EINVAL;
850 return -1;
851 }
852
Dianne Hackborn736910c2011-06-27 13:37:07 -0700853 return 0;
854}
855
Mateusz Nowaka4f48d02015-08-03 18:06:39 +0200856int VolumeManager::createAsec(const char *id, unsigned long numSectors, const char *fstype,
Kenny Root344ca102012-04-03 17:23:01 -0700857 const char *key, const int ownerUid, bool isExternal) {
San Mehatfcf24fe2010-03-03 12:37:32 -0800858 struct asec_superblock sb;
859 memset(&sb, 0, sizeof(sb));
860
Nick Kralevich0de7c612014-01-27 14:58:06 -0800861 if (!isLegalAsecId(id)) {
862 SLOGE("createAsec: Invalid asec id \"%s\"", id);
863 errno = EINVAL;
864 return -1;
865 }
866
Kenny Root344ca102012-04-03 17:23:01 -0700867 const bool wantFilesystem = strcmp(fstype, "none");
868 bool usingExt4 = false;
869 if (wantFilesystem) {
870 usingExt4 = !strcmp(fstype, "ext4");
871 if (usingExt4) {
872 sb.c_opts |= ASEC_SB_C_OPTS_EXT4;
873 } else if (strcmp(fstype, "fat")) {
874 SLOGE("Invalid filesystem type %s", fstype);
875 errno = EINVAL;
876 return -1;
877 }
878 }
879
San Mehatfcf24fe2010-03-03 12:37:32 -0800880 sb.magic = ASEC_SB_MAGIC;
881 sb.ver = ASEC_SB_VER;
San Mehata19b2502010-01-06 10:33:53 -0800882
San Mehatd31e3802010-02-18 08:37:45 -0800883 if (numSectors < ((1024*1024)/512)) {
Mateusz Nowaka4f48d02015-08-03 18:06:39 +0200884 SLOGE("Invalid container size specified (%lu sectors)", numSectors);
San Mehatd31e3802010-02-18 08:37:45 -0800885 errno = EINVAL;
886 return -1;
887 }
888
San Mehata19b2502010-01-06 10:33:53 -0800889 char asecFileName[255];
Kenny Root344ca102012-04-03 17:23:01 -0700890
891 if (!findAsec(id, asecFileName, sizeof(asecFileName))) {
892 SLOGE("ASEC file '%s' currently exists - destroy it first! (%s)",
893 asecFileName, strerror(errno));
894 errno = EADDRINUSE;
895 return -1;
896 }
897
Jeff Sharkey9f18fe72015-04-01 23:32:18 -0700898 const char *asecDir = isExternal ? VolumeManager::SEC_ASECDIR_EXT : VolumeManager::SEC_ASECDIR_INT;
Kenny Root344ca102012-04-03 17:23:01 -0700899
rpcraigd1c226f2012-10-09 06:58:16 -0400900 int written = snprintf(asecFileName, sizeof(asecFileName), "%s/%s.asec", asecDir, id);
901 if ((written < 0) || (size_t(written) >= sizeof(asecFileName))) {
902 errno = EINVAL;
903 return -1;
904 }
San Mehata19b2502010-01-06 10:33:53 -0800905
906 if (!access(asecFileName, F_OK)) {
San Mehat97ac40e2010-03-24 10:24:19 -0700907 SLOGE("ASEC file '%s' currently exists - destroy it first! (%s)",
Kenny Root344ca102012-04-03 17:23:01 -0700908 asecFileName, strerror(errno));
San Mehata19b2502010-01-06 10:33:53 -0800909 errno = EADDRINUSE;
910 return -1;
911 }
912
Mateusz Nowaka4f48d02015-08-03 18:06:39 +0200913 unsigned long numImgSectors;
Daniel Rosenberg6a74dca2014-05-23 13:47:00 -0700914 if (usingExt4)
Daniel Rosenbergfcd34a02014-05-22 11:23:56 -0700915 numImgSectors = adjustSectorNumExt4(numSectors);
Daniel Rosenberg6a74dca2014-05-23 13:47:00 -0700916 else
Daniel Rosenbergfcd34a02014-05-22 11:23:56 -0700917 numImgSectors = adjustSectorNumFAT(numSectors);
San Mehatfcf24fe2010-03-03 12:37:32 -0800918
919 // Add +1 for our superblock which is at the end
920 if (Loop::createImageFile(asecFileName, numImgSectors + 1)) {
San Mehat97ac40e2010-03-24 10:24:19 -0700921 SLOGE("ASEC image file creation failed (%s)", strerror(errno));
San Mehata19b2502010-01-06 10:33:53 -0800922 return -1;
923 }
924
San Mehatd9a4e352010-03-12 13:32:47 -0800925 char idHash[33];
926 if (!asecHash(id, idHash, sizeof(idHash))) {
San Mehat97ac40e2010-03-24 10:24:19 -0700927 SLOGE("Hash of '%s' failed (%s)", id, strerror(errno));
San Mehatd9a4e352010-03-12 13:32:47 -0800928 unlink(asecFileName);
929 return -1;
930 }
931
San Mehata19b2502010-01-06 10:33:53 -0800932 char loopDevice[255];
San Mehatd9a4e352010-03-12 13:32:47 -0800933 if (Loop::create(idHash, asecFileName, loopDevice, sizeof(loopDevice))) {
San Mehat97ac40e2010-03-24 10:24:19 -0700934 SLOGE("ASEC loop device creation failed (%s)", strerror(errno));
San Mehata19b2502010-01-06 10:33:53 -0800935 unlink(asecFileName);
936 return -1;
937 }
938
San Mehatb78a32c2010-01-10 13:02:12 -0800939 char dmDevice[255];
940 bool cleanupDm = false;
San Mehata19b2502010-01-06 10:33:53 -0800941
San Mehatb78a32c2010-01-10 13:02:12 -0800942 if (strcmp(key, "none")) {
San Mehatfcf24fe2010-03-03 12:37:32 -0800943 // XXX: This is all we support for now
944 sb.c_cipher = ASEC_SB_C_CIPHER_TWOFISH;
San Mehatd9a4e352010-03-12 13:32:47 -0800945 if (Devmapper::create(idHash, loopDevice, key, numImgSectors, dmDevice,
San Mehatb78a32c2010-01-10 13:02:12 -0800946 sizeof(dmDevice))) {
San Mehat97ac40e2010-03-24 10:24:19 -0700947 SLOGE("ASEC device mapping failed (%s)", strerror(errno));
San Mehatb78a32c2010-01-10 13:02:12 -0800948 Loop::destroyByDevice(loopDevice);
949 unlink(asecFileName);
950 return -1;
951 }
952 cleanupDm = true;
953 } else {
San Mehatfcf24fe2010-03-03 12:37:32 -0800954 sb.c_cipher = ASEC_SB_C_CIPHER_NONE;
Jeff Sharkey32ebb732017-03-27 16:18:50 -0600955 strlcpy(dmDevice, loopDevice, sizeof(dmDevice));
San Mehatb78a32c2010-01-10 13:02:12 -0800956 }
957
San Mehatfcf24fe2010-03-03 12:37:32 -0800958 /*
959 * Drop down the superblock at the end of the file
960 */
Daniel Rosenbergfcd34a02014-05-22 11:23:56 -0700961 if (writeSuperBlock(loopDevice, &sb, numImgSectors)) {
San Mehatfcf24fe2010-03-03 12:37:32 -0800962 if (cleanupDm) {
San Mehatd9a4e352010-03-12 13:32:47 -0800963 Devmapper::destroy(idHash);
San Mehatfcf24fe2010-03-03 12:37:32 -0800964 }
965 Loop::destroyByDevice(loopDevice);
966 unlink(asecFileName);
967 return -1;
968 }
969
Kenny Root344ca102012-04-03 17:23:01 -0700970 if (wantFilesystem) {
971 int formatStatus;
rpcraiga54e13a2012-09-21 14:17:08 -0400972 char mountPoint[255];
973
Jeff Sharkey9f18fe72015-04-01 23:32:18 -0700974 int written = snprintf(mountPoint, sizeof(mountPoint), "%s/%s", VolumeManager::ASECDIR, id);
rpcraigd1c226f2012-10-09 06:58:16 -0400975 if ((written < 0) || (size_t(written) >= sizeof(mountPoint))) {
976 SLOGE("ASEC fs format failed: couldn't construct mountPoint");
977 if (cleanupDm) {
978 Devmapper::destroy(idHash);
979 }
980 Loop::destroyByDevice(loopDevice);
981 unlink(asecFileName);
982 return -1;
983 }
rpcraiga54e13a2012-09-21 14:17:08 -0400984
Kenny Root344ca102012-04-03 17:23:01 -0700985 if (usingExt4) {
Jeff Sharkeyd0640f62015-05-21 22:35:42 -0700986 formatStatus = android::vold::ext4::Format(dmDevice, numImgSectors, mountPoint);
Kenny Root344ca102012-04-03 17:23:01 -0700987 } else {
Jeff Sharkeyd0640f62015-05-21 22:35:42 -0700988 formatStatus = android::vold::vfat::Format(dmDevice, numImgSectors);
San Mehatb78a32c2010-01-10 13:02:12 -0800989 }
San Mehata19b2502010-01-06 10:33:53 -0800990
Kenny Root344ca102012-04-03 17:23:01 -0700991 if (formatStatus < 0) {
992 SLOGE("ASEC fs format failed (%s)", strerror(errno));
San Mehatb78a32c2010-01-10 13:02:12 -0800993 if (cleanupDm) {
San Mehatd9a4e352010-03-12 13:32:47 -0800994 Devmapper::destroy(idHash);
San Mehatb78a32c2010-01-10 13:02:12 -0800995 }
San Mehateb13a902010-01-07 12:12:50 -0800996 Loop::destroyByDevice(loopDevice);
997 unlink(asecFileName);
998 return -1;
999 }
Kenny Root344ca102012-04-03 17:23:01 -07001000
Kenny Root344ca102012-04-03 17:23:01 -07001001 if (mkdir(mountPoint, 0000)) {
San Mehata1091cb2010-02-28 20:17:20 -08001002 if (errno != EEXIST) {
San Mehat97ac40e2010-03-24 10:24:19 -07001003 SLOGE("Mountpoint creation failed (%s)", strerror(errno));
San Mehata1091cb2010-02-28 20:17:20 -08001004 if (cleanupDm) {
San Mehatd9a4e352010-03-12 13:32:47 -08001005 Devmapper::destroy(idHash);
San Mehata1091cb2010-02-28 20:17:20 -08001006 }
1007 Loop::destroyByDevice(loopDevice);
1008 unlink(asecFileName);
1009 return -1;
1010 }
San Mehatb78a32c2010-01-10 13:02:12 -08001011 }
San Mehata1091cb2010-02-28 20:17:20 -08001012
Kenny Root344ca102012-04-03 17:23:01 -07001013 int mountStatus;
1014 if (usingExt4) {
Jeff Sharkeyd0640f62015-05-21 22:35:42 -07001015 mountStatus = android::vold::ext4::Mount(dmDevice, mountPoint,
1016 false, false, false);
Kenny Root344ca102012-04-03 17:23:01 -07001017 } else {
Jeff Sharkeyd0640f62015-05-21 22:35:42 -07001018 mountStatus = android::vold::vfat::Mount(dmDevice, mountPoint,
1019 false, false, false, ownerUid, 0, 0000, false);
Kenny Root344ca102012-04-03 17:23:01 -07001020 }
1021
1022 if (mountStatus) {
San Mehat97ac40e2010-03-24 10:24:19 -07001023 SLOGE("ASEC FAT mount failed (%s)", strerror(errno));
San Mehata1091cb2010-02-28 20:17:20 -08001024 if (cleanupDm) {
San Mehatd9a4e352010-03-12 13:32:47 -08001025 Devmapper::destroy(idHash);
San Mehata1091cb2010-02-28 20:17:20 -08001026 }
1027 Loop::destroyByDevice(loopDevice);
1028 unlink(asecFileName);
1029 return -1;
1030 }
Kenny Root344ca102012-04-03 17:23:01 -07001031
1032 if (usingExt4) {
Jeff Sharkeyce6a9132015-04-08 21:07:21 -07001033 int dirfd = open(mountPoint, O_DIRECTORY | O_CLOEXEC);
Kenny Root344ca102012-04-03 17:23:01 -07001034 if (dirfd >= 0) {
1035 if (fchown(dirfd, ownerUid, AID_SYSTEM)
1036 || fchmod(dirfd, S_IRUSR | S_IWUSR | S_IXUSR | S_ISGID | S_IRGRP | S_IXGRP)) {
1037 SLOGI("Cannot chown/chmod new ASEC mount point %s", mountPoint);
1038 }
1039 close(dirfd);
1040 }
1041 }
San Mehata1091cb2010-02-28 20:17:20 -08001042 } else {
San Mehat97ac40e2010-03-24 10:24:19 -07001043 SLOGI("Created raw secure container %s (no filesystem)", id);
San Mehata19b2502010-01-06 10:33:53 -08001044 }
San Mehat88705162010-01-15 09:26:28 -08001045
Kenny Rootcbacf782010-09-24 15:11:48 -07001046 mActiveContainers->push_back(new ContainerData(strdup(id), ASEC));
San Mehata19b2502010-01-06 10:33:53 -08001047 return 0;
1048}
1049
Mateusz Nowaka4f48d02015-08-03 18:06:39 +02001050int VolumeManager::resizeAsec(const char *id, unsigned long numSectors, const char *key) {
Daniel Rosenbergfcd34a02014-05-22 11:23:56 -07001051 char asecFileName[255];
1052 char mountPoint[255];
1053 bool cleanupDm = false;
1054
1055 if (!isLegalAsecId(id)) {
1056 SLOGE("resizeAsec: Invalid asec id \"%s\"", id);
1057 errno = EINVAL;
1058 return -1;
1059 }
1060
1061 if (findAsec(id, asecFileName, sizeof(asecFileName))) {
1062 SLOGE("Couldn't find ASEC %s", id);
1063 return -1;
1064 }
1065
Jeff Sharkey9f18fe72015-04-01 23:32:18 -07001066 int written = snprintf(mountPoint, sizeof(mountPoint), "%s/%s", VolumeManager::ASECDIR, id);
Daniel Rosenbergfcd34a02014-05-22 11:23:56 -07001067 if ((written < 0) || (size_t(written) >= sizeof(mountPoint))) {
1068 SLOGE("ASEC resize failed for %s: couldn't construct mountpoint", id);
1069 return -1;
1070 }
1071
1072 if (isMountpointMounted(mountPoint)) {
1073 SLOGE("ASEC %s mounted. Unmount before resizing", id);
1074 errno = EBUSY;
1075 return -1;
1076 }
1077
1078 struct asec_superblock sb;
1079 int fd;
Mateusz Nowaka4f48d02015-08-03 18:06:39 +02001080 unsigned long oldNumSec = 0;
Daniel Rosenbergfcd34a02014-05-22 11:23:56 -07001081
Jeff Sharkeyce6a9132015-04-08 21:07:21 -07001082 if ((fd = open(asecFileName, O_RDONLY | O_CLOEXEC)) < 0) {
Daniel Rosenbergfcd34a02014-05-22 11:23:56 -07001083 SLOGE("Failed to open ASEC file (%s)", strerror(errno));
1084 return -1;
1085 }
1086
1087 struct stat info;
1088 if (fstat(fd, &info) < 0) {
1089 SLOGE("Failed to get file size (%s)", strerror(errno));
1090 close(fd);
1091 return -1;
1092 }
1093
1094 oldNumSec = info.st_size / 512;
1095
Daniel Rosenbergfcd34a02014-05-22 11:23:56 -07001096 /*
1097 * Try to read superblock.
1098 */
1099 memset(&sb, 0, sizeof(struct asec_superblock));
1100 if (lseek(fd, ((oldNumSec - 1) * 512), SEEK_SET) < 0) {
1101 SLOGE("lseek failed (%s)", strerror(errno));
1102 close(fd);
1103 return -1;
1104 }
1105 if (read(fd, &sb, sizeof(struct asec_superblock)) != sizeof(struct asec_superblock)) {
1106 SLOGE("superblock read failed (%s)", strerror(errno));
1107 close(fd);
1108 return -1;
1109 }
1110 close(fd);
1111
1112 if (mDebug) {
1113 SLOGD("Container sb magic/ver (%.8x/%.2x)", sb.magic, sb.ver);
1114 }
1115 if (sb.magic != ASEC_SB_MAGIC || sb.ver != ASEC_SB_VER) {
1116 SLOGE("Bad container magic/version (%.8x/%.2x)", sb.magic, sb.ver);
1117 errno = EMEDIUMTYPE;
1118 return -1;
1119 }
1120
Daniel Rosenberge4c291a2016-04-20 14:07:32 -07001121 unsigned long numImgSectors;
Daniel Rosenbergfcd34a02014-05-22 11:23:56 -07001122 if (!(sb.c_opts & ASEC_SB_C_OPTS_EXT4)) {
1123 SLOGE("Only ext4 partitions are supported for resize");
1124 errno = EINVAL;
1125 return -1;
Daniel Rosenberge4c291a2016-04-20 14:07:32 -07001126 } else {
1127 numImgSectors = adjustSectorNumExt4(numSectors);
1128 }
1129
1130 /*
1131 * add one block for the superblock
1132 */
1133 SLOGD("Resizing from %lu sectors to %lu sectors", oldNumSec, numImgSectors + 1);
1134 if (oldNumSec == numImgSectors + 1) {
1135 SLOGW("Size unchanged; ignoring resize request");
1136 return 0;
1137 } else if (oldNumSec > numImgSectors + 1) {
1138 SLOGE("Only growing is currently supported.");
1139 close(fd);
1140 return -1;
Daniel Rosenbergfcd34a02014-05-22 11:23:56 -07001141 }
1142
1143 if (Loop::resizeImageFile(asecFileName, numImgSectors + 1)) {
1144 SLOGE("Resize of ASEC image file failed. Could not resize %s", id);
1145 return -1;
1146 }
1147
1148 /*
1149 * Drop down a copy of the superblock at the end of the file
1150 */
1151 if (writeSuperBlock(asecFileName, &sb, numImgSectors))
1152 goto fail;
1153
1154 char idHash[33];
1155 if (!asecHash(id, idHash, sizeof(idHash))) {
1156 SLOGE("Hash of '%s' failed (%s)", id, strerror(errno));
1157 goto fail;
1158 }
1159
1160 char loopDevice[255];
1161 if (setupLoopDevice(loopDevice, sizeof(loopDevice), asecFileName, idHash, mDebug))
1162 goto fail;
1163
1164 char dmDevice[255];
1165
1166 if (setupDevMapperDevice(dmDevice, sizeof(dmDevice), loopDevice, asecFileName, key, idHash, numImgSectors, &cleanupDm, mDebug)) {
1167 Loop::destroyByDevice(loopDevice);
1168 goto fail;
1169 }
1170
1171 /*
1172 * Wait for the device mapper node to be created.
1173 */
1174 waitForDevMapper(dmDevice);
1175
Jeff Sharkeyd0640f62015-05-21 22:35:42 -07001176 if (android::vold::ext4::Resize(dmDevice, numImgSectors)) {
Daniel Rosenbergfcd34a02014-05-22 11:23:56 -07001177 SLOGE("Unable to resize %s (%s)", id, strerror(errno));
1178 if (cleanupDm) {
1179 Devmapper::destroy(idHash);
1180 }
1181 Loop::destroyByDevice(loopDevice);
1182 goto fail;
1183 }
1184
1185 return 0;
1186fail:
1187 Loop::resizeImageFile(asecFileName, oldNumSec);
1188 return -1;
1189}
1190
San Mehata19b2502010-01-06 10:33:53 -08001191int VolumeManager::finalizeAsec(const char *id) {
1192 char asecFileName[255];
1193 char loopDevice[255];
1194 char mountPoint[255];
1195
Nick Kralevich0de7c612014-01-27 14:58:06 -08001196 if (!isLegalAsecId(id)) {
1197 SLOGE("finalizeAsec: Invalid asec id \"%s\"", id);
1198 errno = EINVAL;
1199 return -1;
1200 }
1201
Kenny Root344ca102012-04-03 17:23:01 -07001202 if (findAsec(id, asecFileName, sizeof(asecFileName))) {
1203 SLOGE("Couldn't find ASEC %s", id);
1204 return -1;
1205 }
San Mehata19b2502010-01-06 10:33:53 -08001206
San Mehatd9a4e352010-03-12 13:32:47 -08001207 char idHash[33];
1208 if (!asecHash(id, idHash, sizeof(idHash))) {
San Mehat97ac40e2010-03-24 10:24:19 -07001209 SLOGE("Hash of '%s' failed (%s)", id, strerror(errno));
San Mehatd9a4e352010-03-12 13:32:47 -08001210 return -1;
1211 }
1212
1213 if (Loop::lookupActive(idHash, loopDevice, sizeof(loopDevice))) {
San Mehat97ac40e2010-03-24 10:24:19 -07001214 SLOGE("Unable to finalize %s (%s)", id, strerror(errno));
San Mehata19b2502010-01-06 10:33:53 -08001215 return -1;
1216 }
1217
Hiroaki Miyazawa14eab552015-02-04 13:29:15 +09001218 unsigned long nr_sec = 0;
Kenny Root344ca102012-04-03 17:23:01 -07001219 struct asec_superblock sb;
1220
1221 if (Loop::lookupInfo(loopDevice, &sb, &nr_sec)) {
1222 return -1;
1223 }
1224
Jeff Sharkey9f18fe72015-04-01 23:32:18 -07001225 int written = snprintf(mountPoint, sizeof(mountPoint), "%s/%s", VolumeManager::ASECDIR, id);
rpcraigd1c226f2012-10-09 06:58:16 -04001226 if ((written < 0) || (size_t(written) >= sizeof(mountPoint))) {
1227 SLOGE("ASEC finalize failed: couldn't construct mountPoint");
1228 return -1;
1229 }
Kenny Root344ca102012-04-03 17:23:01 -07001230
1231 int result = 0;
1232 if (sb.c_opts & ASEC_SB_C_OPTS_EXT4) {
Jeff Sharkeyd0640f62015-05-21 22:35:42 -07001233 result = android::vold::ext4::Mount(loopDevice, mountPoint,
1234 true, true, true);
Kenny Root344ca102012-04-03 17:23:01 -07001235 } else {
Jeff Sharkeyd0640f62015-05-21 22:35:42 -07001236 result = android::vold::vfat::Mount(loopDevice, mountPoint,
1237 true, true, true, 0, 0, 0227, false);
Kenny Root344ca102012-04-03 17:23:01 -07001238 }
1239
1240 if (result) {
San Mehat97ac40e2010-03-24 10:24:19 -07001241 SLOGE("ASEC finalize mount failed (%s)", strerror(errno));
San Mehata19b2502010-01-06 10:33:53 -08001242 return -1;
1243 }
1244
San Mehatd9a4e352010-03-12 13:32:47 -08001245 if (mDebug) {
San Mehat97ac40e2010-03-24 10:24:19 -07001246 SLOGD("ASEC %s finalized", id);
San Mehatd9a4e352010-03-12 13:32:47 -08001247 }
San Mehata19b2502010-01-06 10:33:53 -08001248 return 0;
1249}
1250
Kenny Root344ca102012-04-03 17:23:01 -07001251int VolumeManager::fixupAsecPermissions(const char *id, gid_t gid, const char* filename) {
1252 char asecFileName[255];
1253 char loopDevice[255];
1254 char mountPoint[255];
1255
1256 if (gid < AID_APP) {
1257 SLOGE("Group ID is not in application range");
1258 return -1;
1259 }
1260
Nick Kralevich0de7c612014-01-27 14:58:06 -08001261 if (!isLegalAsecId(id)) {
1262 SLOGE("fixupAsecPermissions: Invalid asec id \"%s\"", id);
1263 errno = EINVAL;
1264 return -1;
1265 }
1266
Kenny Root344ca102012-04-03 17:23:01 -07001267 if (findAsec(id, asecFileName, sizeof(asecFileName))) {
1268 SLOGE("Couldn't find ASEC %s", id);
1269 return -1;
1270 }
1271
1272 char idHash[33];
1273 if (!asecHash(id, idHash, sizeof(idHash))) {
1274 SLOGE("Hash of '%s' failed (%s)", id, strerror(errno));
1275 return -1;
1276 }
1277
1278 if (Loop::lookupActive(idHash, loopDevice, sizeof(loopDevice))) {
1279 SLOGE("Unable fix permissions during lookup on %s (%s)", id, strerror(errno));
1280 return -1;
1281 }
1282
Hiroaki Miyazawa14eab552015-02-04 13:29:15 +09001283 unsigned long nr_sec = 0;
Kenny Root344ca102012-04-03 17:23:01 -07001284 struct asec_superblock sb;
1285
1286 if (Loop::lookupInfo(loopDevice, &sb, &nr_sec)) {
1287 return -1;
1288 }
1289
Jeff Sharkey9f18fe72015-04-01 23:32:18 -07001290 int written = snprintf(mountPoint, sizeof(mountPoint), "%s/%s", VolumeManager::ASECDIR, id);
rpcraigd1c226f2012-10-09 06:58:16 -04001291 if ((written < 0) || (size_t(written) >= sizeof(mountPoint))) {
1292 SLOGE("Unable remount to fix permissions for %s: couldn't construct mountpoint", id);
1293 return -1;
1294 }
Kenny Root344ca102012-04-03 17:23:01 -07001295
1296 int result = 0;
1297 if ((sb.c_opts & ASEC_SB_C_OPTS_EXT4) == 0) {
1298 return 0;
1299 }
1300
Jeff Sharkeyd0640f62015-05-21 22:35:42 -07001301 int ret = android::vold::ext4::Mount(loopDevice, mountPoint,
Kenny Root344ca102012-04-03 17:23:01 -07001302 false /* read-only */,
1303 true /* remount */,
1304 false /* executable */);
1305 if (ret) {
1306 SLOGE("Unable remount to fix permissions for %s (%s)", id, strerror(errno));
1307 return -1;
1308 }
1309
1310 char *paths[] = { mountPoint, NULL };
1311
1312 FTS *fts = fts_open(paths, FTS_PHYSICAL | FTS_NOCHDIR | FTS_XDEV, NULL);
1313 if (fts) {
1314 // Traverse the entire hierarchy and chown to system UID.
1315 for (FTSENT *ftsent = fts_read(fts); ftsent != NULL; ftsent = fts_read(fts)) {
1316 // We don't care about the lost+found directory.
1317 if (!strcmp(ftsent->fts_name, "lost+found")) {
1318 continue;
1319 }
1320
1321 /*
1322 * There can only be one file marked as private right now.
1323 * This should be more robust, but it satisfies the requirements
1324 * we have for right now.
1325 */
1326 const bool privateFile = !strcmp(ftsent->fts_name, filename);
1327
Jeff Sharkeyce6a9132015-04-08 21:07:21 -07001328 int fd = open(ftsent->fts_accpath, O_NOFOLLOW | O_CLOEXEC);
Kenny Root344ca102012-04-03 17:23:01 -07001329 if (fd < 0) {
1330 SLOGE("Couldn't open file %s: %s", ftsent->fts_accpath, strerror(errno));
1331 result = -1;
1332 continue;
1333 }
1334
1335 result |= fchown(fd, AID_SYSTEM, privateFile? gid : AID_SYSTEM);
1336
1337 if (ftsent->fts_info & FTS_D) {
Kenny Root1a673c82012-05-10 16:45:29 -07001338 result |= fchmod(fd, 0755);
Kenny Root348c8ab2012-05-10 15:39:53 -07001339 } else if (ftsent->fts_info & FTS_F) {
Kenny Root344ca102012-04-03 17:23:01 -07001340 result |= fchmod(fd, privateFile ? 0640 : 0644);
1341 }
Robert Craigb9e3ba52014-02-04 10:53:00 -05001342
Stephen Smalley5093e612014-02-12 09:43:08 -05001343 if (selinux_android_restorecon(ftsent->fts_path, 0) < 0) {
Robert Craigb9e3ba52014-02-04 10:53:00 -05001344 SLOGE("restorecon failed for %s: %s\n", ftsent->fts_path, strerror(errno));
1345 result |= -1;
1346 }
1347
Kenny Root344ca102012-04-03 17:23:01 -07001348 close(fd);
1349 }
1350 fts_close(fts);
1351
1352 // Finally make the directory readable by everyone.
Jeff Sharkeyce6a9132015-04-08 21:07:21 -07001353 int dirfd = open(mountPoint, O_DIRECTORY | O_CLOEXEC);
Kenny Root344ca102012-04-03 17:23:01 -07001354 if (dirfd < 0 || fchmod(dirfd, 0755)) {
1355 SLOGE("Couldn't change owner of existing directory %s: %s", mountPoint, strerror(errno));
1356 result |= -1;
1357 }
1358 close(dirfd);
1359 } else {
1360 result |= -1;
1361 }
1362
Jeff Sharkeyd0640f62015-05-21 22:35:42 -07001363 result |= android::vold::ext4::Mount(loopDevice, mountPoint,
Kenny Root344ca102012-04-03 17:23:01 -07001364 true /* read-only */,
1365 true /* remount */,
1366 true /* execute */);
1367
1368 if (result) {
1369 SLOGE("ASEC fix permissions failed (%s)", strerror(errno));
1370 return -1;
1371 }
1372
1373 if (mDebug) {
1374 SLOGD("ASEC %s permissions fixed", id);
1375 }
1376 return 0;
1377}
1378
San Mehat048b0802010-01-23 08:17:06 -08001379int VolumeManager::renameAsec(const char *id1, const char *id2) {
Kenny Root344ca102012-04-03 17:23:01 -07001380 char asecFilename1[255];
San Mehat048b0802010-01-23 08:17:06 -08001381 char *asecFilename2;
1382 char mountPoint[255];
1383
Kenny Root344ca102012-04-03 17:23:01 -07001384 const char *dir;
1385
Nick Kralevich0de7c612014-01-27 14:58:06 -08001386 if (!isLegalAsecId(id1)) {
1387 SLOGE("renameAsec: Invalid asec id1 \"%s\"", id1);
1388 errno = EINVAL;
1389 return -1;
1390 }
1391
1392 if (!isLegalAsecId(id2)) {
1393 SLOGE("renameAsec: Invalid asec id2 \"%s\"", id2);
1394 errno = EINVAL;
1395 return -1;
1396 }
1397
Kenny Root344ca102012-04-03 17:23:01 -07001398 if (findAsec(id1, asecFilename1, sizeof(asecFilename1), &dir)) {
1399 SLOGE("Couldn't find ASEC %s", id1);
1400 return -1;
1401 }
1402
1403 asprintf(&asecFilename2, "%s/%s.asec", dir, id2);
San Mehat048b0802010-01-23 08:17:06 -08001404
Jeff Sharkey9f18fe72015-04-01 23:32:18 -07001405 int written = snprintf(mountPoint, sizeof(mountPoint), "%s/%s", VolumeManager::ASECDIR, id1);
rpcraigd1c226f2012-10-09 06:58:16 -04001406 if ((written < 0) || (size_t(written) >= sizeof(mountPoint))) {
1407 SLOGE("Rename failed: couldn't construct mountpoint");
1408 goto out_err;
1409 }
1410
San Mehat048b0802010-01-23 08:17:06 -08001411 if (isMountpointMounted(mountPoint)) {
San Mehat97ac40e2010-03-24 10:24:19 -07001412 SLOGW("Rename attempt when src mounted");
San Mehat048b0802010-01-23 08:17:06 -08001413 errno = EBUSY;
1414 goto out_err;
1415 }
1416
Jeff Sharkey9f18fe72015-04-01 23:32:18 -07001417 written = snprintf(mountPoint, sizeof(mountPoint), "%s/%s", VolumeManager::ASECDIR, id2);
rpcraigd1c226f2012-10-09 06:58:16 -04001418 if ((written < 0) || (size_t(written) >= sizeof(mountPoint))) {
1419 SLOGE("Rename failed: couldn't construct mountpoint2");
1420 goto out_err;
1421 }
1422
San Mehat96956ed2010-02-24 08:42:51 -08001423 if (isMountpointMounted(mountPoint)) {
San Mehat97ac40e2010-03-24 10:24:19 -07001424 SLOGW("Rename attempt when dst mounted");
San Mehat96956ed2010-02-24 08:42:51 -08001425 errno = EBUSY;
1426 goto out_err;
1427 }
1428
San Mehat048b0802010-01-23 08:17:06 -08001429 if (!access(asecFilename2, F_OK)) {
San Mehat97ac40e2010-03-24 10:24:19 -07001430 SLOGE("Rename attempt when dst exists");
San Mehat048b0802010-01-23 08:17:06 -08001431 errno = EADDRINUSE;
1432 goto out_err;
1433 }
1434
1435 if (rename(asecFilename1, asecFilename2)) {
San Mehat97ac40e2010-03-24 10:24:19 -07001436 SLOGE("Rename of '%s' to '%s' failed (%s)", asecFilename1, asecFilename2, strerror(errno));
San Mehat048b0802010-01-23 08:17:06 -08001437 goto out_err;
1438 }
1439
San Mehat048b0802010-01-23 08:17:06 -08001440 free(asecFilename2);
1441 return 0;
1442
1443out_err:
San Mehat048b0802010-01-23 08:17:06 -08001444 free(asecFilename2);
1445 return -1;
1446}
1447
Kenny Rootfb7c4d52010-06-30 18:48:41 -07001448#define UNMOUNT_RETRIES 5
1449#define UNMOUNT_SLEEP_BETWEEN_RETRY_MS (1000 * 1000)
San Mehat4ba89482010-02-18 09:00:18 -08001450int VolumeManager::unmountAsec(const char *id, bool force) {
San Mehata19b2502010-01-06 10:33:53 -08001451 char asecFileName[255];
1452 char mountPoint[255];
1453
Nick Kralevich0de7c612014-01-27 14:58:06 -08001454 if (!isLegalAsecId(id)) {
1455 SLOGE("unmountAsec: Invalid asec id \"%s\"", id);
1456 errno = EINVAL;
1457 return -1;
1458 }
1459
Kenny Root344ca102012-04-03 17:23:01 -07001460 if (findAsec(id, asecFileName, sizeof(asecFileName))) {
1461 SLOGE("Couldn't find ASEC %s", id);
1462 return -1;
1463 }
1464
Jeff Sharkey9f18fe72015-04-01 23:32:18 -07001465 int written = snprintf(mountPoint, sizeof(mountPoint), "%s/%s", VolumeManager::ASECDIR, id);
rpcraigd1c226f2012-10-09 06:58:16 -04001466 if ((written < 0) || (size_t(written) >= sizeof(mountPoint))) {
1467 SLOGE("ASEC unmount failed for %s: couldn't construct mountpoint", id);
1468 return -1;
1469 }
San Mehata19b2502010-01-06 10:33:53 -08001470
San Mehatd9a4e352010-03-12 13:32:47 -08001471 char idHash[33];
1472 if (!asecHash(id, idHash, sizeof(idHash))) {
San Mehat97ac40e2010-03-24 10:24:19 -07001473 SLOGE("Hash of '%s' failed (%s)", id, strerror(errno));
San Mehatd9a4e352010-03-12 13:32:47 -08001474 return -1;
1475 }
1476
Kenny Rootfb7c4d52010-06-30 18:48:41 -07001477 return unmountLoopImage(id, idHash, asecFileName, mountPoint, force);
1478}
1479
Kenny Root508c0e12010-07-12 09:59:49 -07001480int VolumeManager::unmountObb(const char *fileName, bool force) {
Kenny Rootfb7c4d52010-06-30 18:48:41 -07001481 char mountPoint[255];
1482
1483 char idHash[33];
1484 if (!asecHash(fileName, idHash, sizeof(idHash))) {
1485 SLOGE("Hash of '%s' failed (%s)", fileName, strerror(errno));
1486 return -1;
1487 }
1488
Jeff Sharkey9f18fe72015-04-01 23:32:18 -07001489 int written = snprintf(mountPoint, sizeof(mountPoint), "%s/%s", VolumeManager::LOOPDIR, idHash);
rpcraigd1c226f2012-10-09 06:58:16 -04001490 if ((written < 0) || (size_t(written) >= sizeof(mountPoint))) {
1491 SLOGE("OBB unmount failed for %s: couldn't construct mountpoint", fileName);
1492 return -1;
1493 }
Kenny Rootfb7c4d52010-06-30 18:48:41 -07001494
1495 return unmountLoopImage(fileName, idHash, fileName, mountPoint, force);
1496}
1497
1498int VolumeManager::unmountLoopImage(const char *id, const char *idHash,
1499 const char *fileName, const char *mountPoint, bool force) {
San Mehat0586d542010-01-12 15:38:59 -08001500 if (!isMountpointMounted(mountPoint)) {
Kenny Rootfb7c4d52010-06-30 18:48:41 -07001501 SLOGE("Unmount request for %s when not mounted", id);
Kenny Root918e5f92010-09-30 18:00:52 -07001502 errno = ENOENT;
San Mehatb78a32c2010-01-10 13:02:12 -08001503 return -1;
1504 }
San Mehat23969932010-01-09 07:08:06 -08001505
San Mehatb78a32c2010-01-10 13:02:12 -08001506 int i, rc;
Kenny Rootfb7c4d52010-06-30 18:48:41 -07001507 for (i = 1; i <= UNMOUNT_RETRIES; i++) {
San Mehatb78a32c2010-01-10 13:02:12 -08001508 rc = umount(mountPoint);
1509 if (!rc) {
1510 break;
San Mehata19b2502010-01-06 10:33:53 -08001511 }
San Mehatb78a32c2010-01-10 13:02:12 -08001512 if (rc && (errno == EINVAL || errno == ENOENT)) {
Kenny Rootfb7c4d52010-06-30 18:48:41 -07001513 SLOGI("Container %s unmounted OK", id);
San Mehatb78a32c2010-01-10 13:02:12 -08001514 rc = 0;
1515 break;
San Mehata19b2502010-01-06 10:33:53 -08001516 }
Kenny Rootfb7c4d52010-06-30 18:48:41 -07001517 SLOGW("%s unmount attempt %d failed (%s)",
San Mehat8c940ef2010-02-13 14:19:53 -08001518 id, i, strerror(errno));
San Mehatb78a32c2010-01-10 13:02:12 -08001519
Jeff Sharkey36801cc2015-03-13 16:09:20 -07001520 int signal = 0; // default is to just complain
San Mehat4ba89482010-02-18 09:00:18 -08001521
1522 if (force) {
Kenny Rootfb7c4d52010-06-30 18:48:41 -07001523 if (i > (UNMOUNT_RETRIES - 2))
Jeff Sharkey36801cc2015-03-13 16:09:20 -07001524 signal = SIGKILL;
Kenny Rootfb7c4d52010-06-30 18:48:41 -07001525 else if (i > (UNMOUNT_RETRIES - 3))
Jeff Sharkey36801cc2015-03-13 16:09:20 -07001526 signal = SIGTERM;
San Mehat4ba89482010-02-18 09:00:18 -08001527 }
San Mehat8c940ef2010-02-13 14:19:53 -08001528
Jeff Sharkey36801cc2015-03-13 16:09:20 -07001529 Process::killProcessesWithOpenFiles(mountPoint, signal);
Kenny Rootfb7c4d52010-06-30 18:48:41 -07001530 usleep(UNMOUNT_SLEEP_BETWEEN_RETRY_MS);
San Mehatb78a32c2010-01-10 13:02:12 -08001531 }
1532
1533 if (rc) {
San Mehat4ba89482010-02-18 09:00:18 -08001534 errno = EBUSY;
San Mehat97ac40e2010-03-24 10:24:19 -07001535 SLOGE("Failed to unmount container %s (%s)", id, strerror(errno));
San Mehatb78a32c2010-01-10 13:02:12 -08001536 return -1;
1537 }
1538
San Mehat12f4b892010-02-24 11:43:22 -08001539 int retries = 10;
1540
1541 while(retries--) {
1542 if (!rmdir(mountPoint)) {
1543 break;
1544 }
1545
San Mehat97ac40e2010-03-24 10:24:19 -07001546 SLOGW("Failed to rmdir %s (%s)", mountPoint, strerror(errno));
Kenny Rootfb7c4d52010-06-30 18:48:41 -07001547 usleep(UNMOUNT_SLEEP_BETWEEN_RETRY_MS);
San Mehat12f4b892010-02-24 11:43:22 -08001548 }
1549
1550 if (!retries) {
San Mehat97ac40e2010-03-24 10:24:19 -07001551 SLOGE("Timed out trying to rmdir %s (%s)", mountPoint, strerror(errno));
San Mehatf5c61982010-02-03 11:04:46 -08001552 }
San Mehat88705162010-01-15 09:26:28 -08001553
Paul Lawrence60dec162014-09-02 10:52:15 -07001554 for (i=1; i <= UNMOUNT_RETRIES; i++) {
1555 if (Devmapper::destroy(idHash) && errno != ENXIO) {
1556 SLOGE("Failed to destroy devmapper instance (%s)", strerror(errno));
1557 usleep(UNMOUNT_SLEEP_BETWEEN_RETRY_MS);
1558 continue;
1559 } else {
1560 break;
1561 }
San Mehata19b2502010-01-06 10:33:53 -08001562 }
1563
1564 char loopDevice[255];
San Mehatd9a4e352010-03-12 13:32:47 -08001565 if (!Loop::lookupActive(idHash, loopDevice, sizeof(loopDevice))) {
San Mehata19b2502010-01-06 10:33:53 -08001566 Loop::destroyByDevice(loopDevice);
San Mehatd9a4e352010-03-12 13:32:47 -08001567 } else {
Kenny Rootfb7c4d52010-06-30 18:48:41 -07001568 SLOGW("Failed to find loop device for {%s} (%s)", fileName, strerror(errno));
San Mehata19b2502010-01-06 10:33:53 -08001569 }
San Mehat88705162010-01-15 09:26:28 -08001570
1571 AsecIdCollection::iterator it;
1572 for (it = mActiveContainers->begin(); it != mActiveContainers->end(); ++it) {
Kenny Rootcbacf782010-09-24 15:11:48 -07001573 ContainerData* cd = *it;
1574 if (!strcmp(cd->id, id)) {
San Mehat88705162010-01-15 09:26:28 -08001575 free(*it);
1576 mActiveContainers->erase(it);
1577 break;
1578 }
1579 }
1580 if (it == mActiveContainers->end()) {
San Mehat97ac40e2010-03-24 10:24:19 -07001581 SLOGW("mActiveContainers is inconsistent!");
San Mehat88705162010-01-15 09:26:28 -08001582 }
San Mehatb78a32c2010-01-10 13:02:12 -08001583 return 0;
1584}
1585
San Mehat4ba89482010-02-18 09:00:18 -08001586int VolumeManager::destroyAsec(const char *id, bool force) {
San Mehatb78a32c2010-01-10 13:02:12 -08001587 char asecFileName[255];
1588 char mountPoint[255];
1589
Nick Kralevich0de7c612014-01-27 14:58:06 -08001590 if (!isLegalAsecId(id)) {
1591 SLOGE("destroyAsec: Invalid asec id \"%s\"", id);
1592 errno = EINVAL;
1593 return -1;
1594 }
1595
Kenny Root344ca102012-04-03 17:23:01 -07001596 if (findAsec(id, asecFileName, sizeof(asecFileName))) {
1597 SLOGE("Couldn't find ASEC %s", id);
1598 return -1;
1599 }
1600
Jeff Sharkey9f18fe72015-04-01 23:32:18 -07001601 int written = snprintf(mountPoint, sizeof(mountPoint), "%s/%s", VolumeManager::ASECDIR, id);
rpcraigd1c226f2012-10-09 06:58:16 -04001602 if ((written < 0) || (size_t(written) >= sizeof(mountPoint))) {
1603 SLOGE("ASEC destroy failed for %s: couldn't construct mountpoint", id);
1604 return -1;
1605 }
San Mehatb78a32c2010-01-10 13:02:12 -08001606
San Mehat0586d542010-01-12 15:38:59 -08001607 if (isMountpointMounted(mountPoint)) {
San Mehatd9a4e352010-03-12 13:32:47 -08001608 if (mDebug) {
San Mehat97ac40e2010-03-24 10:24:19 -07001609 SLOGD("Unmounting container before destroy");
San Mehatd9a4e352010-03-12 13:32:47 -08001610 }
San Mehat4ba89482010-02-18 09:00:18 -08001611 if (unmountAsec(id, force)) {
San Mehat97ac40e2010-03-24 10:24:19 -07001612 SLOGE("Failed to unmount asec %s for destroy (%s)", id, strerror(errno));
San Mehat0586d542010-01-12 15:38:59 -08001613 return -1;
1614 }
1615 }
San Mehata19b2502010-01-06 10:33:53 -08001616
San Mehat0586d542010-01-12 15:38:59 -08001617 if (unlink(asecFileName)) {
San Mehat97ac40e2010-03-24 10:24:19 -07001618 SLOGE("Failed to unlink asec '%s' (%s)", asecFileName, strerror(errno));
San Mehat0586d542010-01-12 15:38:59 -08001619 return -1;
1620 }
San Mehata19b2502010-01-06 10:33:53 -08001621
San Mehatd9a4e352010-03-12 13:32:47 -08001622 if (mDebug) {
San Mehat97ac40e2010-03-24 10:24:19 -07001623 SLOGD("ASEC %s destroyed", id);
San Mehatd9a4e352010-03-12 13:32:47 -08001624 }
San Mehata19b2502010-01-06 10:33:53 -08001625 return 0;
1626}
1627
Nick Kralevich0de7c612014-01-27 14:58:06 -08001628/*
1629 * Legal ASEC ids consist of alphanumeric characters, '-',
1630 * '_', or '.'. ".." is not allowed. The first or last character
1631 * of the ASEC id cannot be '.' (dot).
1632 */
1633bool VolumeManager::isLegalAsecId(const char *id) const {
1634 size_t i;
1635 size_t len = strlen(id);
1636
1637 if (len == 0) {
1638 return false;
1639 }
1640 if ((id[0] == '.') || (id[len - 1] == '.')) {
1641 return false;
1642 }
1643
1644 for (i = 0; i < len; i++) {
1645 if (id[i] == '.') {
1646 // i=0 is guaranteed never to have a dot. See above.
1647 if (id[i-1] == '.') return false;
1648 continue;
1649 }
1650 if (id[i] == '_' || id[i] == '-') continue;
1651 if (id[i] >= 'a' && id[i] <= 'z') continue;
1652 if (id[i] >= 'A' && id[i] <= 'Z') continue;
1653 if (id[i] >= '0' && id[i] <= '9') continue;
1654 return false;
1655 }
1656
1657 return true;
1658}
1659
Kenny Root344ca102012-04-03 17:23:01 -07001660bool VolumeManager::isAsecInDirectory(const char *dir, const char *asecName) const {
Jeff Sharkeyce6a9132015-04-08 21:07:21 -07001661 int dirfd = open(dir, O_DIRECTORY | O_CLOEXEC);
Kenny Root344ca102012-04-03 17:23:01 -07001662 if (dirfd < 0) {
1663 SLOGE("Couldn't open internal ASEC dir (%s)", strerror(errno));
Nick Kralevich25e581a2015-02-06 08:55:08 -08001664 return false;
Kenny Root344ca102012-04-03 17:23:01 -07001665 }
1666
Nick Kralevich25e581a2015-02-06 08:55:08 -08001667 struct stat sb;
1668 bool ret = (fstatat(dirfd, asecName, &sb, AT_SYMLINK_NOFOLLOW) == 0)
1669 && S_ISREG(sb.st_mode);
Kenny Root344ca102012-04-03 17:23:01 -07001670
1671 close(dirfd);
1672
1673 return ret;
1674}
1675
1676int VolumeManager::findAsec(const char *id, char *asecPath, size_t asecPathLen,
1677 const char **directory) const {
Kenny Root344ca102012-04-03 17:23:01 -07001678 char *asecName;
1679
Nick Kralevich0de7c612014-01-27 14:58:06 -08001680 if (!isLegalAsecId(id)) {
1681 SLOGE("findAsec: Invalid asec id \"%s\"", id);
1682 errno = EINVAL;
1683 return -1;
1684 }
1685
Kenny Root344ca102012-04-03 17:23:01 -07001686 if (asprintf(&asecName, "%s.asec", id) < 0) {
1687 SLOGE("Couldn't allocate string to write ASEC name");
1688 return -1;
1689 }
1690
1691 const char *dir;
Jeff Sharkey9f18fe72015-04-01 23:32:18 -07001692 if (isAsecInDirectory(VolumeManager::SEC_ASECDIR_INT, asecName)) {
1693 dir = VolumeManager::SEC_ASECDIR_INT;
1694 } else if (isAsecInDirectory(VolumeManager::SEC_ASECDIR_EXT, asecName)) {
1695 dir = VolumeManager::SEC_ASECDIR_EXT;
Kenny Root344ca102012-04-03 17:23:01 -07001696 } else {
1697 free(asecName);
1698 return -1;
1699 }
1700
1701 if (directory != NULL) {
1702 *directory = dir;
1703 }
1704
1705 if (asecPath != NULL) {
1706 int written = snprintf(asecPath, asecPathLen, "%s/%s", dir, asecName);
rpcraigd1c226f2012-10-09 06:58:16 -04001707 if ((written < 0) || (size_t(written) >= asecPathLen)) {
1708 SLOGE("findAsec failed for %s: couldn't construct ASEC path", id);
Kenny Root344ca102012-04-03 17:23:01 -07001709 free(asecName);
1710 return -1;
1711 }
1712 }
1713
1714 free(asecName);
1715 return 0;
1716}
1717
Jeff Sharkey43ed1232014-08-22 12:29:05 -07001718int VolumeManager::mountAsec(const char *id, const char *key, int ownerUid, bool readOnly) {
San Mehata19b2502010-01-06 10:33:53 -08001719 char asecFileName[255];
1720 char mountPoint[255];
1721
Nick Kralevich0de7c612014-01-27 14:58:06 -08001722 if (!isLegalAsecId(id)) {
1723 SLOGE("mountAsec: Invalid asec id \"%s\"", id);
1724 errno = EINVAL;
1725 return -1;
1726 }
1727
Kenny Root344ca102012-04-03 17:23:01 -07001728 if (findAsec(id, asecFileName, sizeof(asecFileName))) {
1729 SLOGE("Couldn't find ASEC %s", id);
1730 return -1;
1731 }
1732
Jeff Sharkey9f18fe72015-04-01 23:32:18 -07001733 int written = snprintf(mountPoint, sizeof(mountPoint), "%s/%s", VolumeManager::ASECDIR, id);
rpcraigd1c226f2012-10-09 06:58:16 -04001734 if ((written < 0) || (size_t(written) >= sizeof(mountPoint))) {
Colin Cross59846b62014-02-06 20:34:29 -08001735 SLOGE("ASEC mount failed for %s: couldn't construct mountpoint", id);
rpcraigd1c226f2012-10-09 06:58:16 -04001736 return -1;
1737 }
San Mehata19b2502010-01-06 10:33:53 -08001738
1739 if (isMountpointMounted(mountPoint)) {
San Mehat97ac40e2010-03-24 10:24:19 -07001740 SLOGE("ASEC %s already mounted", id);
San Mehata19b2502010-01-06 10:33:53 -08001741 errno = EBUSY;
1742 return -1;
1743 }
1744
San Mehatd9a4e352010-03-12 13:32:47 -08001745 char idHash[33];
1746 if (!asecHash(id, idHash, sizeof(idHash))) {
San Mehat97ac40e2010-03-24 10:24:19 -07001747 SLOGE("Hash of '%s' failed (%s)", id, strerror(errno));
San Mehatd9a4e352010-03-12 13:32:47 -08001748 return -1;
1749 }
Kenny Root7b18a7b2010-03-15 13:13:41 -07001750
San Mehata19b2502010-01-06 10:33:53 -08001751 char loopDevice[255];
Daniel Rosenbergfcd34a02014-05-22 11:23:56 -07001752 if (setupLoopDevice(loopDevice, sizeof(loopDevice), asecFileName, idHash, mDebug))
1753 return -1;
San Mehatb78a32c2010-01-10 13:02:12 -08001754
1755 char dmDevice[255];
1756 bool cleanupDm = false;
Tim Murray8439dc92014-12-15 11:56:11 -08001757
Hiroaki Miyazawa14eab552015-02-04 13:29:15 +09001758 unsigned long nr_sec = 0;
San Mehatfcf24fe2010-03-03 12:37:32 -08001759 struct asec_superblock sb;
San Mehatfcf24fe2010-03-03 12:37:32 -08001760
Kenny Root344ca102012-04-03 17:23:01 -07001761 if (Loop::lookupInfo(loopDevice, &sb, &nr_sec)) {
1762 return -1;
1763 }
San Mehatfcf24fe2010-03-03 12:37:32 -08001764
San Mehatd9a4e352010-03-12 13:32:47 -08001765 if (mDebug) {
San Mehat97ac40e2010-03-24 10:24:19 -07001766 SLOGD("Container sb magic/ver (%.8x/%.2x)", sb.magic, sb.ver);
San Mehatd9a4e352010-03-12 13:32:47 -08001767 }
San Mehatfcf24fe2010-03-03 12:37:32 -08001768 if (sb.magic != ASEC_SB_MAGIC || sb.ver != ASEC_SB_VER) {
San Mehat97ac40e2010-03-24 10:24:19 -07001769 SLOGE("Bad container magic/version (%.8x/%.2x)", sb.magic, sb.ver);
San Mehatfcf24fe2010-03-03 12:37:32 -08001770 Loop::destroyByDevice(loopDevice);
1771 errno = EMEDIUMTYPE;
1772 return -1;
1773 }
1774 nr_sec--; // We don't want the devmapping to extend onto our superblock
1775
Daniel Rosenbergfcd34a02014-05-22 11:23:56 -07001776 if (setupDevMapperDevice(dmDevice, sizeof(dmDevice), loopDevice, asecFileName, key, idHash , nr_sec, &cleanupDm, mDebug)) {
1777 Loop::destroyByDevice(loopDevice);
1778 return -1;
San Mehata19b2502010-01-06 10:33:53 -08001779 }
1780
Kenny Root344ca102012-04-03 17:23:01 -07001781 if (mkdir(mountPoint, 0000)) {
San Mehatb78a32c2010-01-10 13:02:12 -08001782 if (errno != EEXIST) {
San Mehat97ac40e2010-03-24 10:24:19 -07001783 SLOGE("Mountpoint creation failed (%s)", strerror(errno));
San Mehatb78a32c2010-01-10 13:02:12 -08001784 if (cleanupDm) {
San Mehatd9a4e352010-03-12 13:32:47 -08001785 Devmapper::destroy(idHash);
San Mehatb78a32c2010-01-10 13:02:12 -08001786 }
1787 Loop::destroyByDevice(loopDevice);
1788 return -1;
1789 }
San Mehata19b2502010-01-06 10:33:53 -08001790 }
1791
Kenny Rootcdc2a1c2012-05-03 13:49:46 -07001792 /*
Daniel Rosenbergfcd34a02014-05-22 11:23:56 -07001793 * Wait for the device mapper node to be created.
Kenny Rootcdc2a1c2012-05-03 13:49:46 -07001794 */
Daniel Rosenbergfcd34a02014-05-22 11:23:56 -07001795 waitForDevMapper(dmDevice);
Kenny Rootcdc2a1c2012-05-03 13:49:46 -07001796
Kenny Root344ca102012-04-03 17:23:01 -07001797 int result;
1798 if (sb.c_opts & ASEC_SB_C_OPTS_EXT4) {
Jeff Sharkeyd0640f62015-05-21 22:35:42 -07001799 result = android::vold::ext4::Mount(dmDevice, mountPoint,
1800 readOnly, false, readOnly);
Kenny Root344ca102012-04-03 17:23:01 -07001801 } else {
Jeff Sharkeyd0640f62015-05-21 22:35:42 -07001802 result = android::vold::vfat::Mount(dmDevice, mountPoint,
1803 readOnly, false, readOnly, ownerUid, 0, 0222, false);
Kenny Root344ca102012-04-03 17:23:01 -07001804 }
1805
1806 if (result) {
San Mehat97ac40e2010-03-24 10:24:19 -07001807 SLOGE("ASEC mount failed (%s)", strerror(errno));
San Mehatb78a32c2010-01-10 13:02:12 -08001808 if (cleanupDm) {
San Mehatd9a4e352010-03-12 13:32:47 -08001809 Devmapper::destroy(idHash);
San Mehatb78a32c2010-01-10 13:02:12 -08001810 }
1811 Loop::destroyByDevice(loopDevice);
San Mehata19b2502010-01-06 10:33:53 -08001812 return -1;
1813 }
1814
Kenny Rootcbacf782010-09-24 15:11:48 -07001815 mActiveContainers->push_back(new ContainerData(strdup(id), ASEC));
San Mehatd9a4e352010-03-12 13:32:47 -08001816 if (mDebug) {
San Mehat97ac40e2010-03-24 10:24:19 -07001817 SLOGD("ASEC %s mounted", id);
San Mehatd9a4e352010-03-12 13:32:47 -08001818 }
San Mehata19b2502010-01-06 10:33:53 -08001819 return 0;
1820}
1821
Kenny Rootfb7c4d52010-06-30 18:48:41 -07001822/**
1823 * Mounts an image file <code>img</code>.
1824 */
Jeff Sharkey69479042012-09-25 16:14:57 -07001825int VolumeManager::mountObb(const char *img, const char *key, int ownerGid) {
Kenny Rootfb7c4d52010-06-30 18:48:41 -07001826 char mountPoint[255];
1827
Kenny Rootfb7c4d52010-06-30 18:48:41 -07001828 char idHash[33];
1829 if (!asecHash(img, idHash, sizeof(idHash))) {
1830 SLOGE("Hash of '%s' failed (%s)", img, strerror(errno));
1831 return -1;
1832 }
1833
Jeff Sharkey9f18fe72015-04-01 23:32:18 -07001834 int written = snprintf(mountPoint, sizeof(mountPoint), "%s/%s", VolumeManager::LOOPDIR, idHash);
rpcraigd1c226f2012-10-09 06:58:16 -04001835 if ((written < 0) || (size_t(written) >= sizeof(mountPoint))) {
Colin Cross59846b62014-02-06 20:34:29 -08001836 SLOGE("OBB mount failed for %s: couldn't construct mountpoint", img);
rpcraigd1c226f2012-10-09 06:58:16 -04001837 return -1;
1838 }
Kenny Rootfb7c4d52010-06-30 18:48:41 -07001839
1840 if (isMountpointMounted(mountPoint)) {
1841 SLOGE("Image %s already mounted", img);
1842 errno = EBUSY;
1843 return -1;
1844 }
1845
1846 char loopDevice[255];
Daniel Rosenbergfcd34a02014-05-22 11:23:56 -07001847 if (setupLoopDevice(loopDevice, sizeof(loopDevice), img, idHash, mDebug))
1848 return -1;
Kenny Rootfb7c4d52010-06-30 18:48:41 -07001849
1850 char dmDevice[255];
1851 bool cleanupDm = false;
1852 int fd;
Hiroaki Miyazawa14eab552015-02-04 13:29:15 +09001853 unsigned long nr_sec = 0;
Kenny Rootfb7c4d52010-06-30 18:48:41 -07001854
Jeff Sharkeyce6a9132015-04-08 21:07:21 -07001855 if ((fd = open(loopDevice, O_RDWR | O_CLOEXEC)) < 0) {
Kenny Rootfb7c4d52010-06-30 18:48:41 -07001856 SLOGE("Failed to open loopdevice (%s)", strerror(errno));
1857 Loop::destroyByDevice(loopDevice);
1858 return -1;
1859 }
1860
Hiroaki Miyazawa14eab552015-02-04 13:29:15 +09001861 get_blkdev_size(fd, &nr_sec);
1862 if (nr_sec == 0) {
Kenny Rootfb7c4d52010-06-30 18:48:41 -07001863 SLOGE("Failed to get loop size (%s)", strerror(errno));
1864 Loop::destroyByDevice(loopDevice);
1865 close(fd);
1866 return -1;
1867 }
1868
1869 close(fd);
1870
Hiroaki Miyazawa14eab552015-02-04 13:29:15 +09001871 if (setupDevMapperDevice(dmDevice, sizeof(loopDevice), loopDevice, img,key, idHash, nr_sec, &cleanupDm, mDebug)) {
Daniel Rosenbergfcd34a02014-05-22 11:23:56 -07001872 Loop::destroyByDevice(loopDevice);
1873 return -1;
Kenny Rootfb7c4d52010-06-30 18:48:41 -07001874 }
1875
1876 if (mkdir(mountPoint, 0755)) {
1877 if (errno != EEXIST) {
1878 SLOGE("Mountpoint creation failed (%s)", strerror(errno));
1879 if (cleanupDm) {
1880 Devmapper::destroy(idHash);
1881 }
1882 Loop::destroyByDevice(loopDevice);
1883 return -1;
1884 }
1885 }
1886
yoshiyuki hama476a6272015-01-28 16:37:23 +09001887 /*
1888 * Wait for the device mapper node to be created.
1889 */
1890 waitForDevMapper(dmDevice);
1891
Jeff Sharkeyd0640f62015-05-21 22:35:42 -07001892 if (android::vold::vfat::Mount(dmDevice, mountPoint,
1893 true, false, true, 0, ownerGid, 0227, false)) {
Kenny Rootfb7c4d52010-06-30 18:48:41 -07001894 SLOGE("Image mount failed (%s)", strerror(errno));
1895 if (cleanupDm) {
1896 Devmapper::destroy(idHash);
1897 }
1898 Loop::destroyByDevice(loopDevice);
1899 return -1;
1900 }
1901
Kenny Rootcbacf782010-09-24 15:11:48 -07001902 mActiveContainers->push_back(new ContainerData(strdup(img), OBB));
Kenny Rootfb7c4d52010-06-30 18:48:41 -07001903 if (mDebug) {
1904 SLOGD("Image %s mounted", img);
1905 }
1906 return 0;
1907}
1908
Kenny Root508c0e12010-07-12 09:59:49 -07001909int VolumeManager::listMountedObbs(SocketClient* cli) {
Yabin Cuid1104f72015-01-02 13:28:28 -08001910 FILE *fp = setmntent("/proc/mounts", "r");
1911 if (fp == NULL) {
Kenny Root508c0e12010-07-12 09:59:49 -07001912 SLOGE("Error opening /proc/mounts (%s)", strerror(errno));
1913 return -1;
1914 }
1915
1916 // Create a string to compare against that has a trailing slash
Jeff Sharkey9f18fe72015-04-01 23:32:18 -07001917 int loopDirLen = strlen(VolumeManager::LOOPDIR);
Kenny Root508c0e12010-07-12 09:59:49 -07001918 char loopDir[loopDirLen + 2];
Jeff Sharkey32ebb732017-03-27 16:18:50 -06001919 strlcpy(loopDir, VolumeManager::LOOPDIR, sizeof(loopDir));
Kenny Root508c0e12010-07-12 09:59:49 -07001920 loopDir[loopDirLen++] = '/';
1921 loopDir[loopDirLen] = '\0';
1922
Yabin Cuid1104f72015-01-02 13:28:28 -08001923 mntent* mentry;
1924 while ((mentry = getmntent(fp)) != NULL) {
1925 if (!strncmp(mentry->mnt_dir, loopDir, loopDirLen)) {
Jeff Sharkeyce6a9132015-04-08 21:07:21 -07001926 int fd = open(mentry->mnt_fsname, O_RDONLY | O_CLOEXEC);
Kenny Root508c0e12010-07-12 09:59:49 -07001927 if (fd >= 0) {
1928 struct loop_info64 li;
1929 if (ioctl(fd, LOOP_GET_STATUS64, &li) >= 0) {
1930 cli->sendMsg(ResponseCode::AsecListResult,
1931 (const char*) li.lo_file_name, false);
1932 }
1933 close(fd);
1934 }
1935 }
1936 }
Yabin Cuid1104f72015-01-02 13:28:28 -08001937 endmntent(fp);
Kenny Root508c0e12010-07-12 09:59:49 -07001938 return 0;
1939}
1940
Jeff Sharkey9c484982015-03-31 10:35:33 -07001941extern "C" int vold_unmountAll(void) {
Ken Sumrall425524d2012-06-14 20:55:28 -07001942 VolumeManager *vm = VolumeManager::Instance();
Jeff Sharkey9c484982015-03-31 10:35:33 -07001943 return vm->unmountAll();
Ken Sumrall425524d2012-06-14 20:55:28 -07001944}
1945
San Mehata19b2502010-01-06 10:33:53 -08001946bool VolumeManager::isMountpointMounted(const char *mp)
1947{
Yabin Cuid1104f72015-01-02 13:28:28 -08001948 FILE *fp = setmntent("/proc/mounts", "r");
1949 if (fp == NULL) {
San Mehat97ac40e2010-03-24 10:24:19 -07001950 SLOGE("Error opening /proc/mounts (%s)", strerror(errno));
San Mehata19b2502010-01-06 10:33:53 -08001951 return false;
1952 }
1953
Yabin Cuid1104f72015-01-02 13:28:28 -08001954 bool found_mp = false;
1955 mntent* mentry;
1956 while ((mentry = getmntent(fp)) != NULL) {
1957 if (strcmp(mentry->mnt_dir, mp) == 0) {
1958 found_mp = true;
1959 break;
San Mehata19b2502010-01-06 10:33:53 -08001960 }
San Mehata19b2502010-01-06 10:33:53 -08001961 }
Yabin Cuid1104f72015-01-02 13:28:28 -08001962 endmntent(fp);
1963 return found_mp;
San Mehata19b2502010-01-06 10:33:53 -08001964}
1965
Jeff Sharkey9462bdd2017-09-07 15:27:28 -06001966int VolumeManager::mkdirs(const char* path) {
Jeff Sharkey36801cc2015-03-13 16:09:20 -07001967 // Only offer to create directories for paths managed by vold
1968 if (strncmp(path, "/storage/", 9) == 0) {
1969 // fs_mkdirs() does symlink checking and relative path enforcement
1970 return fs_mkdirs(path, 0700);
Jeff Sharkey71ebe152013-09-17 17:24:38 -07001971 } else {
Cylen Yao27cfee32014-05-02 19:23:42 +08001972 SLOGE("Failed to find mounted volume for %s", path);
Jeff Sharkey71ebe152013-09-17 17:24:38 -07001973 return -EINVAL;
1974 }
Jeff Sharkey71ebe152013-09-17 17:24:38 -07001975}
Jeff Sharkey11c2d382017-09-11 10:32:01 -06001976
1977static size_t kAppFuseMaxMountPointName = 32;
1978
1979static android::status_t getMountPath(uid_t uid, const std::string& name, std::string* path) {
1980 if (name.size() > kAppFuseMaxMountPointName) {
1981 LOG(ERROR) << "AppFuse mount name is too long.";
1982 return -EINVAL;
1983 }
1984 for (size_t i = 0; i < name.size(); i++) {
1985 if (!isalnum(name[i])) {
1986 LOG(ERROR) << "AppFuse mount name contains invalid character.";
1987 return -EINVAL;
1988 }
1989 }
1990 *path = android::base::StringPrintf("/mnt/appfuse/%d_%s", uid, name.c_str());
1991 return android::OK;
1992}
1993
1994static android::status_t mountInNamespace(uid_t uid, int device_fd, const std::string& path) {
1995 // Remove existing mount.
1996 android::vold::ForceUnmount(path);
1997
1998 const auto opts = android::base::StringPrintf(
1999 "fd=%i,"
2000 "rootmode=40000,"
2001 "default_permissions,"
2002 "allow_other,"
2003 "user_id=%d,group_id=%d,"
2004 "context=\"u:object_r:app_fuse_file:s0\","
2005 "fscontext=u:object_r:app_fusefs:s0",
2006 device_fd,
2007 uid,
2008 uid);
2009
2010 const int result = TEMP_FAILURE_RETRY(mount(
2011 "/dev/fuse", path.c_str(), "fuse",
2012 MS_NOSUID | MS_NODEV | MS_NOEXEC | MS_NOATIME, opts.c_str()));
2013 if (result != 0) {
2014 PLOG(ERROR) << "Failed to mount " << path;
2015 return -errno;
2016 }
2017
2018 return android::OK;
2019}
2020
2021static android::status_t runCommandInNamespace(const std::string& command,
2022 uid_t uid,
2023 pid_t pid,
2024 const std::string& path,
2025 int device_fd) {
2026 if (DEBUG_APPFUSE) {
2027 LOG(DEBUG) << "Run app fuse command " << command << " for the path " << path
2028 << " in namespace " << uid;
2029 }
2030
2031 unique_fd dir(open("/proc", O_RDONLY | O_DIRECTORY | O_CLOEXEC));
2032 if (dir.get() == -1) {
2033 PLOG(ERROR) << "Failed to open /proc";
2034 return -errno;
2035 }
2036
2037 // Obtains process file descriptor.
2038 const std::string pid_str = android::base::StringPrintf("%d", pid);
2039 const unique_fd pid_fd(
2040 openat(dir.get(), pid_str.c_str(), O_RDONLY | O_DIRECTORY | O_CLOEXEC));
2041 if (pid_fd.get() == -1) {
2042 PLOG(ERROR) << "Failed to open /proc/" << pid;
2043 return -errno;
2044 }
2045
2046 // Check UID of process.
2047 {
2048 struct stat sb;
2049 const int result = fstat(pid_fd.get(), &sb);
2050 if (result == -1) {
2051 PLOG(ERROR) << "Failed to stat /proc/" << pid;
2052 return -errno;
2053 }
2054 if (sb.st_uid != AID_SYSTEM) {
2055 LOG(ERROR) << "Only system can mount appfuse. UID expected=" << AID_SYSTEM
2056 << ", actual=" << sb.st_uid;
2057 return -EPERM;
2058 }
2059 }
2060
2061 // Matches so far, but refuse to touch if in root namespace
2062 {
2063 char rootName[PATH_MAX];
2064 char pidName[PATH_MAX];
2065 const int root_result =
2066 android::vold::SaneReadLinkAt(dir.get(), "1/ns/mnt", rootName, PATH_MAX);
2067 const int pid_result =
2068 android::vold::SaneReadLinkAt(pid_fd.get(), "ns/mnt", pidName, PATH_MAX);
2069 if (root_result == -1) {
2070 LOG(ERROR) << "Failed to readlink for /proc/1/ns/mnt";
2071 return -EPERM;
2072 }
2073 if (pid_result == -1) {
2074 LOG(ERROR) << "Failed to readlink for /proc/" << pid << "/ns/mnt";
2075 return -EPERM;
2076 }
2077 if (!strcmp(rootName, pidName)) {
2078 LOG(ERROR) << "Don't mount appfuse in root namespace";
2079 return -EPERM;
2080 }
2081 }
2082
2083 // We purposefully leave the namespace open across the fork
2084 unique_fd ns_fd(openat(pid_fd.get(), "ns/mnt", O_RDONLY)); // not O_CLOEXEC
2085 if (ns_fd.get() < 0) {
2086 PLOG(ERROR) << "Failed to open namespace for /proc/" << pid << "/ns/mnt";
2087 return -errno;
2088 }
2089
2090 int child = fork();
2091 if (child == 0) {
2092 if (setns(ns_fd.get(), CLONE_NEWNS) != 0) {
2093 PLOG(ERROR) << "Failed to setns";
2094 _exit(-errno);
2095 }
2096
2097 if (command == "mount") {
2098 _exit(mountInNamespace(uid, device_fd, path));
2099 } else if (command == "unmount") {
2100 // If it's just after all FD opened on mount point are closed, umount2 can fail with
2101 // EBUSY. To avoid the case, specify MNT_DETACH.
2102 if (umount2(path.c_str(), UMOUNT_NOFOLLOW | MNT_DETACH) != 0 &&
2103 errno != EINVAL && errno != ENOENT) {
2104 PLOG(ERROR) << "Failed to unmount directory.";
2105 _exit(-errno);
2106 }
2107 if (rmdir(path.c_str()) != 0) {
2108 PLOG(ERROR) << "Failed to remove the mount directory.";
2109 _exit(-errno);
2110 }
2111 _exit(android::OK);
2112 } else {
2113 LOG(ERROR) << "Unknown appfuse command " << command;
2114 _exit(-EPERM);
2115 }
2116 }
2117
2118 if (child == -1) {
2119 PLOG(ERROR) << "Failed to folk child process";
2120 return -errno;
2121 }
2122
2123 android::status_t status;
2124 TEMP_FAILURE_RETRY(waitpid(child, &status, 0));
2125
2126 return status;
2127}
2128
2129int VolumeManager::createObb(const std::string& sourcePath, const std::string& sourceKey,
2130 int32_t ownerGid, std::string* outVolId) {
2131 int id = mNextObbId++;
2132
2133 auto vol = std::shared_ptr<android::vold::VolumeBase>(
2134 new android::vold::ObbVolume(id, sourcePath, sourceKey, ownerGid));
2135 vol->create();
2136
2137 mObbVolumes.push_back(vol);
2138 *outVolId = vol->getId();
2139 return android::OK;
2140}
2141
2142int VolumeManager::destroyObb(const std::string& volId) {
2143 auto i = mObbVolumes.begin();
2144 while (i != mObbVolumes.end()) {
2145 if ((*i)->getId() == volId) {
2146 (*i)->destroy();
2147 i = mObbVolumes.erase(i);
2148 } else {
2149 ++i;
2150 }
2151 }
2152 return android::OK;
2153}
2154
2155int VolumeManager::mountAppFuse(uid_t uid, pid_t pid, int mountId,
2156 android::base::unique_fd* device_fd) {
2157 std::string name = std::to_string(mountId);
2158
2159 // Check mount point name.
2160 std::string path;
2161 if (getMountPath(uid, name, &path) != android::OK) {
2162 LOG(ERROR) << "Invalid mount point name";
2163 return -1;
2164 }
2165
2166 // Create directories.
2167 const android::status_t result = android::vold::PrepareDir(path, 0700, 0, 0);
2168 if (result != android::OK) {
2169 PLOG(ERROR) << "Failed to prepare directory " << path;
2170 return -1;
2171 }
2172
2173 // Open device FD.
2174 device_fd->reset(open("/dev/fuse", O_RDWR)); // not O_CLOEXEC
2175 if (device_fd->get() == -1) {
2176 PLOG(ERROR) << "Failed to open /dev/fuse";
2177 return -1;
2178 }
2179
2180 // Mount.
2181 return runCommandInNamespace("mount", uid, pid, path, device_fd->get());
2182}
2183
2184int VolumeManager::unmountAppFuse(uid_t uid, pid_t pid, int mountId) {
2185 std::string name = std::to_string(mountId);
2186
2187 // Check mount point name.
2188 std::string path;
2189 if (getMountPath(uid, name, &path) != android::OK) {
2190 LOG(ERROR) << "Invalid mount point name";
2191 return -1;
2192 }
2193
2194 return runCommandInNamespace("unmount", uid, pid, path, -1 /* device_fd */);
2195}