blob: 9aab0bac4b72f1b14d7607dd0e10fa4fd46dda78 [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
Mattias Nissler097b6bb2016-03-31 16:32:09 +020017#include <ctype.h>
18#include <dirent.h>
19#include <errno.h>
20#include <fcntl.h>
21#include <libgen.h>
Ken Sumrallc1bf8962012-01-06 19:09:42 -080022#include <stdio.h>
23#include <stdlib.h>
24#include <string.h>
liminghao9a0fd1d2016-07-22 11:48:14 +080025#include <sys/ioctl.h>
Ken Sumrallc1bf8962012-01-06 19:09:42 -080026#include <sys/mount.h>
27#include <sys/stat.h>
Mattias Nissler097b6bb2016-03-31 16:32:09 +020028#include <sys/swap.h>
Ken Sumrallc1bf8962012-01-06 19:09:42 -080029#include <sys/types.h>
30#include <sys/wait.h>
Ken Sumrallc1bf8962012-01-06 19:09:42 -080031#include <time.h>
Mattias Nissler097b6bb2016-03-31 16:32:09 +020032#include <unistd.h>
Ken Sumrallc1bf8962012-01-06 19:09:42 -080033
Bowgo Tsaiaaf70e72017-03-02 00:03:56 +080034#include <memory>
Paul Crowleyc6846962018-01-30 09:56:03 -080035#include <string>
Jinguang Dong9d344962017-06-13 10:20:34 +080036#include <thread>
Paul Crowleyc6846962018-01-30 09:56:03 -080037#include <vector>
Bowgo Tsaiaaf70e72017-03-02 00:03:56 +080038
Keun-young Park3fbf94e2017-03-02 14:33:04 -080039#include <android-base/file.h>
Bowgo Tsaiaaf70e72017-03-02 00:03:56 +080040#include <android-base/properties.h>
Keun-young Park3fbf94e2017-03-02 14:33:04 -080041#include <android-base/stringprintf.h>
Paul Crowleyc6846962018-01-30 09:56:03 -080042#include <android-base/strings.h>
bowgotsaicea7ea72017-01-16 21:49:49 +080043#include <android-base/unique_fd.h>
Jeff Sharkey47dc2362018-01-07 19:17:39 -070044#include <cutils/android_filesystem_config.h>
JP Abgrall4bb7bba2014-06-19 22:12:20 -070045#include <cutils/android_reboot.h>
Ken Sumrallc1bf8962012-01-06 19:09:42 -080046#include <cutils/partition_utils.h>
47#include <cutils/properties.h>
Tao Bao6d881d62016-10-05 17:53:30 -070048#include <ext4_utils/ext4.h>
49#include <ext4_utils/ext4_crypt_init_extensions.h>
50#include <ext4_utils/ext4_sb.h>
51#include <ext4_utils/ext4_utils.h>
52#include <ext4_utils/wipe.h>
liminghao9a0fd1d2016-07-22 11:48:14 +080053#include <linux/fs.h>
Mattias Nissler097b6bb2016-03-31 16:32:09 +020054#include <linux/loop.h>
Keun-young Park6000a3f2017-04-11 18:59:56 -070055#include <linux/magic.h>
Steven Morelandd73be1b2017-04-13 23:48:57 -070056#include <log/log_properties.h>
Ken Sumrallbf021b42013-03-19 19:38:44 -070057#include <logwrap/logwrap.h>
Geremy Condra3ad3d1c2013-02-22 18:11:41 -080058
Bowgo Tsai80d1ad12017-04-13 13:05:42 +080059#include "fs_mgr.h"
60#include "fs_mgr_avb.h"
Ken Sumrallc1bf8962012-01-06 19:09:42 -080061#include "fs_mgr_priv.h"
Bowgo Tsaiaaf70e72017-03-02 00:03:56 +080062#include "fs_mgr_priv_dm_ioctl.h"
Ken Sumrallc1bf8962012-01-06 19:09:42 -080063
64#define KEY_LOC_PROP "ro.crypto.keyfile.userdata"
65#define KEY_IN_FOOTER "footer"
66
67#define E2FSCK_BIN "/system/bin/e2fsck"
liminghao9a0fd1d2016-07-22 11:48:14 +080068#define F2FS_FSCK_BIN "/system/bin/fsck.f2fs"
Ken Sumrall5bc31a22013-07-08 19:11:55 -070069#define MKSWAP_BIN "/system/bin/mkswap"
liminghao9a0fd1d2016-07-22 11:48:14 +080070#define TUNE2FS_BIN "/system/bin/tune2fs"
Ken Sumrall5bc31a22013-07-08 19:11:55 -070071
Ken Sumrall4eaf9052013-09-18 17:49:21 -070072#define FSCK_LOG_FILE "/dev/fscklogs/log"
73
Ken Sumrall5bc31a22013-07-08 19:11:55 -070074#define ZRAM_CONF_DEV "/sys/block/zram0/disksize"
Peter Enderborg4d217f02016-08-26 15:09:35 +020075#define ZRAM_CONF_MCS "/sys/block/zram0/max_comp_streams"
Ken Sumrallc1bf8962012-01-06 19:09:42 -080076
Ken Sumrallbf021b42013-03-19 19:38:44 -070077#define ARRAY_SIZE(a) (sizeof(a) / sizeof(*(a)))
78
Keun-young Park3fbf94e2017-03-02 14:33:04 -080079// record fs stat
80enum FsStatFlags {
Keun-young Park6000a3f2017-04-11 18:59:56 -070081 FS_STAT_IS_EXT4 = 0x0001,
Keun-young Park3fbf94e2017-03-02 14:33:04 -080082 FS_STAT_NEW_IMAGE_VERSION = 0x0002,
Keun-young Park6000a3f2017-04-11 18:59:56 -070083 FS_STAT_E2FSCK_F_ALWAYS = 0x0004,
84 FS_STAT_UNCLEAN_SHUTDOWN = 0x0008,
85 FS_STAT_QUOTA_ENABLED = 0x0010,
Keun-young Park6000a3f2017-04-11 18:59:56 -070086 FS_STAT_RO_MOUNT_FAILED = 0x0040,
Keun-young Park3fbf94e2017-03-02 14:33:04 -080087 FS_STAT_RO_UNMOUNT_FAILED = 0x0080,
88 FS_STAT_FULL_MOUNT_FAILED = 0x0100,
Keun-young Park6000a3f2017-04-11 18:59:56 -070089 FS_STAT_E2FSCK_FAILED = 0x0200,
90 FS_STAT_E2FSCK_FS_FIXED = 0x0400,
91 FS_STAT_EXT4_INVALID_MAGIC = 0x0800,
Eric Biggers8d3bcd42017-07-05 12:21:15 -070092 FS_STAT_TOGGLE_QUOTAS_FAILED = 0x10000,
93 FS_STAT_SET_RESERVED_BLOCKS_FAILED = 0x20000,
Eric Biggerse9811f32017-07-05 12:21:15 -070094 FS_STAT_ENABLE_ENCRYPTION_FAILED = 0x40000,
Keun-young Park3fbf94e2017-03-02 14:33:04 -080095};
96
Jinguang Dong9d344962017-06-13 10:20:34 +080097// TODO: switch to inotify()
98bool fs_mgr_wait_for_file(const std::string& filename,
99 const std::chrono::milliseconds relative_timeout) {
100 auto start_time = std::chrono::steady_clock::now();
Ken Sumrallc1bf8962012-01-06 19:09:42 -0800101
Jinguang Dong9d344962017-06-13 10:20:34 +0800102 while (true) {
103 if (!access(filename.c_str(), F_OK) || errno != ENOENT) {
104 return true;
105 }
106
107 std::this_thread::sleep_for(50ms);
108
109 auto now = std::chrono::steady_clock::now();
110 auto time_elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(now - start_time);
111 if (time_elapsed > relative_timeout) return false;
Ken Sumrallc1bf8962012-01-06 19:09:42 -0800112 }
Ken Sumrallc1bf8962012-01-06 19:09:42 -0800113}
114
Keun-young Park3fbf94e2017-03-02 14:33:04 -0800115static void log_fs_stat(const char* blk_device, int fs_stat)
116{
117 if ((fs_stat & FS_STAT_IS_EXT4) == 0) return; // only log ext4
118 std::string msg = android::base::StringPrintf("\nfs_stat,%s,0x%x\n", blk_device, fs_stat);
119 android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(FSCK_LOG_FILE, O_WRONLY | O_CLOEXEC |
120 O_APPEND | O_CREAT, 0664)));
121 if (fd == -1 || !android::base::WriteStringToFd(msg, fd)) {
122 LWARNING << __FUNCTION__ << "() cannot log " << msg;
123 }
124}
125
Eric Biggers8d3bcd42017-07-05 12:21:15 -0700126static bool is_extfs(const std::string& fs_type) {
127 return fs_type == "ext4" || fs_type == "ext3" || fs_type == "ext2";
128}
129
Keun-young Park40db04d2017-04-13 17:31:08 -0700130static bool should_force_check(int fs_stat) {
Eric Biggerse9811f32017-07-05 12:21:15 -0700131 return fs_stat &
132 (FS_STAT_E2FSCK_F_ALWAYS | FS_STAT_UNCLEAN_SHUTDOWN | FS_STAT_QUOTA_ENABLED |
133 FS_STAT_RO_MOUNT_FAILED | FS_STAT_RO_UNMOUNT_FAILED | FS_STAT_FULL_MOUNT_FAILED |
134 FS_STAT_E2FSCK_FAILED | FS_STAT_TOGGLE_QUOTAS_FAILED |
135 FS_STAT_SET_RESERVED_BLOCKS_FAILED | FS_STAT_ENABLE_ENCRYPTION_FAILED);
Keun-young Park40db04d2017-04-13 17:31:08 -0700136}
137
Keun-young Park3fbf94e2017-03-02 14:33:04 -0800138static void check_fs(const char *blk_device, char *fs_type, char *target, int *fs_stat)
Ken Sumrallc1bf8962012-01-06 19:09:42 -0800139{
Ken Sumrallc1bf8962012-01-06 19:09:42 -0800140 int status;
Ken Sumrall5dc5bfe2012-07-23 19:34:00 -0700141 int ret;
142 long tmpmnt_flags = MS_NOATIME | MS_NOEXEC | MS_NOSUID;
Oreste Salerno6ed84c92015-05-20 17:01:39 +0000143 char tmpmnt_opts[64] = "errors=remount-ro";
Keun-young Park40db04d2017-04-13 17:31:08 -0700144 const char* e2fsck_argv[] = {E2FSCK_BIN, "-y", blk_device};
145 const char* e2fsck_forced_argv[] = {E2FSCK_BIN, "-f", "-y", blk_device};
Ken Sumrallc1bf8962012-01-06 19:09:42 -0800146
147 /* Check for the types of filesystems we know how to check */
Eric Biggers8d3bcd42017-07-05 12:21:15 -0700148 if (is_extfs(fs_type)) {
Keun-young Park6000a3f2017-04-11 18:59:56 -0700149 if (*fs_stat & FS_STAT_EXT4_INVALID_MAGIC) { // will fail, so do not try
150 return;
151 }
Ken Sumrall5dc5bfe2012-07-23 19:34:00 -0700152 /*
153 * First try to mount and unmount the filesystem. We do this because
154 * the kernel is more efficient than e2fsck in running the journal and
155 * processing orphaned inodes, and on at least one device with a
156 * performance issue in the emmc firmware, it can take e2fsck 2.5 minutes
157 * to do what the kernel does in about a second.
158 *
159 * After mounting and unmounting the filesystem, run e2fsck, and if an
160 * error is recorded in the filesystem superblock, e2fsck will do a full
161 * check. Otherwise, it does nothing. If the kernel cannot mount the
162 * filesytsem due to an error, e2fsck is still run to do a full check
163 * fix the filesystem.
164 */
Keun-young Park40db04d2017-04-13 17:31:08 -0700165 if (!(*fs_stat & FS_STAT_FULL_MOUNT_FAILED)) { // already tried if full mount failed
166 errno = 0;
167 if (!strcmp(fs_type, "ext4")) {
168 // This option is only valid with ext4
169 strlcat(tmpmnt_opts, ",nomblk_io_submit", sizeof(tmpmnt_opts));
Nick Kralevich7294eb62015-02-05 16:02:42 -0800170 }
Keun-young Park40db04d2017-04-13 17:31:08 -0700171 ret = mount(blk_device, target, fs_type, tmpmnt_flags, tmpmnt_opts);
172 PINFO << __FUNCTION__ << "(): mount(" << blk_device << "," << target << "," << fs_type
173 << ")=" << ret;
174 if (!ret) {
175 bool umounted = false;
176 int retry_count = 5;
177 while (retry_count-- > 0) {
178 umounted = umount(target) == 0;
179 if (umounted) {
180 LINFO << __FUNCTION__ << "(): unmount(" << target << ") succeeded";
181 break;
182 }
183 PERROR << __FUNCTION__ << "(): umount(" << target << ") failed";
184 if (retry_count) sleep(1);
185 }
186 if (!umounted) {
187 // boot may fail but continue and leave it to later stage for now.
188 PERROR << __FUNCTION__ << "(): umount(" << target << ") timed out";
189 *fs_stat |= FS_STAT_RO_UNMOUNT_FAILED;
190 }
191 } else {
192 *fs_stat |= FS_STAT_RO_MOUNT_FAILED;
193 }
Ken Sumrall5dc5bfe2012-07-23 19:34:00 -0700194 }
195
David 'Digit' Turner28483d72014-02-17 11:14:44 +0100196 /*
197 * Some system images do not have e2fsck for licensing reasons
198 * (e.g. recent SDK system images). Detect these and skip the check.
199 */
200 if (access(E2FSCK_BIN, X_OK)) {
bowgotsai47878de2017-01-23 14:04:34 +0800201 LINFO << "Not running " << E2FSCK_BIN << " on " << blk_device
202 << " (executable not in system image)";
David 'Digit' Turner28483d72014-02-17 11:14:44 +0100203 } else {
bowgotsai47878de2017-01-23 14:04:34 +0800204 LINFO << "Running " << E2FSCK_BIN << " on " << blk_device;
Keun-young Park40db04d2017-04-13 17:31:08 -0700205 if (should_force_check(*fs_stat)) {
206 ret = android_fork_execvp_ext(
207 ARRAY_SIZE(e2fsck_forced_argv), const_cast<char**>(e2fsck_forced_argv), &status,
208 true, LOG_KLOG | LOG_FILE, true, const_cast<char*>(FSCK_LOG_FILE), NULL, 0);
209 } else {
210 ret = android_fork_execvp_ext(
211 ARRAY_SIZE(e2fsck_argv), const_cast<char**>(e2fsck_argv), &status, true,
212 LOG_KLOG | LOG_FILE, true, const_cast<char*>(FSCK_LOG_FILE), NULL, 0);
213 }
Ken Sumrallbf021b42013-03-19 19:38:44 -0700214
David 'Digit' Turner28483d72014-02-17 11:14:44 +0100215 if (ret < 0) {
216 /* No need to check for error in fork, we can't really handle it now */
bowgotsai47878de2017-01-23 14:04:34 +0800217 LERROR << "Failed trying to run " << E2FSCK_BIN;
Keun-young Park3fbf94e2017-03-02 14:33:04 -0800218 *fs_stat |= FS_STAT_E2FSCK_FAILED;
219 } else if (status != 0) {
220 LINFO << "e2fsck returned status 0x" << std::hex << status;
221 *fs_stat |= FS_STAT_E2FSCK_FS_FIXED;
David 'Digit' Turner28483d72014-02-17 11:14:44 +0100222 }
Ken Sumrallc1bf8962012-01-06 19:09:42 -0800223 }
JP Abgrall12351582014-06-17 17:01:14 -0700224 } else if (!strcmp(fs_type, "f2fs")) {
bowgotsaicea7ea72017-01-16 21:49:49 +0800225 const char *f2fs_fsck_argv[] = {
JP Abgrall12351582014-06-17 17:01:14 -0700226 F2FS_FSCK_BIN,
Yusuke Sato0df08272015-07-08 14:57:07 -0700227 "-a",
JP Abgrall12351582014-06-17 17:01:14 -0700228 blk_device
229 };
bowgotsai47878de2017-01-23 14:04:34 +0800230 LINFO << "Running " << F2FS_FSCK_BIN << " -a " << blk_device;
JP Abgrall12351582014-06-17 17:01:14 -0700231
bowgotsaicea7ea72017-01-16 21:49:49 +0800232 ret = android_fork_execvp_ext(ARRAY_SIZE(f2fs_fsck_argv),
233 const_cast<char **>(f2fs_fsck_argv),
JP Abgrall12351582014-06-17 17:01:14 -0700234 &status, true, LOG_KLOG | LOG_FILE,
bowgotsaicea7ea72017-01-16 21:49:49 +0800235 true, const_cast<char *>(FSCK_LOG_FILE),
236 NULL, 0);
JP Abgrall12351582014-06-17 17:01:14 -0700237 if (ret < 0) {
238 /* No need to check for error in fork, we can't really handle it now */
bowgotsai47878de2017-01-23 14:04:34 +0800239 LERROR << "Failed trying to run " << F2FS_FSCK_BIN;
JP Abgrall12351582014-06-17 17:01:14 -0700240 }
Ken Sumrallc1bf8962012-01-06 19:09:42 -0800241 }
242
243 return;
244}
245
Eric Biggers8d3bcd42017-07-05 12:21:15 -0700246static ext4_fsblk_t ext4_blocks_count(const struct ext4_super_block* es) {
liminghao9a0fd1d2016-07-22 11:48:14 +0800247 return ((ext4_fsblk_t)le32_to_cpu(es->s_blocks_count_hi) << 32) |
Eric Biggers8d3bcd42017-07-05 12:21:15 -0700248 le32_to_cpu(es->s_blocks_count_lo);
liminghao9a0fd1d2016-07-22 11:48:14 +0800249}
250
Eric Biggers8d3bcd42017-07-05 12:21:15 -0700251static ext4_fsblk_t ext4_r_blocks_count(const struct ext4_super_block* es) {
liminghao9a0fd1d2016-07-22 11:48:14 +0800252 return ((ext4_fsblk_t)le32_to_cpu(es->s_r_blocks_count_hi) << 32) |
Eric Biggers8d3bcd42017-07-05 12:21:15 -0700253 le32_to_cpu(es->s_r_blocks_count_lo);
liminghao9a0fd1d2016-07-22 11:48:14 +0800254}
255
katao4e8d73f2017-07-05 16:00:54 +0800256static bool is_ext4_superblock_valid(const struct ext4_super_block* es) {
257 if (es->s_magic != EXT4_SUPER_MAGIC) return false;
258 if (es->s_rev_level != EXT4_DYNAMIC_REV && es->s_rev_level != EXT4_GOOD_OLD_REV) return false;
259 if (EXT4_INODES_PER_GROUP(es) == 0) return false;
260 return true;
261}
262
Eric Biggers8d3bcd42017-07-05 12:21:15 -0700263// Read the primary superblock from an ext4 filesystem. On failure return
264// false. If it's not an ext4 filesystem, also set FS_STAT_EXT4_INVALID_MAGIC.
265static bool read_ext4_superblock(const char* blk_device, struct ext4_super_block* sb, int* fs_stat) {
266 android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(blk_device, O_RDONLY | O_CLOEXEC)));
Jeff Sharkey6d896102016-12-14 12:00:51 -0700267
Eric Biggers8d3bcd42017-07-05 12:21:15 -0700268 if (fd < 0) {
269 PERROR << "Failed to open '" << blk_device << "'";
270 return false;
Jeff Sharkey6d896102016-12-14 12:00:51 -0700271 }
Eric Biggers8d3bcd42017-07-05 12:21:15 -0700272
273 if (pread(fd, sb, sizeof(*sb), 1024) != sizeof(*sb)) {
274 PERROR << "Can't read '" << blk_device << "' superblock";
275 return false;
276 }
277
katao4e8d73f2017-07-05 16:00:54 +0800278 if (!is_ext4_superblock_valid(sb)) {
279 LINFO << "Invalid ext4 superblock on '" << blk_device << "'";
Eric Biggers8d3bcd42017-07-05 12:21:15 -0700280 // not a valid fs, tune2fs, fsck, and mount will all fail.
281 *fs_stat |= FS_STAT_EXT4_INVALID_MAGIC;
282 return false;
283 }
284 *fs_stat |= FS_STAT_IS_EXT4;
285 LINFO << "superblock s_max_mnt_count:" << sb->s_max_mnt_count << "," << blk_device;
286 if (sb->s_max_mnt_count == 0xffff) { // -1 (int16) in ext2, but uint16 in ext4
287 *fs_stat |= FS_STAT_NEW_IMAGE_VERSION;
288 }
289 return true;
Jeff Sharkey6d896102016-12-14 12:00:51 -0700290}
291
Eric Biggers8d3bcd42017-07-05 12:21:15 -0700292// Some system images do not have tune2fs for licensing reasons.
293// Detect these and skip running it.
294static bool tune2fs_available(void) {
295 return access(TUNE2FS_BIN, X_OK) == 0;
296}
297
298static bool run_tune2fs(const char* argv[], int argc) {
299 int ret;
300
301 ret = android_fork_execvp_ext(argc, const_cast<char**>(argv), nullptr, true,
302 LOG_KLOG | LOG_FILE, true, nullptr, nullptr, 0);
303 return ret == 0;
304}
305
306// Enable/disable quota support on the filesystem if needed.
307static void tune_quota(const char* blk_device, const struct fstab_rec* rec,
308 const struct ext4_super_block* sb, int* fs_stat) {
309 bool has_quota = (sb->s_feature_ro_compat & cpu_to_le32(EXT4_FEATURE_RO_COMPAT_QUOTA)) != 0;
310 bool want_quota = fs_mgr_is_quota(rec) != 0;
311
312 if (has_quota == want_quota) {
313 return;
314 }
315
316 if (!tune2fs_available()) {
317 LERROR << "Unable to " << (want_quota ? "enable" : "disable") << " quotas on " << blk_device
318 << " because " TUNE2FS_BIN " is missing";
319 return;
320 }
321
322 const char* argv[] = {TUNE2FS_BIN, nullptr, nullptr, blk_device};
323
324 if (want_quota) {
325 LINFO << "Enabling quotas on " << blk_device;
326 argv[1] = "-Oquota";
327 argv[2] = "-Qusrquota,grpquota";
328 *fs_stat |= FS_STAT_QUOTA_ENABLED;
329 } else {
330 LINFO << "Disabling quotas on " << blk_device;
331 argv[1] = "-O^quota";
332 argv[2] = "-Q^usrquota,^grpquota";
333 }
334
335 if (!run_tune2fs(argv, ARRAY_SIZE(argv))) {
336 LERROR << "Failed to run " TUNE2FS_BIN " to " << (want_quota ? "enable" : "disable")
337 << " quotas on " << blk_device;
338 *fs_stat |= FS_STAT_TOGGLE_QUOTAS_FAILED;
339 }
340}
341
342// Set the number of reserved filesystem blocks if needed.
343static void tune_reserved_size(const char* blk_device, const struct fstab_rec* rec,
344 const struct ext4_super_block* sb, int* fs_stat) {
345 if (!(rec->fs_mgr_flags & MF_RESERVEDSIZE)) {
346 return;
347 }
348
349 // The size to reserve is given in the fstab, but we won't reserve more
350 // than 2% of the filesystem.
351 const uint64_t max_reserved_blocks = ext4_blocks_count(sb) * 0.02;
352 uint64_t reserved_blocks = rec->reserved_size / EXT4_BLOCK_SIZE(sb);
353
354 if (reserved_blocks > max_reserved_blocks) {
355 LWARNING << "Reserved blocks " << reserved_blocks << " is too large; "
356 << "capping to " << max_reserved_blocks;
357 reserved_blocks = max_reserved_blocks;
358 }
359
Jeff Sharkey47dc2362018-01-07 19:17:39 -0700360 if ((ext4_r_blocks_count(sb) == reserved_blocks) && (sb->s_def_resgid == AID_RESERVED_DISK)) {
Eric Biggers8d3bcd42017-07-05 12:21:15 -0700361 return;
362 }
363
364 if (!tune2fs_available()) {
365 LERROR << "Unable to set the number of reserved blocks on " << blk_device
366 << " because " TUNE2FS_BIN " is missing";
367 return;
368 }
369
Eric Biggers8d3bcd42017-07-05 12:21:15 -0700370 LINFO << "Setting reserved block count on " << blk_device << " to " << reserved_blocks;
Jeff Sharkey47dc2362018-01-07 19:17:39 -0700371
372 auto reserved_blocks_str = std::to_string(reserved_blocks);
373 auto reserved_gid_str = std::to_string(AID_RESERVED_DISK);
374 const char* argv[] = {
375 TUNE2FS_BIN, "-r", reserved_blocks_str.c_str(), "-g", reserved_gid_str.c_str(), blk_device};
Eric Biggers8d3bcd42017-07-05 12:21:15 -0700376 if (!run_tune2fs(argv, ARRAY_SIZE(argv))) {
377 LERROR << "Failed to run " TUNE2FS_BIN " to set the number of reserved blocks on "
378 << blk_device;
379 *fs_stat |= FS_STAT_SET_RESERVED_BLOCKS_FAILED;
380 }
381}
382
Eric Biggerse9811f32017-07-05 12:21:15 -0700383// Enable file-based encryption if needed.
384static void tune_encrypt(const char* blk_device, const struct fstab_rec* rec,
385 const struct ext4_super_block* sb, int* fs_stat) {
386 bool has_encrypt = (sb->s_feature_incompat & cpu_to_le32(EXT4_FEATURE_INCOMPAT_ENCRYPT)) != 0;
387 bool want_encrypt = fs_mgr_is_file_encrypted(rec) != 0;
388
389 if (has_encrypt || !want_encrypt) {
390 return;
391 }
392
393 if (!tune2fs_available()) {
394 LERROR << "Unable to enable ext4 encryption on " << blk_device
395 << " because " TUNE2FS_BIN " is missing";
396 return;
397 }
398
399 const char* argv[] = {TUNE2FS_BIN, "-Oencrypt", blk_device};
400
401 LINFO << "Enabling ext4 encryption on " << blk_device;
402 if (!run_tune2fs(argv, ARRAY_SIZE(argv))) {
403 LERROR << "Failed to run " TUNE2FS_BIN " to enable "
404 << "ext4 encryption on " << blk_device;
405 *fs_stat |= FS_STAT_ENABLE_ENCRYPTION_FAILED;
406 }
407}
408
Eric Biggers8d3bcd42017-07-05 12:21:15 -0700409//
410// Prepare the filesystem on the given block device to be mounted.
411//
412// If the "check" option was given in the fstab record, or it seems that the
413// filesystem was uncleanly shut down, we'll run fsck on the filesystem.
414//
415// If needed, we'll also enable (or disable) filesystem features as specified by
416// the fstab record.
417//
418static int prepare_fs_for_mount(const char* blk_device, const struct fstab_rec* rec) {
419 int fs_stat = 0;
420
421 if (is_extfs(rec->fs_type)) {
422 struct ext4_super_block sb;
423
424 if (read_ext4_superblock(blk_device, &sb, &fs_stat)) {
425 if ((sb.s_feature_incompat & EXT4_FEATURE_INCOMPAT_RECOVER) != 0 ||
426 (sb.s_state & EXT4_VALID_FS) == 0) {
427 LINFO << "Filesystem on " << blk_device << " was not cleanly shutdown; "
428 << "state flags: 0x" << std::hex << sb.s_state << ", "
429 << "incompat feature flags: 0x" << std::hex << sb.s_feature_incompat;
430 fs_stat |= FS_STAT_UNCLEAN_SHUTDOWN;
431 }
432
433 // Note: quotas should be enabled before running fsck.
434 tune_quota(blk_device, rec, &sb, &fs_stat);
liminghao9a0fd1d2016-07-22 11:48:14 +0800435 } else {
Eric Biggers8d3bcd42017-07-05 12:21:15 -0700436 return fs_stat;
liminghao9a0fd1d2016-07-22 11:48:14 +0800437 }
438 }
Eric Biggers8d3bcd42017-07-05 12:21:15 -0700439
440 if ((rec->fs_mgr_flags & MF_CHECK) ||
441 (fs_stat & (FS_STAT_UNCLEAN_SHUTDOWN | FS_STAT_QUOTA_ENABLED))) {
442 check_fs(blk_device, rec->fs_type, rec->mount_point, &fs_stat);
443 }
444
Eric Biggerse9811f32017-07-05 12:21:15 -0700445 if (is_extfs(rec->fs_type) && (rec->fs_mgr_flags & (MF_RESERVEDSIZE | MF_FILEENCRYPTION))) {
Eric Biggers8d3bcd42017-07-05 12:21:15 -0700446 struct ext4_super_block sb;
447
448 if (read_ext4_superblock(blk_device, &sb, &fs_stat)) {
449 tune_reserved_size(blk_device, rec, &sb, &fs_stat);
Eric Biggerse9811f32017-07-05 12:21:15 -0700450 tune_encrypt(blk_device, rec, &sb, &fs_stat);
Eric Biggers8d3bcd42017-07-05 12:21:15 -0700451 }
452 }
453
454 return fs_stat;
liminghao9a0fd1d2016-07-22 11:48:14 +0800455}
456
Ken Sumrallc1bf8962012-01-06 19:09:42 -0800457static void remove_trailing_slashes(char *n)
458{
459 int len;
460
461 len = strlen(n) - 1;
462 while ((*(n + len) == '/') && len) {
463 *(n + len) = '\0';
464 len--;
465 }
466}
467
Nick Kraleviche18c0d52013-04-16 16:41:32 -0700468/*
469 * Mark the given block device as read-only, using the BLKROSET ioctl.
470 * Return 0 on success, and -1 on error.
471 */
Sami Tolvanen214f33b2014-12-18 16:15:30 +0000472int fs_mgr_set_blk_ro(const char *blockdev)
Nick Kraleviche18c0d52013-04-16 16:41:32 -0700473{
474 int fd;
Sami Tolvanen214f33b2014-12-18 16:15:30 +0000475 int rc = -1;
Nick Kraleviche18c0d52013-04-16 16:41:32 -0700476 int ON = 1;
477
Sami Tolvanen214f33b2014-12-18 16:15:30 +0000478 fd = TEMP_FAILURE_RETRY(open(blockdev, O_RDONLY | O_CLOEXEC));
Nick Kraleviche18c0d52013-04-16 16:41:32 -0700479 if (fd < 0) {
480 // should never happen
Sami Tolvanen214f33b2014-12-18 16:15:30 +0000481 return rc;
Nick Kraleviche18c0d52013-04-16 16:41:32 -0700482 }
483
Sami Tolvanen214f33b2014-12-18 16:15:30 +0000484 rc = ioctl(fd, BLKROSET, &ON);
Elliott Hughes9fc83432015-05-15 19:16:40 -0700485 close(fd);
Sami Tolvanen214f33b2014-12-18 16:15:30 +0000486
487 return rc;
Nick Kraleviche18c0d52013-04-16 16:41:32 -0700488}
489
Bowgo Tsaid1fe3bd2017-07-05 15:37:15 +0800490// Orange state means the device is unlocked, see the following link for details.
491// https://source.android.com/security/verifiedboot/verified-boot#device_state
492bool fs_mgr_is_device_unlocked() {
493 std::string verified_boot_state;
494 if (fs_mgr_get_boot_config("verifiedbootstate", &verified_boot_state)) {
495 return verified_boot_state == "orange";
496 }
497 return false;
498}
499
Nick Kraleviche18c0d52013-04-16 16:41:32 -0700500/*
501 * __mount(): wrapper around the mount() system call which also
502 * sets the underlying block device to read-only if the mount is read-only.
503 * See "man 2 mount" for return values.
504 */
JP Abgrall5c01dac2014-06-18 14:54:37 -0700505static int __mount(const char *source, const char *target, const struct fstab_rec *rec)
Nick Kraleviche18c0d52013-04-16 16:41:32 -0700506{
JP Abgrall5c01dac2014-06-18 14:54:37 -0700507 unsigned long mountflags = rec->flags;
508 int ret;
509 int save_errno;
Daniel Rosenbergf67d6bd2014-06-26 14:55:04 -0700510
511 /* We need this because sometimes we have legacy symlinks
512 * that are lingering around and need cleaning up.
513 */
514 struct stat info;
515 if (!lstat(target, &info))
516 if ((info.st_mode & S_IFMT) == S_IFLNK)
517 unlink(target);
Daniel Rosenbergf530c932014-05-28 14:10:01 -0700518 mkdir(target, 0755);
Mark Salyzyn69a5bd42017-06-28 13:36:52 -0700519 errno = 0;
JP Abgrall5c01dac2014-06-18 14:54:37 -0700520 ret = mount(source, target, rec->fs_type, mountflags, rec->fs_options);
521 save_errno = errno;
Mark Salyzyn69a5bd42017-06-28 13:36:52 -0700522 PINFO << __FUNCTION__ << "(source=" << source << ",target=" << target
523 << ",type=" << rec->fs_type << ")=" << ret;
Nick Kraleviche18c0d52013-04-16 16:41:32 -0700524 if ((ret == 0) && (mountflags & MS_RDONLY) != 0) {
Sami Tolvanen214f33b2014-12-18 16:15:30 +0000525 fs_mgr_set_blk_ro(source);
Nick Kraleviche18c0d52013-04-16 16:41:32 -0700526 }
JP Abgrall5c01dac2014-06-18 14:54:37 -0700527 errno = save_errno;
Nick Kraleviche18c0d52013-04-16 16:41:32 -0700528 return ret;
529}
530
Jin Qian8b7eb7b2016-11-03 13:36:35 -0700531static int fs_match(const char *in1, const char *in2)
Ken Sumrallc1bf8962012-01-06 19:09:42 -0800532{
533 char *n1;
534 char *n2;
535 int ret;
536
537 n1 = strdup(in1);
538 n2 = strdup(in2);
539
540 remove_trailing_slashes(n1);
541 remove_trailing_slashes(n2);
542
543 ret = !strcmp(n1, n2);
544
545 free(n1);
546 free(n2);
547
548 return ret;
549}
550
JP Abgrallf22b7452014-07-02 13:16:04 -0700551/*
552 * Tries to mount any of the consecutive fstab entries that match
553 * the mountpoint of the one given by fstab->recs[start_idx].
554 *
555 * end_idx: On return, will be the last rec that was looked at.
556 * attempted_idx: On return, will indicate which fstab rec
557 * succeeded. In case of failure, it will be the start_idx.
558 * Returns
559 * -1 on failure with errno set to match the 1st mount failure.
560 * 0 on success.
561 */
562static int mount_with_alternatives(struct fstab *fstab, int start_idx, int *end_idx, int *attempted_idx)
JP Abgrall4bb7bba2014-06-19 22:12:20 -0700563{
JP Abgrallf22b7452014-07-02 13:16:04 -0700564 int i;
565 int mount_errno = 0;
566 int mounted = 0;
567
568 if (!end_idx || !attempted_idx || start_idx >= fstab->num_entries) {
569 errno = EINVAL;
570 if (end_idx) *end_idx = start_idx;
forfunc5c03062016-12-14 09:47:33 -0500571 if (attempted_idx) *attempted_idx = start_idx;
JP Abgrallf22b7452014-07-02 13:16:04 -0700572 return -1;
JP Abgrall4bb7bba2014-06-19 22:12:20 -0700573 }
JP Abgrallf22b7452014-07-02 13:16:04 -0700574
575 /* Hunt down an fstab entry for the same mount point that might succeed */
576 for (i = start_idx;
577 /* We required that fstab entries for the same mountpoint be consecutive */
578 i < fstab->num_entries && !strcmp(fstab->recs[start_idx].mount_point, fstab->recs[i].mount_point);
579 i++) {
580 /*
581 * Don't try to mount/encrypt the same mount point again.
582 * Deal with alternate entries for the same point which are required to be all following
583 * each other.
584 */
585 if (mounted) {
bowgotsai47878de2017-01-23 14:04:34 +0800586 LERROR << __FUNCTION__ << "(): skipping fstab dup mountpoint="
587 << fstab->recs[i].mount_point << " rec[" << i
588 << "].fs_type=" << fstab->recs[i].fs_type
589 << " already mounted as "
590 << fstab->recs[*attempted_idx].fs_type;
JP Abgrallf22b7452014-07-02 13:16:04 -0700591 continue;
592 }
593
Eric Biggers8d3bcd42017-07-05 12:21:15 -0700594 int fs_stat = prepare_fs_for_mount(fstab->recs[i].blk_device, &fstab->recs[i]);
Keun-young Park6000a3f2017-04-11 18:59:56 -0700595 if (fs_stat & FS_STAT_EXT4_INVALID_MAGIC) {
596 LERROR << __FUNCTION__ << "(): skipping mount, invalid ext4, mountpoint="
597 << fstab->recs[i].mount_point << " rec[" << i
598 << "].fs_type=" << fstab->recs[i].fs_type;
599 mount_errno = EINVAL; // continue bootup for FDE
600 continue;
601 }
liminghao9a0fd1d2016-07-22 11:48:14 +0800602
Keun-young Park40db04d2017-04-13 17:31:08 -0700603 int retry_count = 2;
604 while (retry_count-- > 0) {
605 if (!__mount(fstab->recs[i].blk_device, fstab->recs[i].mount_point,
606 &fstab->recs[i])) {
607 *attempted_idx = i;
608 mounted = 1;
609 if (i != start_idx) {
610 LERROR << __FUNCTION__ << "(): Mounted " << fstab->recs[i].blk_device
611 << " on " << fstab->recs[i].mount_point
612 << " with fs_type=" << fstab->recs[i].fs_type << " instead of "
613 << fstab->recs[start_idx].fs_type;
614 }
615 fs_stat &= ~FS_STAT_FULL_MOUNT_FAILED;
616 mount_errno = 0;
617 break;
618 } else {
619 if (retry_count <= 0) break; // run check_fs only once
620 fs_stat |= FS_STAT_FULL_MOUNT_FAILED;
621 /* back up the first errno for crypto decisions */
622 if (mount_errno == 0) {
623 mount_errno = errno;
624 }
625 // retry after fsck
626 check_fs(fstab->recs[i].blk_device, fstab->recs[i].fs_type,
627 fstab->recs[i].mount_point, &fs_stat);
NIEJuhu5c31ffe2017-03-09 12:19:08 +0800628 }
JP Abgrallf22b7452014-07-02 13:16:04 -0700629 }
Keun-young Park3fbf94e2017-03-02 14:33:04 -0800630 log_fs_stat(fstab->recs[i].blk_device, fs_stat);
JP Abgrallf22b7452014-07-02 13:16:04 -0700631 }
632
633 /* Adjust i for the case where it was still withing the recs[] */
634 if (i < fstab->num_entries) --i;
635
636 *end_idx = i;
637 if (!mounted) {
638 *attempted_idx = start_idx;
639 errno = mount_errno;
640 return -1;
641 }
642 return 0;
JP Abgrall4bb7bba2014-06-19 22:12:20 -0700643}
644
Christoffer Dall82982342014-12-17 21:26:54 +0100645static int translate_ext_labels(struct fstab_rec *rec)
646{
647 DIR *blockdir = NULL;
648 struct dirent *ent;
649 char *label;
650 size_t label_len;
651 int ret = -1;
652
653 if (strncmp(rec->blk_device, "LABEL=", 6))
654 return 0;
655
656 label = rec->blk_device + 6;
657 label_len = strlen(label);
658
659 if (label_len > 16) {
bowgotsai47878de2017-01-23 14:04:34 +0800660 LERROR << "FS label is longer than allowed by filesystem";
Christoffer Dall82982342014-12-17 21:26:54 +0100661 goto out;
662 }
663
664
665 blockdir = opendir("/dev/block");
666 if (!blockdir) {
bowgotsai47878de2017-01-23 14:04:34 +0800667 LERROR << "couldn't open /dev/block";
Christoffer Dall82982342014-12-17 21:26:54 +0100668 goto out;
669 }
670
671 while ((ent = readdir(blockdir))) {
672 int fd;
673 char super_buf[1024];
674 struct ext4_super_block *sb;
675
676 if (ent->d_type != DT_BLK)
677 continue;
678
679 fd = openat(dirfd(blockdir), ent->d_name, O_RDONLY);
680 if (fd < 0) {
bowgotsai47878de2017-01-23 14:04:34 +0800681 LERROR << "Cannot open block device /dev/block/" << ent->d_name;
Christoffer Dall82982342014-12-17 21:26:54 +0100682 goto out;
683 }
684
685 if (TEMP_FAILURE_RETRY(lseek(fd, 1024, SEEK_SET)) < 0 ||
686 TEMP_FAILURE_RETRY(read(fd, super_buf, 1024)) != 1024) {
687 /* Probably a loopback device or something else without a readable
688 * superblock.
689 */
690 close(fd);
691 continue;
692 }
693
694 sb = (struct ext4_super_block *)super_buf;
695 if (sb->s_magic != EXT4_SUPER_MAGIC) {
bowgotsai47878de2017-01-23 14:04:34 +0800696 LINFO << "/dev/block/" << ent->d_name << " not ext{234}";
Christoffer Dall82982342014-12-17 21:26:54 +0100697 continue;
698 }
699
700 if (!strncmp(label, sb->s_volume_name, label_len)) {
701 char *new_blk_device;
702
703 if (asprintf(&new_blk_device, "/dev/block/%s", ent->d_name) < 0) {
bowgotsai47878de2017-01-23 14:04:34 +0800704 LERROR << "Could not allocate block device string";
Christoffer Dall82982342014-12-17 21:26:54 +0100705 goto out;
706 }
707
bowgotsai47878de2017-01-23 14:04:34 +0800708 LINFO << "resolved label " << rec->blk_device << " to "
709 << new_blk_device;
Christoffer Dall82982342014-12-17 21:26:54 +0100710
711 free(rec->blk_device);
712 rec->blk_device = new_blk_device;
713 ret = 0;
714 break;
715 }
716 }
717
718out:
719 closedir(blockdir);
720 return ret;
721}
722
Paul Crowleyc31f1f32016-02-09 21:05:01 +0000723static bool needs_block_encryption(const struct fstab_rec* rec)
724{
Tom Cherry31121ca2017-10-10 13:30:57 -0700725 if (android::base::GetBoolProperty("ro.vold.forceencryption", false) &&
726 fs_mgr_is_encryptable(rec))
727 return true;
Paul Crowleyc31f1f32016-02-09 21:05:01 +0000728 if (rec->fs_mgr_flags & MF_FORCECRYPT) return true;
729 if (rec->fs_mgr_flags & MF_CRYPT) {
730 /* Check for existence of convert_fde breadcrumb file */
731 char convert_fde_name[PATH_MAX];
732 snprintf(convert_fde_name, sizeof(convert_fde_name),
733 "%s/misc/vold/convert_fde", rec->mount_point);
734 if (access(convert_fde_name, F_OK) == 0) return true;
735 }
736 if (rec->fs_mgr_flags & MF_FORCEFDEORFBE) {
737 /* Check for absence of convert_fbe breadcrumb file */
738 char convert_fbe_name[PATH_MAX];
739 snprintf(convert_fbe_name, sizeof(convert_fbe_name),
740 "%s/convert_fbe", rec->mount_point);
741 if (access(convert_fbe_name, F_OK) != 0) return true;
742 }
743 return false;
744}
745
Paul Lawrence9dbe97b2017-04-21 12:41:48 -0700746static bool should_use_metadata_encryption(const struct fstab_rec* rec) {
747 if (!(rec->fs_mgr_flags & (MF_FILEENCRYPTION | MF_FORCEFDEORFBE))) return false;
748 if (!(rec->fs_mgr_flags & MF_KEYDIRECTORY)) return false;
749 return true;
750}
751
Paul Lawrenceb8c9d272015-03-26 15:49:42 +0000752// Check to see if a mountable volume has encryption requirements
Paul Lawrence69080182016-02-02 10:31:30 -0800753static int handle_encryptable(const struct fstab_rec* rec)
Paul Lawrenceb8c9d272015-03-26 15:49:42 +0000754{
755 /* If this is block encryptable, need to trigger encryption */
Paul Crowleyc31f1f32016-02-09 21:05:01 +0000756 if (needs_block_encryption(rec)) {
Paul Lawrenceb8c9d272015-03-26 15:49:42 +0000757 if (umount(rec->mount_point) == 0) {
758 return FS_MGR_MNTALL_DEV_NEEDS_ENCRYPTION;
759 } else {
bowgotsai47878de2017-01-23 14:04:34 +0800760 PWARNING << "Could not umount " << rec->mount_point
761 << " - allow continue unencrypted";
Paul Lawrenceb8c9d272015-03-26 15:49:42 +0000762 return FS_MGR_MNTALL_DEV_NOT_ENCRYPTED;
763 }
Paul Lawrence9dbe97b2017-04-21 12:41:48 -0700764 } else if (should_use_metadata_encryption(rec)) {
765 if (umount(rec->mount_point) == 0) {
766 return FS_MGR_MNTALL_DEV_NEEDS_METADATA_ENCRYPTION;
767 } else {
768 PERROR << "Could not umount " << rec->mount_point << " - fail since can't encrypt";
769 return FS_MGR_MNTALL_FAIL;
770 }
Paul Crowleyc31f1f32016-02-09 21:05:01 +0000771 } else if (rec->fs_mgr_flags & (MF_FILEENCRYPTION | MF_FORCEFDEORFBE)) {
bowgotsai47878de2017-01-23 14:04:34 +0800772 LINFO << rec->mount_point << " is file encrypted";
Paul Lawrence69080182016-02-02 10:31:30 -0800773 return FS_MGR_MNTALL_DEV_FILE_ENCRYPTED;
Paul Lawrence1098aac2016-03-04 15:52:33 -0800774 } else if (fs_mgr_is_encryptable(rec)) {
Paul Crowleyc31f1f32016-02-09 21:05:01 +0000775 return FS_MGR_MNTALL_DEV_NOT_ENCRYPTED;
Paul Lawrence1098aac2016-03-04 15:52:33 -0800776 } else {
777 return FS_MGR_MNTALL_DEV_NOT_ENCRYPTABLE;
Paul Lawrenceb8c9d272015-03-26 15:49:42 +0000778 }
Paul Lawrenceb8c9d272015-03-26 15:49:42 +0000779}
780
Paul Crowleyc6846962018-01-30 09:56:03 -0800781static bool call_vdc(const std::vector<std::string>& args) {
782 std::vector<char const*> argv;
783 argv.emplace_back("/system/bin/vdc");
784 for (auto& arg : args) {
785 argv.emplace_back(arg.c_str());
786 }
787 LOG(INFO) << "Calling: " << android::base::Join(argv, ' ');
788 int ret = android_fork_execvp(4, const_cast<char**>(argv.data()), nullptr, false, true);
789 if (ret != 0) {
790 LOG(ERROR) << "vdc returned error code: " << ret;
791 return false;
792 }
793 LOG(DEBUG) << "vdc finished successfully";
794 return true;
795}
796
JP Abgrall5c01dac2014-06-18 14:54:37 -0700797/* When multiple fstab records share the same mount_point, it will
798 * try to mount each one in turn, and ignore any duplicates after a
799 * first successful mount.
JP Abgrallf22b7452014-07-02 13:16:04 -0700800 * Returns -1 on error, and FS_MGR_MNTALL_* otherwise.
JP Abgrall5c01dac2014-06-18 14:54:37 -0700801 */
Wei Wang254f4432016-08-23 11:58:09 -0700802int fs_mgr_mount_all(struct fstab *fstab, int mount_mode)
Ken Sumrallc1bf8962012-01-06 19:09:42 -0800803{
JP Abgrallf22b7452014-07-02 13:16:04 -0700804 int i = 0;
Paul Lawrence1098aac2016-03-04 15:52:33 -0800805 int encryptable = FS_MGR_MNTALL_DEV_NOT_ENCRYPTABLE;
Mohamad Ayyash38afe5f2014-03-10 15:40:29 -0700806 int error_count = 0;
JP Abgrall5c01dac2014-06-18 14:54:37 -0700807 int mret = -1;
808 int mount_errno = 0;
JP Abgrallf22b7452014-07-02 13:16:04 -0700809 int attempted_idx = -1;
Bowgo Tsai95c966a2017-03-30 18:42:54 +0800810 FsManagerAvbUniquePtr avb_handle(nullptr);
Ken Sumrallc1bf8962012-01-06 19:09:42 -0800811
Ken Sumrallab6b8522013-02-13 12:58:40 -0800812 if (!fstab) {
Bowgo Tsai359bed32017-04-27 15:44:39 +0800813 return FS_MGR_MNTALL_FAIL;
Ken Sumrallc1bf8962012-01-06 19:09:42 -0800814 }
815
Ken Sumrallab6b8522013-02-13 12:58:40 -0800816 for (i = 0; i < fstab->num_entries; i++) {
Wei Wang254f4432016-08-23 11:58:09 -0700817 /* Don't mount entries that are managed by vold or not for the mount mode*/
818 if ((fstab->recs[i].fs_mgr_flags & (MF_VOLDMANAGED | MF_RECOVERYONLY)) ||
819 ((mount_mode == MOUNT_MODE_LATE) && !fs_mgr_is_latemount(&fstab->recs[i])) ||
820 ((mount_mode == MOUNT_MODE_EARLY) && fs_mgr_is_latemount(&fstab->recs[i]))) {
Ken Sumrallab6b8522013-02-13 12:58:40 -0800821 continue;
Ken Sumrallc1bf8962012-01-06 19:09:42 -0800822 }
823
Ken Sumrall5bc31a22013-07-08 19:11:55 -0700824 /* Skip swap and raw partition entries such as boot, recovery, etc */
825 if (!strcmp(fstab->recs[i].fs_type, "swap") ||
826 !strcmp(fstab->recs[i].fs_type, "emmc") ||
Ken Sumrallab6b8522013-02-13 12:58:40 -0800827 !strcmp(fstab->recs[i].fs_type, "mtd")) {
828 continue;
Ken Sumrallc1bf8962012-01-06 19:09:42 -0800829 }
830
Daniel Rosenberg31a4faf2015-06-29 17:33:05 -0700831 /* Skip mounting the root partition, as it will already have been mounted */
832 if (!strcmp(fstab->recs[i].mount_point, "/")) {
833 if ((fstab->recs[i].fs_mgr_flags & MS_RDONLY) != 0) {
834 fs_mgr_set_blk_ro(fstab->recs[i].blk_device);
835 }
836 continue;
837 }
838
Christoffer Dall82982342014-12-17 21:26:54 +0100839 /* Translate LABEL= file system labels into block devices */
Eric Biggers8d3bcd42017-07-05 12:21:15 -0700840 if (is_extfs(fstab->recs[i].fs_type)) {
Christoffer Dall82982342014-12-17 21:26:54 +0100841 int tret = translate_ext_labels(&fstab->recs[i]);
842 if (tret < 0) {
bowgotsai47878de2017-01-23 14:04:34 +0800843 LERROR << "Could not translate label to block device";
Christoffer Dall82982342014-12-17 21:26:54 +0100844 continue;
845 }
846 }
847
Jinguang Dong9d344962017-06-13 10:20:34 +0800848 if (fstab->recs[i].fs_mgr_flags & MF_WAIT &&
849 !fs_mgr_wait_for_file(fstab->recs[i].blk_device, 20s)) {
850 LERROR << "Skipping '" << fstab->recs[i].blk_device << "' during mount_all";
851 continue;
Ken Sumrallab6b8522013-02-13 12:58:40 -0800852 }
853
Bowgo Tsai95c966a2017-03-30 18:42:54 +0800854 if (fstab->recs[i].fs_mgr_flags & MF_AVB) {
855 if (!avb_handle) {
Bowgo Tsai20651f62017-05-08 20:45:50 +0800856 avb_handle = FsManagerAvbHandle::Open(*fstab);
Bowgo Tsai95c966a2017-03-30 18:42:54 +0800857 if (!avb_handle) {
858 LERROR << "Failed to open FsManagerAvbHandle";
Bowgo Tsai359bed32017-04-27 15:44:39 +0800859 return FS_MGR_MNTALL_FAIL;
Bowgo Tsai95c966a2017-03-30 18:42:54 +0800860 }
861 }
Bowgo Tsai60f19a02017-06-22 22:23:08 +0800862 if (avb_handle->SetUpAvbHashtree(&fstab->recs[i], true /* wait_for_verity_dev */) ==
863 SetUpAvbHashtreeResult::kFail) {
bowgotsai47878de2017-01-23 14:04:34 +0800864 LERROR << "Failed to set up AVB on partition: "
865 << fstab->recs[i].mount_point << ", skipping!";
bowgotsaib51722b2017-01-11 22:21:38 +0800866 /* Skips mounting the device. */
867 continue;
868 }
Bowgo Tsai744361f2017-10-11 14:58:40 +0800869 } else if ((fstab->recs[i].fs_mgr_flags & MF_VERIFY)) {
Hung-ying Tyanecfce132016-12-16 15:00:05 +0800870 int rc = fs_mgr_setup_verity(&fstab->recs[i], true);
Sandeep Patil95366e92017-06-21 12:58:31 -0700871 if (__android_log_is_debuggable() &&
872 (rc == FS_MGR_SETUP_VERITY_DISABLED ||
873 rc == FS_MGR_SETUP_VERITY_SKIPPED)) {
bowgotsai47878de2017-01-23 14:04:34 +0800874 LINFO << "Verity disabled";
Paul Lawrencebbb36312014-10-09 14:22:49 +0000875 } else if (rc != FS_MGR_SETUP_VERITY_SUCCESS) {
bowgotsai47878de2017-01-23 14:04:34 +0800876 LERROR << "Could not set up verified partition, skipping!";
Geremy Condra3ad3d1c2013-02-22 18:11:41 -0800877 continue;
878 }
879 }
bowgotsaib51722b2017-01-11 22:21:38 +0800880
JP Abgrallf22b7452014-07-02 13:16:04 -0700881 int last_idx_inspected;
Chris Fries79f33842013-09-05 13:19:21 -0500882 int top_idx = i;
883
JP Abgrallf22b7452014-07-02 13:16:04 -0700884 mret = mount_with_alternatives(fstab, i, &last_idx_inspected, &attempted_idx);
885 i = last_idx_inspected;
886 mount_errno = errno;
JP Abgrallf786fe52014-06-18 07:28:14 +0000887
JP Abgrall5c01dac2014-06-18 14:54:37 -0700888 /* Deal with encryptability. */
Ken Sumrallc1bf8962012-01-06 19:09:42 -0800889 if (!mret) {
Paul Lawrence69080182016-02-02 10:31:30 -0800890 int status = handle_encryptable(&fstab->recs[attempted_idx]);
Paul Lawrenceb8c9d272015-03-26 15:49:42 +0000891
892 if (status == FS_MGR_MNTALL_FAIL) {
893 /* Fatal error - no point continuing */
894 return status;
Paul Lawrence166fa3d2014-02-03 13:27:49 -0800895 }
Paul Lawrenceb8c9d272015-03-26 15:49:42 +0000896
Paul Lawrence1098aac2016-03-04 15:52:33 -0800897 if (status != FS_MGR_MNTALL_DEV_NOT_ENCRYPTABLE) {
898 if (encryptable != FS_MGR_MNTALL_DEV_NOT_ENCRYPTABLE) {
Paul Lawrenceb8c9d272015-03-26 15:49:42 +0000899 // Log and continue
bowgotsai47878de2017-01-23 14:04:34 +0800900 LERROR << "Only one encryptable/encrypted partition supported";
Paul Lawrenceb8c9d272015-03-26 15:49:42 +0000901 }
902 encryptable = status;
Paul Crowleyc6846962018-01-30 09:56:03 -0800903 if (status == FS_MGR_MNTALL_DEV_NEEDS_METADATA_ENCRYPTION) {
904 if (!call_vdc(
905 {"cryptfs", "encryptFstab", fstab->recs[attempted_idx].mount_point})) {
906 LERROR << "Encryption failed";
907 return FS_MGR_MNTALL_FAIL;
908 }
909 }
Paul Lawrenceb8c9d272015-03-26 15:49:42 +0000910 }
911
Ken Sumrallc1bf8962012-01-06 19:09:42 -0800912 /* Success! Go get the next one */
913 continue;
914 }
915
Chris Fries79f33842013-09-05 13:19:21 -0500916 bool wiped = partition_wiped(fstab->recs[top_idx].blk_device);
Chuanxiao Dongd78dff12016-03-08 15:54:55 +0100917 bool crypt_footer = false;
Chris Fries79f33842013-09-05 13:19:21 -0500918 if (mret && mount_errno != EBUSY && mount_errno != EACCES &&
919 fs_mgr_is_formattable(&fstab->recs[top_idx]) && wiped) {
920 /* top_idx and attempted_idx point at the same partition, but sometimes
921 * at two different lines in the fstab. Use the top one for formatting
922 * as that is the preferred one.
923 */
bowgotsai47878de2017-01-23 14:04:34 +0800924 LERROR << __FUNCTION__ << "(): " << fstab->recs[top_idx].blk_device
925 << " is wiped and " << fstab->recs[top_idx].mount_point
926 << " " << fstab->recs[top_idx].fs_type
927 << " is formattable. Format it.";
Chris Fries79f33842013-09-05 13:19:21 -0500928 if (fs_mgr_is_encryptable(&fstab->recs[top_idx]) &&
929 strcmp(fstab->recs[top_idx].key_loc, KEY_IN_FOOTER)) {
George Burgess IVe7aa2b22016-03-02 14:02:55 -0800930 int fd = open(fstab->recs[top_idx].key_loc, O_WRONLY);
Chris Fries79f33842013-09-05 13:19:21 -0500931 if (fd >= 0) {
bowgotsai47878de2017-01-23 14:04:34 +0800932 LINFO << __FUNCTION__ << "(): also wipe "
933 << fstab->recs[top_idx].key_loc;
Chris Fries79f33842013-09-05 13:19:21 -0500934 wipe_block_device(fd, get_file_size(fd));
935 close(fd);
936 } else {
bowgotsai47878de2017-01-23 14:04:34 +0800937 PERROR << __FUNCTION__ << "(): "
938 << fstab->recs[top_idx].key_loc << " wouldn't open";
Chris Fries79f33842013-09-05 13:19:21 -0500939 }
Chuanxiao Dongd78dff12016-03-08 15:54:55 +0100940 } else if (fs_mgr_is_encryptable(&fstab->recs[top_idx]) &&
941 !strcmp(fstab->recs[top_idx].key_loc, KEY_IN_FOOTER)) {
942 crypt_footer = true;
Chris Fries79f33842013-09-05 13:19:21 -0500943 }
Chuanxiao Dongd78dff12016-03-08 15:54:55 +0100944 if (fs_mgr_do_format(&fstab->recs[top_idx], crypt_footer) == 0) {
Chris Fries79f33842013-09-05 13:19:21 -0500945 /* Let's replay the mount actions. */
946 i = top_idx - 1;
947 continue;
Matthew Bouyack9c59cbc2016-05-02 15:55:30 -0700948 } else {
bowgotsai47878de2017-01-23 14:04:34 +0800949 LERROR << __FUNCTION__ << "(): Format failed. "
950 << "Suggest recovery...";
Matthew Bouyack9c59cbc2016-05-02 15:55:30 -0700951 encryptable = FS_MGR_MNTALL_DEV_NEEDS_RECOVERY;
952 continue;
Chris Fries79f33842013-09-05 13:19:21 -0500953 }
954 }
Paul Lawrence9dbe97b2017-04-21 12:41:48 -0700955
956 /* mount(2) returned an error, handle the encryptable/formattable case */
JP Abgrall5c01dac2014-06-18 14:54:37 -0700957 if (mret && mount_errno != EBUSY && mount_errno != EACCES &&
JP Abgrallcee20682014-07-02 14:26:54 -0700958 fs_mgr_is_encryptable(&fstab->recs[attempted_idx])) {
Chris Fries79f33842013-09-05 13:19:21 -0500959 if (wiped) {
bowgotsai47878de2017-01-23 14:04:34 +0800960 LERROR << __FUNCTION__ << "(): "
961 << fstab->recs[attempted_idx].blk_device
962 << " is wiped and "
963 << fstab->recs[attempted_idx].mount_point << " "
964 << fstab->recs[attempted_idx].fs_type
965 << " is encryptable. Suggest recovery...";
JP Abgrallcee20682014-07-02 14:26:54 -0700966 encryptable = FS_MGR_MNTALL_DEV_NEEDS_RECOVERY;
Mohamad Ayyash38afe5f2014-03-10 15:40:29 -0700967 continue;
JP Abgrall4bb7bba2014-06-19 22:12:20 -0700968 } else {
969 /* Need to mount a tmpfs at this mountpoint for now, and set
970 * properties that vold will query later for decrypting
971 */
bowgotsai47878de2017-01-23 14:04:34 +0800972 LERROR << __FUNCTION__ << "(): possibly an encryptable blkdev "
973 << fstab->recs[attempted_idx].blk_device
974 << " for mount " << fstab->recs[attempted_idx].mount_point
975 << " type " << fstab->recs[attempted_idx].fs_type;
JP Abgrallf22b7452014-07-02 13:16:04 -0700976 if (fs_mgr_do_tmpfs_mount(fstab->recs[attempted_idx].mount_point) < 0) {
JP Abgrall4bb7bba2014-06-19 22:12:20 -0700977 ++error_count;
978 continue;
979 }
Ken Sumrallc1bf8962012-01-06 19:09:42 -0800980 }
JP Abgrallf22b7452014-07-02 13:16:04 -0700981 encryptable = FS_MGR_MNTALL_DEV_MIGHT_BE_ENCRYPTED;
Paul Lawrence9dbe97b2017-04-21 12:41:48 -0700982 } else if (mret && mount_errno != EBUSY && mount_errno != EACCES &&
983 should_use_metadata_encryption(&fstab->recs[attempted_idx])) {
Paul Crowleyc6846962018-01-30 09:56:03 -0800984 if (!call_vdc({"cryptfs", "mountFstab", fstab->recs[attempted_idx].mount_point})) {
985 ++error_count;
986 }
Paul Lawrence9dbe97b2017-04-21 12:41:48 -0700987 encryptable = FS_MGR_MNTALL_DEV_IS_METADATA_ENCRYPTED;
Paul Crowleyc6846962018-01-30 09:56:03 -0800988 continue;
Ken Sumrallc1bf8962012-01-06 19:09:42 -0800989 } else {
Bowgo Tsai59af33c2017-05-24 18:51:36 +0800990 // fs_options might be null so we cannot use PERROR << directly.
991 // Use StringPrintf to output "(null)" instead.
Daniel Rosenbergd38e3c52016-04-07 20:10:25 -0700992 if (fs_mgr_is_nofail(&fstab->recs[attempted_idx])) {
Bowgo Tsai59af33c2017-05-24 18:51:36 +0800993 PERROR << android::base::StringPrintf(
994 "Ignoring failure to mount an un-encryptable or wiped "
995 "partition on %s at %s options: %s",
996 fstab->recs[attempted_idx].blk_device, fstab->recs[attempted_idx].mount_point,
997 fstab->recs[attempted_idx].fs_options);
Daniel Rosenbergd38e3c52016-04-07 20:10:25 -0700998 } else {
Bowgo Tsai59af33c2017-05-24 18:51:36 +0800999 PERROR << android::base::StringPrintf(
1000 "Failed to mount an un-encryptable or wiped partition "
1001 "on %s at %s options: %s",
1002 fstab->recs[attempted_idx].blk_device, fstab->recs[attempted_idx].mount_point,
1003 fstab->recs[attempted_idx].fs_options);
Daniel Rosenbergd38e3c52016-04-07 20:10:25 -07001004 ++error_count;
1005 }
Mohamad Ayyash38afe5f2014-03-10 15:40:29 -07001006 continue;
Ken Sumrallc1bf8962012-01-06 19:09:42 -08001007 }
1008 }
1009
Mohamad Ayyash38afe5f2014-03-10 15:40:29 -07001010 if (error_count) {
Bowgo Tsai359bed32017-04-27 15:44:39 +08001011 return FS_MGR_MNTALL_FAIL;
Mohamad Ayyash38afe5f2014-03-10 15:40:29 -07001012 } else {
Paul Lawrence166fa3d2014-02-03 13:27:49 -08001013 return encryptable;
Mohamad Ayyash38afe5f2014-03-10 15:40:29 -07001014 }
Ken Sumrallc1bf8962012-01-06 19:09:42 -08001015}
1016
Sandeep Patil56f9ada2017-02-14 14:00:14 -08001017/* wrapper to __mount() and expects a fully prepared fstab_rec,
1018 * unlike fs_mgr_do_mount which does more things with avb / verity
1019 * etc.
1020 */
1021int fs_mgr_do_mount_one(struct fstab_rec *rec)
1022{
1023 if (!rec) {
1024 return FS_MGR_DOMNT_FAILED;
1025 }
1026
1027 int ret = __mount(rec->blk_device, rec->mount_point, rec);
1028 if (ret) {
1029 ret = (errno == EBUSY) ? FS_MGR_DOMNT_BUSY : FS_MGR_DOMNT_FAILED;
1030 }
1031
1032 return ret;
1033}
1034
Ken Sumrallab6b8522013-02-13 12:58:40 -08001035/* If tmp_mount_point is non-null, mount the filesystem there. This is for the
Ken Sumrallc1bf8962012-01-06 19:09:42 -08001036 * tmp mount we do to check the user password
JP Abgrall5c01dac2014-06-18 14:54:37 -07001037 * If multiple fstab entries are to be mounted on "n_name", it will try to mount each one
1038 * in turn, and stop on 1st success, or no more match.
Ken Sumrallc1bf8962012-01-06 19:09:42 -08001039 */
Jin Qian8b7eb7b2016-11-03 13:36:35 -07001040int fs_mgr_do_mount(struct fstab *fstab, const char *n_name, char *n_blk_device,
Ken Sumrallab6b8522013-02-13 12:58:40 -08001041 char *tmp_mount_point)
Ken Sumrallc1bf8962012-01-06 19:09:42 -08001042{
1043 int i = 0;
JP Abgrall5c01dac2014-06-18 14:54:37 -07001044 int mount_errors = 0;
1045 int first_mount_errno = 0;
Bowgo Tsai359bed32017-04-27 15:44:39 +08001046 char* mount_point;
Bowgo Tsai95c966a2017-03-30 18:42:54 +08001047 FsManagerAvbUniquePtr avb_handle(nullptr);
Ken Sumrallc1bf8962012-01-06 19:09:42 -08001048
Ken Sumrallab6b8522013-02-13 12:58:40 -08001049 if (!fstab) {
Bowgo Tsai359bed32017-04-27 15:44:39 +08001050 return FS_MGR_DOMNT_FAILED;
Ken Sumrallc1bf8962012-01-06 19:09:42 -08001051 }
1052
Ken Sumrallab6b8522013-02-13 12:58:40 -08001053 for (i = 0; i < fstab->num_entries; i++) {
1054 if (!fs_match(fstab->recs[i].mount_point, n_name)) {
Ken Sumrallc1bf8962012-01-06 19:09:42 -08001055 continue;
1056 }
1057
1058 /* We found our match */
Ken Sumrall5bc31a22013-07-08 19:11:55 -07001059 /* If this swap or a raw partition, report an error */
1060 if (!strcmp(fstab->recs[i].fs_type, "swap") ||
1061 !strcmp(fstab->recs[i].fs_type, "emmc") ||
Ken Sumrallab6b8522013-02-13 12:58:40 -08001062 !strcmp(fstab->recs[i].fs_type, "mtd")) {
bowgotsai47878de2017-01-23 14:04:34 +08001063 LERROR << "Cannot mount filesystem of type "
1064 << fstab->recs[i].fs_type << " on " << n_blk_device;
Bowgo Tsai359bed32017-04-27 15:44:39 +08001065 return FS_MGR_DOMNT_FAILED;
Ken Sumrallc1bf8962012-01-06 19:09:42 -08001066 }
1067
Ken Sumrallab6b8522013-02-13 12:58:40 -08001068 /* First check the filesystem if requested */
Jinguang Dong9d344962017-06-13 10:20:34 +08001069 if (fstab->recs[i].fs_mgr_flags & MF_WAIT && !fs_mgr_wait_for_file(n_blk_device, 20s)) {
1070 LERROR << "Skipping mounting '" << n_blk_device << "'";
1071 continue;
Ken Sumrallab6b8522013-02-13 12:58:40 -08001072 }
1073
Eric Biggers8d3bcd42017-07-05 12:21:15 -07001074 int fs_stat = prepare_fs_for_mount(n_blk_device, &fstab->recs[i]);
liminghao9a0fd1d2016-07-22 11:48:14 +08001075
Bowgo Tsai95c966a2017-03-30 18:42:54 +08001076 if (fstab->recs[i].fs_mgr_flags & MF_AVB) {
1077 if (!avb_handle) {
Bowgo Tsai20651f62017-05-08 20:45:50 +08001078 avb_handle = FsManagerAvbHandle::Open(*fstab);
Bowgo Tsai95c966a2017-03-30 18:42:54 +08001079 if (!avb_handle) {
1080 LERROR << "Failed to open FsManagerAvbHandle";
Bowgo Tsai359bed32017-04-27 15:44:39 +08001081 return FS_MGR_DOMNT_FAILED;
Bowgo Tsai95c966a2017-03-30 18:42:54 +08001082 }
1083 }
Bowgo Tsai60f19a02017-06-22 22:23:08 +08001084 if (avb_handle->SetUpAvbHashtree(&fstab->recs[i], true /* wait_for_verity_dev */) ==
1085 SetUpAvbHashtreeResult::kFail) {
bowgotsai47878de2017-01-23 14:04:34 +08001086 LERROR << "Failed to set up AVB on partition: "
1087 << fstab->recs[i].mount_point << ", skipping!";
bowgotsaib51722b2017-01-11 22:21:38 +08001088 /* Skips mounting the device. */
1089 continue;
1090 }
Bowgo Tsai744361f2017-10-11 14:58:40 +08001091 } else if ((fstab->recs[i].fs_mgr_flags & MF_VERIFY)) {
Hung-ying Tyanecfce132016-12-16 15:00:05 +08001092 int rc = fs_mgr_setup_verity(&fstab->recs[i], true);
Sandeep Patil95366e92017-06-21 12:58:31 -07001093 if (__android_log_is_debuggable() &&
1094 (rc == FS_MGR_SETUP_VERITY_DISABLED ||
1095 rc == FS_MGR_SETUP_VERITY_SKIPPED)) {
bowgotsai47878de2017-01-23 14:04:34 +08001096 LINFO << "Verity disabled";
Paul Lawrencebbb36312014-10-09 14:22:49 +00001097 } else if (rc != FS_MGR_SETUP_VERITY_SUCCESS) {
bowgotsai47878de2017-01-23 14:04:34 +08001098 LERROR << "Could not set up verified partition, skipping!";
Geremy Condra3ad3d1c2013-02-22 18:11:41 -08001099 continue;
1100 }
1101 }
1102
Ken Sumrallc1bf8962012-01-06 19:09:42 -08001103 /* Now mount it where requested */
Ken Sumrallab6b8522013-02-13 12:58:40 -08001104 if (tmp_mount_point) {
Bowgo Tsai359bed32017-04-27 15:44:39 +08001105 mount_point = tmp_mount_point;
Ken Sumrallc1bf8962012-01-06 19:09:42 -08001106 } else {
Bowgo Tsai359bed32017-04-27 15:44:39 +08001107 mount_point = fstab->recs[i].mount_point;
Ken Sumrallc1bf8962012-01-06 19:09:42 -08001108 }
Keun-young Park40db04d2017-04-13 17:31:08 -07001109 int retry_count = 2;
1110 while (retry_count-- > 0) {
Bowgo Tsai359bed32017-04-27 15:44:39 +08001111 if (!__mount(n_blk_device, mount_point, &fstab->recs[i])) {
Keun-young Park40db04d2017-04-13 17:31:08 -07001112 fs_stat &= ~FS_STAT_FULL_MOUNT_FAILED;
Bowgo Tsai359bed32017-04-27 15:44:39 +08001113 return FS_MGR_DOMNT_SUCCESS;
Keun-young Park40db04d2017-04-13 17:31:08 -07001114 } else {
1115 if (retry_count <= 0) break; // run check_fs only once
1116 if (!first_mount_errno) first_mount_errno = errno;
1117 mount_errors++;
1118 fs_stat |= FS_STAT_FULL_MOUNT_FAILED;
1119 // try again after fsck
1120 check_fs(n_blk_device, fstab->recs[i].fs_type, fstab->recs[i].mount_point, &fs_stat);
1121 }
Ken Sumrallc1bf8962012-01-06 19:09:42 -08001122 }
Keun-young Park40db04d2017-04-13 17:31:08 -07001123 log_fs_stat(fstab->recs[i].blk_device, fs_stat);
Ken Sumrallc1bf8962012-01-06 19:09:42 -08001124 }
Bowgo Tsai359bed32017-04-27 15:44:39 +08001125
1126 // Reach here means the mount attempt fails.
JP Abgrall5c01dac2014-06-18 14:54:37 -07001127 if (mount_errors) {
Bowgo Tsai359bed32017-04-27 15:44:39 +08001128 PERROR << "Cannot mount filesystem on " << n_blk_device << " at " << mount_point;
1129 if (first_mount_errno == EBUSY) return FS_MGR_DOMNT_BUSY;
JP Abgrall5c01dac2014-06-18 14:54:37 -07001130 } else {
1131 /* We didn't find a match, say so and return an error */
Bowgo Tsai359bed32017-04-27 15:44:39 +08001132 LERROR << "Cannot find mount point " << n_name << " in fstab";
JP Abgrall5c01dac2014-06-18 14:54:37 -07001133 }
Bowgo Tsai359bed32017-04-27 15:44:39 +08001134 return FS_MGR_DOMNT_FAILED;
Ken Sumrallc1bf8962012-01-06 19:09:42 -08001135}
1136
1137/*
1138 * mount a tmpfs filesystem at the given point.
1139 * return 0 on success, non-zero on failure.
1140 */
Wei Wang4d71bc52017-02-24 17:41:38 -08001141int fs_mgr_do_tmpfs_mount(const char *n_name)
Ken Sumrallc1bf8962012-01-06 19:09:42 -08001142{
1143 int ret;
1144
1145 ret = mount("tmpfs", n_name, "tmpfs",
1146 MS_NOATIME | MS_NOSUID | MS_NODEV, CRYPTO_TMPFS_OPTIONS);
1147 if (ret < 0) {
bowgotsai47878de2017-01-23 14:04:34 +08001148 LERROR << "Cannot mount tmpfs filesystem at " << n_name;
Ken Sumrallc1bf8962012-01-06 19:09:42 -08001149 return -1;
1150 }
1151
1152 /* Success */
1153 return 0;
1154}
1155
Ken Sumrallab6b8522013-02-13 12:58:40 -08001156int fs_mgr_unmount_all(struct fstab *fstab)
Ken Sumrallc1bf8962012-01-06 19:09:42 -08001157{
1158 int i = 0;
1159 int ret = 0;
Ken Sumrallc1bf8962012-01-06 19:09:42 -08001160
Ken Sumrallab6b8522013-02-13 12:58:40 -08001161 if (!fstab) {
Ken Sumrallc1bf8962012-01-06 19:09:42 -08001162 return -1;
1163 }
1164
Ken Sumrallab6b8522013-02-13 12:58:40 -08001165 while (fstab->recs[i].blk_device) {
1166 if (umount(fstab->recs[i].mount_point)) {
bowgotsai47878de2017-01-23 14:04:34 +08001167 LERROR << "Cannot unmount filesystem at "
1168 << fstab->recs[i].mount_point;
Ken Sumrallc1bf8962012-01-06 19:09:42 -08001169 ret = -1;
1170 }
1171 i++;
1172 }
1173
Ken Sumrallc1bf8962012-01-06 19:09:42 -08001174 return ret;
1175}
Ken Sumrall5bc31a22013-07-08 19:11:55 -07001176
1177/* This must be called after mount_all, because the mkswap command needs to be
1178 * available.
1179 */
1180int fs_mgr_swapon_all(struct fstab *fstab)
1181{
1182 int i = 0;
1183 int flags = 0;
1184 int err = 0;
1185 int ret = 0;
1186 int status;
bowgotsaicea7ea72017-01-16 21:49:49 +08001187 const char *mkswap_argv[2] = {
Ken Sumrall5bc31a22013-07-08 19:11:55 -07001188 MKSWAP_BIN,
bowgotsaicea7ea72017-01-16 21:49:49 +08001189 nullptr
Ken Sumrall5bc31a22013-07-08 19:11:55 -07001190 };
1191
1192 if (!fstab) {
1193 return -1;
1194 }
1195
1196 for (i = 0; i < fstab->num_entries; i++) {
1197 /* Skip non-swap entries */
1198 if (strcmp(fstab->recs[i].fs_type, "swap")) {
1199 continue;
1200 }
1201
1202 if (fstab->recs[i].zram_size > 0) {
1203 /* A zram_size was specified, so we need to configure the
1204 * device. There is no point in having multiple zram devices
1205 * on a system (all the memory comes from the same pool) so
1206 * we can assume the device number is 0.
1207 */
1208 FILE *zram_fp;
Peter Enderborg4d217f02016-08-26 15:09:35 +02001209 FILE *zram_mcs_fp;
1210
1211 if (fstab->recs[i].max_comp_streams >= 0) {
1212 zram_mcs_fp = fopen(ZRAM_CONF_MCS, "r+");
1213 if (zram_mcs_fp == NULL) {
bowgotsai47878de2017-01-23 14:04:34 +08001214 LERROR << "Unable to open zram conf comp device "
1215 << ZRAM_CONF_MCS;
Peter Enderborg4d217f02016-08-26 15:09:35 +02001216 ret = -1;
1217 continue;
1218 }
1219 fprintf(zram_mcs_fp, "%d\n", fstab->recs[i].max_comp_streams);
1220 fclose(zram_mcs_fp);
1221 }
Ken Sumrall5bc31a22013-07-08 19:11:55 -07001222
1223 zram_fp = fopen(ZRAM_CONF_DEV, "r+");
1224 if (zram_fp == NULL) {
bowgotsai47878de2017-01-23 14:04:34 +08001225 LERROR << "Unable to open zram conf device " << ZRAM_CONF_DEV;
Ken Sumrall5bc31a22013-07-08 19:11:55 -07001226 ret = -1;
1227 continue;
1228 }
Jinguang Dongf7d10142017-06-01 19:42:22 +08001229 fprintf(zram_fp, "%u\n", fstab->recs[i].zram_size);
Ken Sumrall5bc31a22013-07-08 19:11:55 -07001230 fclose(zram_fp);
1231 }
1232
Jinguang Dong9d344962017-06-13 10:20:34 +08001233 if (fstab->recs[i].fs_mgr_flags & MF_WAIT &&
1234 !fs_mgr_wait_for_file(fstab->recs[i].blk_device, 20s)) {
1235 LERROR << "Skipping mkswap for '" << fstab->recs[i].blk_device << "'";
1236 ret = -1;
1237 continue;
Ken Sumrall5bc31a22013-07-08 19:11:55 -07001238 }
1239
1240 /* Initialize the swap area */
1241 mkswap_argv[1] = fstab->recs[i].blk_device;
bowgotsaicea7ea72017-01-16 21:49:49 +08001242 err = android_fork_execvp_ext(ARRAY_SIZE(mkswap_argv),
1243 const_cast<char **>(mkswap_argv),
Yusuke Satod81c3c62015-08-14 01:22:53 -07001244 &status, true, LOG_KLOG, false, NULL,
1245 NULL, 0);
Ken Sumrall5bc31a22013-07-08 19:11:55 -07001246 if (err) {
bowgotsai47878de2017-01-23 14:04:34 +08001247 LERROR << "mkswap failed for " << fstab->recs[i].blk_device;
Ken Sumrall5bc31a22013-07-08 19:11:55 -07001248 ret = -1;
1249 continue;
1250 }
1251
1252 /* If -1, then no priority was specified in fstab, so don't set
1253 * SWAP_FLAG_PREFER or encode the priority */
1254 if (fstab->recs[i].swap_prio >= 0) {
1255 flags = (fstab->recs[i].swap_prio << SWAP_FLAG_PRIO_SHIFT) &
1256 SWAP_FLAG_PRIO_MASK;
1257 flags |= SWAP_FLAG_PREFER;
1258 } else {
1259 flags = 0;
1260 }
1261 err = swapon(fstab->recs[i].blk_device, flags);
1262 if (err) {
bowgotsai47878de2017-01-23 14:04:34 +08001263 LERROR << "swapon failed for " << fstab->recs[i].blk_device;
Ken Sumrall5bc31a22013-07-08 19:11:55 -07001264 ret = -1;
1265 }
1266 }
1267
1268 return ret;
1269}
1270
Paul Lawrence9dbe97b2017-04-21 12:41:48 -07001271struct fstab_rec const* fs_mgr_get_crypt_entry(struct fstab const* fstab) {
1272 int i;
Ken Sumrallc1bf8962012-01-06 19:09:42 -08001273
Ken Sumrallab6b8522013-02-13 12:58:40 -08001274 if (!fstab) {
Paul Lawrence9dbe97b2017-04-21 12:41:48 -07001275 return NULL;
Ken Sumrallc1bf8962012-01-06 19:09:42 -08001276 }
1277
1278 /* Look for the encryptable partition to find the data */
Ken Sumrallab6b8522013-02-13 12:58:40 -08001279 for (i = 0; i < fstab->num_entries; i++) {
1280 /* Don't deal with vold managed enryptable partitions here */
Paul Lawrence9dbe97b2017-04-21 12:41:48 -07001281 if (!(fstab->recs[i].fs_mgr_flags & MF_VOLDMANAGED) &&
1282 (fstab->recs[i].fs_mgr_flags &
1283 (MF_CRYPT | MF_FORCECRYPT | MF_FORCEFDEORFBE | MF_FILEENCRYPTION))) {
1284 return &fstab->recs[i];
Ken Sumrallab6b8522013-02-13 12:58:40 -08001285 }
Ken Sumrallc1bf8962012-01-06 19:09:42 -08001286 }
Paul Lawrence9dbe97b2017-04-21 12:41:48 -07001287 return NULL;
1288}
Ken Sumrallc1bf8962012-01-06 19:09:42 -08001289
Paul Lawrence9dbe97b2017-04-21 12:41:48 -07001290/*
1291 * key_loc must be at least PROPERTY_VALUE_MAX bytes long
1292 *
1293 * real_blk_device must be at least PROPERTY_VALUE_MAX bytes long
1294 */
1295void fs_mgr_get_crypt_info(struct fstab* fstab, char* key_loc, char* real_blk_device, size_t size) {
1296 struct fstab_rec const* rec = fs_mgr_get_crypt_entry(fstab);
1297 if (key_loc) {
1298 if (rec) {
1299 strlcpy(key_loc, rec->key_loc, size);
1300 } else {
1301 *key_loc = '\0';
1302 }
1303 }
1304 if (real_blk_device) {
1305 if (rec) {
1306 strlcpy(real_blk_device, rec->blk_device, size);
1307 } else {
1308 *real_blk_device = '\0';
1309 }
1310 }
Ken Sumrallc1bf8962012-01-06 19:09:42 -08001311}
Bowgo Tsaiaaf70e72017-03-02 00:03:56 +08001312
1313bool fs_mgr_load_verity_state(int* mode) {
1314 /* return the default mode, unless any of the verified partitions are in
1315 * logging mode, in which case return that */
1316 *mode = VERITY_MODE_DEFAULT;
1317
1318 std::unique_ptr<fstab, decltype(&fs_mgr_free_fstab)> fstab(fs_mgr_read_fstab_default(),
1319 fs_mgr_free_fstab);
1320 if (!fstab) {
1321 LERROR << "Failed to read default fstab";
1322 return false;
1323 }
1324
1325 for (int i = 0; i < fstab->num_entries; i++) {
1326 if (fs_mgr_is_avb(&fstab->recs[i])) {
1327 *mode = VERITY_MODE_RESTART; // avb only supports restart mode.
1328 break;
1329 } else if (!fs_mgr_is_verified(&fstab->recs[i])) {
1330 continue;
1331 }
1332
1333 int current;
1334 if (load_verity_state(&fstab->recs[i], &current) < 0) {
1335 continue;
1336 }
1337 if (current != VERITY_MODE_DEFAULT) {
1338 *mode = current;
1339 break;
1340 }
1341 }
1342
1343 return true;
1344}
1345
1346bool fs_mgr_update_verity_state(fs_mgr_verity_state_callback callback) {
1347 if (!callback) {
1348 return false;
1349 }
1350
1351 int mode;
1352 if (!fs_mgr_load_verity_state(&mode)) {
1353 return false;
1354 }
1355
1356 android::base::unique_fd fd(TEMP_FAILURE_RETRY(open("/dev/device-mapper", O_RDWR | O_CLOEXEC)));
1357 if (fd == -1) {
1358 PERROR << "Error opening device mapper";
1359 return false;
1360 }
1361
1362 std::unique_ptr<fstab, decltype(&fs_mgr_free_fstab)> fstab(fs_mgr_read_fstab_default(),
1363 fs_mgr_free_fstab);
1364 if (!fstab) {
1365 LERROR << "Failed to read default fstab";
1366 return false;
1367 }
1368
1369 alignas(dm_ioctl) char buffer[DM_BUF_SIZE];
1370 struct dm_ioctl* io = (struct dm_ioctl*)buffer;
1371 bool system_root = android::base::GetProperty("ro.build.system_root_image", "") == "true";
1372
1373 for (int i = 0; i < fstab->num_entries; i++) {
1374 if (!fs_mgr_is_verified(&fstab->recs[i]) && !fs_mgr_is_avb(&fstab->recs[i])) {
1375 continue;
1376 }
1377
1378 std::string mount_point;
1379 if (system_root && !strcmp(fstab->recs[i].mount_point, "/")) {
Bowgo Tsai48fdc292017-04-27 18:18:56 +08001380 // In AVB, the dm device name is vroot instead of system.
1381 mount_point = fs_mgr_is_avb(&fstab->recs[i]) ? "vroot" : "system";
Bowgo Tsaiaaf70e72017-03-02 00:03:56 +08001382 } else {
1383 mount_point = basename(fstab->recs[i].mount_point);
1384 }
1385
1386 fs_mgr_verity_ioctl_init(io, mount_point, 0);
1387
1388 const char* status;
1389 if (ioctl(fd, DM_TABLE_STATUS, io)) {
1390 if (fstab->recs[i].fs_mgr_flags & MF_VERIFYATBOOT) {
1391 status = "V";
1392 } else {
1393 PERROR << "Failed to query DM_TABLE_STATUS for " << mount_point.c_str();
1394 continue;
1395 }
1396 }
1397
1398 status = &buffer[io->data_start + sizeof(struct dm_target_spec)];
1399
Bowgo Tsai48fdc292017-04-27 18:18:56 +08001400 // To be consistent in vboot 1.0 and vboot 2.0 (AVB), change the mount_point
1401 // back to 'system' for the callback. So it has property [partition.system.verified]
1402 // instead of [partition.vroot.verified].
1403 if (mount_point == "vroot") mount_point = "system";
Bowgo Tsaiaaf70e72017-03-02 00:03:56 +08001404 if (*status == 'C' || *status == 'V') {
1405 callback(&fstab->recs[i], mount_point.c_str(), mode, *status);
1406 }
1407 }
1408
1409 return true;
1410}