blob: 497a7be6e57391761c1eeadc3fb02b527543a238 [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
San Mehat49e2bce2009-10-12 16:29:01 -070017#include <stdlib.h>
San Mehatf1b736b2009-10-10 17:22:08 -070018#include <string.h>
San Mehat49e2bce2009-10-12 16:29:01 -070019#include <dirent.h>
20#include <errno.h>
21#include <fcntl.h>
Yabin Cuid1104f72015-01-02 13:28:28 -080022#include <mntent.h>
San Mehat49e2bce2009-10-12 16:29:01 -070023
24#include <sys/types.h>
25#include <sys/stat.h>
26#include <sys/types.h>
27#include <sys/mman.h>
San Mehata2677e42009-12-13 10:40:18 -080028#include <sys/mount.h>
Ken Sumrall29d8da82011-05-18 17:20:07 -070029#include <sys/param.h>
San Mehata2677e42009-12-13 10:40:18 -080030
31#include <linux/kdev_t.h>
32
33#include <cutils/properties.h>
34
San Mehat2a5b8ce2010-03-10 12:48:57 -080035#include <diskconfig/diskconfig.h>
San Mehatf1b736b2009-10-10 17:22:08 -070036
Mike Lockwood9092b1d2011-03-23 14:55:49 -040037#include <private/android_filesystem_config.h>
38
San Mehatf1b736b2009-10-10 17:22:08 -070039#define LOG_TAG "Vold"
40
Jeff Sharkeyba6ae8d2013-07-15 18:14:25 -070041#include <cutils/fs.h>
San Mehatf1b736b2009-10-10 17:22:08 -070042#include <cutils/log.h>
43
Jeff Sharkey0de365f2013-10-16 16:24:19 -070044#include <string>
45
San Mehatf1b736b2009-10-10 17:22:08 -070046#include "Volume.h"
San Mehata2677e42009-12-13 10:40:18 -080047#include "VolumeManager.h"
48#include "ResponseCode.h"
San Mehatbf041852010-01-04 10:09:16 -080049#include "Fat.h"
San Mehat586536c2010-02-16 17:12:00 -080050#include "Process.h"
Ken Sumrall29d8da82011-05-18 17:20:07 -070051#include "cryptfs.h"
Stephen Smalley684e6622014-09-30 10:29:24 -040052#include "sehandle.h"
San Mehatf1b736b2009-10-10 17:22:08 -070053
San Mehata2677e42009-12-13 10:40:18 -080054extern "C" void dos_partition_dec(void const *pp, struct dos_partition *d);
55extern "C" void dos_partition_enc(void *pp, struct dos_partition *d);
San Mehat49e2bce2009-10-12 16:29:01 -070056
San Mehat3bb60202010-02-19 18:14:36 -080057
58/*
Jeff Sharkeyba6ae8d2013-07-15 18:14:25 -070059 * Media directory - stuff that only media_rw user can see
San Mehat3bb60202010-02-19 18:14:36 -080060 */
Jeff Sharkeyba6ae8d2013-07-15 18:14:25 -070061const char *Volume::MEDIA_DIR = "/mnt/media_rw";
San Mehat3bb60202010-02-19 18:14:36 -080062
63/*
Jeff Sharkeyba6ae8d2013-07-15 18:14:25 -070064 * Fuse directory - location where fuse wrapped filesystems go
San Mehat3bb60202010-02-19 18:14:36 -080065 */
Jeff Sharkeyba6ae8d2013-07-15 18:14:25 -070066const char *Volume::FUSE_DIR = "/storage";
San Mehat3bb60202010-02-19 18:14:36 -080067
68/*
Kenny Root344ca102012-04-03 17:23:01 -070069 * Path to external storage where *only* root can access ASEC image files
San Mehat3bb60202010-02-19 18:14:36 -080070 */
Kenny Root344ca102012-04-03 17:23:01 -070071const char *Volume::SEC_ASECDIR_EXT = "/mnt/secure/asec";
San Mehat3bb60202010-02-19 18:14:36 -080072
73/*
Kenny Root344ca102012-04-03 17:23:01 -070074 * Path to internal storage where *only* root can access ASEC image files
75 */
76const char *Volume::SEC_ASECDIR_INT = "/data/app-asec";
Jeff Sharkey8c2c15b2013-10-17 15:17:19 -070077
Kenny Root344ca102012-04-03 17:23:01 -070078/*
San Mehat3bb60202010-02-19 18:14:36 -080079 * Path to where secure containers are mounted
80 */
81const char *Volume::ASECDIR = "/mnt/asec";
82
Kenny Rootfb7c4d52010-06-30 18:48:41 -070083/*
Kenny Root508c0e12010-07-12 09:59:49 -070084 * Path to where OBBs are mounted
Kenny Rootfb7c4d52010-06-30 18:48:41 -070085 */
Kenny Root508c0e12010-07-12 09:59:49 -070086const char *Volume::LOOPDIR = "/mnt/obb";
Kenny Rootfb7c4d52010-06-30 18:48:41 -070087
Jeff Sharkey0de365f2013-10-16 16:24:19 -070088const char *Volume::BLKID_PATH = "/system/bin/blkid";
89
San Mehata2677e42009-12-13 10:40:18 -080090static const char *stateToStr(int state) {
91 if (state == Volume::State_Init)
92 return "Initializing";
93 else if (state == Volume::State_NoMedia)
94 return "No-Media";
95 else if (state == Volume::State_Idle)
96 return "Idle-Unmounted";
97 else if (state == Volume::State_Pending)
98 return "Pending";
99 else if (state == Volume::State_Mounted)
100 return "Mounted";
101 else if (state == Volume::State_Unmounting)
102 return "Unmounting";
103 else if (state == Volume::State_Checking)
104 return "Checking";
105 else if (state == Volume::State_Formatting)
106 return "Formatting";
107 else if (state == Volume::State_Shared)
108 return "Shared-Unmounted";
109 else if (state == Volume::State_SharedMnt)
110 return "Shared-Mounted";
111 else
112 return "Unknown-Error";
113}
114
Jeff Sharkeyba6ae8d2013-07-15 18:14:25 -0700115Volume::Volume(VolumeManager *vm, const fstab_rec* rec, int flags) {
San Mehata2677e42009-12-13 10:40:18 -0800116 mVm = vm;
San Mehatd9a4e352010-03-12 13:32:47 -0800117 mDebug = false;
Jeff Sharkeyba6ae8d2013-07-15 18:14:25 -0700118 mLabel = strdup(rec->label);
Jeff Sharkey0de365f2013-10-16 16:24:19 -0700119 mUuid = NULL;
120 mUserLabel = NULL;
San Mehatf1b736b2009-10-10 17:22:08 -0700121 mState = Volume::State_Init;
Jeff Sharkeyba6ae8d2013-07-15 18:14:25 -0700122 mFlags = flags;
San Mehata2677e42009-12-13 10:40:18 -0800123 mCurrentlyMountedKdev = -1;
Jeff Sharkeyba6ae8d2013-07-15 18:14:25 -0700124 mPartIdx = rec->partnum;
Joseph Lehrer507d31b2011-04-11 15:02:50 -0700125 mRetryMount = false;
San Mehatf1b736b2009-10-10 17:22:08 -0700126}
127
128Volume::~Volume() {
129 free(mLabel);
Jeff Sharkey0de365f2013-10-16 16:24:19 -0700130 free(mUuid);
131 free(mUserLabel);
San Mehatcb4dac82010-03-14 13:41:54 -0700132}
133
San Mehatd9a4e352010-03-12 13:32:47 -0800134void Volume::setDebug(bool enable) {
135 mDebug = enable;
136}
137
San Mehata2677e42009-12-13 10:40:18 -0800138dev_t Volume::getDiskDevice() {
139 return MKDEV(0, 0);
140};
141
Mike Lockwood2dfe2972010-09-17 18:50:51 -0400142dev_t Volume::getShareDevice() {
143 return getDiskDevice();
144}
145
San Mehata2677e42009-12-13 10:40:18 -0800146void Volume::handleVolumeShared() {
147}
148
149void Volume::handleVolumeUnshared() {
150}
151
Mark Salyzyn5eecc442014-02-12 14:16:14 -0800152int Volume::handleBlockEvent(NetlinkEvent * /*evt*/) {
San Mehatf1b736b2009-10-10 17:22:08 -0700153 errno = ENOSYS;
154 return -1;
155}
156
Jeff Sharkey0de365f2013-10-16 16:24:19 -0700157void Volume::setUuid(const char* uuid) {
158 char msg[256];
159
160 if (mUuid) {
161 free(mUuid);
162 }
163
164 if (uuid) {
165 mUuid = strdup(uuid);
166 snprintf(msg, sizeof(msg), "%s %s \"%s\"", getLabel(),
167 getFuseMountpoint(), mUuid);
168 } else {
169 mUuid = NULL;
170 snprintf(msg, sizeof(msg), "%s %s", getLabel(), getFuseMountpoint());
171 }
172
173 mVm->getBroadcaster()->sendBroadcast(ResponseCode::VolumeUuidChange, msg,
174 false);
175}
176
177void Volume::setUserLabel(const char* userLabel) {
178 char msg[256];
179
180 if (mUserLabel) {
181 free(mUserLabel);
182 }
183
184 if (userLabel) {
185 mUserLabel = strdup(userLabel);
186 snprintf(msg, sizeof(msg), "%s %s \"%s\"", getLabel(),
187 getFuseMountpoint(), mUserLabel);
188 } else {
189 mUserLabel = NULL;
190 snprintf(msg, sizeof(msg), "%s %s", getLabel(), getFuseMountpoint());
191 }
192
193 mVm->getBroadcaster()->sendBroadcast(ResponseCode::VolumeUserLabelChange,
194 msg, false);
195}
196
San Mehatf1b736b2009-10-10 17:22:08 -0700197void Volume::setState(int state) {
San Mehata2677e42009-12-13 10:40:18 -0800198 char msg[255];
199 int oldState = mState;
200
201 if (oldState == state) {
San Mehat97ac40e2010-03-24 10:24:19 -0700202 SLOGW("Duplicate state (%d)\n", state);
San Mehata2677e42009-12-13 10:40:18 -0800203 return;
204 }
205
Joseph Lehrer507d31b2011-04-11 15:02:50 -0700206 if ((oldState == Volume::State_Pending) && (state != Volume::State_Idle)) {
207 mRetryMount = false;
208 }
209
San Mehatf1b736b2009-10-10 17:22:08 -0700210 mState = state;
San Mehata2677e42009-12-13 10:40:18 -0800211
San Mehat97ac40e2010-03-24 10:24:19 -0700212 SLOGD("Volume %s state changing %d (%s) -> %d (%s)", mLabel,
San Mehata2677e42009-12-13 10:40:18 -0800213 oldState, stateToStr(oldState), mState, stateToStr(mState));
214 snprintf(msg, sizeof(msg),
215 "Volume %s %s state changed from %d (%s) to %d (%s)", getLabel(),
Jeff Sharkeyba6ae8d2013-07-15 18:14:25 -0700216 getFuseMountpoint(), oldState, stateToStr(oldState), mState,
San Mehata2677e42009-12-13 10:40:18 -0800217 stateToStr(mState));
218
219 mVm->getBroadcaster()->sendBroadcast(ResponseCode::VolumeStateChange,
220 msg, false);
San Mehatf1b736b2009-10-10 17:22:08 -0700221}
San Mehat49e2bce2009-10-12 16:29:01 -0700222
San Mehatdd9b8e92009-10-21 11:06:52 -0700223int Volume::createDeviceNode(const char *path, int major, int minor) {
Stephen Smalley684e6622014-09-30 10:29:24 -0400224 char *secontext = NULL;
San Mehatdd9b8e92009-10-21 11:06:52 -0700225 mode_t mode = 0660 | S_IFBLK;
226 dev_t dev = (major << 8) | minor;
Stephen Smalley684e6622014-09-30 10:29:24 -0400227 int rc;
228 if (sehandle) {
229 rc = selabel_lookup(sehandle, &secontext, path, S_IFBLK);
230 if (rc == 0)
231 setfscreatecon(secontext);
232 }
San Mehatdd9b8e92009-10-21 11:06:52 -0700233 if (mknod(path, mode, dev) < 0) {
234 if (errno != EEXIST) {
Stephen Smalley684e6622014-09-30 10:29:24 -0400235 int sverrno = errno;
236 if (secontext) {
237 freecon(secontext);
238 setfscreatecon(NULL);
239 }
240 errno = sverrno;
San Mehatdd9b8e92009-10-21 11:06:52 -0700241 return -1;
242 }
243 }
Stephen Smalley684e6622014-09-30 10:29:24 -0400244 if (secontext) {
245 setfscreatecon(NULL);
246 freecon(secontext);
247 }
San Mehatdd9b8e92009-10-21 11:06:52 -0700248 return 0;
249}
250
Ken Sumrall9caab762013-06-11 19:10:20 -0700251int Volume::formatVol(bool wipe) {
San Mehat49e2bce2009-10-12 16:29:01 -0700252
San Mehata2677e42009-12-13 10:40:18 -0800253 if (getState() == Volume::State_NoMedia) {
254 errno = ENODEV;
255 return -1;
256 } else if (getState() != Volume::State_Idle) {
257 errno = EBUSY;
San Mehat49e2bce2009-10-12 16:29:01 -0700258 return -1;
259 }
260
San Mehata2677e42009-12-13 10:40:18 -0800261 if (isMountpointMounted(getMountpoint())) {
San Mehat97ac40e2010-03-24 10:24:19 -0700262 SLOGW("Volume is idle but appears to be mounted - fixing");
San Mehata2677e42009-12-13 10:40:18 -0800263 setState(Volume::State_Mounted);
264 // mCurrentlyMountedKdev = XXX
265 errno = EBUSY;
San Mehat49e2bce2009-10-12 16:29:01 -0700266 return -1;
267 }
268
Mike Lockwooda4886f12010-09-21 13:56:35 -0400269 bool formatEntireDevice = (mPartIdx == -1);
San Mehata2677e42009-12-13 10:40:18 -0800270 char devicePath[255];
271 dev_t diskNode = getDiskDevice();
Blair Prescottcc21d6e2013-10-21 15:25:37 -0700272 dev_t partNode =
273 MKDEV(MAJOR(diskNode),
Bogdan George Stefan1a89e8b2014-06-30 15:40:03 +0300274 MINOR(diskNode) + (formatEntireDevice ? 0 : mPartIdx));
San Mehata2677e42009-12-13 10:40:18 -0800275
San Mehat2a5b8ce2010-03-10 12:48:57 -0800276 setState(Volume::State_Formatting);
San Mehata2677e42009-12-13 10:40:18 -0800277
Chih-Wei Huang64382de2010-11-16 13:18:19 +0800278 int ret = -1;
Mike Lockwooda4886f12010-09-21 13:56:35 -0400279 // Only initialize the MBR if we are formatting the entire device
280 if (formatEntireDevice) {
281 sprintf(devicePath, "/dev/block/vold/%d:%d",
Colin Cross346c5b22014-01-22 23:59:41 -0800282 major(diskNode), minor(diskNode));
Mike Lockwooda4886f12010-09-21 13:56:35 -0400283
284 if (initializeMbr(devicePath)) {
285 SLOGE("Failed to initialize MBR (%s)", strerror(errno));
286 goto err;
287 }
San Mehat49e2bce2009-10-12 16:29:01 -0700288 }
289
San Mehata2677e42009-12-13 10:40:18 -0800290 sprintf(devicePath, "/dev/block/vold/%d:%d",
Colin Cross346c5b22014-01-22 23:59:41 -0800291 major(partNode), minor(partNode));
San Mehatdd9b8e92009-10-21 11:06:52 -0700292
Mike Lockwooda4886f12010-09-21 13:56:35 -0400293 if (mDebug) {
294 SLOGI("Formatting volume %s (%s)", getLabel(), devicePath);
295 }
296
Ken Sumrall9caab762013-06-11 19:10:20 -0700297 if (Fat::format(devicePath, 0, wipe)) {
San Mehat97ac40e2010-03-24 10:24:19 -0700298 SLOGE("Failed to format (%s)", strerror(errno));
San Mehata2677e42009-12-13 10:40:18 -0800299 goto err;
300 }
301
Chih-Wei Huang64382de2010-11-16 13:18:19 +0800302 ret = 0;
303
San Mehata2677e42009-12-13 10:40:18 -0800304err:
Chih-Wei Huang64382de2010-11-16 13:18:19 +0800305 setState(Volume::State_Idle);
306 return ret;
San Mehata2677e42009-12-13 10:40:18 -0800307}
308
309bool Volume::isMountpointMounted(const char *path) {
Yabin Cuid1104f72015-01-02 13:28:28 -0800310 FILE *fp = setmntent("/proc/mounts", "r");
311 if (fp == NULL) {
San Mehat97ac40e2010-03-24 10:24:19 -0700312 SLOGE("Error opening /proc/mounts (%s)", strerror(errno));
San Mehata2677e42009-12-13 10:40:18 -0800313 return false;
314 }
315
Yabin Cuid1104f72015-01-02 13:28:28 -0800316 bool found_path = false;
317 mntent* mentry;
318 while ((mentry = getmntent(fp)) != NULL) {
319 if (strcmp(mentry->mnt_dir, path) == 0) {
320 found_path = true;
321 break;
San Mehata2677e42009-12-13 10:40:18 -0800322 }
San Mehata2677e42009-12-13 10:40:18 -0800323 }
Yabin Cuid1104f72015-01-02 13:28:28 -0800324 endmntent(fp);
325 return found_path;
San Mehata2677e42009-12-13 10:40:18 -0800326}
327
328int Volume::mountVol() {
329 dev_t deviceNodes[4];
Tim Murray8439dc92014-12-15 11:56:11 -0800330 int n, i;
San Mehata2677e42009-12-13 10:40:18 -0800331 char errmsg[255];
Jeff Sharkeyba6ae8d2013-07-15 18:14:25 -0700332
333 int flags = getFlags();
334 bool providesAsec = (flags & VOL_PROVIDES_ASEC) != 0;
335
336 // TODO: handle "bind" style mounts, for emulated storage
337
Ken Sumrall29d8da82011-05-18 17:20:07 -0700338 char decrypt_state[PROPERTY_VALUE_MAX];
339 char crypto_state[PROPERTY_VALUE_MAX];
340 char encrypt_progress[PROPERTY_VALUE_MAX];
San Mehata2677e42009-12-13 10:40:18 -0800341
Ken Sumrall29d8da82011-05-18 17:20:07 -0700342 property_get("vold.decrypt", decrypt_state, "");
343 property_get("vold.encrypt_progress", encrypt_progress, "");
344
345 /* Don't try to mount the volumes if we have not yet entered the disk password
346 * or are in the process of encrypting.
347 */
348 if ((getState() == Volume::State_NoMedia) ||
Jeff Sharkeyba6ae8d2013-07-15 18:14:25 -0700349 ((!strcmp(decrypt_state, "1") || encrypt_progress[0]) && providesAsec)) {
San Mehata2677e42009-12-13 10:40:18 -0800350 snprintf(errmsg, sizeof(errmsg),
351 "Volume %s %s mount failed - no media",
Jeff Sharkeyba6ae8d2013-07-15 18:14:25 -0700352 getLabel(), getFuseMountpoint());
San Mehata2677e42009-12-13 10:40:18 -0800353 mVm->getBroadcaster()->sendBroadcast(
354 ResponseCode::VolumeMountFailedNoMedia,
355 errmsg, false);
356 errno = ENODEV;
357 return -1;
358 } else if (getState() != Volume::State_Idle) {
359 errno = EBUSY;
Joseph Lehrer507d31b2011-04-11 15:02:50 -0700360 if (getState() == Volume::State_Pending) {
361 mRetryMount = true;
362 }
San Mehata2677e42009-12-13 10:40:18 -0800363 return -1;
364 }
365
366 if (isMountpointMounted(getMountpoint())) {
San Mehat97ac40e2010-03-24 10:24:19 -0700367 SLOGW("Volume is idle but appears to be mounted - fixing");
San Mehata2677e42009-12-13 10:40:18 -0800368 setState(Volume::State_Mounted);
369 // mCurrentlyMountedKdev = XXX
370 return 0;
371 }
372
373 n = getDeviceNodes((dev_t *) &deviceNodes, 4);
374 if (!n) {
San Mehat97ac40e2010-03-24 10:24:19 -0700375 SLOGE("Failed to get device nodes (%s)\n", strerror(errno));
San Mehata2677e42009-12-13 10:40:18 -0800376 return -1;
377 }
378
Ken Sumrall29d8da82011-05-18 17:20:07 -0700379 /* If we're running encrypted, and the volume is marked as encryptable and nonremovable,
Jeff Sharkeyba6ae8d2013-07-15 18:14:25 -0700380 * and also marked as providing Asec storage, then we need to decrypt
Ken Sumrall29d8da82011-05-18 17:20:07 -0700381 * that partition, and update the volume object to point to it's new decrypted
382 * block device
383 */
384 property_get("ro.crypto.state", crypto_state, "");
Jeff Sharkeyba6ae8d2013-07-15 18:14:25 -0700385 if (providesAsec &&
Ken Sumrall29d8da82011-05-18 17:20:07 -0700386 ((flags & (VOL_NONREMOVABLE | VOL_ENCRYPTABLE))==(VOL_NONREMOVABLE | VOL_ENCRYPTABLE)) &&
387 !strcmp(crypto_state, "encrypted") && !isDecrypted()) {
388 char new_sys_path[MAXPATHLEN];
389 char nodepath[256];
390 int new_major, new_minor;
391
392 if (n != 1) {
393 /* We only expect one device node returned when mounting encryptable volumes */
Colin Cross59846b62014-02-06 20:34:29 -0800394 SLOGE("Too many device nodes returned when mounting %s\n", getMountpoint());
Ken Sumrall29d8da82011-05-18 17:20:07 -0700395 return -1;
396 }
397
398 if (cryptfs_setup_volume(getLabel(), MAJOR(deviceNodes[0]), MINOR(deviceNodes[0]),
399 new_sys_path, sizeof(new_sys_path),
400 &new_major, &new_minor)) {
Colin Cross59846b62014-02-06 20:34:29 -0800401 SLOGE("Cannot setup encryption mapping for %s\n", getMountpoint());
Ken Sumrall29d8da82011-05-18 17:20:07 -0700402 return -1;
403 }
404 /* We now have the new sysfs path for the decrypted block device, and the
405 * majore and minor numbers for it. So, create the device, update the
406 * path to the new sysfs path, and continue.
407 */
408 snprintf(nodepath,
409 sizeof(nodepath), "/dev/block/vold/%d:%d",
410 new_major, new_minor);
411 if (createDeviceNode(nodepath, new_major, new_minor)) {
412 SLOGE("Error making device node '%s' (%s)", nodepath,
413 strerror(errno));
414 }
415
416 // Todo: Either create sys filename from nodepath, or pass in bogus path so
417 // vold ignores state changes on this internal device.
418 updateDeviceInfo(nodepath, new_major, new_minor);
419
420 /* Get the device nodes again, because they just changed */
421 n = getDeviceNodes((dev_t *) &deviceNodes, 4);
422 if (!n) {
423 SLOGE("Failed to get device nodes (%s)\n", strerror(errno));
424 return -1;
425 }
426 }
427
San Mehata2677e42009-12-13 10:40:18 -0800428 for (i = 0; i < n; i++) {
429 char devicePath[255];
430
Colin Cross346c5b22014-01-22 23:59:41 -0800431 sprintf(devicePath, "/dev/block/vold/%d:%d", major(deviceNodes[i]),
432 minor(deviceNodes[i]));
San Mehata2677e42009-12-13 10:40:18 -0800433
San Mehat97ac40e2010-03-24 10:24:19 -0700434 SLOGI("%s being considered for volume %s\n", devicePath, getLabel());
San Mehata2677e42009-12-13 10:40:18 -0800435
436 errno = 0;
San Mehatbf041852010-01-04 10:09:16 -0800437 setState(Volume::State_Checking);
438
San Mehat3bb60202010-02-19 18:14:36 -0800439 if (Fat::check(devicePath)) {
San Mehata2677e42009-12-13 10:40:18 -0800440 if (errno == ENODATA) {
San Mehat97ac40e2010-03-24 10:24:19 -0700441 SLOGW("%s does not contain a FAT filesystem\n", devicePath);
San Mehata2677e42009-12-13 10:40:18 -0800442 continue;
San Mehata2677e42009-12-13 10:40:18 -0800443 }
San Mehateba65e92010-01-29 05:15:16 -0800444 errno = EIO;
445 /* Badness - abort the mount */
San Mehat97ac40e2010-03-24 10:24:19 -0700446 SLOGE("%s failed FS checks (%s)", devicePath, strerror(errno));
San Mehateba65e92010-01-29 05:15:16 -0800447 setState(Volume::State_Idle);
448 return -1;
San Mehata2677e42009-12-13 10:40:18 -0800449 }
450
San Mehata2677e42009-12-13 10:40:18 -0800451 errno = 0;
Mike Lockwood9092b1d2011-03-23 14:55:49 -0400452
Jeff Sharkeyba6ae8d2013-07-15 18:14:25 -0700453 if (Fat::doMount(devicePath, getMountpoint(), false, false, false,
454 AID_MEDIA_RW, AID_MEDIA_RW, 0007, true)) {
San Mehat97ac40e2010-03-24 10:24:19 -0700455 SLOGE("%s failed to mount via VFAT (%s)\n", devicePath, strerror(errno));
San Mehat3bb60202010-02-19 18:14:36 -0800456 continue;
San Mehata2677e42009-12-13 10:40:18 -0800457 }
458
Jeff Sharkey0de365f2013-10-16 16:24:19 -0700459 extractMetadata(devicePath);
San Mehatcb4dac82010-03-14 13:41:54 -0700460
Jeff Sharkeyba6ae8d2013-07-15 18:14:25 -0700461 if (providesAsec && mountAsecExternal() != 0) {
462 SLOGE("Failed to mount secure area (%s)", strerror(errno));
463 umount(getMountpoint());
San Mehat3bb60202010-02-19 18:14:36 -0800464 setState(Volume::State_Idle);
465 return -1;
466 }
467
Jeff Sharkeyba6ae8d2013-07-15 18:14:25 -0700468 char service[64];
469 snprintf(service, 64, "fuse_%s", getLabel());
470 property_set("ctl.start", service);
471
San Mehat3bb60202010-02-19 18:14:36 -0800472 setState(Volume::State_Mounted);
473 mCurrentlyMountedKdev = deviceNodes[i];
474 return 0;
San Mehata2677e42009-12-13 10:40:18 -0800475 }
476
San Mehat97ac40e2010-03-24 10:24:19 -0700477 SLOGE("Volume %s found no suitable devices for mounting :(\n", getLabel());
San Mehata2677e42009-12-13 10:40:18 -0800478 setState(Volume::State_Idle);
479
San Mehateba65e92010-01-29 05:15:16 -0800480 return -1;
San Mehata2677e42009-12-13 10:40:18 -0800481}
482
Jeff Sharkeyba6ae8d2013-07-15 18:14:25 -0700483int Volume::mountAsecExternal() {
484 char legacy_path[PATH_MAX];
485 char secure_path[PATH_MAX];
San Mehat3bb60202010-02-19 18:14:36 -0800486
Jeff Sharkeyba6ae8d2013-07-15 18:14:25 -0700487 snprintf(legacy_path, PATH_MAX, "%s/android_secure", getMountpoint());
488 snprintf(secure_path, PATH_MAX, "%s/.android_secure", getMountpoint());
489
490 // Recover legacy secure path
491 if (!access(legacy_path, R_OK | X_OK) && access(secure_path, R_OK | X_OK)) {
492 if (rename(legacy_path, secure_path)) {
San Mehat97ac40e2010-03-24 10:24:19 -0700493 SLOGE("Failed to rename legacy asec dir (%s)", strerror(errno));
San Mehat52c2ccb2010-02-23 18:26:13 -0800494 }
495 }
496
Jeff Sharkeyba6ae8d2013-07-15 18:14:25 -0700497 if (fs_prepare_dir(secure_path, 0770, AID_MEDIA_RW, AID_MEDIA_RW) != 0) {
Jeff Sharkey8c2c15b2013-10-17 15:17:19 -0700498 SLOGW("fs_prepare_dir failed: %s", strerror(errno));
San Mehat3bb60202010-02-19 18:14:36 -0800499 return -1;
500 }
501
Jeff Sharkeyba6ae8d2013-07-15 18:14:25 -0700502 if (mount(secure_path, SEC_ASECDIR_EXT, "", MS_BIND, NULL)) {
503 SLOGE("Failed to bind mount points %s -> %s (%s)", secure_path,
504 SEC_ASECDIR_EXT, strerror(errno));
San Mehat3bb60202010-02-19 18:14:36 -0800505 return -1;
506 }
507
508 return 0;
509}
510
San Mehat3bb60202010-02-19 18:14:36 -0800511int Volume::doUnmount(const char *path, bool force) {
512 int retries = 10;
513
San Mehatd9a4e352010-03-12 13:32:47 -0800514 if (mDebug) {
San Mehat97ac40e2010-03-24 10:24:19 -0700515 SLOGD("Unmounting {%s}, force = %d", path, force);
San Mehatd9a4e352010-03-12 13:32:47 -0800516 }
517
San Mehat3bb60202010-02-19 18:14:36 -0800518 while (retries--) {
519 if (!umount(path) || errno == EINVAL || errno == ENOENT) {
San Mehat97ac40e2010-03-24 10:24:19 -0700520 SLOGI("%s sucessfully unmounted", path);
San Mehat3bb60202010-02-19 18:14:36 -0800521 return 0;
522 }
523
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700524 int signal = 0;
San Mehat3bb60202010-02-19 18:14:36 -0800525
526 if (force) {
527 if (retries == 1) {
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700528 signal = SIGKILL;
San Mehat3bb60202010-02-19 18:14:36 -0800529 } else if (retries == 2) {
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700530 signal = SIGTERM;
San Mehat3bb60202010-02-19 18:14:36 -0800531 }
532 }
533
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700534 SLOGW("Failed to unmount %s (%s, retries %d, signal %d)",
535 path, strerror(errno), retries, signal);
San Mehat3bb60202010-02-19 18:14:36 -0800536
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700537 Process::killProcessesWithOpenFiles(path, signal);
San Mehat3bb60202010-02-19 18:14:36 -0800538 usleep(1000*1000);
539 }
540 errno = EBUSY;
San Mehat97ac40e2010-03-24 10:24:19 -0700541 SLOGE("Giving up on unmount %s (%s)", path, strerror(errno));
San Mehat3bb60202010-02-19 18:14:36 -0800542 return -1;
543}
544
Ken Sumrall0b8b5972011-08-31 16:14:23 -0700545int Volume::unmountVol(bool force, bool revert) {
Jeff Sharkeyba6ae8d2013-07-15 18:14:25 -0700546 int flags = getFlags();
547 bool providesAsec = (flags & VOL_PROVIDES_ASEC) != 0;
548
San Mehata2677e42009-12-13 10:40:18 -0800549 if (getState() != Volume::State_Mounted) {
San Mehat97ac40e2010-03-24 10:24:19 -0700550 SLOGE("Volume %s unmount request when not mounted", getLabel());
San Mehata2677e42009-12-13 10:40:18 -0800551 errno = EINVAL;
Ken Sumrall319b1042011-06-14 14:01:55 -0700552 return UNMOUNT_NOT_MOUNTED_ERR;
San Mehata2677e42009-12-13 10:40:18 -0800553 }
554
555 setState(Volume::State_Unmounting);
San Mehat4ba89482010-02-18 09:00:18 -0800556 usleep(1000 * 1000); // Give the framework some time to react
San Mehata2677e42009-12-13 10:40:18 -0800557
Jeff Sharkeyba6ae8d2013-07-15 18:14:25 -0700558 char service[64];
559 snprintf(service, 64, "fuse_%s", getLabel());
560 property_set("ctl.stop", service);
561 /* Give it a chance to stop. I wish we had a synchronous way to determine this... */
562 sleep(1);
563
564 // TODO: determine failure mode if FUSE times out
565
566 if (providesAsec && doUnmount(Volume::SEC_ASECDIR_EXT, force) != 0) {
567 SLOGE("Failed to unmount secure area on %s (%s)", getMountpoint(), strerror(errno));
568 goto out_mounted;
San Mehat3bb60202010-02-19 18:14:36 -0800569 }
570
Jeff Sharkeyba6ae8d2013-07-15 18:14:25 -0700571 /* Now that the fuse daemon is dead, unmount it */
572 if (doUnmount(getFuseMountpoint(), force) != 0) {
573 SLOGE("Failed to unmount %s (%s)", getFuseMountpoint(), strerror(errno));
574 goto fail_remount_secure;
Jeff Sharkey7a3c3d42012-10-04 16:49:22 -0700575 }
576
Jeff Sharkeyba6ae8d2013-07-15 18:14:25 -0700577 /* Unmount the real sd card */
578 if (doUnmount(getMountpoint(), force) != 0) {
579 SLOGE("Failed to unmount %s (%s)", getMountpoint(), strerror(errno));
580 goto fail_remount_secure;
San Mehat3bb60202010-02-19 18:14:36 -0800581 }
582
Jeff Sharkeyba6ae8d2013-07-15 18:14:25 -0700583 SLOGI("%s unmounted successfully", getMountpoint());
San Mehat3bb60202010-02-19 18:14:36 -0800584
Ken Sumrall0b8b5972011-08-31 16:14:23 -0700585 /* If this is an encrypted volume, and we've been asked to undo
586 * the crypto mapping, then revert the dm-crypt mapping, and revert
587 * the device info to the original values.
588 */
589 if (revert && isDecrypted()) {
590 cryptfs_revert_volume(getLabel());
591 revertDeviceInfo();
592 SLOGI("Encrypted volume %s reverted successfully", getMountpoint());
593 }
594
Jeff Sharkey0de365f2013-10-16 16:24:19 -0700595 setUuid(NULL);
596 setUserLabel(NULL);
San Mehat3bb60202010-02-19 18:14:36 -0800597 setState(Volume::State_Idle);
598 mCurrentlyMountedKdev = -1;
599 return 0;
600
Jeff Sharkeyba6ae8d2013-07-15 18:14:25 -0700601fail_remount_secure:
602 if (providesAsec && mountAsecExternal() != 0) {
603 SLOGE("Failed to remount secure area (%s)", strerror(errno));
San Mehat3bb60202010-02-19 18:14:36 -0800604 goto out_nomedia;
605 }
606
Jeff Sharkeyba6ae8d2013-07-15 18:14:25 -0700607out_mounted:
San Mehata2677e42009-12-13 10:40:18 -0800608 setState(Volume::State_Mounted);
609 return -1;
San Mehat3bb60202010-02-19 18:14:36 -0800610
611out_nomedia:
612 setState(Volume::State_NoMedia);
613 return -1;
San Mehata2677e42009-12-13 10:40:18 -0800614}
Jeff Sharkeyba6ae8d2013-07-15 18:14:25 -0700615
San Mehata2677e42009-12-13 10:40:18 -0800616int Volume::initializeMbr(const char *deviceNode) {
San Mehat2a5b8ce2010-03-10 12:48:57 -0800617 struct disk_info dinfo;
San Mehata2677e42009-12-13 10:40:18 -0800618
San Mehat2a5b8ce2010-03-10 12:48:57 -0800619 memset(&dinfo, 0, sizeof(dinfo));
620
621 if (!(dinfo.part_lst = (struct part_info *) malloc(MAX_NUM_PARTS * sizeof(struct part_info)))) {
San Mehat97ac40e2010-03-24 10:24:19 -0700622 SLOGE("Failed to malloc prt_lst");
San Mehata2677e42009-12-13 10:40:18 -0800623 return -1;
624 }
625
San Mehat2a5b8ce2010-03-10 12:48:57 -0800626 memset(dinfo.part_lst, 0, MAX_NUM_PARTS * sizeof(struct part_info));
627 dinfo.device = strdup(deviceNode);
628 dinfo.scheme = PART_SCHEME_MBR;
629 dinfo.sect_size = 512;
630 dinfo.skip_lba = 2048;
631 dinfo.num_lba = 0;
632 dinfo.num_parts = 1;
633
634 struct part_info *pinfo = &dinfo.part_lst[0];
635
636 pinfo->name = strdup("android_sdcard");
637 pinfo->flags |= PART_ACTIVE_FLAG;
638 pinfo->type = PC_PART_TYPE_FAT32;
639 pinfo->len_kb = -1;
640
641 int rc = apply_disk_config(&dinfo, 0);
642
643 if (rc) {
San Mehat97ac40e2010-03-24 10:24:19 -0700644 SLOGE("Failed to apply disk configuration (%d)", rc);
San Mehat2a5b8ce2010-03-10 12:48:57 -0800645 goto out;
San Mehata2677e42009-12-13 10:40:18 -0800646 }
647
San Mehat2a5b8ce2010-03-10 12:48:57 -0800648 out:
649 free(pinfo->name);
650 free(dinfo.device);
651 free(dinfo.part_lst);
San Mehata2677e42009-12-13 10:40:18 -0800652
San Mehat2a5b8ce2010-03-10 12:48:57 -0800653 return rc;
San Mehata2677e42009-12-13 10:40:18 -0800654}
Jeff Sharkey0de365f2013-10-16 16:24:19 -0700655
656/*
657 * Use blkid to extract UUID and label from device, since it handles many
658 * obscure edge cases around partition types and formats. Always broadcasts
659 * updated metadata values.
660 */
661int Volume::extractMetadata(const char* devicePath) {
662 int res = 0;
663
664 std::string cmd;
665 cmd = BLKID_PATH;
666 cmd += " -c /dev/null ";
667 cmd += devicePath;
668
669 FILE* fp = popen(cmd.c_str(), "r");
670 if (!fp) {
671 ALOGE("Failed to run %s: %s", cmd.c_str(), strerror(errno));
672 res = -1;
673 goto done;
674 }
675
676 char line[1024];
677 char value[128];
678 if (fgets(line, sizeof(line), fp) != NULL) {
Jeff Sharkey8c2c15b2013-10-17 15:17:19 -0700679 ALOGD("blkid identified as %s", line);
Jeff Sharkey0de365f2013-10-16 16:24:19 -0700680
Jeff Sharkey6bcd3622013-11-11 14:46:39 -0800681 char* start = strstr(line, "UUID=");
682 if (start != NULL && sscanf(start + 5, "\"%127[^\"]\"", value) == 1) {
Jeff Sharkey0de365f2013-10-16 16:24:19 -0700683 setUuid(value);
684 } else {
685 setUuid(NULL);
686 }
687
Jeff Sharkey6bcd3622013-11-11 14:46:39 -0800688 start = strstr(line, "LABEL=");
689 if (start != NULL && sscanf(start + 6, "\"%127[^\"]\"", value) == 1) {
Jeff Sharkey0de365f2013-10-16 16:24:19 -0700690 setUserLabel(value);
691 } else {
692 setUserLabel(NULL);
693 }
694 } else {
Jeff Sharkey8c2c15b2013-10-17 15:17:19 -0700695 ALOGW("blkid failed to identify %s", devicePath);
Jeff Sharkey0de365f2013-10-16 16:24:19 -0700696 res = -1;
697 }
698
699 pclose(fp);
700
701done:
702 if (res == -1) {
703 setUuid(NULL);
704 setUserLabel(NULL);
705 }
706 return res;
707}