diff options
Diffstat (limited to 'fs_mgr')
| -rw-r--r-- | fs_mgr/README.overlayfs.md | 11 | ||||
| -rw-r--r-- | fs_mgr/fs_mgr.cpp | 71 | ||||
| -rw-r--r-- | fs_mgr/fs_mgr_fstab.cpp | 1 | ||||
| -rw-r--r-- | fs_mgr/fs_mgr_overlayfs.cpp | 161 | ||||
| -rw-r--r-- | fs_mgr/fs_mgr_priv.h | 52 | ||||
| -rw-r--r-- | fs_mgr/include/fs_mgr.h | 9 | ||||
| -rw-r--r-- | fs_mgr/include/fs_mgr_overlayfs.h | 2 | ||||
| -rw-r--r-- | fs_mgr/libfs_avb/Android.bp | 26 | ||||
| -rw-r--r-- | fs_mgr/libfs_avb/avb_ops.h | 2 | ||||
| -rw-r--r-- | fs_mgr/libfs_avb/avb_util.cpp | 104 | ||||
| -rw-r--r-- | fs_mgr/libfs_avb/avb_util.h | 23 | ||||
| -rw-r--r-- | fs_mgr/libfs_avb/fs_avb.cpp | 27 | ||||
| -rw-r--r-- | fs_mgr/libfs_avb/fs_avb_util.cpp | 78 | ||||
| -rw-r--r-- | fs_mgr/libfs_avb/include/fs_avb/fs_avb.h | 66 | ||||
| -rw-r--r-- | fs_mgr/libfs_avb/include/fs_avb/fs_avb_util.h | 40 | ||||
| -rw-r--r-- | fs_mgr/libfs_avb/include/fs_avb/types.h | 110 | ||||
| -rwxr-xr-x | fs_mgr/libfs_avb/run_tests.sh | 8 | ||||
| -rw-r--r-- | fs_mgr/libfs_avb/tests/fs_avb_device_test.cpp | 93 | ||||
| -rw-r--r-- | fs_mgr/libfs_avb/tests/fs_avb_test_util.h | 2 | ||||
| -rw-r--r-- | fs_mgr/libfs_avb/tests/fs_avb_util_test.cpp | 120 | ||||
| -rw-r--r-- | fs_mgr/libfs_avb/types.cpp | 94 | ||||
| -rwxr-xr-x | fs_mgr/tests/adb-remount-test.sh | 216 |
22 files changed, 917 insertions, 399 deletions
diff --git a/fs_mgr/README.overlayfs.md b/fs_mgr/README.overlayfs.md index 8784c94b9..2aac2601a 100644 --- a/fs_mgr/README.overlayfs.md +++ b/fs_mgr/README.overlayfs.md @@ -74,7 +74,7 @@ a probe of the filesystem types and space remaining. When *overlayfs* logic is feasible, it will use either the **/cache/overlay/** directory for non-A/B devices, or the **/mnt/scratch/overlay** directory for A/B devices that have -access to *Logical Resizeable Android Partitions*. +access to *Logical Resizable Android Partitions*. The backing store is used as soon as possible in the boot process and can occur at first stage init, or at the mount_all init rc commands. @@ -94,12 +94,17 @@ Caveats and thus free dynamic partition space. - Kernel must have CONFIG_OVERLAY_FS=y and will need to be patched with "*overlayfs: override_creds=off option bypass creator_cred*" - if higher than 4.6. + if kernel is higher than 4.6. + The patch is available on the upstream mailing list and the latest as of + Feb 8 2019 is https://lore.kernel.org/patchwork/patch/1009299/. + This patch adds an override_creds _mount_ option to overlayfs that + permits legacy behavior for systems that do not have overlapping + sepolicy rules, principals of least privilege, which is how Android behaves. - *adb enable-verity* will free up overlayfs and as a bonus the device will be reverted pristine to before any content was updated. Update engine does not take advantage of this, will perform a full OTA. - Update engine may not run if *fs_mgr_overlayfs_is_setup*() reports - true as adb remount overrides are incompatable with an OTA resources. + true as adb remount overrides are incompatible with an OTA resources. - For implementation simplicity on retrofit dynamic partition devices, take the whole alternate super (eg: if "*a*" slot, then the whole of "*system_b*"). diff --git a/fs_mgr/fs_mgr.cpp b/fs_mgr/fs_mgr.cpp index e6842938d..b69e773e4 100644 --- a/fs_mgr/fs_mgr.cpp +++ b/fs_mgr/fs_mgr.cpp @@ -85,6 +85,7 @@ #define ARRAY_SIZE(a) (sizeof(a) / sizeof(*(a))) +using android::base::Basename; using android::base::Realpath; using android::base::StartsWith; using android::base::unique_fd; @@ -1576,65 +1577,41 @@ bool fs_mgr_load_verity_state(int* mode) { return true; } -bool fs_mgr_update_verity_state( - std::function<void(const std::string& mount_point, int mode)> callback) { - if (!callback) { +bool fs_mgr_is_verity_enabled(const FstabEntry& entry) { + if (!entry.fs_mgr_flags.verify && !entry.fs_mgr_flags.avb) { return false; } - int mode; - if (!fs_mgr_load_verity_state(&mode)) { - return false; + DeviceMapper& dm = DeviceMapper::Instance(); + + std::string mount_point; + if (entry.mount_point == "/") { + // In AVB, the dm device name is vroot instead of system. + mount_point = entry.fs_mgr_flags.avb ? "vroot" : "system"; + } else { + mount_point = Basename(entry.mount_point); } - Fstab fstab; - if (!ReadDefaultFstab(&fstab)) { - LERROR << "Failed to read default fstab"; + if (dm.GetState(mount_point) == DmDeviceState::INVALID) { return false; } - DeviceMapper& dm = DeviceMapper::Instance(); - - for (const auto& entry : fstab) { - if (!entry.fs_mgr_flags.verify && !entry.fs_mgr_flags.avb) { - continue; - } - - std::string mount_point; - if (entry.mount_point == "/") { - // In AVB, the dm device name is vroot instead of system. - mount_point = entry.fs_mgr_flags.avb ? "vroot" : "system"; - } else { - mount_point = basename(entry.mount_point.c_str()); - } - - if (dm.GetState(mount_point) == DmDeviceState::INVALID) { - PERROR << "Could not find verity device for mount point: " << mount_point; - continue; - } - - const char* status; - std::vector<DeviceMapper::TargetInfo> table; - if (!dm.GetTableStatus(mount_point, &table) || table.empty() || table[0].data.empty()) { - if (!entry.fs_mgr_flags.verify_at_boot) { - PERROR << "Failed to query DM_TABLE_STATUS for " << mount_point; - continue; - } - status = "V"; - } else { - status = table[0].data.c_str(); + const char* status; + std::vector<DeviceMapper::TargetInfo> table; + if (!dm.GetTableStatus(mount_point, &table) || table.empty() || table[0].data.empty()) { + if (!entry.fs_mgr_flags.verify_at_boot) { + return false; } + status = "V"; + } else { + status = table[0].data.c_str(); + } - // To be consistent in vboot 1.0 and vboot 2.0 (AVB), change the mount_point - // back to 'system' for the callback. So it has property [partition.system.verified] - // instead of [partition.vroot.verified]. - if (mount_point == "vroot") mount_point = "system"; - if (*status == 'C' || *status == 'V') { - callback(mount_point, mode); - } + if (*status == 'C' || *status == 'V') { + return true; } - return true; + return false; } std::string fs_mgr_get_super_partition_name(int slot) { diff --git a/fs_mgr/fs_mgr_fstab.cpp b/fs_mgr/fs_mgr_fstab.cpp index 6d86bed73..4659add6f 100644 --- a/fs_mgr/fs_mgr_fstab.cpp +++ b/fs_mgr/fs_mgr_fstab.cpp @@ -176,6 +176,7 @@ void ParseMountFlags(const std::string& flags, FstabEntry* entry) { void ParseFsMgrFlags(const std::string& flags, FstabEntry* entry) { for (const auto& flag : Split(flags, ",")) { + if (flag.empty() || flag == "defaults") continue; std::string arg; if (auto equal_sign = flag.find('='); equal_sign != std::string::npos) { arg = flag.substr(equal_sign + 1); diff --git a/fs_mgr/fs_mgr_overlayfs.cpp b/fs_mgr/fs_mgr_overlayfs.cpp index c7d2cb9fd..9364b2df6 100644 --- a/fs_mgr/fs_mgr_overlayfs.cpp +++ b/fs_mgr/fs_mgr_overlayfs.cpp @@ -67,10 +67,21 @@ bool fs_mgr_access(const std::string& path) { return ret; } +// determine if a filesystem is available +bool fs_mgr_overlayfs_filesystem_available(const std::string& filesystem) { + std::string filesystems; + if (!android::base::ReadFileToString("/proc/filesystems", &filesystems)) return false; + return filesystems.find("\t" + filesystem + "\n") != std::string::npos; +} + } // namespace #if ALLOW_ADBD_DISABLE_VERITY == 0 // If we are a user build, provide stubs +Fstab fs_mgr_overlayfs_candidate_list(const Fstab&) { + return {}; +} + bool fs_mgr_overlayfs_mount_all(Fstab*) { return false; } @@ -231,8 +242,7 @@ std::string fs_mgr_get_overlayfs_options(const std::string& mount_point) { return ret; } -const char* fs_mgr_mount_point(const char* mount_point) { - if (!mount_point) return mount_point; +const std::string fs_mgr_mount_point(const std::string& mount_point) { if ("/"s != mount_point) return mount_point; return "/system"; } @@ -265,15 +275,6 @@ bool fs_mgr_overlayfs_already_mounted(const std::string& mount_point, bool overl return false; } -std::vector<std::string> fs_mgr_overlayfs_verity_enabled_list() { - std::vector<std::string> ret; - auto save_errno = errno; - fs_mgr_update_verity_state( - [&ret](const std::string& mount_point, int) { ret.emplace_back(mount_point); }); - if ((errno == ENOENT) || (errno == ENXIO)) errno = save_errno; - return ret; -} - bool fs_mgr_wants_overlayfs(FstabEntry* entry) { // Don't check entries that are managed by vold. if (entry->fs_mgr_flags.vold_managed || entry->fs_mgr_flags.recovery_only) return false; @@ -321,6 +322,7 @@ bool fs_mgr_overlayfs_setup_dir(const std::string& dir, std::string* overlay, bo bool fs_mgr_overlayfs_setup_one(const std::string& overlay, const std::string& mount_point, bool* change) { auto ret = true; + if (fs_mgr_overlayfs_already_mounted(mount_point)) return ret; auto fsrec_mount_point = overlay + "/" + android::base::Basename(mount_point) + "/"; if (setfscreatecon(kOverlayfsFileContext)) { @@ -527,56 +529,6 @@ bool fs_mgr_overlayfs_mount(const std::string& mount_point) { } } -std::vector<std::string> fs_mgr_candidate_list(Fstab* fstab, const char* mount_point = nullptr) { - std::vector<std::string> mounts; - auto verity = fs_mgr_overlayfs_verity_enabled_list(); - for (auto& entry : *fstab) { - if (!fs_mgr_wants_overlayfs(&entry)) continue; - std::string new_mount_point(fs_mgr_mount_point(entry.mount_point.c_str())); - if (mount_point && (new_mount_point != mount_point)) continue; - if (std::find(verity.begin(), verity.end(), android::base::Basename(new_mount_point)) != - verity.end()) { - continue; - } - auto duplicate_or_more_specific = false; - for (auto it = mounts.begin(); it != mounts.end();) { - if ((*it == new_mount_point) || - (android::base::StartsWith(new_mount_point, *it + "/"))) { - duplicate_or_more_specific = true; - break; - } - if (android::base::StartsWith(*it, new_mount_point + "/")) { - it = mounts.erase(it); - } else { - ++it; - } - } - if (!duplicate_or_more_specific) mounts.emplace_back(new_mount_point); - } - - // if not itemized /system or /, system as root, fake one up? - - // do we want or need to? - if (mount_point && ("/system"s != mount_point)) return mounts; - if (std::find(mounts.begin(), mounts.end(), "/system") != mounts.end()) return mounts; - - // fs_mgr_overlayfs_verity_enabled_list says not to? - if (std::find(verity.begin(), verity.end(), "system") != verity.end()) return mounts; - - // confirm that fstab is missing system - if (GetEntryForMountPoint(fstab, "/") != nullptr || - GetEntryForMountPoint(fstab, "/system") != nullptr) { - return mounts; - } - - // We have a stunted fstab (w/o system or / ) passed in by the caller, - // verity claims are assumed accurate because they are collected internally - // from fs_mgr_fstab_default() from within fs_mgr_update_verity_state(), - // Can (re)evaluate /system with impunity since we know it is ever-present. - mounts.emplace_back("/system"); - return mounts; -} - // Mount kScratchMountPoint bool fs_mgr_overlayfs_mount_scratch(const std::string& device_path, const std::string mnt_type, bool readonly = false) { @@ -625,8 +577,12 @@ const std::string kMkExt4("/system/bin/mke2fs"); // Only a suggestion for _first_ try during mounting std::string fs_mgr_overlayfs_scratch_mount_type() { - if (!access(kMkF2fs.c_str(), X_OK) && fs_mgr_access("/sys/fs/f2fs")) return "f2fs"; - if (!access(kMkExt4.c_str(), X_OK) && fs_mgr_access("/sys/fs/ext4")) return "ext4"; + if (!access(kMkF2fs.c_str(), X_OK) && fs_mgr_overlayfs_filesystem_available("f2fs")) { + return "f2fs"; + } + if (!access(kMkExt4.c_str(), X_OK) && fs_mgr_overlayfs_filesystem_available("ext4")) { + return "ext4"; + } return "auto"; } @@ -657,7 +613,7 @@ bool fs_mgr_overlayfs_make_scratch(const std::string& scratch_device, const std: if (mnt_type == "f2fs") { command = kMkF2fs + " -w 4096 -f -d1 -l" + android::base::Basename(kScratchMountPoint); } else if (mnt_type == "ext4") { - command = kMkExt4 + " -b 4096 -t ext4 -m 0 -O has_journal -M " + kScratchMountPoint; + command = kMkExt4 + " -F -b 4096 -t ext4 -m 0 -O has_journal -M " + kScratchMountPoint; } else { errno = ESRCH; LERROR << mnt_type << " has no mkfs cookbook"; @@ -815,13 +771,46 @@ bool fs_mgr_overlayfs_invalid() { } // namespace +Fstab fs_mgr_overlayfs_candidate_list(const Fstab& fstab) { + Fstab candidates; + for (const auto& entry : fstab) { + FstabEntry new_entry = entry; + if (!fs_mgr_overlayfs_already_mounted(entry.mount_point) && + !fs_mgr_wants_overlayfs(&new_entry)) { + continue; + } + auto new_mount_point = fs_mgr_mount_point(entry.mount_point); + auto duplicate_or_more_specific = false; + for (auto it = candidates.begin(); it != candidates.end();) { + auto it_mount_point = fs_mgr_mount_point(it->mount_point); + if ((it_mount_point == new_mount_point) || + (android::base::StartsWith(new_mount_point, it_mount_point + "/"))) { + duplicate_or_more_specific = true; + break; + } + if (android::base::StartsWith(it_mount_point, new_mount_point + "/")) { + it = candidates.erase(it); + } else { + ++it; + } + } + if (!duplicate_or_more_specific) candidates.emplace_back(std::move(new_entry)); + } + return candidates; +} + bool fs_mgr_overlayfs_mount_all(Fstab* fstab) { auto ret = false; if (fs_mgr_overlayfs_invalid()) return ret; auto scratch_can_be_mounted = true; - for (const auto& mount_point : fs_mgr_candidate_list(fstab)) { - if (fs_mgr_overlayfs_already_mounted(mount_point)) continue; + for (const auto& entry : fs_mgr_overlayfs_candidate_list(*fstab)) { + if (fs_mgr_is_verity_enabled(entry)) continue; + auto mount_point = fs_mgr_mount_point(entry.mount_point); + if (fs_mgr_overlayfs_already_mounted(mount_point)) { + ret = true; + continue; + } if (scratch_can_be_mounted) { scratch_can_be_mounted = false; auto scratch_device = fs_mgr_overlayfs_scratch_device(); @@ -850,8 +839,9 @@ std::vector<std::string> fs_mgr_overlayfs_required_devices(Fstab* fstab) { return {}; } - for (const auto& mount_point : fs_mgr_candidate_list(fstab)) { - if (fs_mgr_overlayfs_already_mounted(mount_point)) continue; + for (const auto& entry : fs_mgr_overlayfs_candidate_list(*fstab)) { + if (fs_mgr_is_verity_enabled(entry)) continue; + if (fs_mgr_overlayfs_already_mounted(fs_mgr_mount_point(entry.mount_point))) continue; auto device = fs_mgr_overlayfs_scratch_device(); if (!fs_mgr_overlayfs_scratch_can_be_mounted(device)) break; return {device}; @@ -877,8 +867,24 @@ bool fs_mgr_overlayfs_setup(const char* backing, const char* mount_point, bool* return false; } errno = save_errno; - auto mounts = fs_mgr_candidate_list(&fstab, fs_mgr_mount_point(mount_point)); - if (mounts.empty()) return ret; + auto candidates = fs_mgr_overlayfs_candidate_list(fstab); + for (auto it = candidates.begin(); it != candidates.end();) { + if (mount_point && + (fs_mgr_mount_point(it->mount_point) != fs_mgr_mount_point(mount_point))) { + it = candidates.erase(it); + continue; + } + save_errno = errno; + auto verity_enabled = fs_mgr_is_verity_enabled(*it); + if (errno == ENOENT || errno == ENXIO) errno = save_errno; + if (verity_enabled) { + it = candidates.erase(it); + continue; + } + ++it; + } + + if (candidates.empty()) return ret; std::string dir; for (const auto& overlay_mount_point : kOverlayMountPoints) { @@ -901,8 +907,8 @@ bool fs_mgr_overlayfs_setup(const char* backing, const char* mount_point, bool* std::string overlay; ret |= fs_mgr_overlayfs_setup_dir(dir, &overlay, change); - for (const auto& fsrec_mount_point : mounts) { - ret |= fs_mgr_overlayfs_setup_one(overlay, fsrec_mount_point, change); + for (const auto& entry : candidates) { + ret |= fs_mgr_overlayfs_setup_one(overlay, fs_mgr_mount_point(entry.mount_point), change); } return ret; } @@ -911,7 +917,6 @@ bool fs_mgr_overlayfs_setup(const char* backing, const char* mount_point, bool* // If something is altered, set *change. bool fs_mgr_overlayfs_teardown(const char* mount_point, bool* change) { if (change) *change = false; - mount_point = fs_mgr_mount_point(mount_point); auto ret = true; // If scratch exists, but is not mounted, lets gain access to clean // specific override entries. @@ -929,7 +934,8 @@ bool fs_mgr_overlayfs_teardown(const char* mount_point, bool* change) { fs_mgr_overlayfs_scratch_mount_type()); } for (const auto& overlay_mount_point : kOverlayMountPoints) { - ret &= fs_mgr_overlayfs_teardown_one(overlay_mount_point, mount_point ?: "", change); + ret &= fs_mgr_overlayfs_teardown_one( + overlay_mount_point, mount_point ? fs_mgr_mount_point(mount_point) : "", change); } if (fs_mgr_overlayfs_valid() == OverlayfsValidResult::kNotSupported) { // After obligatory teardown to make sure everything is clean, but if @@ -956,8 +962,9 @@ bool fs_mgr_overlayfs_is_setup() { return false; } if (fs_mgr_overlayfs_invalid()) return false; - for (const auto& mount_point : fs_mgr_candidate_list(&fstab)) { - if (fs_mgr_overlayfs_already_mounted(mount_point)) return true; + for (const auto& entry : fs_mgr_overlayfs_candidate_list(fstab)) { + if (fs_mgr_is_verity_enabled(entry)) continue; + if (fs_mgr_overlayfs_already_mounted(fs_mgr_mount_point(entry.mount_point))) return true; } return false; } @@ -1002,7 +1009,7 @@ OverlayfsValidResult fs_mgr_overlayfs_valid() { if (fs_mgr_access("/sys/module/overlay/parameters/override_creds")) { return OverlayfsValidResult::kOverrideCredsRequired; } - if (!fs_mgr_access("/sys/module/overlay")) { + if (!fs_mgr_overlayfs_filesystem_available("overlay")) { return OverlayfsValidResult::kNotSupported; } struct utsname uts; diff --git a/fs_mgr/fs_mgr_priv.h b/fs_mgr/fs_mgr_priv.h index 83e5d7bfa..166c32b30 100644 --- a/fs_mgr/fs_mgr_priv.h +++ b/fs_mgr/fs_mgr_priv.h @@ -14,8 +14,7 @@ * limitations under the License. */ -#ifndef __CORE_FS_MGR_PRIV_H -#define __CORE_FS_MGR_PRIV_H +#pragma once #include <chrono> #include <string> @@ -85,53 +84,6 @@ * */ -// clang-format off -#define MF_WAIT 0x1 -#define MF_CHECK 0x2 -#define MF_CRYPT 0x4 -#define MF_NONREMOVABLE 0x8 -#define MF_VOLDMANAGED 0x10 -#define MF_LENGTH 0x20 -#define MF_RECOVERYONLY 0x40 -#define MF_SWAPPRIO 0x80 -#define MF_ZRAMSIZE 0x100 -#define MF_VERIFY 0x200 -#define MF_FORCECRYPT 0x400 -#define MF_NOEMULATEDSD 0x800 /* no emulated sdcard daemon, sd card is the only - external storage */ -#define MF_NOTRIM 0x1000 -#define MF_FILEENCRYPTION 0x2000 -#define MF_FORMATTABLE 0x4000 -#define MF_SLOTSELECT 0x8000 -#define MF_FORCEFDEORFBE 0x10000 -#define MF_LATEMOUNT 0x20000 -#define MF_NOFAIL 0x40000 -#define MF_VERIFYATBOOT 0x80000 -#define MF_MAX_COMP_STREAMS 0x100000 -#define MF_RESERVEDSIZE 0x200000 -#define MF_QUOTA 0x400000 -#define MF_ERASEBLKSIZE 0x800000 -#define MF_LOGICALBLKSIZE 0X1000000 -#define MF_AVB 0X2000000 -#define MF_KEYDIRECTORY 0X4000000 -#define MF_SYSFS 0X8000000 -#define MF_LOGICAL 0x10000000 -#define MF_CHECKPOINT_BLK 0x20000000 -#define MF_CHECKPOINT_FS 0x40000000 -#define MF_FIRST_STAGE_MOUNT \ - 0x80000000 -#define MF_SLOTSELECT_OTHER \ - 0x100000000 -#define MF_ZRAM_LOOPBACK_PATH \ - 0x200000000 -#define MF_ZRAM_LOOPBACK_SIZE \ - 0x400000000 -#define MF_ZRAM_BACKING_DEV_PATH \ - 0x800000000 -#define MF_FS_VERITY \ - 0x1000000000 -// clang-format on - #define DM_BUF_SIZE 4096 using namespace std::chrono_literals; @@ -148,5 +100,3 @@ bool fs_mgr_is_device_unlocked(); const std::string& get_android_dt_dir(); bool is_dt_compatible(); int load_verity_state(const android::fs_mgr::FstabEntry& entry, int* mode); - -#endif /* __CORE_FS_MGR_PRIV_H */ diff --git a/fs_mgr/include/fs_mgr.h b/fs_mgr/include/fs_mgr.h index 8af80a7ad..a3bb85215 100644 --- a/fs_mgr/include/fs_mgr.h +++ b/fs_mgr/include/fs_mgr.h @@ -14,8 +14,7 @@ * limitations under the License. */ -#ifndef __CORE_FS_MGR_H -#define __CORE_FS_MGR_H +#pragma once #include <stdio.h> #include <stdint.h> @@ -73,8 +72,8 @@ int fs_mgr_do_mount_one(const android::fs_mgr::FstabEntry& entry, const std::string& mount_point = ""); int fs_mgr_do_tmpfs_mount(const char *n_name); bool fs_mgr_load_verity_state(int* mode); -bool fs_mgr_update_verity_state( - std::function<void(const std::string& mount_point, int mode)> callback); +// Returns true if verity is enabled on this particular FstabEntry. +bool fs_mgr_is_verity_enabled(const android::fs_mgr::FstabEntry& entry); bool fs_mgr_swapon_all(const android::fs_mgr::Fstab& fstab); bool fs_mgr_update_logical_partition(android::fs_mgr::FstabEntry* entry); @@ -90,5 +89,3 @@ int fs_mgr_setup_verity(android::fs_mgr::FstabEntry* fstab, bool wait_for_verity // specified, the super partition for the corresponding metadata slot will be // returned. Otherwise, it will use the current slot. std::string fs_mgr_get_super_partition_name(int slot = -1); - -#endif /* __CORE_FS_MGR_H */ diff --git a/fs_mgr/include/fs_mgr_overlayfs.h b/fs_mgr/include/fs_mgr_overlayfs.h index 64682cced..6aaf1f3c1 100644 --- a/fs_mgr/include/fs_mgr_overlayfs.h +++ b/fs_mgr/include/fs_mgr_overlayfs.h @@ -21,6 +21,8 @@ #include <string> #include <vector> +android::fs_mgr::Fstab fs_mgr_overlayfs_candidate_list(const android::fs_mgr::Fstab& fstab); + bool fs_mgr_overlayfs_mount_all(android::fs_mgr::Fstab* fstab); std::vector<std::string> fs_mgr_overlayfs_required_devices(android::fs_mgr::Fstab* fstab); bool fs_mgr_overlayfs_setup(const char* backing = nullptr, const char* mount_point = nullptr, diff --git a/fs_mgr/libfs_avb/Android.bp b/fs_mgr/libfs_avb/Android.bp index 3e9326529..a3c76abbb 100644 --- a/fs_mgr/libfs_avb/Android.bp +++ b/fs_mgr/libfs_avb/Android.bp @@ -24,6 +24,8 @@ cc_library_static { "avb_ops.cpp", "avb_util.cpp", "fs_avb.cpp", + "fs_avb_util.cpp", + "types.cpp", "util.cpp", ], static_libs: [ @@ -98,6 +100,7 @@ cc_test_host { srcs: [ "tests/basic_test.cpp", "tests/fs_avb_test.cpp", + "tests/fs_avb_util_test.cpp", ], } @@ -115,3 +118,26 @@ cc_test_host { "tests/util_test.cpp", ], } + +cc_test { + name: "libfs_avb_device_test", + test_suites: ["device-tests"], + static_libs: [ + "libavb", + "libdm", + "libfs_avb", + "libfstab", + ], + shared_libs: [ + "libbase", + "libcrypto", + ], + srcs: [ + "tests/fs_avb_device_test.cpp", + ], + cflags: [ + "-Wall", + "-Wextra", + "-Werror", + ], +} diff --git a/fs_mgr/libfs_avb/avb_ops.h b/fs_mgr/libfs_avb/avb_ops.h index c0f12aa79..a849d94ff 100644 --- a/fs_mgr/libfs_avb/avb_ops.h +++ b/fs_mgr/libfs_avb/avb_ops.h @@ -27,7 +27,7 @@ #include <string> #include <vector> -#include <fs_avb/fs_avb.h> +#include <fs_avb/types.h> #include <libavb/libavb.h> namespace android { diff --git a/fs_mgr/libfs_avb/avb_util.cpp b/fs_mgr/libfs_avb/avb_util.cpp index 08f87b460..fa9080eea 100644 --- a/fs_mgr/libfs_avb/avb_util.cpp +++ b/fs_mgr/libfs_avb/avb_util.cpp @@ -34,56 +34,11 @@ using android::base::unique_fd; namespace android { namespace fs_mgr { -// Helper functions to print enum class VBMetaVerifyResult. -const char* VBMetaVerifyResultToString(VBMetaVerifyResult result) { - // clang-format off - static const char* const name[] = { - "ResultSuccess", - "ResultError", - "ResultErrorVerification", - "ResultUnknown", - }; - // clang-format on - - uint32_t index = static_cast<uint32_t>(result); - uint32_t unknown_index = sizeof(name) / sizeof(char*) - 1; - if (index >= unknown_index) { - index = unknown_index; - } - - return name[index]; -} - -std::ostream& operator<<(std::ostream& os, VBMetaVerifyResult result) { - os << VBMetaVerifyResultToString(result); - return os; -} - -// class VBMetaData -// ---------------- -std::unique_ptr<AvbVBMetaImageHeader> VBMetaData::GetVBMetaHeader(bool update_vbmeta_size) { - auto vbmeta_header = std::make_unique<AvbVBMetaImageHeader>(); - - if (!vbmeta_header) return nullptr; - - /* Byteswap the header. */ - avb_vbmeta_image_header_to_host_byte_order((AvbVBMetaImageHeader*)vbmeta_ptr_.get(), - vbmeta_header.get()); - if (update_vbmeta_size) { - vbmeta_size_ = sizeof(AvbVBMetaImageHeader) + - vbmeta_header->authentication_data_block_size + - vbmeta_header->auxiliary_data_block_size; - } - - return vbmeta_header; -} - // Constructs dm-verity arguments for sending DM_TABLE_LOAD ioctl to kernel. // See the following link for more details: // https://gitlab.com/cryptsetup/cryptsetup/wikis/DMVerity -bool ConstructVerityTable(const AvbHashtreeDescriptor& hashtree_desc, const std::string& salt, - const std::string& root_digest, const std::string& blk_device, - android::dm::DmTable* table) { +bool ConstructVerityTable(const FsAvbHashtreeDescriptor& hashtree_desc, + const std::string& blk_device, android::dm::DmTable* table) { // Loads androidboot.veritymode from kernel cmdline. std::string verity_mode; if (!fs_mgr_get_boot_config("veritymode", &verity_mode)) { @@ -104,12 +59,12 @@ bool ConstructVerityTable(const AvbHashtreeDescriptor& hashtree_desc, const std: std::ostringstream hash_algorithm; hash_algorithm << hashtree_desc.hash_algorithm; - android::dm::DmTargetVerity target(0, hashtree_desc.image_size / 512, - hashtree_desc.dm_verity_version, blk_device, blk_device, - hashtree_desc.data_block_size, hashtree_desc.hash_block_size, - hashtree_desc.image_size / hashtree_desc.data_block_size, - hashtree_desc.tree_offset / hashtree_desc.hash_block_size, - hash_algorithm.str(), root_digest, salt); + android::dm::DmTargetVerity target( + 0, hashtree_desc.image_size / 512, hashtree_desc.dm_verity_version, blk_device, + blk_device, hashtree_desc.data_block_size, hashtree_desc.hash_block_size, + hashtree_desc.image_size / hashtree_desc.data_block_size, + hashtree_desc.tree_offset / hashtree_desc.hash_block_size, hash_algorithm.str(), + hashtree_desc.root_digest, hashtree_desc.salt); if (hashtree_desc.fec_size > 0) { target.UseFec(blk_device, hashtree_desc.fec_num_roots, hashtree_desc.fec_offset / hashtree_desc.data_block_size, @@ -126,12 +81,10 @@ bool ConstructVerityTable(const AvbHashtreeDescriptor& hashtree_desc, const std: return table->AddTarget(std::make_unique<android::dm::DmTargetVerity>(target)); } -bool HashtreeDmVeritySetup(FstabEntry* fstab_entry, const AvbHashtreeDescriptor& hashtree_desc, - const std::string& salt, const std::string& root_digest, +bool HashtreeDmVeritySetup(FstabEntry* fstab_entry, const FsAvbHashtreeDescriptor& hashtree_desc, bool wait_for_verity_dev) { android::dm::DmTable table; - if (!ConstructVerityTable(hashtree_desc, salt, root_digest, fstab_entry->blk_device, &table) || - !table.valid()) { + if (!ConstructVerityTable(hashtree_desc, fstab_entry->blk_device, &table) || !table.valid()) { LERROR << "Failed to construct verity table."; return false; } @@ -164,12 +117,11 @@ bool HashtreeDmVeritySetup(FstabEntry* fstab_entry, const AvbHashtreeDescriptor& return true; } -std::unique_ptr<AvbHashtreeDescriptor> GetHashtreeDescriptor( - const std::string& partition_name, const std::vector<VBMetaData>& vbmeta_images, - std::string* out_salt, std::string* out_digest) { +std::unique_ptr<FsAvbHashtreeDescriptor> GetHashtreeDescriptor( + const std::string& partition_name, const std::vector<VBMetaData>& vbmeta_images) { bool found = false; const uint8_t* desc_partition_name; - auto hashtree_desc = std::make_unique<AvbHashtreeDescriptor>(); + auto hashtree_desc = std::make_unique<FsAvbHashtreeDescriptor>(); for (const auto& vbmeta : vbmeta_images) { size_t num_descriptors; @@ -209,15 +161,17 @@ std::unique_ptr<AvbHashtreeDescriptor> GetHashtreeDescriptor( } if (!found) { - LERROR << "Partition descriptor not found: " << partition_name.c_str(); + LERROR << "Hashtree descriptor not found: " << partition_name; return nullptr; } + hashtree_desc->partition_name = partition_name; + const uint8_t* desc_salt = desc_partition_name + hashtree_desc->partition_name_len; - *out_salt = BytesToHex(desc_salt, hashtree_desc->salt_len); + hashtree_desc->salt = BytesToHex(desc_salt, hashtree_desc->salt_len); const uint8_t* desc_digest = desc_salt + hashtree_desc->salt_len; - *out_digest = BytesToHex(desc_digest, hashtree_desc->root_digest_len); + hashtree_desc->root_digest = BytesToHex(desc_digest, hashtree_desc->root_digest_len); return hashtree_desc; } @@ -235,18 +189,15 @@ bool LoadAvbHashtreeToEnableVerity(FstabEntry* fstab_entry, bool wait_for_verity return false; } - std::string salt; - std::string root_digest; - std::unique_ptr<AvbHashtreeDescriptor> hashtree_descriptor = - GetHashtreeDescriptor(partition_name, vbmeta_images, &salt, &root_digest); + std::unique_ptr<FsAvbHashtreeDescriptor> hashtree_descriptor = + GetHashtreeDescriptor(partition_name, vbmeta_images); if (!hashtree_descriptor) { return false; } // Converts HASHTREE descriptor to verity table to load into kernel. // When success, the new device path will be returned, e.g., /dev/block/dm-2. - return HashtreeDmVeritySetup(fstab_entry, *hashtree_descriptor, salt, root_digest, - wait_for_verity_dev); + return HashtreeDmVeritySetup(fstab_entry, *hashtree_descriptor, wait_for_verity_dev); } // Converts a AVB partition_name (without A/B suffix) to a device partition name. @@ -420,6 +371,10 @@ std::unique_ptr<VBMetaData> VerifyVBMetaData(int fd, const std::string& partitio uint64_t vbmeta_size = VBMetaData::kMaxVBMetaSize; bool is_vbmeta_partition = StartsWith(partition_name, "vbmeta"); + if (out_verify_result) { + *out_verify_result = VBMetaVerifyResult::kError; + } + if (!is_vbmeta_partition) { std::unique_ptr<AvbFooter> footer = GetAvbFooter(fd); if (!footer) { @@ -445,7 +400,10 @@ std::unique_ptr<VBMetaData> VerifyVBMetaData(int fd, const std::string& partitio auto verify_result = VerifyVBMetaSignature(*vbmeta, expected_public_key_blob, out_public_key_data); - if (out_verify_result != nullptr) *out_verify_result = verify_result; + + if (out_verify_result != nullptr) { + *out_verify_result = verify_result; + } if (verify_result == VBMetaVerifyResult::kSuccess || verify_result == VBMetaVerifyResult::kErrorVerification) { @@ -508,6 +466,10 @@ std::unique_ptr<VBMetaData> LoadAndVerifyVbmetaByPath( const std::string& expected_public_key_blob, bool allow_verification_error, bool rollback_protection, bool is_chained_vbmeta, std::string* out_public_key_data, bool* out_verification_disabled, VBMetaVerifyResult* out_verify_result) { + if (out_verify_result) { + *out_verify_result = VBMetaVerifyResult::kError; + } + // Ensures the device path (might be a symlink created by init) is ready to access. if (!WaitForFile(image_path, 1s)) { PERROR << "No such path: " << image_path; diff --git a/fs_mgr/libfs_avb/avb_util.h b/fs_mgr/libfs_avb/avb_util.h index 4b54e27b8..9babd8802 100644 --- a/fs_mgr/libfs_avb/avb_util.h +++ b/fs_mgr/libfs_avb/avb_util.h @@ -24,19 +24,11 @@ #include <libavb/libavb.h> #include <libdm/dm.h> -#include "fs_avb/fs_avb.h" +#include "fs_avb/types.h" namespace android { namespace fs_mgr { -enum class VBMetaVerifyResult { - kSuccess = 0, - kError = 1, - kErrorVerification = 2, -}; - -std::ostream& operator<<(std::ostream& os, VBMetaVerifyResult); - struct ChainInfo { std::string partition_name; std::string public_key_blob; @@ -46,16 +38,13 @@ struct ChainInfo { }; // AvbHashtreeDescriptor to dm-verity table setup. -std::unique_ptr<AvbHashtreeDescriptor> GetHashtreeDescriptor( - const std::string& partition_name, const std::vector<VBMetaData>& vbmeta_images, - std::string* out_salt, std::string* out_digest); +std::unique_ptr<FsAvbHashtreeDescriptor> GetHashtreeDescriptor( + const std::string& partition_name, const std::vector<VBMetaData>& vbmeta_images); -bool ConstructVerityTable(const AvbHashtreeDescriptor& hashtree_desc, const std::string& salt, - const std::string& root_digest, const std::string& blk_device, - android::dm::DmTable* table); +bool ConstructVerityTable(const FsAvbHashtreeDescriptor& hashtree_desc, + const std::string& blk_device, android::dm::DmTable* table); -bool HashtreeDmVeritySetup(FstabEntry* fstab_entry, const AvbHashtreeDescriptor& hashtree_desc, - const std::string& salt, const std::string& root_digest, +bool HashtreeDmVeritySetup(FstabEntry* fstab_entry, const FsAvbHashtreeDescriptor& hashtree_desc, bool wait_for_verity_dev); // Searches a Avb hashtree descriptor in vbmeta_images for fstab_entry, to enable dm-verity. diff --git a/fs_mgr/libfs_avb/fs_avb.cpp b/fs_mgr/libfs_avb/fs_avb.cpp index 1af3b3321..938e149df 100644 --- a/fs_mgr/libfs_avb/fs_avb.cpp +++ b/fs_mgr/libfs_avb/fs_avb.cpp @@ -76,33 +76,6 @@ std::pair<std::string, size_t> CalculateVbmetaDigest(const std::vector<VBMetaDat return std::make_pair(digest, total_size); } -// Helper functions to dump enum class AvbHandleStatus. -const char* AvbHandleStatusToString(AvbHandleStatus status) { - // clang-format off - static const char* const name[] = { - "Success", - "Uninitialized", - "HashtreeDisabled", - "VerificationDisabled", - "VerificationError", - "Unknown", - }; - // clang-format on - - uint32_t index = static_cast<uint32_t>(status); - uint32_t unknown_index = sizeof(name) / sizeof(char*) - 1; - if (index >= unknown_index) { - index = unknown_index; - } - - return name[index]; -} - -std::ostream& operator<<(std::ostream& os, AvbHandleStatus status) { - os << AvbHandleStatusToString(status); - return os; -} - // class AvbVerifier // ----------------- // Reads the following values from kernel cmdline and provides the diff --git a/fs_mgr/libfs_avb/fs_avb_util.cpp b/fs_mgr/libfs_avb/fs_avb_util.cpp new file mode 100644 index 000000000..f82f83dea --- /dev/null +++ b/fs_mgr/libfs_avb/fs_avb_util.cpp @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "fs_avb/fs_avb_util.h" + +#include <memory> +#include <string> +#include <vector> + +#include <android-base/strings.h> +#include <fstab/fstab.h> +#include <libavb/libavb.h> +#include <libdm/dm.h> + +#include "avb_util.h" +#include "util.h" + +namespace android { +namespace fs_mgr { + +// Given a FstabEntry, loads and verifies the vbmeta, to extract the Avb Hashtree descriptor. +std::unique_ptr<VBMetaData> LoadAndVerifyVbmeta(const FstabEntry& fstab_entry, + const std::string& expected_public_key_blob, + std::string* out_public_key_data, + std::string* out_avb_partition_name, + VBMetaVerifyResult* out_verify_result) { + // Derives partition_name from blk_device to query the corresponding AVB HASHTREE descriptor + // to setup dm-verity. The partition_names in AVB descriptors are without A/B suffix. + std::string avb_partition_name = DeriveAvbPartitionName(fstab_entry, fs_mgr_get_slot_suffix(), + fs_mgr_get_other_slot_suffix()); + if (out_avb_partition_name) { + *out_avb_partition_name = avb_partition_name; + } + + // Updates fstab_entry->blk_device from <partition> to /dev/block/dm-<N> if + // it's a logical partition. + std::string device_path = fstab_entry.blk_device; + if (fstab_entry.fs_mgr_flags.logical && + !android::base::StartsWith(fstab_entry.blk_device, "/")) { + dm::DeviceMapper& dm = dm::DeviceMapper::Instance(); + if (!dm.GetDmDevicePathByName(fstab_entry.blk_device, &device_path)) { + LERROR << "Failed to resolve logical device path for: " << fstab_entry.blk_device; + return nullptr; + } + } + + return LoadAndVerifyVbmetaByPath(device_path, avb_partition_name, expected_public_key_blob, + true /* allow_verification_error */, + false /* rollback_protection */, false /* is_chained_vbmeta */, + out_public_key_data, nullptr /* out_verification_disabled */, + out_verify_result); +} + +// Given a path, loads and verifies the vbmeta, to extract the Avb Hashtree descriptor. +std::unique_ptr<FsAvbHashtreeDescriptor> GetHashtreeDescriptor( + const std::string& avb_partition_name, VBMetaData&& vbmeta) { + if (!vbmeta.size()) return nullptr; + + std::vector<VBMetaData> vbmeta_images; + vbmeta_images.emplace_back(std::move(vbmeta)); + return GetHashtreeDescriptor(avb_partition_name, vbmeta_images); +} + +} // namespace fs_mgr +} // namespace android diff --git a/fs_mgr/libfs_avb/include/fs_avb/fs_avb.h b/fs_mgr/libfs_avb/include/fs_avb/fs_avb.h index d4e3a6e46..d02672211 100644 --- a/fs_mgr/libfs_avb/include/fs_avb/fs_avb.h +++ b/fs_mgr/libfs_avb/include/fs_avb/fs_avb.h @@ -21,32 +21,13 @@ #include <string> #include <vector> +#include <fs_avb/types.h> #include <fstab/fstab.h> #include <libavb/libavb.h> namespace android { namespace fs_mgr { -enum class AvbHashtreeResult { - kSuccess = 0, - kFail, - kDisabled, -}; - -enum class HashAlgorithm { - kInvalid = 0, - kSHA256 = 1, - kSHA512 = 2, -}; - -enum class AvbHandleStatus { - kSuccess = 0, - kUninitialized = 1, - kHashtreeDisabled = 2, - kVerificationDisabled = 3, - kVerificationError = 4, -}; - struct VBMetaInfo { std::string digest; HashAlgorithm hash_algorithm; @@ -58,51 +39,6 @@ struct VBMetaInfo { : digest(std::move(digest_value)), hash_algorithm(algorithm), total_size(size) {} }; -class VBMetaData { - public: - // Constructors - VBMetaData() : vbmeta_ptr_(nullptr), vbmeta_size_(0){}; - - VBMetaData(const uint8_t* data, size_t size, const std::string& partition_name) - : vbmeta_ptr_(new (std::nothrow) uint8_t[size]), - vbmeta_size_(size), - partition_name_(partition_name) { - // The ownership of data is NOT transferred, i.e., the caller still - // needs to release the memory as we make a copy here. - memcpy(vbmeta_ptr_.get(), data, size * sizeof(uint8_t)); - } - - explicit VBMetaData(size_t size, const std::string& partition_name) - : vbmeta_ptr_(new (std::nothrow) uint8_t[size]), - vbmeta_size_(size), - partition_name_(partition_name) {} - - // Extracts vbmeta header from the vbmeta buffer, set update_vbmeta_size to - // true to update vbmeta_size_ to the actual size with valid content. - std::unique_ptr<AvbVBMetaImageHeader> GetVBMetaHeader(bool update_vbmeta_size = false); - - // Sets the vbmeta_path where we load the vbmeta data. Could be a partition or a file. - // e.g., - // - /dev/block/by-name/system_a - // - /path/to/system_other.img. - void set_vbmeta_path(std::string vbmeta_path) { vbmeta_path_ = std::move(vbmeta_path); } - - // Get methods for each data member. - const std::string& partition() const { return partition_name_; } - const std::string& vbmeta_path() const { return vbmeta_path_; } - uint8_t* data() const { return vbmeta_ptr_.get(); } - const size_t& size() const { return vbmeta_size_; } - - // Maximum size of a vbmeta data - 64 KiB. - static const size_t kMaxVBMetaSize = 64 * 1024; - - private: - std::unique_ptr<uint8_t[]> vbmeta_ptr_; - size_t vbmeta_size_; - std::string partition_name_; - std::string vbmeta_path_; -}; - class FsManagerAvbOps; class AvbHandle; diff --git a/fs_mgr/libfs_avb/include/fs_avb/fs_avb_util.h b/fs_mgr/libfs_avb/include/fs_avb/fs_avb_util.h new file mode 100644 index 000000000..ec8badbcb --- /dev/null +++ b/fs_mgr/libfs_avb/include/fs_avb/fs_avb_util.h @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include <string> + +#include <fs_avb/types.h> +#include <fstab/fstab.h> +#include <libavb/libavb.h> + +namespace android { +namespace fs_mgr { + +// Given a FstabEntry, loads and verifies the vbmeta. +std::unique_ptr<VBMetaData> LoadAndVerifyVbmeta(const FstabEntry& fstab_entry, + const std::string& expected_public_key_blob, + std::string* out_public_key_data, + std::string* out_avb_partition_name, + VBMetaVerifyResult* out_verify_result); + +// Gets the hashtree descriptor for avb_partition_name from the vbmeta. +std::unique_ptr<FsAvbHashtreeDescriptor> GetHashtreeDescriptor( + const std::string& avb_partition_name, VBMetaData&& vbmeta); + +} // namespace fs_mgr +} // namespace android diff --git a/fs_mgr/libfs_avb/include/fs_avb/types.h b/fs_mgr/libfs_avb/include/fs_avb/types.h new file mode 100644 index 000000000..bd638e663 --- /dev/null +++ b/fs_mgr/libfs_avb/include/fs_avb/types.h @@ -0,0 +1,110 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include <cstring> +#include <memory> +#include <ostream> + +#include <libavb/libavb.h> + +namespace android { +namespace fs_mgr { + +enum class VBMetaVerifyResult { + kSuccess = 0, + kError = 1, + kErrorVerification = 2, +}; + +std::ostream& operator<<(std::ostream& os, VBMetaVerifyResult); + +enum class AvbHashtreeResult { + kSuccess = 0, + kFail, + kDisabled, +}; + +enum class HashAlgorithm { + kInvalid = 0, + kSHA256 = 1, + kSHA512 = 2, +}; + +enum class AvbHandleStatus { + kSuccess = 0, + kUninitialized = 1, + kHashtreeDisabled = 2, + kVerificationDisabled = 3, + kVerificationError = 4, +}; + +std::ostream& operator<<(std::ostream& os, AvbHandleStatus status); + +struct FsAvbHashtreeDescriptor : AvbHashtreeDescriptor { + std::string partition_name; + std::string salt; + std::string root_digest; +}; + +class VBMetaData { + public: + // Constructors + VBMetaData() : vbmeta_ptr_(nullptr), vbmeta_size_(0){}; + + VBMetaData(const uint8_t* data, size_t size, const std::string& partition_name) + : vbmeta_ptr_(new (std::nothrow) uint8_t[size]), + vbmeta_size_(size), + partition_name_(partition_name) { + // The ownership of data is NOT transferred, i.e., the caller still + // needs to release the memory as we make a copy here. + std::memcpy(vbmeta_ptr_.get(), data, size * sizeof(uint8_t)); + } + + explicit VBMetaData(size_t size, const std::string& partition_name) + : vbmeta_ptr_(new (std::nothrow) uint8_t[size]), + vbmeta_size_(size), + partition_name_(partition_name) {} + + // Extracts vbmeta header from the vbmeta buffer, set update_vbmeta_size to + // true to update vbmeta_size_ to the actual size with valid content. + std::unique_ptr<AvbVBMetaImageHeader> GetVBMetaHeader(bool update_vbmeta_size = false); + + // Sets the vbmeta_path where we load the vbmeta data. Could be a partition or a file. + // e.g., + // - /dev/block/by-name/system_a + // - /path/to/system_other.img. + void set_vbmeta_path(std::string vbmeta_path) { vbmeta_path_ = std::move(vbmeta_path); } + + // Get methods for each data member. + const std::string& partition() const { return partition_name_; } + const std::string& vbmeta_path() const { return vbmeta_path_; } + uint8_t* data() const { return vbmeta_ptr_.get(); } + const size_t& size() const { return vbmeta_size_; } + + // Maximum size of a vbmeta data - 64 KiB. + static const size_t kMaxVBMetaSize = 64 * 1024; + + private: + std::unique_ptr<uint8_t[]> vbmeta_ptr_; + size_t vbmeta_size_; + std::string partition_name_; + std::string vbmeta_path_; +}; + +} // namespace fs_mgr +} // namespace android diff --git a/fs_mgr/libfs_avb/run_tests.sh b/fs_mgr/libfs_avb/run_tests.sh new file mode 100755 index 000000000..5d2ce3df6 --- /dev/null +++ b/fs_mgr/libfs_avb/run_tests.sh @@ -0,0 +1,8 @@ +#!/bin/sh +# +# Run host tests +atest libfs_avb_test # Tests public libfs_avb APIs. +atest libfs_avb_internal_test # Tests libfs_avb private APIs. + +# Run device tests +atest libfs_avb_device_test # Test public libfs_avb APIs on a device. diff --git a/fs_mgr/libfs_avb/tests/fs_avb_device_test.cpp b/fs_mgr/libfs_avb/tests/fs_avb_device_test.cpp new file mode 100644 index 000000000..fc4eb5f8e --- /dev/null +++ b/fs_mgr/libfs_avb/tests/fs_avb_device_test.cpp @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <android-base/properties.h> +#include <fs_avb/fs_avb_util.h> +#include <fstab/fstab.h> +#include <gtest/gtest.h> + +#include <sys/types.h> +#include <unistd.h> + +using android::fs_mgr::Fstab; +using android::fs_mgr::FstabEntry; +using android::fs_mgr::VBMetaData; +using android::fs_mgr::VBMetaVerifyResult; + +namespace fs_avb_device_test { + +// system vbmeta might not be at the end of /system when dynamic partition is +// enabled. Therefore, disable it by default. +TEST(PublicFsAvbDeviceTest, DISABLED_LoadAndVerifyVbmeta_SystemVbmeta) { + Fstab fstab; + EXPECT_TRUE(ReadDefaultFstab(&fstab)); + + FstabEntry* system_entry = GetEntryForMountPoint(&fstab, "/system"); + EXPECT_NE(nullptr, system_entry); + + std::string out_public_key_data; + std::string out_avb_partition_name; + VBMetaVerifyResult out_verify_result; + std::unique_ptr<VBMetaData> vbmeta = + LoadAndVerifyVbmeta(*system_entry, "" /* expected_public_key_blob */, + &out_public_key_data, &out_avb_partition_name, &out_verify_result); + + EXPECT_NE(nullptr, vbmeta); + EXPECT_EQ(VBMetaVerifyResult::kSuccess, out_verify_result); + EXPECT_EQ("system", out_avb_partition_name); + EXPECT_NE("", out_public_key_data); +} + +TEST(PublicFsAvbDeviceTest, GetHashtreeDescriptor_SystemOther) { + // Non-A/B device doesn't have system_other partition. + if (fs_mgr_get_slot_suffix() == "") return; + + // Skip running this test if system_other is a logical partition. + // Note that system_other is still a physical partition on "retrofit" devices. + if (android::base::GetBoolProperty("ro.boot.dynamic_partitions", false) && + !android::base::GetBoolProperty("ro.boot.dynamic_partitions_retrofit", false)) { + return; + } + + Fstab fstab; + EXPECT_TRUE(ReadFstabFromFile("/system/etc/fstab.postinstall", &fstab)); + + // It should have two lines in the fstab, the first for logical system_other, + // the other for physical system_other. + EXPECT_EQ(2UL, fstab.size()); + + // Use the 2nd fstab entry, which is for physical system_other partition. + FstabEntry* system_other = &fstab[1]; + EXPECT_NE(nullptr, system_other); + + std::string out_public_key_data; + std::string out_avb_partition_name; + VBMetaVerifyResult out_verify_result; + std::unique_ptr<VBMetaData> system_other_vbmeta = + LoadAndVerifyVbmeta(*system_other, "" /* expected_public_key_blob */, + &out_public_key_data, &out_avb_partition_name, &out_verify_result); + + EXPECT_NE(nullptr, system_other_vbmeta); + EXPECT_EQ(VBMetaVerifyResult::kSuccess, out_verify_result); + EXPECT_EQ("system_other", out_avb_partition_name); + EXPECT_NE("", out_public_key_data); + + auto hashtree_desc = + GetHashtreeDescriptor(out_avb_partition_name, std::move(*system_other_vbmeta)); + EXPECT_NE(nullptr, hashtree_desc); +} + +} // namespace fs_avb_device_test diff --git a/fs_mgr/libfs_avb/tests/fs_avb_test_util.h b/fs_mgr/libfs_avb/tests/fs_avb_test_util.h index 2e466440d..ab1980bb9 100644 --- a/fs_mgr/libfs_avb/tests/fs_avb_test_util.h +++ b/fs_mgr/libfs_avb/tests/fs_avb_test_util.h @@ -29,7 +29,7 @@ #include <android-base/unique_fd.h> #include <base/files/file_path.h> #include <base/strings/stringprintf.h> -#include <fs_avb/fs_avb.h> +#include <fs_avb/types.h> #include <gtest/gtest.h> // Utility macro to run the command expressed by the printf()-style string diff --git a/fs_mgr/libfs_avb/tests/fs_avb_util_test.cpp b/fs_mgr/libfs_avb/tests/fs_avb_util_test.cpp new file mode 100644 index 000000000..7c340099e --- /dev/null +++ b/fs_mgr/libfs_avb/tests/fs_avb_util_test.cpp @@ -0,0 +1,120 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <fs_avb/fs_avb_util.h> + +#include "fs_avb_test_util.h" + +namespace fs_avb_host_test { + +class PublicFsAvbUtilTest : public BaseFsAvbTest { + public: + PublicFsAvbUtilTest(){}; + + protected: + ~PublicFsAvbUtilTest(){}; +}; + +TEST_F(PublicFsAvbUtilTest, GetHashtreeDescriptor) { + // Generates a raw system_other.img, use a smaller size to speed-up unit test. + const size_t system_image_size = 10 * 1024 * 1024; + const size_t system_partition_size = 15 * 1024 * 1024; + base::FilePath system_path = GenerateImage("system.img", system_image_size); + + // Adds AVB Hashtree Footer. + AddAvbFooter(system_path, "hashtree", "system", system_partition_size, "SHA512_RSA4096", 20, + data_dir_.Append("testkey_rsa4096.pem"), "d00df00d", + "--internal_release_string \"unit test\""); + + auto system_vbmeta = ExtractAndLoadVBMetaData(system_path, "system-vbmeta.img"); + + auto hashtree_desc = + GetHashtreeDescriptor("system" /* avb_partition_name */, std::move(system_vbmeta)); + EXPECT_NE(nullptr, hashtree_desc); + + // Checks the returned hashtree_desc matches the following info returned by avbtool. + EXPECT_EQ( + "Footer version: 1.0\n" + "Image size: 15728640 bytes\n" + "Original image size: 10485760 bytes\n" + "VBMeta offset: 10661888\n" + "VBMeta size: 2112 bytes\n" + "--\n" + "Minimum libavb version: 1.0\n" + "Header Block: 256 bytes\n" + "Authentication Block: 576 bytes\n" + "Auxiliary Block: 1280 bytes\n" + "Algorithm: SHA512_RSA4096\n" + "Rollback Index: 20\n" + "Flags: 0\n" + "Release String: 'unit test'\n" + "Descriptors:\n" + " Hashtree descriptor:\n" + " Version of dm-verity: 1\n" + " Image Size: 10485760 bytes\n" + " Tree Offset: 10485760\n" + " Tree Size: 86016 bytes\n" + " Data Block Size: 4096 bytes\n" + " Hash Block Size: 4096 bytes\n" + " FEC num roots: 2\n" + " FEC offset: 10571776\n" + " FEC size: 90112 bytes\n" + " Hash Algorithm: sha1\n" + " Partition Name: system\n" + " Salt: d00df00d\n" + " Root Digest: a3d5dd307341393d85de356c384ff543ec1ed81b\n" + " Flags: 0\n", + InfoImage(system_path)); + + EXPECT_EQ(1UL, hashtree_desc->dm_verity_version); + EXPECT_EQ(10485760UL, hashtree_desc->image_size); + EXPECT_EQ(10485760UL, hashtree_desc->tree_offset); + EXPECT_EQ(86016UL, hashtree_desc->tree_size); + EXPECT_EQ(4096UL, hashtree_desc->data_block_size); + EXPECT_EQ(4096UL, hashtree_desc->hash_block_size); + EXPECT_EQ(2UL, hashtree_desc->fec_num_roots); + EXPECT_EQ(10571776UL, hashtree_desc->fec_offset); + EXPECT_EQ(90112UL, hashtree_desc->fec_size); + EXPECT_EQ(std::string("sha1"), + std::string(reinterpret_cast<const char*>(hashtree_desc->hash_algorithm))); + EXPECT_EQ(std::string("system").length(), hashtree_desc->partition_name_len); + EXPECT_EQ(hashtree_desc->partition_name, "system"); + EXPECT_EQ(hashtree_desc->salt, "d00df00d"); + EXPECT_EQ(hashtree_desc->root_digest, "a3d5dd307341393d85de356c384ff543ec1ed81b"); + + // Checks it's null if partition name doesn't match. + EXPECT_EQ(nullptr, GetHashtreeDescriptor("system_not_exist" /* avb_partition_name */, + std::move(system_vbmeta))); +} + +TEST_F(PublicFsAvbUtilTest, GetHashtreeDescriptor_NotFound) { + // Generates a raw boot.img + const size_t image_size = 5 * 1024 * 1024; + const size_t partition_size = 10 * 1024 * 1024; + base::FilePath boot_path = GenerateImage("boot.img", image_size); + // Appends AVB Hash Footer. + AddAvbFooter(boot_path, "hash", "boot", partition_size, "SHA256_RSA4096", 10, + data_dir_.Append("testkey_rsa4096.pem"), "d00df00d", + "--internal_release_string \"unit test\""); + // Extracts boot vbmeta from boot.img into boot-vbmeta.img. + auto boot_vbmeta = ExtractAndLoadVBMetaData(boot_path, "boot-vbmeta.img"); + + auto hashtree_desc = + GetHashtreeDescriptor("boot" /* avb_partition_name */, std::move(boot_vbmeta)); + EXPECT_EQ(nullptr, hashtree_desc); +} + +} // namespace fs_avb_host_test diff --git a/fs_mgr/libfs_avb/types.cpp b/fs_mgr/libfs_avb/types.cpp new file mode 100644 index 000000000..3c277f34b --- /dev/null +++ b/fs_mgr/libfs_avb/types.cpp @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "fs_avb/types.h" + +namespace android { +namespace fs_mgr { + +// Helper functions to print enum class VBMetaVerifyResult. +const char* VBMetaVerifyResultToString(VBMetaVerifyResult result) { + // clang-format off + static const char* const name[] = { + "ResultSuccess", + "ResultError", + "ResultErrorVerification", + "ResultUnknown", + }; + // clang-format on + + uint32_t index = static_cast<uint32_t>(result); + uint32_t unknown_index = sizeof(name) / sizeof(char*) - 1; + if (index >= unknown_index) { + index = unknown_index; + } + + return name[index]; +} + +std::ostream& operator<<(std::ostream& os, VBMetaVerifyResult result) { + os << VBMetaVerifyResultToString(result); + return os; +} + +// Helper functions to dump enum class AvbHandleStatus. +const char* AvbHandleStatusToString(AvbHandleStatus status) { + // clang-format off + static const char* const name[] = { + "Success", + "Uninitialized", + "HashtreeDisabled", + "VerificationDisabled", + "VerificationError", + "Unknown", + }; + // clang-format on + + uint32_t index = static_cast<uint32_t>(status); + uint32_t unknown_index = sizeof(name) / sizeof(char*) - 1; + if (index >= unknown_index) { + index = unknown_index; + } + + return name[index]; +} + +std::ostream& operator<<(std::ostream& os, AvbHandleStatus status) { + os << AvbHandleStatusToString(status); + return os; +} + +// class VBMetaData +// ---------------- +std::unique_ptr<AvbVBMetaImageHeader> VBMetaData::GetVBMetaHeader(bool update_vbmeta_size) { + auto vbmeta_header = std::make_unique<AvbVBMetaImageHeader>(); + + if (!vbmeta_header) return nullptr; + + /* Byteswap the header. */ + avb_vbmeta_image_header_to_host_byte_order((AvbVBMetaImageHeader*)vbmeta_ptr_.get(), + vbmeta_header.get()); + if (update_vbmeta_size) { + vbmeta_size_ = sizeof(AvbVBMetaImageHeader) + + vbmeta_header->authentication_data_block_size + + vbmeta_header->auxiliary_data_block_size; + } + + return vbmeta_header; +} + +} // namespace fs_mgr +} // namespace android diff --git a/fs_mgr/tests/adb-remount-test.sh b/fs_mgr/tests/adb-remount-test.sh index 4d9bc610f..7fc951831 100755 --- a/fs_mgr/tests/adb-remount-test.sh +++ b/fs_mgr/tests/adb-remount-test.sh @@ -1,4 +1,15 @@ #! /bin/bash +# +# Divided into four section: +# +## USAGE +## Helper Variables +## Helper Functions +## MAINLINE + +## +## USAGE +## USAGE="USAGE: `basename ${0}` [-s <SerialNumber>] @@ -17,20 +28,26 @@ if [ X"${1}" = X"--help" -o X"${1}" = X"-h" -o X"${1}" = X"-?" ]; then exit 0 fi -# Helper Variables +## +## Helper Variables +## SPACE=" " # A _real_ embedded tab character TAB="`echo | tr '\n' '\t'`" # A _real_ embedded escape character ESCAPE="`echo | tr '\n' '\033'`" +# A _real_ embedded carriage return character +CR="`echo | tr '\n' '\r'`" GREEN="${ESCAPE}[38;5;40m" RED="${ESCAPE}[38;5;196m" ORANGE="${ESCAPE}[38;5;255:165:0m" BLUE="${ESCAPE}[35m" NORMAL="${ESCAPE}[0m" -# Helper functions +## +## Helper Functions +## [ "USAGE: inFastboot @@ -68,6 +85,8 @@ adb_sh() { args="${args}${i}" elif [ X"${i}" != X"${i#* }" ]; then args="${args}'${i}'" + elif [ X"${i}" != X"${i#*${TAB}}" ]; then + args="${args}'${i}'" else args="${args}${i}" fi @@ -130,21 +149,82 @@ adb_cat() { Returns: true if the reboot command succeeded" ] adb_reboot() { - adb reboot remount-test && + adb reboot remount-test || true sleep 2 } +[ "USAGE: format_duration [<seconds>|<seconds>s|<minutes>m|<hours>h|<days>d] + +human readable output whole seconds, whole minutes or mm:ss" ] +format_duration() { + if [ -z "${1}" ]; then + echo unknown + return + fi + duration="${1}" + if [ X"${duration}" != X"${duration%s}" ]; then + duration=${duration%s} + elif [ X"${duration}" != X"${duration%m}" ]; then + duration=`expr ${duration%m} \* 60` + elif [ X"${duration}" != X"${duration%h}" ]; then + duration=`expr ${duration%h} \* 3600` + elif [ X"${duration}" != X"${duration%d}" ]; then + duration=`expr ${duration%d} \* 86400` + fi + seconds=`expr ${duration} % 60` + minutes=`expr \( ${duration} / 60 \) % 60` + hours=`expr ${duration} / 3600` + if [ 0 -eq ${minutes} -a 0 -eq ${hours} ]; then + if [ 1 -eq ${duration} ]; then + echo 1 second + return + fi + echo ${duration} seconds + return + elif [ 60 -eq ${duration} ]; then + echo 1 minute + return + elif [ 0 -eq ${seconds} -a 0 -eq ${hours} ]; then + echo ${minutes} minutes + return + fi + if [ 0 -eq ${hours} ]; then + echo ${minutes}:`expr ${seconds} / 10``expr ${seconds} % 10` + return + fi + echo ${hours}:`expr ${minutes} / 10``expr ${minutes} % 10`:`expr ${seconds} / 10``expr ${seconds} % 10` +} + [ "USAGE: adb_wait [timeout] Returns: waits until the device has returned for adb or optional timeout" ] adb_wait() { if [ -n "${1}" ]; then + echo -n ". . . waiting `format_duration ${1}`" ${ANDROID_SERIAL} ${USB_ADDRESS} "${CR}" timeout --preserve-status --signal=KILL ${1} adb wait-for-device + retval=${?} + echo -n " ${CR}" + return ${retval} else adb wait-for-device fi } +[ "USAGE: usb_status > stdout + +If adb_wait failed, check if device is in fastboot mode and report status + +Returns: \"(USB stack borken?)\", \"(In fastboot mode)\" or \"(in adb mode)\"" ] +usb_status() { + if inFastboot; then + echo "(In fastboot mode)" + elif inAdb; then + echo "(In adb mode)" + else + echo "(USB stack borken?)" + fi +} + [ "USAGE: fastboot_wait [timeout] Returns: waits until the device has returned for fastboot or optional timeout" ] @@ -152,10 +232,14 @@ fastboot_wait() { # fastboot has no wait-for-device, but it does an automatic # wait and requires (even a nonsensical) command to do so. if [ -n "${1}" ]; then - timeout --preserve-status --signal=KILL ${1} fastboot wait-for-device + echo -n ". . . waiting `format_duration ${1}`" ${ANDROID_SERIAL} ${USB_ADDRESS} "${CR}" + timeout --preserve-status --signal=KILL ${1} fastboot wait-for-device >/dev/null 2>/dev/null + retval=${?} + echo -n " ${CR}" + ( exit ${retval} ) else - fastboot wait-for-device >/dev/null - fi >/dev/null 2>/dev/null || + fastboot wait-for-device >/dev/null 2>/dev/null + fi || inFastboot } @@ -310,9 +394,25 @@ skip_administrative_mounts() { -e "^\(overlay\|tmpfs\|none\|sysfs\|proc\|selinuxfs\|debugfs\) " \ -e "^\(bpf\|cg2_bpf\|pstore\|tracefs\|adb\|mtp\|ptp\|devpts\) " \ -e "^\(/data/media\|/dev/block/loop[0-9]*\) " \ + -e "^rootfs / rootfs rw," \ -e " /\(cache\|mnt/scratch\|mnt/vendor/persist\|persist\|metadata\) " } +[ "USAGE: skip_unrelated_mounts < /proc/mounts + +or output from df + +Filters out all apex and vendor override administrative overlay mounts +uninteresting to the test" ] +skip_unrelated_mounts() { + grep -v "^overlay.* /\(apex\|bionic\|system\|vendor\)/[^ ]" | + grep -v "[%] /\(apex\|bionic\|system\|vendor\)/[^ ][^ ]*$" +} + +## +## MAINLINE +## + if [ X"-s" = X"${1}" -a -n "${2}" ]; then export ANDROID_SERIAL="${2}" shift 2 @@ -320,7 +420,7 @@ fi inFastboot && die "device in fastboot mode" if ! inAdb; then - echo "${ORANGE}[ WARNING ]${NORMAL} device not in adb mode ... waiting 2 minutes" + echo "${ORANGE}[ WARNING ]${NORMAL} device not in adb mode" adb_wait 2m fi inAdb || die "specified device not in adb mode" @@ -331,19 +431,38 @@ if ! adb_su getenforce </dev/null | grep 'Enforcing' >/dev/null; then enforcing=false fi -# Do something +# Do something. D=`get_property ro.serialno` [ -n "${D}" ] || D=`get_property ro.boot.serialno` [ -z "${D}" ] || ANDROID_SERIAL=${D} +USB_SERIAL= +[ -z "${ANDROID_SERIAL}" ] || USB_SERIAL=`find /sys/devices -name serial | + grep usb | + xargs grep -l ${ANDROID_SERIAL}` +USB_ADDRESS= +if [ -n "${USB_SERIAL}" ]; then + USB_ADDRESS=${USB_SERIAL%/serial} + USB_ADDRESS=usb${USB_ADDRESS##*/} +fi +[ -z "${ANDROID_SERIAL}${USB_ADDRESS}" ] || + echo "${BLUE}[ INFO ]${NORMAL}" ${ANDROID_SERIAL} ${USB_ADDRESS} >&2 BUILD_DESCRIPTION=`get_property ro.build.description` -echo "${BLUE}[ INFO ]${NORMAL} ${ANDROID_SERIAL} ${BUILD_DESCRIPTION}" >&2 +[ -z "${BUILD_DESCRIPTION}" ] || + echo "${BLUE}[ INFO ]${NORMAL} ${BUILD_DESCRIPTION}" >&2 + +VERITY_WAS_ENABLED=false +if [ "orange" = "`get_property ro.boot.verifiedbootstate`" -a \ + "2" = "`get_property partition.system.verified`" ]; then + VERITY_WAS_ENABLED=true +fi echo "${GREEN}[ RUN ]${NORMAL} Testing kernel support for overlayfs" >&2 overlayfs_supported=true; adb_wait || die "wait for device failed" -adb_sh ls -d /sys/module/overlay </dev/null >/dev/null && +adb_sh ls -d /sys/module/overlay </dev/null >/dev/null 2>/dev/null || + adb_sh grep "nodev${TAB}overlay" /proc/filesystems </dev/null >/dev/null 2>/dev/null && echo "${GREEN}[ OK ]${NORMAL} overlay module present" >&2 || ( echo "${ORANGE}[ WARNING ]${NORMAL} overlay module not present" >&2 && @@ -391,9 +510,9 @@ if ${reboot}; then echo "${ORANGE}[ WARNING ]${NORMAL} rebooting before test" >&2 adb_reboot && adb_wait 2m || - die "lost device after reboot after wipe" + die "lost device after reboot after wipe `usb_status`" adb_root || - die "lost device after elevation to root after wipe" + die "lost device after elevation to root after wipe `usb_status`" fi D=`adb_sh df -k </dev/null` && H=`echo "${D}" | head -1` && @@ -416,7 +535,8 @@ for d in ${D}; do grep "Filesystem features:.*shared_blocks" >/dev/null && no_dedupe=false done -D=`adb_sh df -k ${D} </dev/null` +D=`adb_sh df -k ${D} </dev/null | + sed 's@\([%] /\)\(apex\|bionic\|system\|vendor\)/[^ ][^ ]*$@\1@'` echo "${D}" if [ X"${D}" = X"${D##* 100[%] }" ] && ${no_dedupe} ; then overlayfs_needed=false @@ -455,9 +575,9 @@ if [ X"${D}" != X"${H}" ]; then L=`adb_logcat -b all -v nsec -t ${T} 2>&1` adb_reboot && adb_wait 2m || - die "lost device after reboot requested" + die "lost device after reboot requested `usb_status`" adb_root || - die "lost device after elevation to root" + die "lost device after elevation to root `usb_status`" rebooted=true # re-disable verity to see the setup remarks expected T=`adb_date` @@ -500,7 +620,7 @@ adb remount || die -t "${T}" "adb remount failed" D=`adb_sh df -k </dev/null` && H=`echo "${D}" | head -1` && - D=`echo "${D}" | grep -v " /vendor/..*$" | grep "^overlay "` || + D=`echo "${D}" | skip_unrelated_mounts | grep "^overlay "` || ( [ -n "${L}" ] && echo "${L}" && false ) ret=${?} uses_dynamic_scratch=false @@ -544,7 +664,7 @@ if ${overlayfs_needed}; then echo "${D}" | grep "^overlay .* /system\$" >/dev/null || die "overlay takeover after remount" !(adb_sh grep "^overlay " /proc/mounts </dev/null | - grep -v "^overlay /\(vendor\|system\)/..* overlay ro," | + skip_unrelated_mounts | grep " overlay ro,") && !(adb_sh grep " rw," /proc/mounts </dev/null | skip_administrative_mounts data) || @@ -555,7 +675,7 @@ else fi fi -# Check something +# Check something. echo "${GREEN}[ RUN ]${NORMAL} push content to /system and /vendor" >&2 @@ -569,17 +689,22 @@ B="`adb_cat /vendor/hello`" || die "vendor hello" check_eq "${A}" "${B}" /vendor before reboot -# download libc.so, append some gargage, push back, and check if the file is updated. +# Download libc.so, append some gargage, push back, and check if the file +# is updated. tempdir="`mktemp -d`" cleanup() { rm -rf ${tempdir} } -adb pull /system/lib/bootstrap/libc.so ${tempdir} || die "pull libc.so from device" +adb pull /system/lib/bootstrap/libc.so ${tempdir} >/dev/null || + die "pull libc.so from device" garbage="`hexdump -n 16 -e '4/4 "%08X" 1 "\n"' /dev/random`" echo ${garbage} >> ${tempdir}/libc.so -adb push ${tempdir}/libc.so /system/lib/bootstrap/libc.so || die "push libc.so to device" -adb pull /system/lib/bootstrap/libc.so ${tempdir}/libc.so.fromdevice || die "pull libc.so from device" -diff ${tempdir}/libc.so ${tempdir}/libc.so.fromdevice > /dev/null || die "libc.so differ" +adb push ${tempdir}/libc.so /system/lib/bootstrap/libc.so >/dev/null || + die "push libc.so to device" +adb pull /system/lib/bootstrap/libc.so ${tempdir}/libc.so.fromdevice >/dev/null || + die "pull libc.so from device" +diff ${tempdir}/libc.so ${tempdir}/libc.so.fromdevice > /dev/null || + die "libc.so differ" echo "${GREEN}[ RUN ]${NORMAL} reboot to confirm content persistent" >&2 @@ -596,7 +721,7 @@ if ${overlayfs_needed}; then adb_su sed -n '1,/overlay \/system/p' /proc/mounts </dev/null | skip_administrative_mounts | - grep -v ' \(squashfs\|ext4\|f2fs\) ' && + grep -v ' \(squashfs\|ext4\|f2fs\|vfat\) ' && echo "${ORANGE}[ WARNING ]${NORMAL} overlay takeover after first stage init" >&2 || echo "${GREEN}[ OK ]${NORMAL} overlay takeover in first stage init" >&2 fi @@ -605,7 +730,7 @@ B="`adb_cat /system/hello`" || die "re-read /system/hello after reboot" check_eq "${A}" "${B}" /system after reboot echo "${GREEN}[ OK ]${NORMAL} /system content remains after reboot" >&2 -# Only root can read vendor if sepolicy permissions are as expected +# Only root can read vendor if sepolicy permissions are as expected. if ${enforcing}; then adb_unroot B="`adb_cat /vendor/hello`" && @@ -619,9 +744,9 @@ adb_root && check_eq "${A}" "${B}" vendor after reboot echo "${GREEN}[ OK ]${NORMAL} /vendor content remains after reboot" >&2 -# check if the updated libc.so is persistent after reboot +# Check if the updated libc.so is persistent after reboot. adb_root && - adb pull /system/lib/bootstrap/libc.so ${tempdir}/libc.so.fromdevice || + adb pull /system/lib/bootstrap/libc.so ${tempdir}/libc.so.fromdevice >/dev/null || die "pull libc.so from device" diff ${tempdir}/libc.so ${tempdir}/libc.so.fromdevice > /dev/null || die "libc.so differ" rm -r ${tempdir} @@ -677,14 +802,14 @@ else fi fastboot reboot || die "can not reboot out of fastboot" - echo "${ORANGE}[ WARNING ]${NORMAL} adb after fastboot ... waiting 2 minutes" + echo "${ORANGE}[ WARNING ]${NORMAL} adb after fastboot" adb_wait 2m || die "did not reboot after flash" if ${overlayfs_needed}; then adb_root && D=`adb_sh df -k </dev/null` && H=`echo "${D}" | head -1` && - D=`echo "${D}" | grep -v " /vendor/..*$" | grep "^overlay "` && + D=`echo "${D}" | skip_unrelated_mounts | grep "^overlay "` && echo "${H}" && echo "${D}" && echo "${D}" | grep "^overlay .* /system\$" >/dev/null || @@ -719,9 +844,26 @@ fi echo "${GREEN}[ RUN ]${NORMAL} remove test content (cleanup)" >&2 T=`adb_date` -adb remount && +H=`adb remount 2>&1` +err=${?} +L= +D="${H%?Now reboot your device for settings to take effect}" +if [ X"${H}" != X"${D}" ]; then + echo "${ORANGE}[ WARNING ]${NORMAL} adb remount requires a reboot after partial flash (legacy avb)" + L=`adb_logcat -b all -v nsec -t ${T} 2>&1` + adb_reboot && + adb_wait 2m && + adb_root || + die "failed to reboot" + T=`adb_date` + H=`adb remount 2>&1` + err=${?} +fi +echo "${H}" +[ ${err} = 0 ] && ( adb_sh rm /vendor/hello </dev/null 2>/dev/null || true ) && adb_sh rm /system/hello </dev/null || + ( [ -n "${L}" ] && echo "${L}" && false ) || die -t ${T} "cleanup hello" B="`adb_cat /system/hello`" && die "re-read /system/hello after rm" @@ -768,12 +910,12 @@ if [ -n "${scratch_partition}" ]; then die -t ${T} "setup for overlayfs" fi -echo "${GREEN}[ RUN ]${NORMAL} test raw remount command" >&2 +echo "${GREEN}[ RUN ]${NORMAL} test raw remount commands" >&2 -# prerequisite is a prepped device from above +# Prerequisite is a prepped device from above. adb_reboot && adb_wait 2m || - die "lost device after reboot to ro state" + die "lost device after reboot to ro state `usb_status`" adb_sh grep " /vendor .* rw," /proc/mounts >/dev/null && die "/vendor is not read-only" adb_su mount -o rw,remount /vendor || @@ -782,4 +924,12 @@ adb_sh grep " /vendor .* rw," /proc/mounts >/dev/null || die "/vendor is not read-write" echo "${GREEN}[ OK ]${NORMAL} mount -o rw,remount command works" >&2 +if $VERITY_WAS_ENABLED && $overlayfs_supported; then + adb_root && + adb enable-verity && + adb_reboot && + adb_wait 2m || + die "failed to restore verity" >&2 +fi + echo "${GREEN}[ PASSED ]${NORMAL} adb remount" >&2 |
