blob: a1391e0452e8d581e23bb0ff9aebcb79c9a26190 [file] [log] [blame]
Ken Sumrallc1bf8962012-01-06 19:09:42 -08001/*
2 * Copyright (C) 2012 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
Ken Sumrallc1bf8962012-01-06 19:09:42 -080017#include <stdio.h>
18#include <stdlib.h>
19#include <string.h>
20#include <unistd.h>
21#include <fcntl.h>
22#include <ctype.h>
23#include <sys/mount.h>
24#include <sys/stat.h>
25#include <errno.h>
26#include <sys/types.h>
27#include <sys/wait.h>
28#include <libgen.h>
29#include <time.h>
Ken Sumrall5bc31a22013-07-08 19:11:55 -070030#include <sys/swap.h>
Christoffer Dall82982342014-12-17 21:26:54 +010031#include <dirent.h>
32#include <ext4.h>
33#include <ext4_sb.h>
Ken Sumrallc1bf8962012-01-06 19:09:42 -080034
Geremy Condra3ad3d1c2013-02-22 18:11:41 -080035#include <linux/loop.h>
Ken Sumrallc1bf8962012-01-06 19:09:42 -080036#include <private/android_filesystem_config.h>
JP Abgrall4bb7bba2014-06-19 22:12:20 -070037#include <cutils/android_reboot.h>
Ken Sumrallc1bf8962012-01-06 19:09:42 -080038#include <cutils/partition_utils.h>
39#include <cutils/properties.h>
Ken Sumrallbf021b42013-03-19 19:38:44 -070040#include <logwrap/logwrap.h>
Ken Sumrallc1bf8962012-01-06 19:09:42 -080041
Geremy Condra3ad3d1c2013-02-22 18:11:41 -080042#include "mincrypt/rsa.h"
43#include "mincrypt/sha.h"
44#include "mincrypt/sha256.h"
45
Ken Sumrallc1bf8962012-01-06 19:09:42 -080046#include "fs_mgr_priv.h"
Geremy Condra3ad3d1c2013-02-22 18:11:41 -080047#include "fs_mgr_priv_verity.h"
Ken Sumrallc1bf8962012-01-06 19:09:42 -080048
49#define KEY_LOC_PROP "ro.crypto.keyfile.userdata"
50#define KEY_IN_FOOTER "footer"
51
52#define E2FSCK_BIN "/system/bin/e2fsck"
JP Abgrall12351582014-06-17 17:01:14 -070053#define F2FS_FSCK_BIN "/system/bin/fsck.f2fs"
Ken Sumrall5bc31a22013-07-08 19:11:55 -070054#define MKSWAP_BIN "/system/bin/mkswap"
55
Ken Sumrall4eaf9052013-09-18 17:49:21 -070056#define FSCK_LOG_FILE "/dev/fscklogs/log"
57
Ken Sumrall5bc31a22013-07-08 19:11:55 -070058#define ZRAM_CONF_DEV "/sys/block/zram0/disksize"
Ken Sumrallc1bf8962012-01-06 19:09:42 -080059
Ken Sumrallbf021b42013-03-19 19:38:44 -070060#define ARRAY_SIZE(a) (sizeof(a) / sizeof(*(a)))
61
Ken Sumrallc1bf8962012-01-06 19:09:42 -080062/*
63 * gettime() - returns the time in seconds of the system's monotonic clock or
64 * zero on error.
65 */
66static time_t gettime(void)
67{
68 struct timespec ts;
69 int ret;
70
71 ret = clock_gettime(CLOCK_MONOTONIC, &ts);
72 if (ret < 0) {
73 ERROR("clock_gettime(CLOCK_MONOTONIC) failed: %s\n", strerror(errno));
74 return 0;
75 }
76
77 return ts.tv_sec;
78}
79
80static int wait_for_file(const char *filename, int timeout)
81{
82 struct stat info;
83 time_t timeout_time = gettime() + timeout;
84 int ret = -1;
85
86 while (gettime() < timeout_time && ((ret = stat(filename, &info)) < 0))
87 usleep(10000);
88
89 return ret;
90}
91
Ken Sumrallab6b8522013-02-13 12:58:40 -080092static void check_fs(char *blk_device, char *fs_type, char *target)
Ken Sumrallc1bf8962012-01-06 19:09:42 -080093{
Ken Sumrallc1bf8962012-01-06 19:09:42 -080094 int status;
Ken Sumrall5dc5bfe2012-07-23 19:34:00 -070095 int ret;
96 long tmpmnt_flags = MS_NOATIME | MS_NOEXEC | MS_NOSUID;
97 char *tmpmnt_opts = "nomblk_io_submit,errors=remount-ro";
Ken Sumrallbf021b42013-03-19 19:38:44 -070098 char *e2fsck_argv[] = {
99 E2FSCK_BIN,
100 "-y",
101 blk_device
102 };
Ken Sumrallc1bf8962012-01-06 19:09:42 -0800103
104 /* Check for the types of filesystems we know how to check */
Ken Sumrallab6b8522013-02-13 12:58:40 -0800105 if (!strcmp(fs_type, "ext2") || !strcmp(fs_type, "ext3") || !strcmp(fs_type, "ext4")) {
Ken Sumrall5dc5bfe2012-07-23 19:34:00 -0700106 /*
107 * First try to mount and unmount the filesystem. We do this because
108 * the kernel is more efficient than e2fsck in running the journal and
109 * processing orphaned inodes, and on at least one device with a
110 * performance issue in the emmc firmware, it can take e2fsck 2.5 minutes
111 * to do what the kernel does in about a second.
112 *
113 * After mounting and unmounting the filesystem, run e2fsck, and if an
114 * error is recorded in the filesystem superblock, e2fsck will do a full
115 * check. Otherwise, it does nothing. If the kernel cannot mount the
116 * filesytsem due to an error, e2fsck is still run to do a full check
117 * fix the filesystem.
118 */
Ken Sumrallab6b8522013-02-13 12:58:40 -0800119 ret = mount(blk_device, target, fs_type, tmpmnt_flags, tmpmnt_opts);
JP Abgrall5c01dac2014-06-18 14:54:37 -0700120 INFO("%s(): mount(%s,%s,%s)=%d\n", __func__, blk_device, target, fs_type, ret);
Ken Sumrallab6b8522013-02-13 12:58:40 -0800121 if (!ret) {
Nick Kralevich7294eb62015-02-05 16:02:42 -0800122 int i;
123 for (i = 0; i < 5; i++) {
124 // Try to umount 5 times before continuing on.
125 // Should we try rebooting if all attempts fail?
126 int result = umount(target);
127 if (result == 0) {
128 break;
129 }
130 ERROR("%s(): umount(%s)=%d: %s\n", __func__, target, result, strerror(errno));
131 sleep(1);
132 }
Ken Sumrall5dc5bfe2012-07-23 19:34:00 -0700133 }
134
David 'Digit' Turner28483d72014-02-17 11:14:44 +0100135 /*
136 * Some system images do not have e2fsck for licensing reasons
137 * (e.g. recent SDK system images). Detect these and skip the check.
138 */
139 if (access(E2FSCK_BIN, X_OK)) {
140 INFO("Not running %s on %s (executable not in system image)\n",
141 E2FSCK_BIN, blk_device);
142 } else {
143 INFO("Running %s on %s\n", E2FSCK_BIN, blk_device);
Ken Sumrallc1bf8962012-01-06 19:09:42 -0800144
David 'Digit' Turner28483d72014-02-17 11:14:44 +0100145 ret = android_fork_execvp_ext(ARRAY_SIZE(e2fsck_argv), e2fsck_argv,
146 &status, true, LOG_KLOG | LOG_FILE,
147 true, FSCK_LOG_FILE);
Ken Sumrallbf021b42013-03-19 19:38:44 -0700148
David 'Digit' Turner28483d72014-02-17 11:14:44 +0100149 if (ret < 0) {
150 /* No need to check for error in fork, we can't really handle it now */
151 ERROR("Failed trying to run %s\n", E2FSCK_BIN);
152 }
Ken Sumrallc1bf8962012-01-06 19:09:42 -0800153 }
JP Abgrall12351582014-06-17 17:01:14 -0700154 } else if (!strcmp(fs_type, "f2fs")) {
155 char *f2fs_fsck_argv[] = {
156 F2FS_FSCK_BIN,
157 blk_device
158 };
159 INFO("Running %s on %s\n", F2FS_FSCK_BIN, blk_device);
160
161 ret = android_fork_execvp_ext(ARRAY_SIZE(f2fs_fsck_argv), f2fs_fsck_argv,
162 &status, true, LOG_KLOG | LOG_FILE,
163 true, FSCK_LOG_FILE);
164 if (ret < 0) {
165 /* No need to check for error in fork, we can't really handle it now */
166 ERROR("Failed trying to run %s\n", F2FS_FSCK_BIN);
167 }
Ken Sumrallc1bf8962012-01-06 19:09:42 -0800168 }
169
170 return;
171}
172
173static void remove_trailing_slashes(char *n)
174{
175 int len;
176
177 len = strlen(n) - 1;
178 while ((*(n + len) == '/') && len) {
179 *(n + len) = '\0';
180 len--;
181 }
182}
183
Nick Kraleviche18c0d52013-04-16 16:41:32 -0700184/*
185 * Mark the given block device as read-only, using the BLKROSET ioctl.
186 * Return 0 on success, and -1 on error.
187 */
188static void fs_set_blk_ro(const char *blockdev)
189{
190 int fd;
191 int ON = 1;
192
193 fd = open(blockdev, O_RDONLY);
194 if (fd < 0) {
195 // should never happen
196 return;
197 }
198
199 ioctl(fd, BLKROSET, &ON);
200 close(fd);
201}
202
203/*
204 * __mount(): wrapper around the mount() system call which also
205 * sets the underlying block device to read-only if the mount is read-only.
206 * See "man 2 mount" for return values.
207 */
JP Abgrall5c01dac2014-06-18 14:54:37 -0700208static int __mount(const char *source, const char *target, const struct fstab_rec *rec)
Nick Kraleviche18c0d52013-04-16 16:41:32 -0700209{
JP Abgrall5c01dac2014-06-18 14:54:37 -0700210 unsigned long mountflags = rec->flags;
211 int ret;
212 int save_errno;
Daniel Rosenbergf67d6bd2014-06-26 14:55:04 -0700213
214 /* We need this because sometimes we have legacy symlinks
215 * that are lingering around and need cleaning up.
216 */
217 struct stat info;
218 if (!lstat(target, &info))
219 if ((info.st_mode & S_IFMT) == S_IFLNK)
220 unlink(target);
Daniel Rosenbergf530c932014-05-28 14:10:01 -0700221 mkdir(target, 0755);
JP Abgrall5c01dac2014-06-18 14:54:37 -0700222 ret = mount(source, target, rec->fs_type, mountflags, rec->fs_options);
223 save_errno = errno;
224 INFO("%s(source=%s,target=%s,type=%s)=%d\n", __func__, source, target, rec->fs_type, ret);
Nick Kraleviche18c0d52013-04-16 16:41:32 -0700225 if ((ret == 0) && (mountflags & MS_RDONLY) != 0) {
226 fs_set_blk_ro(source);
227 }
JP Abgrall5c01dac2014-06-18 14:54:37 -0700228 errno = save_errno;
Nick Kraleviche18c0d52013-04-16 16:41:32 -0700229 return ret;
230}
231
Ken Sumrallc1bf8962012-01-06 19:09:42 -0800232static int fs_match(char *in1, char *in2)
233{
234 char *n1;
235 char *n2;
236 int ret;
237
238 n1 = strdup(in1);
239 n2 = strdup(in2);
240
241 remove_trailing_slashes(n1);
242 remove_trailing_slashes(n2);
243
244 ret = !strcmp(n1, n2);
245
246 free(n1);
247 free(n2);
248
249 return ret;
250}
251
Geremy Condracd642fc2014-04-02 13:42:06 -0700252static int device_is_debuggable() {
253 int ret = -1;
254 char value[PROP_VALUE_MAX];
255 ret = __system_property_get("ro.debuggable", value);
256 if (ret < 0)
257 return ret;
258 return strcmp(value, "1") ? 0 : 1;
259}
260
Paul Lawrenceec900bb2014-10-09 14:22:49 +0000261static int device_is_secure() {
262 int ret = -1;
263 char value[PROP_VALUE_MAX];
264 ret = __system_property_get("ro.secure", value);
265 /* If error, we want to fail secure */
266 if (ret < 0)
267 return 1;
268 return strcmp(value, "0") ? 1 : 0;
269}
270
Paul Lawrence2f7ee6b2015-01-07 11:44:51 -0800271static int device_is_force_encrypted() {
272 int ret = -1;
273 char value[PROP_VALUE_MAX];
274 ret = __system_property_get("ro.vold.forceencryption", value);
275 if (ret < 0)
276 return 0;
277 return strcmp(value, "1") ? 0 : 1;
278}
279
JP Abgrallf22b7452014-07-02 13:16:04 -0700280/*
281 * Tries to mount any of the consecutive fstab entries that match
282 * the mountpoint of the one given by fstab->recs[start_idx].
283 *
284 * end_idx: On return, will be the last rec that was looked at.
285 * attempted_idx: On return, will indicate which fstab rec
286 * succeeded. In case of failure, it will be the start_idx.
287 * Returns
288 * -1 on failure with errno set to match the 1st mount failure.
289 * 0 on success.
290 */
291static int mount_with_alternatives(struct fstab *fstab, int start_idx, int *end_idx, int *attempted_idx)
JP Abgrall4bb7bba2014-06-19 22:12:20 -0700292{
JP Abgrallf22b7452014-07-02 13:16:04 -0700293 int i;
294 int mount_errno = 0;
295 int mounted = 0;
296
297 if (!end_idx || !attempted_idx || start_idx >= fstab->num_entries) {
298 errno = EINVAL;
299 if (end_idx) *end_idx = start_idx;
300 if (attempted_idx) *end_idx = start_idx;
301 return -1;
JP Abgrall4bb7bba2014-06-19 22:12:20 -0700302 }
JP Abgrallf22b7452014-07-02 13:16:04 -0700303
304 /* Hunt down an fstab entry for the same mount point that might succeed */
305 for (i = start_idx;
306 /* We required that fstab entries for the same mountpoint be consecutive */
307 i < fstab->num_entries && !strcmp(fstab->recs[start_idx].mount_point, fstab->recs[i].mount_point);
308 i++) {
309 /*
310 * Don't try to mount/encrypt the same mount point again.
311 * Deal with alternate entries for the same point which are required to be all following
312 * each other.
313 */
314 if (mounted) {
315 ERROR("%s(): skipping fstab dup mountpoint=%s rec[%d].fs_type=%s already mounted as %s.\n", __func__,
316 fstab->recs[i].mount_point, i, fstab->recs[i].fs_type, fstab->recs[*attempted_idx].fs_type);
317 continue;
318 }
319
320 if (fstab->recs[i].fs_mgr_flags & MF_CHECK) {
321 check_fs(fstab->recs[i].blk_device, fstab->recs[i].fs_type,
322 fstab->recs[i].mount_point);
323 }
324 if (!__mount(fstab->recs[i].blk_device, fstab->recs[i].mount_point, &fstab->recs[i])) {
325 *attempted_idx = i;
326 mounted = 1;
327 if (i != start_idx) {
328 ERROR("%s(): Mounted %s on %s with fs_type=%s instead of %s\n", __func__,
329 fstab->recs[i].blk_device, fstab->recs[i].mount_point, fstab->recs[i].fs_type,
330 fstab->recs[start_idx].fs_type);
331 }
332 } else {
333 /* back up errno for crypto decisions */
334 mount_errno = errno;
335 }
336 }
337
338 /* Adjust i for the case where it was still withing the recs[] */
339 if (i < fstab->num_entries) --i;
340
341 *end_idx = i;
342 if (!mounted) {
343 *attempted_idx = start_idx;
344 errno = mount_errno;
345 return -1;
346 }
347 return 0;
JP Abgrall4bb7bba2014-06-19 22:12:20 -0700348}
349
Christoffer Dall82982342014-12-17 21:26:54 +0100350static int translate_ext_labels(struct fstab_rec *rec)
351{
352 DIR *blockdir = NULL;
353 struct dirent *ent;
354 char *label;
355 size_t label_len;
356 int ret = -1;
357
358 if (strncmp(rec->blk_device, "LABEL=", 6))
359 return 0;
360
361 label = rec->blk_device + 6;
362 label_len = strlen(label);
363
364 if (label_len > 16) {
365 ERROR("FS label is longer than allowed by filesystem\n");
366 goto out;
367 }
368
369
370 blockdir = opendir("/dev/block");
371 if (!blockdir) {
372 ERROR("couldn't open /dev/block\n");
373 goto out;
374 }
375
376 while ((ent = readdir(blockdir))) {
377 int fd;
378 char super_buf[1024];
379 struct ext4_super_block *sb;
380
381 if (ent->d_type != DT_BLK)
382 continue;
383
384 fd = openat(dirfd(blockdir), ent->d_name, O_RDONLY);
385 if (fd < 0) {
386 ERROR("Cannot open block device /dev/block/%s\n", ent->d_name);
387 goto out;
388 }
389
390 if (TEMP_FAILURE_RETRY(lseek(fd, 1024, SEEK_SET)) < 0 ||
391 TEMP_FAILURE_RETRY(read(fd, super_buf, 1024)) != 1024) {
392 /* Probably a loopback device or something else without a readable
393 * superblock.
394 */
395 close(fd);
396 continue;
397 }
398
399 sb = (struct ext4_super_block *)super_buf;
400 if (sb->s_magic != EXT4_SUPER_MAGIC) {
401 INFO("/dev/block/%s not ext{234}\n", ent->d_name);
402 continue;
403 }
404
405 if (!strncmp(label, sb->s_volume_name, label_len)) {
406 char *new_blk_device;
407
408 if (asprintf(&new_blk_device, "/dev/block/%s", ent->d_name) < 0) {
409 ERROR("Could not allocate block device string\n");
410 goto out;
411 }
412
413 INFO("resolved label %s to %s\n", rec->blk_device, new_blk_device);
414
415 free(rec->blk_device);
416 rec->blk_device = new_blk_device;
417 ret = 0;
418 break;
419 }
420 }
421
422out:
423 closedir(blockdir);
424 return ret;
425}
426
JP Abgrall5c01dac2014-06-18 14:54:37 -0700427/* When multiple fstab records share the same mount_point, it will
428 * try to mount each one in turn, and ignore any duplicates after a
429 * first successful mount.
JP Abgrallf22b7452014-07-02 13:16:04 -0700430 * Returns -1 on error, and FS_MGR_MNTALL_* otherwise.
JP Abgrall5c01dac2014-06-18 14:54:37 -0700431 */
Ken Sumrallab6b8522013-02-13 12:58:40 -0800432int fs_mgr_mount_all(struct fstab *fstab)
Ken Sumrallc1bf8962012-01-06 19:09:42 -0800433{
JP Abgrallf22b7452014-07-02 13:16:04 -0700434 int i = 0;
435 int encryptable = FS_MGR_MNTALL_DEV_NOT_ENCRYPTED;
Mohamad Ayyash38afe5f2014-03-10 15:40:29 -0700436 int error_count = 0;
JP Abgrall5c01dac2014-06-18 14:54:37 -0700437 int mret = -1;
438 int mount_errno = 0;
JP Abgrallf22b7452014-07-02 13:16:04 -0700439 int attempted_idx = -1;
Ken Sumrallc1bf8962012-01-06 19:09:42 -0800440
Ken Sumrallab6b8522013-02-13 12:58:40 -0800441 if (!fstab) {
Mohamad Ayyash38afe5f2014-03-10 15:40:29 -0700442 return -1;
Ken Sumrallc1bf8962012-01-06 19:09:42 -0800443 }
444
Ken Sumrallab6b8522013-02-13 12:58:40 -0800445 for (i = 0; i < fstab->num_entries; i++) {
446 /* Don't mount entries that are managed by vold */
Ken Sumrall6c2c1212013-02-22 17:36:21 -0800447 if (fstab->recs[i].fs_mgr_flags & (MF_VOLDMANAGED | MF_RECOVERYONLY)) {
Ken Sumrallab6b8522013-02-13 12:58:40 -0800448 continue;
Ken Sumrallc1bf8962012-01-06 19:09:42 -0800449 }
450
Ken Sumrall5bc31a22013-07-08 19:11:55 -0700451 /* Skip swap and raw partition entries such as boot, recovery, etc */
452 if (!strcmp(fstab->recs[i].fs_type, "swap") ||
453 !strcmp(fstab->recs[i].fs_type, "emmc") ||
Ken Sumrallab6b8522013-02-13 12:58:40 -0800454 !strcmp(fstab->recs[i].fs_type, "mtd")) {
455 continue;
Ken Sumrallc1bf8962012-01-06 19:09:42 -0800456 }
457
Christoffer Dall82982342014-12-17 21:26:54 +0100458 /* Translate LABEL= file system labels into block devices */
459 if (!strcmp(fstab->recs[i].fs_type, "ext2") ||
460 !strcmp(fstab->recs[i].fs_type, "ext3") ||
461 !strcmp(fstab->recs[i].fs_type, "ext4")) {
462 int tret = translate_ext_labels(&fstab->recs[i]);
463 if (tret < 0) {
464 ERROR("Could not translate label to block device\n");
465 continue;
466 }
467 }
468
Ken Sumrallab6b8522013-02-13 12:58:40 -0800469 if (fstab->recs[i].fs_mgr_flags & MF_WAIT) {
470 wait_for_file(fstab->recs[i].blk_device, WAIT_TIMEOUT);
471 }
472
Paul Lawrenceec900bb2014-10-09 14:22:49 +0000473 if ((fstab->recs[i].fs_mgr_flags & MF_VERIFY) && device_is_secure()) {
474 int rc = fs_mgr_setup_verity(&fstab->recs[i]);
475 if (device_is_debuggable() && rc == FS_MGR_SETUP_VERITY_DISABLED) {
476 INFO("Verity disabled");
477 } else if (rc != FS_MGR_SETUP_VERITY_SUCCESS) {
JP Abgrall4bb7bba2014-06-19 22:12:20 -0700478 ERROR("Could not set up verified partition, skipping!\n");
Geremy Condra3ad3d1c2013-02-22 18:11:41 -0800479 continue;
480 }
481 }
JP Abgrallf22b7452014-07-02 13:16:04 -0700482 int last_idx_inspected;
483 mret = mount_with_alternatives(fstab, i, &last_idx_inspected, &attempted_idx);
484 i = last_idx_inspected;
485 mount_errno = errno;
JP Abgrallf786fe52014-06-18 07:28:14 +0000486
JP Abgrall5c01dac2014-06-18 14:54:37 -0700487 /* Deal with encryptability. */
Ken Sumrallc1bf8962012-01-06 19:09:42 -0800488 if (!mret) {
Paul Lawrence166fa3d2014-02-03 13:27:49 -0800489 /* If this is encryptable, need to trigger encryption */
Paul Lawrence36d0eae2015-01-21 09:57:01 -0800490 if (fs_mgr_is_encryptable(&fstab->recs[attempted_idx])) {
JP Abgrallf22b7452014-07-02 13:16:04 -0700491 if (umount(fstab->recs[attempted_idx].mount_point) == 0) {
492 if (encryptable == FS_MGR_MNTALL_DEV_NOT_ENCRYPTED) {
493 ERROR("Will try to encrypt %s %s\n", fstab->recs[attempted_idx].mount_point,
494 fstab->recs[attempted_idx].fs_type);
495 encryptable = FS_MGR_MNTALL_DEV_NEEDS_ENCRYPTION;
Paul Lawrence166fa3d2014-02-03 13:27:49 -0800496 } else {
JP Abgrall4bb7bba2014-06-19 22:12:20 -0700497 ERROR("Only one encryptable/encrypted partition supported\n");
JP Abgrallf22b7452014-07-02 13:16:04 -0700498 encryptable = FS_MGR_MNTALL_DEV_MIGHT_BE_ENCRYPTED;
Paul Lawrence166fa3d2014-02-03 13:27:49 -0800499 }
500 } else {
Nick Kralevich7294eb62015-02-05 16:02:42 -0800501 WARNING("Could not umount %s (%s) - allow continue unencrypted\n",
502 fstab->recs[attempted_idx].mount_point, strerror(errno));
Paul Lawrence166fa3d2014-02-03 13:27:49 -0800503 continue;
504 }
505 }
Ken Sumrallc1bf8962012-01-06 19:09:42 -0800506 /* Success! Go get the next one */
507 continue;
508 }
509
Mohamad Ayyash38afe5f2014-03-10 15:40:29 -0700510 /* mount(2) returned an error, check if it's encryptable and deal with it */
JP Abgrall5c01dac2014-06-18 14:54:37 -0700511 if (mret && mount_errno != EBUSY && mount_errno != EACCES &&
JP Abgrallcee20682014-07-02 14:26:54 -0700512 fs_mgr_is_encryptable(&fstab->recs[attempted_idx])) {
513 if(partition_wiped(fstab->recs[attempted_idx].blk_device)) {
514 ERROR("%s(): %s is wiped and %s %s is encryptable. Suggest recovery...\n", __func__,
515 fstab->recs[attempted_idx].blk_device, fstab->recs[attempted_idx].mount_point,
516 fstab->recs[attempted_idx].fs_type);
517 encryptable = FS_MGR_MNTALL_DEV_NEEDS_RECOVERY;
Mohamad Ayyash38afe5f2014-03-10 15:40:29 -0700518 continue;
JP Abgrall4bb7bba2014-06-19 22:12:20 -0700519 } else {
520 /* Need to mount a tmpfs at this mountpoint for now, and set
521 * properties that vold will query later for decrypting
522 */
JP Abgrallf22b7452014-07-02 13:16:04 -0700523 ERROR("%s(): possibly an encryptable blkdev %s for mount %s type %s )\n", __func__,
524 fstab->recs[attempted_idx].blk_device, fstab->recs[attempted_idx].mount_point,
525 fstab->recs[attempted_idx].fs_type);
526 if (fs_mgr_do_tmpfs_mount(fstab->recs[attempted_idx].mount_point) < 0) {
JP Abgrall4bb7bba2014-06-19 22:12:20 -0700527 ++error_count;
528 continue;
529 }
Ken Sumrallc1bf8962012-01-06 19:09:42 -0800530 }
JP Abgrallf22b7452014-07-02 13:16:04 -0700531 encryptable = FS_MGR_MNTALL_DEV_MIGHT_BE_ENCRYPTED;
Ken Sumrallc1bf8962012-01-06 19:09:42 -0800532 } else {
William Roberts071f28a2014-01-14 14:33:44 -0500533 ERROR("Failed to mount an un-encryptable or wiped partition on"
Mohamad Ayyash38afe5f2014-03-10 15:40:29 -0700534 "%s at %s options: %s error: %s\n",
JP Abgrallf22b7452014-07-02 13:16:04 -0700535 fstab->recs[attempted_idx].blk_device, fstab->recs[attempted_idx].mount_point,
536 fstab->recs[attempted_idx].fs_options, strerror(mount_errno));
Mohamad Ayyash38afe5f2014-03-10 15:40:29 -0700537 ++error_count;
538 continue;
Ken Sumrallc1bf8962012-01-06 19:09:42 -0800539 }
540 }
541
Mohamad Ayyash38afe5f2014-03-10 15:40:29 -0700542 if (error_count) {
543 return -1;
Mohamad Ayyash38afe5f2014-03-10 15:40:29 -0700544 } else {
Paul Lawrence166fa3d2014-02-03 13:27:49 -0800545 return encryptable;
Mohamad Ayyash38afe5f2014-03-10 15:40:29 -0700546 }
Ken Sumrallc1bf8962012-01-06 19:09:42 -0800547}
548
Ken Sumrallab6b8522013-02-13 12:58:40 -0800549/* If tmp_mount_point is non-null, mount the filesystem there. This is for the
Ken Sumrallc1bf8962012-01-06 19:09:42 -0800550 * tmp mount we do to check the user password
JP Abgrall5c01dac2014-06-18 14:54:37 -0700551 * If multiple fstab entries are to be mounted on "n_name", it will try to mount each one
552 * in turn, and stop on 1st success, or no more match.
Ken Sumrallc1bf8962012-01-06 19:09:42 -0800553 */
Ken Sumrallab6b8522013-02-13 12:58:40 -0800554int fs_mgr_do_mount(struct fstab *fstab, char *n_name, char *n_blk_device,
555 char *tmp_mount_point)
Ken Sumrallc1bf8962012-01-06 19:09:42 -0800556{
557 int i = 0;
Paul Lawrencecf234dc2014-09-09 10:44:51 -0700558 int ret = FS_MGR_DOMNT_FAILED;
JP Abgrall5c01dac2014-06-18 14:54:37 -0700559 int mount_errors = 0;
560 int first_mount_errno = 0;
Ken Sumrallc1bf8962012-01-06 19:09:42 -0800561 char *m;
562
Ken Sumrallab6b8522013-02-13 12:58:40 -0800563 if (!fstab) {
Ken Sumrallc1bf8962012-01-06 19:09:42 -0800564 return ret;
565 }
566
Ken Sumrallab6b8522013-02-13 12:58:40 -0800567 for (i = 0; i < fstab->num_entries; i++) {
568 if (!fs_match(fstab->recs[i].mount_point, n_name)) {
Ken Sumrallc1bf8962012-01-06 19:09:42 -0800569 continue;
570 }
571
572 /* We found our match */
Ken Sumrall5bc31a22013-07-08 19:11:55 -0700573 /* If this swap or a raw partition, report an error */
574 if (!strcmp(fstab->recs[i].fs_type, "swap") ||
575 !strcmp(fstab->recs[i].fs_type, "emmc") ||
Ken Sumrallab6b8522013-02-13 12:58:40 -0800576 !strcmp(fstab->recs[i].fs_type, "mtd")) {
577 ERROR("Cannot mount filesystem of type %s on %s\n",
578 fstab->recs[i].fs_type, n_blk_device);
579 goto out;
Ken Sumrallc1bf8962012-01-06 19:09:42 -0800580 }
581
Ken Sumrallab6b8522013-02-13 12:58:40 -0800582 /* First check the filesystem if requested */
583 if (fstab->recs[i].fs_mgr_flags & MF_WAIT) {
584 wait_for_file(n_blk_device, WAIT_TIMEOUT);
585 }
586
587 if (fstab->recs[i].fs_mgr_flags & MF_CHECK) {
588 check_fs(n_blk_device, fstab->recs[i].fs_type,
589 fstab->recs[i].mount_point);
Ken Sumrallc1bf8962012-01-06 19:09:42 -0800590 }
591
Paul Lawrenceec900bb2014-10-09 14:22:49 +0000592 if ((fstab->recs[i].fs_mgr_flags & MF_VERIFY) && device_is_secure()) {
593 int rc = fs_mgr_setup_verity(&fstab->recs[i]);
594 if (device_is_debuggable() && rc == FS_MGR_SETUP_VERITY_DISABLED) {
595 INFO("Verity disabled");
596 } else if (rc != FS_MGR_SETUP_VERITY_SUCCESS) {
JP Abgrall4bb7bba2014-06-19 22:12:20 -0700597 ERROR("Could not set up verified partition, skipping!\n");
Geremy Condra3ad3d1c2013-02-22 18:11:41 -0800598 continue;
599 }
600 }
601
Ken Sumrallc1bf8962012-01-06 19:09:42 -0800602 /* Now mount it where requested */
Ken Sumrallab6b8522013-02-13 12:58:40 -0800603 if (tmp_mount_point) {
604 m = tmp_mount_point;
Ken Sumrallc1bf8962012-01-06 19:09:42 -0800605 } else {
Ken Sumrallab6b8522013-02-13 12:58:40 -0800606 m = fstab->recs[i].mount_point;
Ken Sumrallc1bf8962012-01-06 19:09:42 -0800607 }
JP Abgrall5c01dac2014-06-18 14:54:37 -0700608 if (__mount(n_blk_device, m, &fstab->recs[i])) {
609 if (!first_mount_errno) first_mount_errno = errno;
610 mount_errors++;
611 continue;
Ken Sumrallc1bf8962012-01-06 19:09:42 -0800612 } else {
613 ret = 0;
614 goto out;
615 }
616 }
JP Abgrall5c01dac2014-06-18 14:54:37 -0700617 if (mount_errors) {
618 ERROR("Cannot mount filesystem on %s at %s. error: %s\n",
619 n_blk_device, m, strerror(first_mount_errno));
Paul Lawrencecf234dc2014-09-09 10:44:51 -0700620 if (first_mount_errno == EBUSY) {
621 ret = FS_MGR_DOMNT_BUSY;
622 } else {
623 ret = FS_MGR_DOMNT_FAILED;
624 }
JP Abgrall5c01dac2014-06-18 14:54:37 -0700625 } else {
626 /* We didn't find a match, say so and return an error */
627 ERROR("Cannot find mount point %s in fstab\n", fstab->recs[i].mount_point);
628 }
Ken Sumrallc1bf8962012-01-06 19:09:42 -0800629
630out:
Ken Sumrallc1bf8962012-01-06 19:09:42 -0800631 return ret;
632}
633
634/*
635 * mount a tmpfs filesystem at the given point.
636 * return 0 on success, non-zero on failure.
637 */
638int fs_mgr_do_tmpfs_mount(char *n_name)
639{
640 int ret;
641
642 ret = mount("tmpfs", n_name, "tmpfs",
643 MS_NOATIME | MS_NOSUID | MS_NODEV, CRYPTO_TMPFS_OPTIONS);
644 if (ret < 0) {
645 ERROR("Cannot mount tmpfs filesystem at %s\n", n_name);
646 return -1;
647 }
648
649 /* Success */
650 return 0;
651}
652
Ken Sumrallab6b8522013-02-13 12:58:40 -0800653int fs_mgr_unmount_all(struct fstab *fstab)
Ken Sumrallc1bf8962012-01-06 19:09:42 -0800654{
655 int i = 0;
656 int ret = 0;
Ken Sumrallc1bf8962012-01-06 19:09:42 -0800657
Ken Sumrallab6b8522013-02-13 12:58:40 -0800658 if (!fstab) {
Ken Sumrallc1bf8962012-01-06 19:09:42 -0800659 return -1;
660 }
661
Ken Sumrallab6b8522013-02-13 12:58:40 -0800662 while (fstab->recs[i].blk_device) {
663 if (umount(fstab->recs[i].mount_point)) {
664 ERROR("Cannot unmount filesystem at %s\n", fstab->recs[i].mount_point);
Ken Sumrallc1bf8962012-01-06 19:09:42 -0800665 ret = -1;
666 }
667 i++;
668 }
669
Ken Sumrallc1bf8962012-01-06 19:09:42 -0800670 return ret;
671}
Ken Sumrall5bc31a22013-07-08 19:11:55 -0700672
673/* This must be called after mount_all, because the mkswap command needs to be
674 * available.
675 */
676int fs_mgr_swapon_all(struct fstab *fstab)
677{
678 int i = 0;
679 int flags = 0;
680 int err = 0;
681 int ret = 0;
682 int status;
683 char *mkswap_argv[2] = {
684 MKSWAP_BIN,
685 NULL
686 };
687
688 if (!fstab) {
689 return -1;
690 }
691
692 for (i = 0; i < fstab->num_entries; i++) {
693 /* Skip non-swap entries */
694 if (strcmp(fstab->recs[i].fs_type, "swap")) {
695 continue;
696 }
697
698 if (fstab->recs[i].zram_size > 0) {
699 /* A zram_size was specified, so we need to configure the
700 * device. There is no point in having multiple zram devices
701 * on a system (all the memory comes from the same pool) so
702 * we can assume the device number is 0.
703 */
704 FILE *zram_fp;
705
706 zram_fp = fopen(ZRAM_CONF_DEV, "r+");
707 if (zram_fp == NULL) {
JP Abgrall4bb7bba2014-06-19 22:12:20 -0700708 ERROR("Unable to open zram conf device %s\n", ZRAM_CONF_DEV);
Ken Sumrall5bc31a22013-07-08 19:11:55 -0700709 ret = -1;
710 continue;
711 }
712 fprintf(zram_fp, "%d\n", fstab->recs[i].zram_size);
713 fclose(zram_fp);
714 }
715
716 if (fstab->recs[i].fs_mgr_flags & MF_WAIT) {
717 wait_for_file(fstab->recs[i].blk_device, WAIT_TIMEOUT);
718 }
719
720 /* Initialize the swap area */
721 mkswap_argv[1] = fstab->recs[i].blk_device;
722 err = android_fork_execvp_ext(ARRAY_SIZE(mkswap_argv), mkswap_argv,
Ken Sumrall4eaf9052013-09-18 17:49:21 -0700723 &status, true, LOG_KLOG, false, NULL);
Ken Sumrall5bc31a22013-07-08 19:11:55 -0700724 if (err) {
725 ERROR("mkswap failed for %s\n", fstab->recs[i].blk_device);
726 ret = -1;
727 continue;
728 }
729
730 /* If -1, then no priority was specified in fstab, so don't set
731 * SWAP_FLAG_PREFER or encode the priority */
732 if (fstab->recs[i].swap_prio >= 0) {
733 flags = (fstab->recs[i].swap_prio << SWAP_FLAG_PRIO_SHIFT) &
734 SWAP_FLAG_PRIO_MASK;
735 flags |= SWAP_FLAG_PREFER;
736 } else {
737 flags = 0;
738 }
739 err = swapon(fstab->recs[i].blk_device, flags);
740 if (err) {
741 ERROR("swapon failed for %s\n", fstab->recs[i].blk_device);
742 ret = -1;
743 }
744 }
745
746 return ret;
747}
748
Ken Sumrallc1bf8962012-01-06 19:09:42 -0800749/*
750 * key_loc must be at least PROPERTY_VALUE_MAX bytes long
751 *
Ken Sumrallab6b8522013-02-13 12:58:40 -0800752 * real_blk_device must be at least PROPERTY_VALUE_MAX bytes long
Ken Sumrallc1bf8962012-01-06 19:09:42 -0800753 */
Ken Sumrallab6b8522013-02-13 12:58:40 -0800754int fs_mgr_get_crypt_info(struct fstab *fstab, char *key_loc, char *real_blk_device, int size)
Ken Sumrallc1bf8962012-01-06 19:09:42 -0800755{
756 int i = 0;
Ken Sumrallc1bf8962012-01-06 19:09:42 -0800757
Ken Sumrallab6b8522013-02-13 12:58:40 -0800758 if (!fstab) {
Ken Sumrallc1bf8962012-01-06 19:09:42 -0800759 return -1;
760 }
761 /* Initialize return values to null strings */
762 if (key_loc) {
763 *key_loc = '\0';
764 }
Ken Sumrallab6b8522013-02-13 12:58:40 -0800765 if (real_blk_device) {
766 *real_blk_device = '\0';
Ken Sumrallc1bf8962012-01-06 19:09:42 -0800767 }
768
769 /* Look for the encryptable partition to find the data */
Ken Sumrallab6b8522013-02-13 12:58:40 -0800770 for (i = 0; i < fstab->num_entries; i++) {
771 /* Don't deal with vold managed enryptable partitions here */
772 if (fstab->recs[i].fs_mgr_flags & MF_VOLDMANAGED) {
773 continue;
774 }
Paul Lawrence2e5ae0a2014-04-04 09:34:19 -0700775 if (!(fstab->recs[i].fs_mgr_flags & (MF_CRYPT | MF_FORCECRYPT))) {
Ken Sumrallc1bf8962012-01-06 19:09:42 -0800776 continue;
777 }
778
779 /* We found a match */
780 if (key_loc) {
Ken Sumrallab6b8522013-02-13 12:58:40 -0800781 strlcpy(key_loc, fstab->recs[i].key_loc, size);
Ken Sumrallc1bf8962012-01-06 19:09:42 -0800782 }
Ken Sumrallab6b8522013-02-13 12:58:40 -0800783 if (real_blk_device) {
784 strlcpy(real_blk_device, fstab->recs[i].blk_device, size);
Ken Sumrallc1bf8962012-01-06 19:09:42 -0800785 }
786 break;
787 }
788
Ken Sumrallc1bf8962012-01-06 19:09:42 -0800789 return 0;
790}