• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 
17 #include "fs_mgr.h"
18 
19 #include <ctype.h>
20 #include <dirent.h>
21 #include <errno.h>
22 #include <fcntl.h>
23 #include <inttypes.h>
24 #include <libgen.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <sys/ioctl.h>
29 #include <sys/mount.h>
30 #include <sys/stat.h>
31 #include <sys/swap.h>
32 #include <sys/types.h>
33 #include <sys/wait.h>
34 #include <time.h>
35 #include <unistd.h>
36 
37 #include <functional>
38 #include <map>
39 #include <memory>
40 #include <string>
41 #include <thread>
42 #include <utility>
43 #include <vector>
44 
45 #include <android-base/file.h>
46 #include <android-base/properties.h>
47 #include <android-base/stringprintf.h>
48 #include <android-base/strings.h>
49 #include <android-base/unique_fd.h>
50 #include <cutils/android_filesystem_config.h>
51 #include <cutils/android_reboot.h>
52 #include <cutils/partition_utils.h>
53 #include <cutils/properties.h>
54 #include <ext4_utils/ext4.h>
55 #include <ext4_utils/ext4_sb.h>
56 #include <ext4_utils/ext4_utils.h>
57 #include <ext4_utils/wipe.h>
58 #include <fs_avb/fs_avb.h>
59 #include <fs_mgr_overlayfs.h>
60 #include <libdm/dm.h>
61 #include <liblp/metadata_format.h>
62 #include <linux/fs.h>
63 #include <linux/loop.h>
64 #include <linux/magic.h>
65 #include <log/log_properties.h>
66 #include <logwrap/logwrap.h>
67 
68 #include "fs_mgr_priv.h"
69 
70 #define KEY_LOC_PROP   "ro.crypto.keyfile.userdata"
71 #define KEY_IN_FOOTER  "footer"
72 
73 #define E2FSCK_BIN      "/system/bin/e2fsck"
74 #define F2FS_FSCK_BIN   "/system/bin/fsck.f2fs"
75 #define MKSWAP_BIN      "/system/bin/mkswap"
76 #define TUNE2FS_BIN     "/system/bin/tune2fs"
77 
78 #define FSCK_LOG_FILE   "/dev/fscklogs/log"
79 
80 #define ZRAM_CONF_DEV   "/sys/block/zram0/disksize"
81 #define ZRAM_CONF_MCS   "/sys/block/zram0/max_comp_streams"
82 #define ZRAM_BACK_DEV   "/sys/block/zram0/backing_dev"
83 
84 #define SYSFS_EXT4_VERITY "/sys/fs/ext4/features/verity"
85 
86 #define ARRAY_SIZE(a) (sizeof(a) / sizeof(*(a)))
87 
88 using android::base::Basename;
89 using android::base::Realpath;
90 using android::base::StartsWith;
91 using android::base::unique_fd;
92 using android::dm::DeviceMapper;
93 using android::dm::DmDeviceState;
94 
95 // Realistically, this file should be part of the android::fs_mgr namespace;
96 using namespace android::fs_mgr;
97 
98 using namespace std::literals;
99 
100 // record fs stat
101 enum FsStatFlags {
102     FS_STAT_IS_EXT4 = 0x0001,
103     FS_STAT_NEW_IMAGE_VERSION = 0x0002,
104     FS_STAT_E2FSCK_F_ALWAYS = 0x0004,
105     FS_STAT_UNCLEAN_SHUTDOWN = 0x0008,
106     FS_STAT_QUOTA_ENABLED = 0x0010,
107     FS_STAT_RO_MOUNT_FAILED = 0x0040,
108     FS_STAT_RO_UNMOUNT_FAILED = 0x0080,
109     FS_STAT_FULL_MOUNT_FAILED = 0x0100,
110     FS_STAT_E2FSCK_FAILED = 0x0200,
111     FS_STAT_E2FSCK_FS_FIXED = 0x0400,
112     FS_STAT_INVALID_MAGIC = 0x0800,
113     FS_STAT_TOGGLE_QUOTAS_FAILED = 0x10000,
114     FS_STAT_SET_RESERVED_BLOCKS_FAILED = 0x20000,
115     FS_STAT_ENABLE_ENCRYPTION_FAILED = 0x40000,
116     FS_STAT_ENABLE_VERITY_FAILED = 0x80000,
117 };
118 
119 // TODO: switch to inotify()
fs_mgr_wait_for_file(const std::string & filename,const std::chrono::milliseconds relative_timeout,FileWaitMode file_wait_mode)120 bool fs_mgr_wait_for_file(const std::string& filename,
121                           const std::chrono::milliseconds relative_timeout,
122                           FileWaitMode file_wait_mode) {
123     auto start_time = std::chrono::steady_clock::now();
124 
125     while (true) {
126         int rv = access(filename.c_str(), F_OK);
127         if (file_wait_mode == FileWaitMode::Exists) {
128             if (!rv || errno != ENOENT) return true;
129         } else if (file_wait_mode == FileWaitMode::DoesNotExist) {
130             if (rv && errno == ENOENT) return true;
131         }
132 
133         std::this_thread::sleep_for(50ms);
134 
135         auto now = std::chrono::steady_clock::now();
136         auto time_elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(now - start_time);
137         if (time_elapsed > relative_timeout) return false;
138     }
139 }
140 
log_fs_stat(const std::string & blk_device,int fs_stat)141 static void log_fs_stat(const std::string& blk_device, int fs_stat) {
142     if ((fs_stat & FS_STAT_IS_EXT4) == 0) return; // only log ext4
143     std::string msg =
144             android::base::StringPrintf("\nfs_stat,%s,0x%x\n", blk_device.c_str(), fs_stat);
145     android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(FSCK_LOG_FILE, O_WRONLY | O_CLOEXEC |
146                                                         O_APPEND | O_CREAT, 0664)));
147     if (fd == -1 || !android::base::WriteStringToFd(msg, fd)) {
148         LWARNING << __FUNCTION__ << "() cannot log " << msg;
149     }
150 }
151 
is_extfs(const std::string & fs_type)152 static bool is_extfs(const std::string& fs_type) {
153     return fs_type == "ext4" || fs_type == "ext3" || fs_type == "ext2";
154 }
155 
is_f2fs(const std::string & fs_type)156 static bool is_f2fs(const std::string& fs_type) {
157     return fs_type == "f2fs";
158 }
159 
realpath(const std::string & blk_device)160 static std::string realpath(const std::string& blk_device) {
161     std::string real_path;
162     if (!Realpath(blk_device, &real_path)) {
163         real_path = blk_device;
164     }
165     return real_path;
166 }
167 
should_force_check(int fs_stat)168 static bool should_force_check(int fs_stat) {
169     return fs_stat &
170            (FS_STAT_E2FSCK_F_ALWAYS | FS_STAT_UNCLEAN_SHUTDOWN | FS_STAT_QUOTA_ENABLED |
171             FS_STAT_RO_MOUNT_FAILED | FS_STAT_RO_UNMOUNT_FAILED | FS_STAT_FULL_MOUNT_FAILED |
172             FS_STAT_E2FSCK_FAILED | FS_STAT_TOGGLE_QUOTAS_FAILED |
173             FS_STAT_SET_RESERVED_BLOCKS_FAILED | FS_STAT_ENABLE_ENCRYPTION_FAILED);
174 }
175 
check_fs(const std::string & blk_device,const std::string & fs_type,const std::string & target,int * fs_stat)176 static void check_fs(const std::string& blk_device, const std::string& fs_type,
177                      const std::string& target, int* fs_stat) {
178     int status;
179     int ret;
180     long tmpmnt_flags = MS_NOATIME | MS_NOEXEC | MS_NOSUID;
181     auto tmpmnt_opts = "errors=remount-ro"s;
182     const char* e2fsck_argv[] = {E2FSCK_BIN, "-y", blk_device.c_str()};
183     const char* e2fsck_forced_argv[] = {E2FSCK_BIN, "-f", "-y", blk_device.c_str()};
184 
185     if (*fs_stat & FS_STAT_INVALID_MAGIC) {  // will fail, so do not try
186         return;
187     }
188 
189     /* Check for the types of filesystems we know how to check */
190     if (is_extfs(fs_type)) {
191         /*
192          * First try to mount and unmount the filesystem.  We do this because
193          * the kernel is more efficient than e2fsck in running the journal and
194          * processing orphaned inodes, and on at least one device with a
195          * performance issue in the emmc firmware, it can take e2fsck 2.5 minutes
196          * to do what the kernel does in about a second.
197          *
198          * After mounting and unmounting the filesystem, run e2fsck, and if an
199          * error is recorded in the filesystem superblock, e2fsck will do a full
200          * check.  Otherwise, it does nothing.  If the kernel cannot mount the
201          * filesytsem due to an error, e2fsck is still run to do a full check
202          * fix the filesystem.
203          */
204         if (!(*fs_stat & FS_STAT_FULL_MOUNT_FAILED)) {  // already tried if full mount failed
205             errno = 0;
206             if (fs_type == "ext4") {
207                 // This option is only valid with ext4
208                 tmpmnt_opts += ",nomblk_io_submit";
209             }
210             ret = mount(blk_device.c_str(), target.c_str(), fs_type.c_str(), tmpmnt_flags,
211                         tmpmnt_opts.c_str());
212             PINFO << __FUNCTION__ << "(): mount(" << blk_device << "," << target << "," << fs_type
213                   << ")=" << ret;
214             if (!ret) {
215                 bool umounted = false;
216                 int retry_count = 5;
217                 while (retry_count-- > 0) {
218                     umounted = umount(target.c_str()) == 0;
219                     if (umounted) {
220                         LINFO << __FUNCTION__ << "(): unmount(" << target << ") succeeded";
221                         break;
222                     }
223                     PERROR << __FUNCTION__ << "(): umount(" << target << ") failed";
224                     if (retry_count) sleep(1);
225                 }
226                 if (!umounted) {
227                     // boot may fail but continue and leave it to later stage for now.
228                     PERROR << __FUNCTION__ << "(): umount(" << target << ") timed out";
229                     *fs_stat |= FS_STAT_RO_UNMOUNT_FAILED;
230                 }
231             } else {
232                 *fs_stat |= FS_STAT_RO_MOUNT_FAILED;
233             }
234         }
235 
236         /*
237          * Some system images do not have e2fsck for licensing reasons
238          * (e.g. recent SDK system images). Detect these and skip the check.
239          */
240         if (access(E2FSCK_BIN, X_OK)) {
241             LINFO << "Not running " << E2FSCK_BIN << " on " << realpath(blk_device)
242                   << " (executable not in system image)";
243         } else {
244             LINFO << "Running " << E2FSCK_BIN << " on " << realpath(blk_device);
245             if (should_force_check(*fs_stat)) {
246                 ret = android_fork_execvp_ext(
247                     ARRAY_SIZE(e2fsck_forced_argv), const_cast<char**>(e2fsck_forced_argv), &status,
248                     true, LOG_KLOG | LOG_FILE, true, const_cast<char*>(FSCK_LOG_FILE), NULL, 0);
249             } else {
250                 ret = android_fork_execvp_ext(
251                     ARRAY_SIZE(e2fsck_argv), const_cast<char**>(e2fsck_argv), &status, true,
252                     LOG_KLOG | LOG_FILE, true, const_cast<char*>(FSCK_LOG_FILE), NULL, 0);
253             }
254 
255             if (ret < 0) {
256                 /* No need to check for error in fork, we can't really handle it now */
257                 LERROR << "Failed trying to run " << E2FSCK_BIN;
258                 *fs_stat |= FS_STAT_E2FSCK_FAILED;
259             } else if (status != 0) {
260                 LINFO << "e2fsck returned status 0x" << std::hex << status;
261                 *fs_stat |= FS_STAT_E2FSCK_FS_FIXED;
262             }
263         }
264     } else if (is_f2fs(fs_type)) {
265         const char* f2fs_fsck_argv[] = {F2FS_FSCK_BIN, "-a", blk_device.c_str()};
266         LINFO << "Running " << F2FS_FSCK_BIN << " -a " << realpath(blk_device);
267 
268         ret = android_fork_execvp_ext(ARRAY_SIZE(f2fs_fsck_argv),
269                                       const_cast<char **>(f2fs_fsck_argv),
270                                       &status, true, LOG_KLOG | LOG_FILE,
271                                       true, const_cast<char *>(FSCK_LOG_FILE),
272                                       NULL, 0);
273         if (ret < 0) {
274             /* No need to check for error in fork, we can't really handle it now */
275             LERROR << "Failed trying to run " << F2FS_FSCK_BIN;
276         }
277     }
278 
279     return;
280 }
281 
ext4_blocks_count(const struct ext4_super_block * es)282 static ext4_fsblk_t ext4_blocks_count(const struct ext4_super_block* es) {
283     return ((ext4_fsblk_t)le32_to_cpu(es->s_blocks_count_hi) << 32) |
284            le32_to_cpu(es->s_blocks_count_lo);
285 }
286 
ext4_r_blocks_count(const struct ext4_super_block * es)287 static ext4_fsblk_t ext4_r_blocks_count(const struct ext4_super_block* es) {
288     return ((ext4_fsblk_t)le32_to_cpu(es->s_r_blocks_count_hi) << 32) |
289            le32_to_cpu(es->s_r_blocks_count_lo);
290 }
291 
is_ext4_superblock_valid(const struct ext4_super_block * es)292 static bool is_ext4_superblock_valid(const struct ext4_super_block* es) {
293     if (es->s_magic != EXT4_SUPER_MAGIC) return false;
294     if (es->s_rev_level != EXT4_DYNAMIC_REV && es->s_rev_level != EXT4_GOOD_OLD_REV) return false;
295     if (EXT4_INODES_PER_GROUP(es) == 0) return false;
296     return true;
297 }
298 
299 // Read the primary superblock from an ext4 filesystem.  On failure return
300 // false.  If it's not an ext4 filesystem, also set FS_STAT_INVALID_MAGIC.
read_ext4_superblock(const std::string & blk_device,struct ext4_super_block * sb,int * fs_stat)301 static bool read_ext4_superblock(const std::string& blk_device, struct ext4_super_block* sb,
302                                  int* fs_stat) {
303     android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(blk_device.c_str(), O_RDONLY | O_CLOEXEC)));
304 
305     if (fd < 0) {
306         PERROR << "Failed to open '" << blk_device << "'";
307         return false;
308     }
309 
310     if (TEMP_FAILURE_RETRY(pread(fd, sb, sizeof(*sb), 1024)) != sizeof(*sb)) {
311         PERROR << "Can't read '" << blk_device << "' superblock";
312         return false;
313     }
314 
315     if (!is_ext4_superblock_valid(sb)) {
316         LINFO << "Invalid ext4 superblock on '" << blk_device << "'";
317         // not a valid fs, tune2fs, fsck, and mount  will all fail.
318         *fs_stat |= FS_STAT_INVALID_MAGIC;
319         return false;
320     }
321     *fs_stat |= FS_STAT_IS_EXT4;
322     LINFO << "superblock s_max_mnt_count:" << sb->s_max_mnt_count << "," << blk_device;
323     if (sb->s_max_mnt_count == 0xffff) {  // -1 (int16) in ext2, but uint16 in ext4
324         *fs_stat |= FS_STAT_NEW_IMAGE_VERSION;
325     }
326     return true;
327 }
328 
329 // exported silent version of the above that just answer the question is_ext4
fs_mgr_is_ext4(const std::string & blk_device)330 bool fs_mgr_is_ext4(const std::string& blk_device) {
331     android::base::ErrnoRestorer restore;
332     android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(blk_device.c_str(), O_RDONLY | O_CLOEXEC)));
333     if (fd < 0) return false;
334     ext4_super_block sb;
335     if (TEMP_FAILURE_RETRY(pread(fd, &sb, sizeof(sb), 1024)) != sizeof(sb)) return false;
336     if (!is_ext4_superblock_valid(&sb)) return false;
337     return true;
338 }
339 
340 // Some system images do not have tune2fs for licensing reasons.
341 // Detect these and skip running it.
tune2fs_available(void)342 static bool tune2fs_available(void) {
343     return access(TUNE2FS_BIN, X_OK) == 0;
344 }
345 
run_tune2fs(const char * argv[],int argc)346 static bool run_tune2fs(const char* argv[], int argc) {
347     int ret;
348 
349     ret = android_fork_execvp_ext(argc, const_cast<char**>(argv), nullptr, true,
350                                   LOG_KLOG | LOG_FILE, true, nullptr, nullptr, 0);
351     return ret == 0;
352 }
353 
354 // Enable/disable quota support on the filesystem if needed.
tune_quota(const std::string & blk_device,const FstabEntry & entry,const struct ext4_super_block * sb,int * fs_stat)355 static void tune_quota(const std::string& blk_device, const FstabEntry& entry,
356                        const struct ext4_super_block* sb, int* fs_stat) {
357     bool has_quota = (sb->s_feature_ro_compat & cpu_to_le32(EXT4_FEATURE_RO_COMPAT_QUOTA)) != 0;
358     bool want_quota = entry.fs_mgr_flags.quota;
359 
360     if (has_quota == want_quota) {
361         return;
362     }
363 
364     if (!tune2fs_available()) {
365         LERROR << "Unable to " << (want_quota ? "enable" : "disable") << " quotas on " << blk_device
366                << " because " TUNE2FS_BIN " is missing";
367         return;
368     }
369 
370     const char* argv[] = {TUNE2FS_BIN, nullptr, nullptr, blk_device.c_str()};
371 
372     if (want_quota) {
373         LINFO << "Enabling quotas on " << blk_device;
374         argv[1] = "-Oquota";
375         argv[2] = "-Qusrquota,grpquota";
376         *fs_stat |= FS_STAT_QUOTA_ENABLED;
377     } else {
378         LINFO << "Disabling quotas on " << blk_device;
379         argv[1] = "-O^quota";
380         argv[2] = "-Q^usrquota,^grpquota";
381     }
382 
383     if (!run_tune2fs(argv, ARRAY_SIZE(argv))) {
384         LERROR << "Failed to run " TUNE2FS_BIN " to " << (want_quota ? "enable" : "disable")
385                << " quotas on " << blk_device;
386         *fs_stat |= FS_STAT_TOGGLE_QUOTAS_FAILED;
387     }
388 }
389 
390 // Set the number of reserved filesystem blocks if needed.
tune_reserved_size(const std::string & blk_device,const FstabEntry & entry,const struct ext4_super_block * sb,int * fs_stat)391 static void tune_reserved_size(const std::string& blk_device, const FstabEntry& entry,
392                                const struct ext4_super_block* sb, int* fs_stat) {
393     if (entry.reserved_size == 0) {
394         return;
395     }
396 
397     // The size to reserve is given in the fstab, but we won't reserve more
398     // than 2% of the filesystem.
399     const uint64_t max_reserved_blocks = ext4_blocks_count(sb) * 0.02;
400     uint64_t reserved_blocks = entry.reserved_size / EXT4_BLOCK_SIZE(sb);
401 
402     if (reserved_blocks > max_reserved_blocks) {
403         LWARNING << "Reserved blocks " << reserved_blocks << " is too large; "
404                  << "capping to " << max_reserved_blocks;
405         reserved_blocks = max_reserved_blocks;
406     }
407 
408     if ((ext4_r_blocks_count(sb) == reserved_blocks) && (sb->s_def_resgid == AID_RESERVED_DISK)) {
409         return;
410     }
411 
412     if (!tune2fs_available()) {
413         LERROR << "Unable to set the number of reserved blocks on " << blk_device
414                << " because " TUNE2FS_BIN " is missing";
415         return;
416     }
417 
418     LINFO << "Setting reserved block count on " << blk_device << " to " << reserved_blocks;
419 
420     auto reserved_blocks_str = std::to_string(reserved_blocks);
421     auto reserved_gid_str = std::to_string(AID_RESERVED_DISK);
422     const char* argv[] = {
423             TUNE2FS_BIN,       "-r", reserved_blocks_str.c_str(), "-g", reserved_gid_str.c_str(),
424             blk_device.c_str()};
425     if (!run_tune2fs(argv, ARRAY_SIZE(argv))) {
426         LERROR << "Failed to run " TUNE2FS_BIN " to set the number of reserved blocks on "
427                << blk_device;
428         *fs_stat |= FS_STAT_SET_RESERVED_BLOCKS_FAILED;
429     }
430 }
431 
432 // Enable file-based encryption if needed.
tune_encrypt(const std::string & blk_device,const FstabEntry & entry,const struct ext4_super_block * sb,int * fs_stat)433 static void tune_encrypt(const std::string& blk_device, const FstabEntry& entry,
434                          const struct ext4_super_block* sb, int* fs_stat) {
435     bool has_encrypt = (sb->s_feature_incompat & cpu_to_le32(EXT4_FEATURE_INCOMPAT_ENCRYPT)) != 0;
436     bool want_encrypt = entry.fs_mgr_flags.file_encryption;
437 
438     if (has_encrypt || !want_encrypt) {
439         return;
440     }
441 
442     if (!tune2fs_available()) {
443         LERROR << "Unable to enable ext4 encryption on " << blk_device
444                << " because " TUNE2FS_BIN " is missing";
445         return;
446     }
447 
448     const char* argv[] = {TUNE2FS_BIN, "-Oencrypt", blk_device.c_str()};
449 
450     LINFO << "Enabling ext4 encryption on " << blk_device;
451     if (!run_tune2fs(argv, ARRAY_SIZE(argv))) {
452         LERROR << "Failed to run " TUNE2FS_BIN " to enable "
453                << "ext4 encryption on " << blk_device;
454         *fs_stat |= FS_STAT_ENABLE_ENCRYPTION_FAILED;
455     }
456 }
457 
458 // Enable fs-verity if needed.
tune_verity(const std::string & blk_device,const FstabEntry & entry,const struct ext4_super_block * sb,int * fs_stat)459 static void tune_verity(const std::string& blk_device, const FstabEntry& entry,
460                         const struct ext4_super_block* sb, int* fs_stat) {
461     bool has_verity = (sb->s_feature_ro_compat & cpu_to_le32(EXT4_FEATURE_RO_COMPAT_VERITY)) != 0;
462     bool want_verity = entry.fs_mgr_flags.fs_verity;
463 
464     if (has_verity || !want_verity) {
465         return;
466     }
467 
468     std::string verity_support;
469     if (!android::base::ReadFileToString(SYSFS_EXT4_VERITY, &verity_support)) {
470         LERROR << "Failed to open " << SYSFS_EXT4_VERITY;
471         return;
472     }
473 
474     if (!(android::base::Trim(verity_support) == "supported")) {
475         LERROR << "Current ext4 verity not supported by kernel";
476         return;
477     }
478 
479     if (!tune2fs_available()) {
480         LERROR << "Unable to enable ext4 verity on " << blk_device
481                << " because " TUNE2FS_BIN " is missing";
482         return;
483     }
484 
485     LINFO << "Enabling ext4 verity on " << blk_device;
486 
487     const char* argv[] = {TUNE2FS_BIN, "-O", "verity", blk_device.c_str()};
488     if (!run_tune2fs(argv, ARRAY_SIZE(argv))) {
489         LERROR << "Failed to run " TUNE2FS_BIN " to enable "
490                << "ext4 verity on " << blk_device;
491         *fs_stat |= FS_STAT_ENABLE_VERITY_FAILED;
492     }
493 }
494 
495 // Read the primary superblock from an f2fs filesystem.  On failure return
496 // false.  If it's not an f2fs filesystem, also set FS_STAT_INVALID_MAGIC.
497 #define F2FS_BLKSIZE 4096
498 #define F2FS_SUPER_OFFSET 1024
read_f2fs_superblock(const std::string & blk_device,int * fs_stat)499 static bool read_f2fs_superblock(const std::string& blk_device, int* fs_stat) {
500     android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(blk_device.c_str(), O_RDONLY | O_CLOEXEC)));
501     __le32 sb1, sb2;
502 
503     if (fd < 0) {
504         PERROR << "Failed to open '" << blk_device << "'";
505         return false;
506     }
507 
508     if (TEMP_FAILURE_RETRY(pread(fd, &sb1, sizeof(sb1), F2FS_SUPER_OFFSET)) != sizeof(sb1)) {
509         PERROR << "Can't read '" << blk_device << "' superblock1";
510         return false;
511     }
512     if (TEMP_FAILURE_RETRY(pread(fd, &sb2, sizeof(sb2), F2FS_BLKSIZE + F2FS_SUPER_OFFSET)) !=
513         sizeof(sb2)) {
514         PERROR << "Can't read '" << blk_device << "' superblock2";
515         return false;
516     }
517 
518     if (sb1 != cpu_to_le32(F2FS_SUPER_MAGIC) && sb2 != cpu_to_le32(F2FS_SUPER_MAGIC)) {
519         LINFO << "Invalid f2fs superblock on '" << blk_device << "'";
520         *fs_stat |= FS_STAT_INVALID_MAGIC;
521         return false;
522     }
523     return true;
524 }
525 
526 // exported silent version of the above that just answer the question is_f2fs
fs_mgr_is_f2fs(const std::string & blk_device)527 bool fs_mgr_is_f2fs(const std::string& blk_device) {
528     android::base::ErrnoRestorer restore;
529     android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(blk_device.c_str(), O_RDONLY | O_CLOEXEC)));
530     if (fd < 0) return false;
531     __le32 sb;
532     if (TEMP_FAILURE_RETRY(pread(fd, &sb, sizeof(sb), F2FS_SUPER_OFFSET)) != sizeof(sb)) {
533         return false;
534     }
535     if (sb == cpu_to_le32(F2FS_SUPER_MAGIC)) return true;
536     if (TEMP_FAILURE_RETRY(pread(fd, &sb, sizeof(sb), F2FS_BLKSIZE + F2FS_SUPER_OFFSET)) !=
537         sizeof(sb)) {
538         return false;
539     }
540     return sb == cpu_to_le32(F2FS_SUPER_MAGIC);
541 }
542 
543 //
544 // Prepare the filesystem on the given block device to be mounted.
545 //
546 // If the "check" option was given in the fstab record, or it seems that the
547 // filesystem was uncleanly shut down, we'll run fsck on the filesystem.
548 //
549 // If needed, we'll also enable (or disable) filesystem features as specified by
550 // the fstab record.
551 //
prepare_fs_for_mount(const std::string & blk_device,const FstabEntry & entry)552 static int prepare_fs_for_mount(const std::string& blk_device, const FstabEntry& entry) {
553     int fs_stat = 0;
554 
555     if (is_extfs(entry.fs_type)) {
556         struct ext4_super_block sb;
557 
558         if (read_ext4_superblock(blk_device, &sb, &fs_stat)) {
559             if ((sb.s_feature_incompat & EXT4_FEATURE_INCOMPAT_RECOVER) != 0 ||
560                 (sb.s_state & EXT4_VALID_FS) == 0) {
561                 LINFO << "Filesystem on " << blk_device << " was not cleanly shutdown; "
562                       << "state flags: 0x" << std::hex << sb.s_state << ", "
563                       << "incompat feature flags: 0x" << std::hex << sb.s_feature_incompat;
564                 fs_stat |= FS_STAT_UNCLEAN_SHUTDOWN;
565             }
566 
567             // Note: quotas should be enabled before running fsck.
568             tune_quota(blk_device, entry, &sb, &fs_stat);
569         } else {
570             return fs_stat;
571         }
572     } else if (is_f2fs(entry.fs_type)) {
573         if (!read_f2fs_superblock(blk_device, &fs_stat)) {
574             return fs_stat;
575         }
576     }
577 
578     if (entry.fs_mgr_flags.check ||
579         (fs_stat & (FS_STAT_UNCLEAN_SHUTDOWN | FS_STAT_QUOTA_ENABLED))) {
580         check_fs(blk_device, entry.fs_type, entry.mount_point, &fs_stat);
581     }
582 
583     if (is_extfs(entry.fs_type) &&
584         (entry.reserved_size != 0 || entry.fs_mgr_flags.file_encryption ||
585          entry.fs_mgr_flags.fs_verity)) {
586         struct ext4_super_block sb;
587 
588         if (read_ext4_superblock(blk_device, &sb, &fs_stat)) {
589             tune_reserved_size(blk_device, entry, &sb, &fs_stat);
590             tune_encrypt(blk_device, entry, &sb, &fs_stat);
591             tune_verity(blk_device, entry, &sb, &fs_stat);
592         }
593     }
594 
595     return fs_stat;
596 }
597 
598 // Mark the given block device as read-only, using the BLKROSET ioctl.
fs_mgr_set_blk_ro(const std::string & blockdev,bool readonly)599 bool fs_mgr_set_blk_ro(const std::string& blockdev, bool readonly) {
600     unique_fd fd(TEMP_FAILURE_RETRY(open(blockdev.c_str(), O_RDONLY | O_CLOEXEC)));
601     if (fd < 0) {
602         return false;
603     }
604 
605     int ON = readonly;
606     return ioctl(fd, BLKROSET, &ON) == 0;
607 }
608 
609 // Orange state means the device is unlocked, see the following link for details.
610 // https://source.android.com/security/verifiedboot/verified-boot#device_state
fs_mgr_is_device_unlocked()611 bool fs_mgr_is_device_unlocked() {
612     std::string verified_boot_state;
613     if (fs_mgr_get_boot_config("verifiedbootstate", &verified_boot_state)) {
614         return verified_boot_state == "orange";
615     }
616     return false;
617 }
618 
619 // __mount(): wrapper around the mount() system call which also
620 // sets the underlying block device to read-only if the mount is read-only.
621 // See "man 2 mount" for return values.
__mount(const std::string & source,const std::string & target,const FstabEntry & entry)622 static int __mount(const std::string& source, const std::string& target, const FstabEntry& entry) {
623     // We need this because sometimes we have legacy symlinks that are
624     // lingering around and need cleaning up.
625     struct stat info;
626     if (lstat(target.c_str(), &info) == 0 && (info.st_mode & S_IFMT) == S_IFLNK) {
627         unlink(target.c_str());
628     }
629     mkdir(target.c_str(), 0755);
630     errno = 0;
631     unsigned long mountflags = entry.flags;
632     int ret = 0;
633     int save_errno = 0;
634     do {
635         if (save_errno == EAGAIN) {
636             PINFO << "Retrying mount (source=" << source << ",target=" << target
637                   << ",type=" << entry.fs_type << ")=" << ret << "(" << save_errno << ")";
638         }
639         ret = mount(source.c_str(), target.c_str(), entry.fs_type.c_str(), mountflags,
640                     entry.fs_options.c_str());
641         save_errno = errno;
642     } while (ret && save_errno == EAGAIN);
643     const char* target_missing = "";
644     const char* source_missing = "";
645     if (save_errno == ENOENT) {
646         if (access(target.c_str(), F_OK)) {
647             target_missing = "(missing)";
648         } else if (access(source.c_str(), F_OK)) {
649             source_missing = "(missing)";
650         }
651         errno = save_errno;
652     }
653     PINFO << __FUNCTION__ << "(source=" << source << source_missing << ",target=" << target
654           << target_missing << ",type=" << entry.fs_type << ")=" << ret;
655     if ((ret == 0) && (mountflags & MS_RDONLY) != 0) {
656         fs_mgr_set_blk_ro(source);
657     }
658     errno = save_errno;
659     return ret;
660 }
661 
fs_match(const std::string & in1,const std::string & in2)662 static bool fs_match(const std::string& in1, const std::string& in2) {
663     if (in1.empty() || in2.empty()) {
664         return false;
665     }
666 
667     auto in1_end = in1.size() - 1;
668     while (in1_end > 0 && in1[in1_end] == '/') {
669         in1_end--;
670     }
671 
672     auto in2_end = in2.size() - 1;
673     while (in2_end > 0 && in2[in2_end] == '/') {
674         in2_end--;
675     }
676 
677     if (in1_end != in2_end) {
678         return false;
679     }
680 
681     for (size_t i = 0; i <= in1_end; ++i) {
682         if (in1[i] != in2[i]) {
683             return false;
684         }
685     }
686 
687     return true;
688 }
689 
690 // Tries to mount any of the consecutive fstab entries that match
691 // the mountpoint of the one given by fstab[start_idx].
692 //
693 // end_idx: On return, will be the last entry that was looked at.
694 // attempted_idx: On return, will indicate which fstab entry
695 //     succeeded. In case of failure, it will be the start_idx.
696 // Sets errno to match the 1st mount failure on failure.
mount_with_alternatives(const Fstab & fstab,int start_idx,int * end_idx,int * attempted_idx)697 static bool mount_with_alternatives(const Fstab& fstab, int start_idx, int* end_idx,
698                                     int* attempted_idx) {
699     unsigned long i;
700     int mount_errno = 0;
701     bool mounted = false;
702 
703     // Hunt down an fstab entry for the same mount point that might succeed.
704     for (i = start_idx;
705          // We required that fstab entries for the same mountpoint be consecutive.
706          i < fstab.size() && fstab[start_idx].mount_point == fstab[i].mount_point; i++) {
707         // Don't try to mount/encrypt the same mount point again.
708         // Deal with alternate entries for the same point which are required to be all following
709         // each other.
710         if (mounted) {
711             LERROR << __FUNCTION__ << "(): skipping fstab dup mountpoint=" << fstab[i].mount_point
712                    << " rec[" << i << "].fs_type=" << fstab[i].fs_type << " already mounted as "
713                    << fstab[*attempted_idx].fs_type;
714             continue;
715         }
716 
717         int fs_stat = prepare_fs_for_mount(fstab[i].blk_device, fstab[i]);
718         if (fs_stat & FS_STAT_INVALID_MAGIC) {
719             LERROR << __FUNCTION__
720                    << "(): skipping mount due to invalid magic, mountpoint=" << fstab[i].mount_point
721                    << " blk_dev=" << realpath(fstab[i].blk_device) << " rec[" << i
722                    << "].fs_type=" << fstab[i].fs_type;
723             mount_errno = EINVAL;  // continue bootup for FDE
724             continue;
725         }
726 
727         int retry_count = 2;
728         while (retry_count-- > 0) {
729             if (!__mount(fstab[i].blk_device, fstab[i].mount_point, fstab[i])) {
730                 *attempted_idx = i;
731                 mounted = true;
732                 if (i != start_idx) {
733                     LERROR << __FUNCTION__ << "(): Mounted " << fstab[i].blk_device << " on "
734                            << fstab[i].mount_point << " with fs_type=" << fstab[i].fs_type
735                            << " instead of " << fstab[start_idx].fs_type;
736                 }
737                 fs_stat &= ~FS_STAT_FULL_MOUNT_FAILED;
738                 mount_errno = 0;
739                 break;
740             } else {
741                 if (retry_count <= 0) break;  // run check_fs only once
742                 fs_stat |= FS_STAT_FULL_MOUNT_FAILED;
743                 // back up the first errno for crypto decisions.
744                 if (mount_errno == 0) {
745                     mount_errno = errno;
746                 }
747                 // retry after fsck
748                 check_fs(fstab[i].blk_device, fstab[i].fs_type, fstab[i].mount_point, &fs_stat);
749             }
750         }
751         log_fs_stat(fstab[i].blk_device, fs_stat);
752     }
753 
754     /* Adjust i for the case where it was still withing the recs[] */
755     if (i < fstab.size()) --i;
756 
757     *end_idx = i;
758     if (!mounted) {
759         *attempted_idx = start_idx;
760         errno = mount_errno;
761         return false;
762     }
763     return true;
764 }
765 
TranslateExtLabels(FstabEntry * entry)766 static bool TranslateExtLabels(FstabEntry* entry) {
767     if (!StartsWith(entry->blk_device, "LABEL=")) {
768         return true;
769     }
770 
771     std::string label = entry->blk_device.substr(6);
772     if (label.size() > 16) {
773         LERROR << "FS label is longer than allowed by filesystem";
774         return false;
775     }
776 
777     auto blockdir = std::unique_ptr<DIR, decltype(&closedir)>{opendir("/dev/block"), closedir};
778     if (!blockdir) {
779         LERROR << "couldn't open /dev/block";
780         return false;
781     }
782 
783     struct dirent* ent;
784     while ((ent = readdir(blockdir.get()))) {
785         if (ent->d_type != DT_BLK)
786             continue;
787 
788         unique_fd fd(TEMP_FAILURE_RETRY(
789                 openat(dirfd(blockdir.get()), ent->d_name, O_RDONLY | O_CLOEXEC)));
790         if (fd < 0) {
791             LERROR << "Cannot open block device /dev/block/" << ent->d_name;
792             return false;
793         }
794 
795         ext4_super_block super_block;
796         if (TEMP_FAILURE_RETRY(lseek(fd, 1024, SEEK_SET)) < 0 ||
797             TEMP_FAILURE_RETRY(read(fd, &super_block, sizeof(super_block))) !=
798                     sizeof(super_block)) {
799             // Probably a loopback device or something else without a readable superblock.
800             continue;
801         }
802 
803         if (super_block.s_magic != EXT4_SUPER_MAGIC) {
804             LINFO << "/dev/block/" << ent->d_name << " not ext{234}";
805             continue;
806         }
807 
808         if (label == super_block.s_volume_name) {
809             std::string new_blk_device = "/dev/block/"s + ent->d_name;
810 
811             LINFO << "resolved label " << entry->blk_device << " to " << new_blk_device;
812 
813             entry->blk_device = new_blk_device;
814             return true;
815         }
816     }
817 
818     return false;
819 }
820 
needs_block_encryption(const FstabEntry & entry)821 static bool needs_block_encryption(const FstabEntry& entry) {
822     if (android::base::GetBoolProperty("ro.vold.forceencryption", false) && entry.is_encryptable())
823         return true;
824     if (entry.fs_mgr_flags.force_crypt) return true;
825     if (entry.fs_mgr_flags.crypt) {
826         // Check for existence of convert_fde breadcrumb file.
827         auto convert_fde_name = entry.mount_point + "/misc/vold/convert_fde";
828         if (access(convert_fde_name.c_str(), F_OK) == 0) return true;
829     }
830     if (entry.fs_mgr_flags.force_fde_or_fbe) {
831         // Check for absence of convert_fbe breadcrumb file.
832         auto convert_fbe_name = entry.mount_point + "/convert_fbe";
833         if (access(convert_fbe_name.c_str(), F_OK) != 0) return true;
834     }
835     return false;
836 }
837 
should_use_metadata_encryption(const FstabEntry & entry)838 static bool should_use_metadata_encryption(const FstabEntry& entry) {
839     return !entry.key_dir.empty() &&
840            (entry.fs_mgr_flags.file_encryption || entry.fs_mgr_flags.force_fde_or_fbe);
841 }
842 
843 // Check to see if a mountable volume has encryption requirements
handle_encryptable(const FstabEntry & entry)844 static int handle_encryptable(const FstabEntry& entry) {
845     // If this is block encryptable, need to trigger encryption.
846     if (needs_block_encryption(entry)) {
847         if (umount(entry.mount_point.c_str()) == 0) {
848             return FS_MGR_MNTALL_DEV_NEEDS_ENCRYPTION;
849         } else {
850             PWARNING << "Could not umount " << entry.mount_point << " - allow continue unencrypted";
851             return FS_MGR_MNTALL_DEV_NOT_ENCRYPTED;
852         }
853     } else if (should_use_metadata_encryption(entry)) {
854         if (umount(entry.mount_point.c_str()) == 0) {
855             return FS_MGR_MNTALL_DEV_NEEDS_METADATA_ENCRYPTION;
856         } else {
857             PERROR << "Could not umount " << entry.mount_point << " - fail since can't encrypt";
858             return FS_MGR_MNTALL_FAIL;
859         }
860     } else if (entry.fs_mgr_flags.file_encryption || entry.fs_mgr_flags.force_fde_or_fbe) {
861         LINFO << entry.mount_point << " is file encrypted";
862         return FS_MGR_MNTALL_DEV_FILE_ENCRYPTED;
863     } else if (entry.is_encryptable()) {
864         return FS_MGR_MNTALL_DEV_NOT_ENCRYPTED;
865     } else {
866         return FS_MGR_MNTALL_DEV_NOT_ENCRYPTABLE;
867     }
868 }
869 
call_vdc(const std::vector<std::string> & args)870 static bool call_vdc(const std::vector<std::string>& args) {
871     std::vector<char const*> argv;
872     argv.emplace_back("/system/bin/vdc");
873     for (auto& arg : args) {
874         argv.emplace_back(arg.c_str());
875     }
876     LOG(INFO) << "Calling: " << android::base::Join(argv, ' ');
877     int ret =
878             android_fork_execvp(argv.size(), const_cast<char**>(argv.data()), nullptr, false, true);
879     if (ret != 0) {
880         LOG(ERROR) << "vdc returned error code: " << ret;
881         return false;
882     }
883     LOG(DEBUG) << "vdc finished successfully";
884     return true;
885 }
886 
call_vdc_ret(const std::vector<std::string> & args,int * ret)887 static bool call_vdc_ret(const std::vector<std::string>& args, int* ret) {
888     std::vector<char const*> argv;
889     argv.emplace_back("/system/bin/vdc");
890     for (auto& arg : args) {
891         argv.emplace_back(arg.c_str());
892     }
893     LOG(INFO) << "Calling: " << android::base::Join(argv, ' ');
894     int err = android_fork_execvp(argv.size(), const_cast<char**>(argv.data()), ret, false, true);
895     if (err != 0) {
896         LOG(ERROR) << "vdc call failed with error code: " << err;
897         return false;
898     }
899     LOG(DEBUG) << "vdc finished successfully";
900     *ret = WEXITSTATUS(*ret);
901     return true;
902 }
903 
fs_mgr_update_logical_partition(FstabEntry * entry)904 bool fs_mgr_update_logical_partition(FstabEntry* entry) {
905     // Logical partitions are specified with a named partition rather than a
906     // block device, so if the block device is a path, then it has already
907     // been updated.
908     if (entry->blk_device[0] == '/') {
909         return true;
910     }
911 
912     DeviceMapper& dm = DeviceMapper::Instance();
913     std::string device_name;
914     if (!dm.GetDmDevicePathByName(entry->blk_device, &device_name)) {
915         return false;
916     }
917 
918     entry->blk_device = device_name;
919     return true;
920 }
921 
922 class CheckpointManager {
923   public:
CheckpointManager(int needs_checkpoint=-1)924     CheckpointManager(int needs_checkpoint = -1) : needs_checkpoint_(needs_checkpoint) {}
925 
Update(FstabEntry * entry,const std::string & block_device=std::string ())926     bool Update(FstabEntry* entry, const std::string& block_device = std::string()) {
927         if (!entry->fs_mgr_flags.checkpoint_blk && !entry->fs_mgr_flags.checkpoint_fs) {
928             return true;
929         }
930 
931         if (entry->fs_mgr_flags.checkpoint_blk) {
932             call_vdc({"checkpoint", "restoreCheckpoint", entry->blk_device});
933         }
934 
935         if (needs_checkpoint_ == UNKNOWN &&
936             !call_vdc_ret({"checkpoint", "needsCheckpoint"}, &needs_checkpoint_)) {
937             LERROR << "Failed to find if checkpointing is needed. Assuming no.";
938             needs_checkpoint_ = NO;
939         }
940 
941         if (needs_checkpoint_ != YES) {
942             return true;
943         }
944 
945         if (!UpdateCheckpointPartition(entry, block_device)) {
946             LERROR << "Could not set up checkpoint partition, skipping!";
947             return false;
948         }
949 
950         return true;
951     }
952 
Revert(FstabEntry * entry)953     bool Revert(FstabEntry* entry) {
954         if (!entry->fs_mgr_flags.checkpoint_blk && !entry->fs_mgr_flags.checkpoint_fs) {
955             return true;
956         }
957 
958         if (device_map_.find(entry->blk_device) == device_map_.end()) {
959             return true;
960         }
961 
962         std::string bow_device = entry->blk_device;
963         entry->blk_device = device_map_[bow_device];
964         device_map_.erase(bow_device);
965 
966         DeviceMapper& dm = DeviceMapper::Instance();
967         if (!dm.DeleteDevice("bow")) {
968             PERROR << "Failed to remove bow device";
969         }
970 
971         return true;
972     }
973 
974   private:
UpdateCheckpointPartition(FstabEntry * entry,const std::string & block_device)975     bool UpdateCheckpointPartition(FstabEntry* entry, const std::string& block_device) {
976         if (entry->fs_mgr_flags.checkpoint_fs) {
977             if (is_f2fs(entry->fs_type)) {
978                 entry->fs_options += ",checkpoint=disable";
979             } else {
980                 LERROR << entry->fs_type << " does not implement checkpoints.";
981             }
982         } else if (entry->fs_mgr_flags.checkpoint_blk) {
983             auto actual_block_device = block_device.empty() ? entry->blk_device : block_device;
984             if (fs_mgr_find_bow_device(actual_block_device).empty()) {
985                 unique_fd fd(
986                         TEMP_FAILURE_RETRY(open(entry->blk_device.c_str(), O_RDONLY | O_CLOEXEC)));
987                 if (fd < 0) {
988                     PERROR << "Cannot open device " << entry->blk_device;
989                     return false;
990                 }
991 
992                 uint64_t size = get_block_device_size(fd) / 512;
993                 if (!size) {
994                     PERROR << "Cannot get device size";
995                     return false;
996                 }
997 
998                 android::dm::DmTable table;
999                 if (!table.AddTarget(std::make_unique<android::dm::DmTargetBow>(
1000                             0, size, entry->blk_device))) {
1001                     LERROR << "Failed to add bow target";
1002                     return false;
1003                 }
1004 
1005                 DeviceMapper& dm = DeviceMapper::Instance();
1006                 if (!dm.CreateDevice("bow", table)) {
1007                     PERROR << "Failed to create bow device";
1008                     return false;
1009                 }
1010 
1011                 std::string name;
1012                 if (!dm.GetDmDevicePathByName("bow", &name)) {
1013                     PERROR << "Failed to get bow device name";
1014                     return false;
1015                 }
1016 
1017                 device_map_[name] = entry->blk_device;
1018                 entry->blk_device = name;
1019             }
1020         }
1021         return true;
1022     }
1023 
1024     enum { UNKNOWN = -1, NO = 0, YES = 1 };
1025     int needs_checkpoint_;
1026     std::map<std::string, std::string> device_map_;
1027 };
1028 
fs_mgr_find_bow_device(const std::string & block_device)1029 std::string fs_mgr_find_bow_device(const std::string& block_device) {
1030     if (block_device.substr(0, 5) != "/dev/") {
1031         LOG(ERROR) << "Expected block device, got " << block_device;
1032         return std::string();
1033     }
1034 
1035     std::string sys_dir = std::string("/sys/") + block_device.substr(5);
1036 
1037     for (;;) {
1038         std::string name;
1039         if (!android::base::ReadFileToString(sys_dir + "/dm/name", &name)) {
1040             PLOG(ERROR) << block_device << " is not dm device";
1041             return std::string();
1042         }
1043 
1044         if (name == "bow\n") return sys_dir;
1045 
1046         std::string slaves = sys_dir + "/slaves";
1047         std::unique_ptr<DIR, decltype(&closedir)> directory(opendir(slaves.c_str()), closedir);
1048         if (!directory) {
1049             PLOG(ERROR) << "Can't open slave directory " << slaves;
1050             return std::string();
1051         }
1052 
1053         int count = 0;
1054         for (dirent* entry = readdir(directory.get()); entry; entry = readdir(directory.get())) {
1055             if (entry->d_type != DT_LNK) continue;
1056 
1057             if (count == 1) {
1058                 LOG(ERROR) << "Too many slaves in " << slaves;
1059                 return std::string();
1060             }
1061 
1062             ++count;
1063             sys_dir = std::string("/sys/block/") + entry->d_name;
1064         }
1065 
1066         if (count != 1) {
1067             LOG(ERROR) << "No slave in " << slaves;
1068             return std::string();
1069         }
1070     }
1071 }
1072 
IsMountPointMounted(const std::string & mount_point)1073 static bool IsMountPointMounted(const std::string& mount_point) {
1074     // Check if this is already mounted.
1075     Fstab fstab;
1076     if (!ReadFstabFromFile("/proc/mounts", &fstab)) {
1077         return false;
1078     }
1079     return GetEntryForMountPoint(&fstab, mount_point) != nullptr;
1080 }
1081 
1082 // When multiple fstab records share the same mount_point, it will try to mount each
1083 // one in turn, and ignore any duplicates after a first successful mount.
1084 // Returns -1 on error, and  FS_MGR_MNTALL_* otherwise.
fs_mgr_mount_all(Fstab * fstab,int mount_mode)1085 int fs_mgr_mount_all(Fstab* fstab, int mount_mode) {
1086     int encryptable = FS_MGR_MNTALL_DEV_NOT_ENCRYPTABLE;
1087     int error_count = 0;
1088     CheckpointManager checkpoint_manager;
1089     AvbUniquePtr avb_handle(nullptr);
1090 
1091     if (fstab->empty()) {
1092         return FS_MGR_MNTALL_FAIL;
1093     }
1094 
1095     for (size_t i = 0; i < fstab->size(); i++) {
1096         auto& current_entry = (*fstab)[i];
1097 
1098         // If a filesystem should have been mounted in the first stage, we
1099         // ignore it here. With one exception, if the filesystem is
1100         // formattable, then it can only be formatted in the second stage,
1101         // so we allow it to mount here.
1102         if (current_entry.fs_mgr_flags.first_stage_mount &&
1103             (!current_entry.fs_mgr_flags.formattable ||
1104              IsMountPointMounted(current_entry.mount_point))) {
1105             continue;
1106         }
1107 
1108         // Don't mount entries that are managed by vold or not for the mount mode.
1109         if (current_entry.fs_mgr_flags.vold_managed || current_entry.fs_mgr_flags.recovery_only ||
1110             ((mount_mode == MOUNT_MODE_LATE) && !current_entry.fs_mgr_flags.late_mount) ||
1111             ((mount_mode == MOUNT_MODE_EARLY) && current_entry.fs_mgr_flags.late_mount)) {
1112             continue;
1113         }
1114 
1115         // Skip swap and raw partition entries such as boot, recovery, etc.
1116         if (current_entry.fs_type == "swap" || current_entry.fs_type == "emmc" ||
1117             current_entry.fs_type == "mtd") {
1118             continue;
1119         }
1120 
1121         // Skip mounting the root partition, as it will already have been mounted.
1122         if (current_entry.mount_point == "/" || current_entry.mount_point == "/system") {
1123             if ((current_entry.flags & MS_RDONLY) != 0) {
1124                 fs_mgr_set_blk_ro(current_entry.blk_device);
1125             }
1126             continue;
1127         }
1128 
1129         // Translate LABEL= file system labels into block devices.
1130         if (is_extfs(current_entry.fs_type)) {
1131             if (!TranslateExtLabels(&current_entry)) {
1132                 LERROR << "Could not translate label to block device";
1133                 continue;
1134             }
1135         }
1136 
1137         if (current_entry.fs_mgr_flags.logical) {
1138             if (!fs_mgr_update_logical_partition(&current_entry)) {
1139                 LERROR << "Could not set up logical partition, skipping!";
1140                 continue;
1141             }
1142         }
1143 
1144         if (!checkpoint_manager.Update(&current_entry)) {
1145             continue;
1146         }
1147 
1148         if (current_entry.fs_mgr_flags.wait &&
1149             !fs_mgr_wait_for_file(current_entry.blk_device, 20s)) {
1150             LERROR << "Skipping '" << current_entry.blk_device << "' during mount_all";
1151             continue;
1152         }
1153 
1154         if (current_entry.fs_mgr_flags.avb) {
1155             if (!avb_handle) {
1156                 avb_handle = AvbHandle::Open();
1157                 if (!avb_handle) {
1158                     LERROR << "Failed to open AvbHandle";
1159                     return FS_MGR_MNTALL_FAIL;
1160                 }
1161             }
1162             if (avb_handle->SetUpAvbHashtree(&current_entry, true /* wait_for_verity_dev */) ==
1163                 AvbHashtreeResult::kFail) {
1164                 LERROR << "Failed to set up AVB on partition: " << current_entry.mount_point
1165                        << ", skipping!";
1166                 // Skips mounting the device.
1167                 continue;
1168             }
1169         } else if (!current_entry.avb_keys.empty()) {
1170             if (AvbHandle::SetUpStandaloneAvbHashtree(&current_entry) == AvbHashtreeResult::kFail) {
1171                 LERROR << "Failed to set up AVB on standalone partition: "
1172                        << current_entry.mount_point << ", skipping!";
1173                 // Skips mounting the device.
1174                 continue;
1175             }
1176         } else if ((current_entry.fs_mgr_flags.verify)) {
1177             int rc = fs_mgr_setup_verity(&current_entry, true);
1178             if (rc == FS_MGR_SETUP_VERITY_DISABLED || rc == FS_MGR_SETUP_VERITY_SKIPPED) {
1179                 LINFO << "Verity disabled";
1180             } else if (rc != FS_MGR_SETUP_VERITY_SUCCESS) {
1181                 LERROR << "Could not set up verified partition, skipping!";
1182                 continue;
1183             }
1184         }
1185 
1186         int last_idx_inspected;
1187         int top_idx = i;
1188         int attempted_idx = -1;
1189 
1190         bool mret = mount_with_alternatives(*fstab, i, &last_idx_inspected, &attempted_idx);
1191         auto& attempted_entry = (*fstab)[attempted_idx];
1192         i = last_idx_inspected;
1193         int mount_errno = errno;
1194 
1195         // Handle success and deal with encryptability.
1196         if (mret) {
1197             int status = handle_encryptable(attempted_entry);
1198 
1199             if (status == FS_MGR_MNTALL_FAIL) {
1200                 // Fatal error - no point continuing.
1201                 return status;
1202             }
1203 
1204             if (status != FS_MGR_MNTALL_DEV_NOT_ENCRYPTABLE) {
1205                 if (encryptable != FS_MGR_MNTALL_DEV_NOT_ENCRYPTABLE) {
1206                     // Log and continue
1207                     LERROR << "Only one encryptable/encrypted partition supported";
1208                 }
1209                 encryptable = status;
1210                 if (status == FS_MGR_MNTALL_DEV_NEEDS_METADATA_ENCRYPTION) {
1211                     if (!call_vdc({"cryptfs", "encryptFstab", attempted_entry.blk_device,
1212                                    attempted_entry.mount_point})) {
1213                         LERROR << "Encryption failed";
1214                         return FS_MGR_MNTALL_FAIL;
1215                     }
1216                 }
1217             }
1218 
1219             // Success!  Go get the next one.
1220             continue;
1221         }
1222 
1223         // Mounting failed, understand why and retry.
1224         bool wiped = partition_wiped(current_entry.blk_device.c_str());
1225         bool crypt_footer = false;
1226         if (mount_errno != EBUSY && mount_errno != EACCES &&
1227             current_entry.fs_mgr_flags.formattable && wiped) {
1228             // current_entry and attempted_entry point at the same partition, but sometimes
1229             // at two different lines in the fstab.  Use current_entry for formatting
1230             // as that is the preferred one.
1231             LERROR << __FUNCTION__ << "(): " << realpath(current_entry.blk_device)
1232                    << " is wiped and " << current_entry.mount_point << " " << current_entry.fs_type
1233                    << " is formattable. Format it.";
1234 
1235             checkpoint_manager.Revert(&current_entry);
1236 
1237             if (current_entry.is_encryptable() && current_entry.key_loc != KEY_IN_FOOTER) {
1238                 unique_fd fd(TEMP_FAILURE_RETRY(
1239                         open(current_entry.key_loc.c_str(), O_WRONLY | O_CLOEXEC)));
1240                 if (fd >= 0) {
1241                     LINFO << __FUNCTION__ << "(): also wipe " << current_entry.key_loc;
1242                     wipe_block_device(fd, get_file_size(fd));
1243                 } else {
1244                     PERROR << __FUNCTION__ << "(): " << current_entry.key_loc << " wouldn't open";
1245                 }
1246             } else if (current_entry.is_encryptable() && current_entry.key_loc == KEY_IN_FOOTER) {
1247                 crypt_footer = true;
1248             }
1249             if (fs_mgr_do_format(current_entry, crypt_footer) == 0) {
1250                 // Let's replay the mount actions.
1251                 i = top_idx - 1;
1252                 continue;
1253             } else {
1254                 LERROR << __FUNCTION__ << "(): Format failed. "
1255                        << "Suggest recovery...";
1256                 encryptable = FS_MGR_MNTALL_DEV_NEEDS_RECOVERY;
1257                 continue;
1258             }
1259         }
1260 
1261         // mount(2) returned an error, handle the encryptable/formattable case.
1262         if (mount_errno != EBUSY && mount_errno != EACCES && attempted_entry.is_encryptable()) {
1263             if (wiped) {
1264                 LERROR << __FUNCTION__ << "(): " << attempted_entry.blk_device << " is wiped and "
1265                        << attempted_entry.mount_point << " " << attempted_entry.fs_type
1266                        << " is encryptable. Suggest recovery...";
1267                 encryptable = FS_MGR_MNTALL_DEV_NEEDS_RECOVERY;
1268                 continue;
1269             } else {
1270                 // Need to mount a tmpfs at this mountpoint for now, and set
1271                 // properties that vold will query later for decrypting
1272                 LERROR << __FUNCTION__ << "(): possibly an encryptable blkdev "
1273                        << attempted_entry.blk_device << " for mount " << attempted_entry.mount_point
1274                        << " type " << attempted_entry.fs_type;
1275                 if (fs_mgr_do_tmpfs_mount(attempted_entry.mount_point.c_str()) < 0) {
1276                     ++error_count;
1277                     continue;
1278                 }
1279             }
1280             encryptable = FS_MGR_MNTALL_DEV_MIGHT_BE_ENCRYPTED;
1281         } else if (mount_errno != EBUSY && mount_errno != EACCES &&
1282                    should_use_metadata_encryption(attempted_entry)) {
1283             if (!call_vdc({"cryptfs", "mountFstab", attempted_entry.blk_device,
1284                            attempted_entry.mount_point})) {
1285                 ++error_count;
1286             }
1287             encryptable = FS_MGR_MNTALL_DEV_IS_METADATA_ENCRYPTED;
1288             continue;
1289         } else {
1290             // fs_options might be null so we cannot use PERROR << directly.
1291             // Use StringPrintf to output "(null)" instead.
1292             if (attempted_entry.fs_mgr_flags.no_fail) {
1293                 PERROR << android::base::StringPrintf(
1294                         "Ignoring failure to mount an un-encryptable or wiped "
1295                         "partition on %s at %s options: %s",
1296                         attempted_entry.blk_device.c_str(), attempted_entry.mount_point.c_str(),
1297                         attempted_entry.fs_options.c_str());
1298             } else {
1299                 PERROR << android::base::StringPrintf(
1300                         "Failed to mount an un-encryptable or wiped partition "
1301                         "on %s at %s options: %s",
1302                         attempted_entry.blk_device.c_str(), attempted_entry.mount_point.c_str(),
1303                         attempted_entry.fs_options.c_str());
1304                 ++error_count;
1305             }
1306             continue;
1307         }
1308     }
1309 
1310 #if ALLOW_ADBD_DISABLE_VERITY == 1  // "userdebug" build
1311     fs_mgr_overlayfs_mount_all(fstab);
1312 #endif
1313 
1314     if (error_count) {
1315         return FS_MGR_MNTALL_FAIL;
1316     } else {
1317         return encryptable;
1318     }
1319 }
1320 
fs_mgr_umount_all(android::fs_mgr::Fstab * fstab)1321 int fs_mgr_umount_all(android::fs_mgr::Fstab* fstab) {
1322     AvbUniquePtr avb_handle(nullptr);
1323     int ret = FsMgrUmountStatus::SUCCESS;
1324     for (auto& current_entry : *fstab) {
1325         if (!IsMountPointMounted(current_entry.mount_point)) {
1326             continue;
1327         }
1328 
1329         if (umount(current_entry.mount_point.c_str()) == -1) {
1330             PERROR << "Failed to umount " << current_entry.mount_point;
1331             ret |= FsMgrUmountStatus::ERROR_UMOUNT;
1332             continue;
1333         }
1334 
1335         if (current_entry.fs_mgr_flags.logical) {
1336             if (!fs_mgr_update_logical_partition(&current_entry)) {
1337                 LERROR << "Could not get logical partition blk_device, skipping!";
1338                 ret |= FsMgrUmountStatus::ERROR_DEVICE_MAPPER;
1339                 continue;
1340             }
1341         }
1342 
1343         if (current_entry.fs_mgr_flags.avb || !current_entry.avb_keys.empty()) {
1344             if (!AvbHandle::TearDownAvbHashtree(&current_entry, true /* wait */)) {
1345                 LERROR << "Failed to tear down AVB on mount point: " << current_entry.mount_point;
1346                 ret |= FsMgrUmountStatus::ERROR_VERITY;
1347                 continue;
1348             }
1349         } else if ((current_entry.fs_mgr_flags.verify)) {
1350             if (!fs_mgr_teardown_verity(&current_entry, true /* wait */)) {
1351                 LERROR << "Failed to tear down verified partition on mount point: "
1352                        << current_entry.mount_point;
1353                 ret |= FsMgrUmountStatus::ERROR_VERITY;
1354                 continue;
1355             }
1356         }
1357     }
1358     return ret;
1359 }
1360 
1361 // wrapper to __mount() and expects a fully prepared fstab_rec,
1362 // unlike fs_mgr_do_mount which does more things with avb / verity etc.
fs_mgr_do_mount_one(const FstabEntry & entry,const std::string & mount_point)1363 int fs_mgr_do_mount_one(const FstabEntry& entry, const std::string& mount_point) {
1364     // Run fsck if needed
1365     prepare_fs_for_mount(entry.blk_device, entry);
1366 
1367     int ret =
1368             __mount(entry.blk_device, mount_point.empty() ? entry.mount_point : mount_point, entry);
1369     if (ret) {
1370       ret = (errno == EBUSY) ? FS_MGR_DOMNT_BUSY : FS_MGR_DOMNT_FAILED;
1371     }
1372 
1373     return ret;
1374 }
1375 
1376 // If tmp_mount_point is non-null, mount the filesystem there.  This is for the
1377 // tmp mount we do to check the user password
1378 // If multiple fstab entries are to be mounted on "n_name", it will try to mount each one
1379 // in turn, and stop on 1st success, or no more match.
fs_mgr_do_mount_helper(Fstab * fstab,const std::string & n_name,const std::string & n_blk_device,const char * tmp_mount_point,int needs_checkpoint)1380 static int fs_mgr_do_mount_helper(Fstab* fstab, const std::string& n_name,
1381                                   const std::string& n_blk_device, const char* tmp_mount_point,
1382                                   int needs_checkpoint) {
1383     int mount_errors = 0;
1384     int first_mount_errno = 0;
1385     std::string mount_point;
1386     CheckpointManager checkpoint_manager(needs_checkpoint);
1387     AvbUniquePtr avb_handle(nullptr);
1388 
1389     if (!fstab) {
1390         return FS_MGR_DOMNT_FAILED;
1391     }
1392 
1393     for (auto& fstab_entry : *fstab) {
1394         if (!fs_match(fstab_entry.mount_point, n_name)) {
1395             continue;
1396         }
1397 
1398         // We found our match.
1399         // If this swap or a raw partition, report an error.
1400         if (fstab_entry.fs_type == "swap" || fstab_entry.fs_type == "emmc" ||
1401             fstab_entry.fs_type == "mtd") {
1402             LERROR << "Cannot mount filesystem of type " << fstab_entry.fs_type << " on "
1403                    << n_blk_device;
1404             return FS_MGR_DOMNT_FAILED;
1405         }
1406 
1407         if (fstab_entry.fs_mgr_flags.logical) {
1408             if (!fs_mgr_update_logical_partition(&fstab_entry)) {
1409                 LERROR << "Could not set up logical partition, skipping!";
1410                 continue;
1411             }
1412         }
1413 
1414         if (!checkpoint_manager.Update(&fstab_entry, n_blk_device)) {
1415             LERROR << "Could not set up checkpoint partition, skipping!";
1416             continue;
1417         }
1418 
1419         // First check the filesystem if requested.
1420         if (fstab_entry.fs_mgr_flags.wait && !fs_mgr_wait_for_file(n_blk_device, 20s)) {
1421             LERROR << "Skipping mounting '" << n_blk_device << "'";
1422             continue;
1423         }
1424 
1425         int fs_stat = prepare_fs_for_mount(n_blk_device, fstab_entry);
1426 
1427         if (fstab_entry.fs_mgr_flags.avb) {
1428             if (!avb_handle) {
1429                 avb_handle = AvbHandle::Open();
1430                 if (!avb_handle) {
1431                     LERROR << "Failed to open AvbHandle";
1432                     return FS_MGR_DOMNT_FAILED;
1433                 }
1434             }
1435             if (avb_handle->SetUpAvbHashtree(&fstab_entry, true /* wait_for_verity_dev */) ==
1436                 AvbHashtreeResult::kFail) {
1437                 LERROR << "Failed to set up AVB on partition: " << fstab_entry.mount_point
1438                        << ", skipping!";
1439                 // Skips mounting the device.
1440                 continue;
1441             }
1442         } else if (!fstab_entry.avb_keys.empty()) {
1443             if (AvbHandle::SetUpStandaloneAvbHashtree(&fstab_entry) == AvbHashtreeResult::kFail) {
1444                 LERROR << "Failed to set up AVB on standalone partition: "
1445                        << fstab_entry.mount_point << ", skipping!";
1446                 // Skips mounting the device.
1447                 continue;
1448             }
1449         } else if (fstab_entry.fs_mgr_flags.verify) {
1450             int rc = fs_mgr_setup_verity(&fstab_entry, true);
1451             if (rc == FS_MGR_SETUP_VERITY_DISABLED || rc == FS_MGR_SETUP_VERITY_SKIPPED) {
1452                 LINFO << "Verity disabled";
1453             } else if (rc != FS_MGR_SETUP_VERITY_SUCCESS) {
1454                 LERROR << "Could not set up verified partition, skipping!";
1455                 continue;
1456             }
1457         }
1458 
1459         // Now mount it where requested */
1460         if (tmp_mount_point) {
1461             mount_point = tmp_mount_point;
1462         } else {
1463             mount_point = fstab_entry.mount_point;
1464         }
1465         int retry_count = 2;
1466         while (retry_count-- > 0) {
1467             if (!__mount(n_blk_device, mount_point, fstab_entry)) {
1468                 fs_stat &= ~FS_STAT_FULL_MOUNT_FAILED;
1469                 return FS_MGR_DOMNT_SUCCESS;
1470             } else {
1471                 if (retry_count <= 0) break;  // run check_fs only once
1472                 if (!first_mount_errno) first_mount_errno = errno;
1473                 mount_errors++;
1474                 fs_stat |= FS_STAT_FULL_MOUNT_FAILED;
1475                 // try again after fsck
1476                 check_fs(n_blk_device, fstab_entry.fs_type, fstab_entry.mount_point, &fs_stat);
1477             }
1478         }
1479         log_fs_stat(fstab_entry.blk_device, fs_stat);
1480     }
1481 
1482     // Reach here means the mount attempt fails.
1483     if (mount_errors) {
1484         PERROR << "Cannot mount filesystem on " << n_blk_device << " at " << mount_point;
1485         if (first_mount_errno == EBUSY) return FS_MGR_DOMNT_BUSY;
1486     } else {
1487         // We didn't find a match, say so and return an error.
1488         LERROR << "Cannot find mount point " << n_name << " in fstab";
1489     }
1490     return FS_MGR_DOMNT_FAILED;
1491 }
1492 
fs_mgr_do_mount(Fstab * fstab,const char * n_name,char * n_blk_device,char * tmp_mount_point)1493 int fs_mgr_do_mount(Fstab* fstab, const char* n_name, char* n_blk_device, char* tmp_mount_point) {
1494     return fs_mgr_do_mount_helper(fstab, n_name, n_blk_device, tmp_mount_point, -1);
1495 }
1496 
fs_mgr_do_mount(Fstab * fstab,const char * n_name,char * n_blk_device,char * tmp_mount_point,bool needs_checkpoint)1497 int fs_mgr_do_mount(Fstab* fstab, const char* n_name, char* n_blk_device, char* tmp_mount_point,
1498                     bool needs_checkpoint) {
1499     return fs_mgr_do_mount_helper(fstab, n_name, n_blk_device, tmp_mount_point, needs_checkpoint);
1500 }
1501 
1502 /*
1503  * mount a tmpfs filesystem at the given point.
1504  * return 0 on success, non-zero on failure.
1505  */
fs_mgr_do_tmpfs_mount(const char * n_name)1506 int fs_mgr_do_tmpfs_mount(const char *n_name)
1507 {
1508     int ret;
1509 
1510     ret = mount("tmpfs", n_name, "tmpfs", MS_NOATIME | MS_NOSUID | MS_NODEV | MS_NOEXEC,
1511                 CRYPTO_TMPFS_OPTIONS);
1512     if (ret < 0) {
1513         LERROR << "Cannot mount tmpfs filesystem at " << n_name;
1514         return -1;
1515     }
1516 
1517     /* Success */
1518     return 0;
1519 }
1520 
InstallZramDevice(const std::string & device)1521 static bool InstallZramDevice(const std::string& device) {
1522     if (!android::base::WriteStringToFile(device, ZRAM_BACK_DEV)) {
1523         PERROR << "Cannot write " << device << " in: " << ZRAM_BACK_DEV;
1524         return false;
1525     }
1526     LINFO << "Success to set " << device << " to " << ZRAM_BACK_DEV;
1527     return true;
1528 }
1529 
PrepareZramDevice(const std::string & loop,off64_t size,const std::string & bdev)1530 static bool PrepareZramDevice(const std::string& loop, off64_t size, const std::string& bdev) {
1531     if (loop.empty() && bdev.empty()) return true;
1532 
1533     if (bdev.length()) {
1534         return InstallZramDevice(bdev);
1535     }
1536 
1537     // Get free loopback
1538     unique_fd loop_fd(TEMP_FAILURE_RETRY(open("/dev/loop-control", O_RDWR | O_CLOEXEC)));
1539     if (loop_fd.get() == -1) {
1540         PERROR << "Cannot open loop-control";
1541         return false;
1542     }
1543 
1544     int num = ioctl(loop_fd.get(), LOOP_CTL_GET_FREE);
1545     if (num == -1) {
1546         PERROR << "Cannot get free loop slot";
1547         return false;
1548     }
1549 
1550     // Prepare target path
1551     unique_fd target_fd(TEMP_FAILURE_RETRY(open(loop.c_str(), O_RDWR | O_CREAT | O_CLOEXEC, 0600)));
1552     if (target_fd.get() == -1) {
1553         PERROR << "Cannot open target path: " << loop;
1554         return false;
1555     }
1556     if (fallocate(target_fd.get(), 0, 0, size) < 0) {
1557         PERROR << "Cannot truncate target path: " << loop;
1558         return false;
1559     }
1560 
1561     // Connect loopback (device_fd) to target path (target_fd)
1562     std::string device = android::base::StringPrintf("/dev/block/loop%d", num);
1563     unique_fd device_fd(TEMP_FAILURE_RETRY(open(device.c_str(), O_RDWR | O_CLOEXEC)));
1564     if (device_fd.get() == -1) {
1565         PERROR << "Cannot open /dev/block/loop" << num;
1566         return false;
1567     }
1568 
1569     if (ioctl(device_fd.get(), LOOP_SET_FD, target_fd.get())) {
1570         PERROR << "Cannot set loopback to target path";
1571         return false;
1572     }
1573 
1574     // set block size & direct IO
1575     if (ioctl(device_fd.get(), LOOP_SET_BLOCK_SIZE, 4096)) {
1576         PWARNING << "Cannot set 4KB blocksize to /dev/block/loop" << num;
1577     }
1578     if (ioctl(device_fd.get(), LOOP_SET_DIRECT_IO, 1)) {
1579         PWARNING << "Cannot set direct_io to /dev/block/loop" << num;
1580     }
1581 
1582     return InstallZramDevice(device);
1583 }
1584 
fs_mgr_swapon_all(const Fstab & fstab)1585 bool fs_mgr_swapon_all(const Fstab& fstab) {
1586     bool ret = true;
1587     for (const auto& entry : fstab) {
1588         // Skip non-swap entries.
1589         if (entry.fs_type != "swap") {
1590             continue;
1591         }
1592 
1593         if (!PrepareZramDevice(entry.zram_loopback_path, entry.zram_loopback_size, entry.zram_backing_dev_path)) {
1594             LERROR << "Skipping losetup for '" << entry.blk_device << "'";
1595         }
1596 
1597         if (entry.zram_size > 0) {
1598             // A zram_size was specified, so we need to configure the
1599             // device.  There is no point in having multiple zram devices
1600             // on a system (all the memory comes from the same pool) so
1601             // we can assume the device number is 0.
1602             if (entry.max_comp_streams >= 0) {
1603                 auto zram_mcs_fp = std::unique_ptr<FILE, decltype(&fclose)>{
1604                         fopen(ZRAM_CONF_MCS, "re"), fclose};
1605                 if (zram_mcs_fp == nullptr) {
1606                     LERROR << "Unable to open zram conf comp device " << ZRAM_CONF_MCS;
1607                     ret = false;
1608                     continue;
1609                 }
1610                 fprintf(zram_mcs_fp.get(), "%d\n", entry.max_comp_streams);
1611             }
1612 
1613             auto zram_fp =
1614                     std::unique_ptr<FILE, decltype(&fclose)>{fopen(ZRAM_CONF_DEV, "re+"), fclose};
1615             if (zram_fp == nullptr) {
1616                 LERROR << "Unable to open zram conf device " << ZRAM_CONF_DEV;
1617                 ret = false;
1618                 continue;
1619             }
1620             fprintf(zram_fp.get(), "%" PRId64 "\n", entry.zram_size);
1621         }
1622 
1623         if (entry.fs_mgr_flags.wait && !fs_mgr_wait_for_file(entry.blk_device, 20s)) {
1624             LERROR << "Skipping mkswap for '" << entry.blk_device << "'";
1625             ret = false;
1626             continue;
1627         }
1628 
1629         // Initialize the swap area.
1630         const char* mkswap_argv[2] = {
1631                 MKSWAP_BIN,
1632                 entry.blk_device.c_str(),
1633         };
1634         int err = 0;
1635         int status;
1636         err = android_fork_execvp_ext(ARRAY_SIZE(mkswap_argv), const_cast<char**>(mkswap_argv),
1637                                       &status, true, LOG_KLOG, false, nullptr, nullptr, 0);
1638         if (err) {
1639             LERROR << "mkswap failed for " << entry.blk_device;
1640             ret = false;
1641             continue;
1642         }
1643 
1644         /* If -1, then no priority was specified in fstab, so don't set
1645          * SWAP_FLAG_PREFER or encode the priority */
1646         int flags = 0;
1647         if (entry.swap_prio >= 0) {
1648             flags = (entry.swap_prio << SWAP_FLAG_PRIO_SHIFT) & SWAP_FLAG_PRIO_MASK;
1649             flags |= SWAP_FLAG_PREFER;
1650         } else {
1651             flags = 0;
1652         }
1653         err = swapon(entry.blk_device.c_str(), flags);
1654         if (err) {
1655             LERROR << "swapon failed for " << entry.blk_device;
1656             ret = false;
1657         }
1658     }
1659 
1660     return ret;
1661 }
1662 
fs_mgr_load_verity_state(int * mode)1663 bool fs_mgr_load_verity_state(int* mode) {
1664     /* return the default mode, unless any of the verified partitions are in
1665      * logging mode, in which case return that */
1666     *mode = VERITY_MODE_DEFAULT;
1667 
1668     Fstab fstab;
1669     if (!ReadDefaultFstab(&fstab)) {
1670         LERROR << "Failed to read default fstab";
1671         return false;
1672     }
1673 
1674     for (const auto& entry : fstab) {
1675         if (entry.fs_mgr_flags.avb) {
1676             *mode = VERITY_MODE_RESTART;  // avb only supports restart mode.
1677             break;
1678         } else if (!entry.fs_mgr_flags.verify) {
1679             continue;
1680         }
1681 
1682         int current;
1683         if (load_verity_state(entry, &current) < 0) {
1684             continue;
1685         }
1686         if (current != VERITY_MODE_DEFAULT) {
1687             *mode = current;
1688             break;
1689         }
1690     }
1691 
1692     return true;
1693 }
1694 
fs_mgr_is_verity_enabled(const FstabEntry & entry)1695 bool fs_mgr_is_verity_enabled(const FstabEntry& entry) {
1696     if (!entry.fs_mgr_flags.verify && !entry.fs_mgr_flags.avb) {
1697         return false;
1698     }
1699 
1700     DeviceMapper& dm = DeviceMapper::Instance();
1701 
1702     std::string mount_point = GetVerityDeviceName(entry);
1703     if (dm.GetState(mount_point) == DmDeviceState::INVALID) {
1704         return false;
1705     }
1706 
1707     const char* status;
1708     std::vector<DeviceMapper::TargetInfo> table;
1709     if (!dm.GetTableStatus(mount_point, &table) || table.empty() || table[0].data.empty()) {
1710         if (!entry.fs_mgr_flags.verify_at_boot) {
1711             return false;
1712         }
1713         status = "V";
1714     } else {
1715         status = table[0].data.c_str();
1716     }
1717 
1718     if (*status == 'C' || *status == 'V') {
1719         return true;
1720     }
1721 
1722     return false;
1723 }
1724 
fs_mgr_verity_is_check_at_most_once(const android::fs_mgr::FstabEntry & entry)1725 bool fs_mgr_verity_is_check_at_most_once(const android::fs_mgr::FstabEntry& entry) {
1726     if (!entry.fs_mgr_flags.verify && !entry.fs_mgr_flags.avb) {
1727         return false;
1728     }
1729 
1730     DeviceMapper& dm = DeviceMapper::Instance();
1731     std::string device = GetVerityDeviceName(entry);
1732 
1733     std::vector<DeviceMapper::TargetInfo> table;
1734     if (dm.GetState(device) == DmDeviceState::INVALID || !dm.GetTableInfo(device, &table)) {
1735         return false;
1736     }
1737     for (const auto& target : table) {
1738         if (strcmp(target.spec.target_type, "verity") == 0 &&
1739             target.data.find("check_at_most_once") != std::string::npos) {
1740             return true;
1741         }
1742     }
1743     return false;
1744 }
1745 
fs_mgr_get_super_partition_name(int slot)1746 std::string fs_mgr_get_super_partition_name(int slot) {
1747     // Devices upgrading to dynamic partitions are allowed to specify a super
1748     // partition name. This includes cuttlefish, which is a non-A/B device.
1749     std::string super_partition;
1750     if (fs_mgr_get_boot_config_from_kernel_cmdline("super_partition", &super_partition)) {
1751         if (fs_mgr_get_slot_suffix().empty()) {
1752             return super_partition;
1753         }
1754         std::string suffix;
1755         if (slot == 0) {
1756             suffix = "_a";
1757         } else if (slot == 1) {
1758             suffix = "_b";
1759         } else if (slot == -1) {
1760             suffix = fs_mgr_get_slot_suffix();
1761         }
1762         return super_partition + suffix;
1763     }
1764     return LP_METADATA_DEFAULT_PARTITION_NAME;
1765 }
1766