From 23816e84ca8821f303d9a3e753d7c050881bacd5 Mon Sep 17 00:00:00 2001 From: Yi-Yo Chiang Date: Wed, 19 May 2021 17:19:58 +0800 Subject: [PATCH] Make fs_mgr_overlayfs_mount_fstab_entry() available for user builds Rename fs_mgr_overlayfs_mount_fstab_entry() to fs_mgr_mount_overlayfs_fstab_entry() and move it out of fs_mgr_overlayfs.cpp to make it available for user builds. Add checks to unsure overlayfs mount point doesn't contain symbolic link or /../. Check the mount point with an allowlist if user build. The mount point should either be /vendor, /product ... or their submounts, or strict submounts of /mnt/vendor and /mnt/product. Bug: 188862155 Test: Boot test with overlayfs mount entries on user build Change-Id: I3b60dfa4b63cf2ae0754f53d1d08365aa7be1ee0 --- fs_mgr/fs_mgr.cpp | 69 +++++++++++++++++++++++++++++++ fs_mgr/fs_mgr_overlayfs.cpp | 32 -------------- fs_mgr/include/fs_mgr.h | 5 +++ fs_mgr/include/fs_mgr_overlayfs.h | 1 - init/first_stage_mount.cpp | 2 +- 5 files changed, 75 insertions(+), 34 deletions(-) diff --git a/fs_mgr/fs_mgr.cpp b/fs_mgr/fs_mgr.cpp index ea9d33350..08ead7a06 100644 --- a/fs_mgr/fs_mgr.cpp +++ b/fs_mgr/fs_mgr.cpp @@ -2265,3 +2265,72 @@ std::string fs_mgr_get_super_partition_name(int slot) { } return LP_METADATA_DEFAULT_PARTITION_NAME; } + +bool fs_mgr_mount_overlayfs_fstab_entry(const FstabEntry& entry) { + auto overlayfs_valid_result = fs_mgr_overlayfs_valid(); + if (overlayfs_valid_result == OverlayfsValidResult::kNotSupported) { + LERROR << __FUNCTION__ << "(): kernel does not support overlayfs"; + return false; + } + +#if ALLOW_ADBD_DISABLE_VERITY == 0 + // Allowlist the mount point if user build. + static const std::vector kAllowedPaths = { + "/odm", "/odm_dlkm", "/oem", "/product", "/system_ext", "/vendor", "/vendor_dlkm", + }; + static const std::vector kAllowedPrefixes = { + "/mnt/product/", + "/mnt/vendor/", + }; + if (std::none_of(kAllowedPaths.begin(), kAllowedPaths.end(), + [&entry](const auto& path) -> bool { + return entry.mount_point == path || + StartsWith(entry.mount_point, path + "/"); + }) && + std::none_of(kAllowedPrefixes.begin(), kAllowedPrefixes.end(), + [&entry](const auto& prefix) -> bool { + return entry.mount_point != prefix && + StartsWith(entry.mount_point, prefix); + })) { + LERROR << __FUNCTION__ + << "(): mount point is forbidden on user build: " << entry.mount_point; + return false; + } +#endif // ALLOW_ADBD_DISABLE_VERITY == 0 + + // Create the mount point in case it doesn't exist. + mkdir(entry.mount_point.c_str(), 0755); + + // Ensure that mount point exists and doesn't contain symbolic link or /../. + std::string mount_point; + if (!Realpath(entry.mount_point, &mount_point)) { + PERROR << __FUNCTION__ << "(): failed to realpath " << entry.mount_point; + return false; + } + if (entry.mount_point != mount_point) { + LERROR << __FUNCTION__ << "(): mount point must be a canonicalized path: realpath " + << entry.mount_point << " = " << mount_point; + return false; + } + + auto options = "lowerdir=" + entry.lowerdir; + if (overlayfs_valid_result == OverlayfsValidResult::kOverrideCredsRequired) { + options += ",override_creds=off"; + } + + // Use "overlay-" + entry.blk_device as the mount() source, so that adb-remout-test don't + // confuse this with adb remount overlay, whose device name is "overlay". + // Overlayfs is a pseudo filesystem, so the source device is a symbolic value and isn't used to + // back the filesystem. However the device name would be shown in /proc/mounts. + auto source = "overlay-" + entry.blk_device; + auto report = "__mount(source=" + source + ",target=" + entry.mount_point + ",type=overlay," + + options + ")="; + auto ret = mount(source.c_str(), entry.mount_point.c_str(), "overlay", MS_RDONLY | MS_NOATIME, + options.c_str()); + if (ret) { + PERROR << report << ret; + return false; + } + LINFO << report << ret; + return true; +} diff --git a/fs_mgr/fs_mgr_overlayfs.cpp b/fs_mgr/fs_mgr_overlayfs.cpp index 9fb658e77..cb0938363 100644 --- a/fs_mgr/fs_mgr_overlayfs.cpp +++ b/fs_mgr/fs_mgr_overlayfs.cpp @@ -92,10 +92,6 @@ bool fs_mgr_overlayfs_mount_all(Fstab*) { return false; } -bool fs_mgr_overlayfs_mount_fstab_entry(const android::fs_mgr::FstabEntry&) { - return false; -} - std::vector fs_mgr_overlayfs_required_devices(Fstab*) { return {}; } @@ -1299,34 +1295,6 @@ static void TryMountScratch() { } } -bool fs_mgr_overlayfs_mount_fstab_entry(const android::fs_mgr::FstabEntry& entry) { - if (fs_mgr_overlayfs_invalid()) return false; - - // Create the mount point in case it doesn't exist. - mkdir(entry.mount_point.c_str(), 0755); - - auto options = kLowerdirOption + entry.lowerdir; - if (fs_mgr_overlayfs_valid() == OverlayfsValidResult::kOverrideCredsRequired) { - options += ",override_creds=off"; - } - - // Use "overlay-" + entry.blk_device as the mount() source, so that adb-remout-test don't - // confuse this with adb remount overlay, whose device name is "overlay". - // Overlayfs is a pseudo filesystem, so the source device is a symbolic value and isn't used to - // back the filesystem. However the device name would be shown in /proc/mounts. - auto source = "overlay-" + entry.blk_device; - auto report = "__mount(source=" + source + ",target=" + entry.mount_point + ",type=overlay," + - options + ")="; - auto ret = mount(source.c_str(), entry.mount_point.c_str(), "overlay", MS_RDONLY | MS_NOATIME, - options.c_str()); - if (ret) { - PERROR << report << ret; - return false; - } - LINFO << report << ret; - return true; -} - bool fs_mgr_overlayfs_mount_all(Fstab* fstab) { auto ret = false; if (fs_mgr_overlayfs_invalid()) return ret; diff --git a/fs_mgr/include/fs_mgr.h b/fs_mgr/include/fs_mgr.h index 22c02ccf8..b8ebd63a4 100644 --- a/fs_mgr/include/fs_mgr.h +++ b/fs_mgr/include/fs_mgr.h @@ -131,3 +131,8 @@ int fs_mgr_remount_userdata_into_checkpointing(android::fs_mgr::Fstab* fstab); // Finds the dm_bow device on which this block device is stacked, or returns // empty string std::string fs_mgr_find_bow_device(const std::string& block_device); + +// Like fs_mgr_do_mount_one() but for overlayfs fstab entries. +// Unlike fs_mgr_overlayfs, mount overlayfs without upperdir and workdir, so the +// filesystem cannot be remount read-write. +bool fs_mgr_mount_overlayfs_fstab_entry(const android::fs_mgr::FstabEntry& entry); diff --git a/fs_mgr/include/fs_mgr_overlayfs.h b/fs_mgr/include/fs_mgr_overlayfs.h index 22d12e753..d45e2de72 100644 --- a/fs_mgr/include/fs_mgr_overlayfs.h +++ b/fs_mgr/include/fs_mgr_overlayfs.h @@ -27,7 +27,6 @@ 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); -bool fs_mgr_overlayfs_mount_fstab_entry(const android::fs_mgr::FstabEntry& entry); std::vector fs_mgr_overlayfs_required_devices(android::fs_mgr::Fstab* fstab); bool fs_mgr_overlayfs_setup(const char* backing = nullptr, const char* mount_point = nullptr, bool* change = nullptr, bool force = true); diff --git a/init/first_stage_mount.cpp b/init/first_stage_mount.cpp index 616d28540..546ea8ed8 100644 --- a/init/first_stage_mount.cpp +++ b/init/first_stage_mount.cpp @@ -574,7 +574,7 @@ bool FirstStageMount::MountPartitions() { for (const auto& entry : fstab_) { if (entry.fs_type == "overlay") { - fs_mgr_overlayfs_mount_fstab_entry(entry); + fs_mgr_mount_overlayfs_fstab_entry(entry); } }