From 84fe96bfbc1441eaace6b6b88997c2779abf03b6 Mon Sep 17 00:00:00 2001 From: Yi-Yo Chiang Date: Thu, 27 May 2021 22:29:32 +0800 Subject: [PATCH] first_stage_mount: mount point must be canonical path Ban weird paths such as /../system or //vendor in first stage mount. Add utility function fs_mgr_create_canonical_mount_point() that: * mkdir(mount_point) to ensure mount_point's existence * Test that realpath(mount_point) =?= mount_point Bug: 188898525 Test: Presubmit Test: Boot CF Change-Id: Iaf2ec52701277f26cc81f3e15a47b6083a788334 Merged-In: Iaf2ec52701277f26cc81f3e15a47b6083a788334 (cherry picked from commit 3431d52675f25020b279c9fbcda6b8648f9cf67b) --- fs_mgr/fs_mgr.cpp | 33 +++++++++++++++++++++------------ fs_mgr/include/fs_mgr.h | 4 ++++ init/first_stage_mount.cpp | 4 ++++ 3 files changed, 29 insertions(+), 12 deletions(-) diff --git a/fs_mgr/fs_mgr.cpp b/fs_mgr/fs_mgr.cpp index 08ead7a06..af71fe6d5 100644 --- a/fs_mgr/fs_mgr.cpp +++ b/fs_mgr/fs_mgr.cpp @@ -2266,6 +2266,26 @@ std::string fs_mgr_get_super_partition_name(int slot) { return LP_METADATA_DEFAULT_PARTITION_NAME; } +bool fs_mgr_create_canonical_mount_point(const std::string& mount_point) { + auto saved_errno = errno; + auto ok = true; + auto created_mount_point = !mkdir(mount_point.c_str(), 0755); + std::string real_mount_point; + if (!Realpath(mount_point, &real_mount_point)) { + ok = false; + PERROR << "failed to realpath(" << mount_point << ")"; + } else if (mount_point != real_mount_point) { + ok = false; + LERROR << "mount point is not canonical: realpath(" << mount_point << ") -> " + << real_mount_point; + } + if (!ok && created_mount_point) { + rmdir(mount_point.c_str()); + } + errno = saved_errno; + return ok; +} + bool fs_mgr_mount_overlayfs_fstab_entry(const FstabEntry& entry) { auto overlayfs_valid_result = fs_mgr_overlayfs_valid(); if (overlayfs_valid_result == OverlayfsValidResult::kNotSupported) { @@ -2298,18 +2318,7 @@ bool fs_mgr_mount_overlayfs_fstab_entry(const FstabEntry& entry) { } #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; + if (!fs_mgr_create_canonical_mount_point(entry.mount_point)) { return false; } diff --git a/fs_mgr/include/fs_mgr.h b/fs_mgr/include/fs_mgr.h index b8ebd63a4..4d3ecc9dc 100644 --- a/fs_mgr/include/fs_mgr.h +++ b/fs_mgr/include/fs_mgr.h @@ -132,6 +132,10 @@ int fs_mgr_remount_userdata_into_checkpointing(android::fs_mgr::Fstab* fstab); // empty string std::string fs_mgr_find_bow_device(const std::string& block_device); +// Creates mount point if not already existed, and checks that mount point is a +// canonical path that doesn't contain any symbolic link or /../. +bool fs_mgr_create_canonical_mount_point(const std::string& mount_point); + // 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. diff --git a/init/first_stage_mount.cpp b/init/first_stage_mount.cpp index 546ea8ed8..f5c10bbd4 100644 --- a/init/first_stage_mount.cpp +++ b/init/first_stage_mount.cpp @@ -420,6 +420,10 @@ bool FirstStageMount::MountPartition(const Fstab::iterator& begin, bool erase_sa *end = begin + 1; } + if (!fs_mgr_create_canonical_mount_point(begin->mount_point)) { + return false; + } + if (begin->fs_mgr_flags.logical) { if (!fs_mgr_update_logical_partition(&(*begin))) { return false;