diff options
author | David Anderson <dvander@google.com> | 2018-11-16 15:53:35 -0800 |
---|---|---|
committer | David Anderson <dvander@google.com> | 2018-11-20 12:10:16 -0800 |
commit | 8956964ee2f211ea7792832582b8c0d139260cb0 (patch) | |
tree | 26100530302eef9c7d2426add5fe005d787f7c43 | |
parent | a3c47e63a659515d457e1a0509171b586a236e44 (diff) | |
download | system_core-8956964ee2f211ea7792832582b8c0d139260cb0.tar.gz system_core-8956964ee2f211ea7792832582b8c0d139260cb0.tar.bz2 system_core-8956964ee2f211ea7792832582b8c0d139260cb0.zip |
fastboot: Warn when flashing dynamic partitions in the bootloader.
On retrofit devices, it is easy to accidentally overwrite
system/vendor/product by flashing system in the bootloader. The reason
is that GPT system_a is really the super partition, and the bootloader
doesn't know it.
Addressing this in bootloaders would require two separate commands: one
that rejects flashing system/vendor/product, and another for
expert/factory use that would allow direct flashing.
This patch introduces protection into the host fastboot tool instead.
It's not mutually exclusive with bootloader changes; having protection
in the host tool affords us better and consistent UI. However it does
rely on users having newer builds.
With this change, the following will not work in the bootloader:
fastboot flash system # or vendor, product, etc
The message is the same whether or not the device is a retrofit. To
continue anyway, you can do:
fastboot flash --force system
If we decide on bootloader protection as well, the --force flag can be
re-used.
Bug: 119689480
Test: fastboot flash system # disallowed in bootloader, allowed in fastbootd
fastboot flash --force system # allowed in bootloader
Change-Id: I0861e3f28a15be925886d5c30c7ebd4b20c477cf
-rw-r--r-- | fastboot/Android.bp | 8 | ||||
-rw-r--r-- | fastboot/fastboot.cpp | 41 | ||||
-rw-r--r-- | fastboot/fuzzy_fastboot/Android.bp | 3 | ||||
-rw-r--r-- | fs_mgr/liblp/images.cpp | 6 | ||||
-rw-r--r-- | fs_mgr/liblp/include/liblp/liblp.h | 2 |
5 files changed, 56 insertions, 4 deletions
diff --git a/fastboot/Android.bp b/fastboot/Android.bp index 50d18edd8..faed376ab 100644 --- a/fastboot/Android.bp +++ b/fastboot/Android.bp @@ -43,6 +43,7 @@ cc_library_host_static { "libgtest_main", "libbase", "libadb_host", + "liblp", ], header_libs: [ @@ -173,6 +174,11 @@ cc_defaults { host_ldlibs: ["-lws2_32"], }, + not_windows: { + static_libs: [ + "libext4_utils", + ], + }, }, stl: "libc++_static", @@ -193,6 +199,8 @@ cc_defaults { "libbase", "libcutils", "libgtest_host", + "liblp", + "libcrypto", ], } diff --git a/fastboot/fastboot.cpp b/fastboot/fastboot.cpp index 3e090d7a5..e066bfff7 100644 --- a/fastboot/fastboot.cpp +++ b/fastboot/fastboot.cpp @@ -58,6 +58,7 @@ #include <android-base/strings.h> #include <android-base/unique_fd.h> #include <build/version.h> +#include <liblp/liblp.h> #include <platform_tools_version.h> #include <sparse/sparse.h> #include <ziparchive/zip_archive.h> @@ -407,6 +408,7 @@ static int show_help() { " -s SERIAL Specify a USB device.\n" " -s tcp|udp:HOST[:PORT] Specify a network device.\n" " -S SIZE[K|M|G] Break into sparse files no larger than SIZE.\n" + " --force Force a flash operation that may be unsafe.\n" " --slot SLOT Use SLOT; 'all' for both slots, 'other' for\n" " non-current slot (default: current active slot).\n" " --set-active[=SLOT] Sets the active slot before rebooting.\n" @@ -1505,6 +1507,31 @@ failed: fprintf(stderr, "FAILED (%s)\n", fb->Error().c_str()); } +static bool should_flash_in_userspace(const std::string& partition_name) { + auto path = find_item_given_name("super_empty.img"); + if (path.empty()) { + return false; + } + auto metadata = android::fs_mgr::ReadFromImageFile(path); + if (!metadata) { + return false; + } + for (const auto& partition : metadata->partitions) { + auto candidate = android::fs_mgr::GetPartitionName(partition); + if (partition.attributes & LP_PARTITION_ATTR_SLOT_SUFFIXED) { + // On retrofit devices, we don't know if, or whether, the A or B + // slot has been flashed for dynamic partitions. Instead we add + // both names to the list as a conservative guess. + if (candidate + "_a" == partition_name || candidate + "_b" == partition_name) { + return true; + } + } else if (candidate == partition_name) { + return true; + } + } + return false; +} + int FastBootTool::Main(int argc, char* argv[]) { bool wants_wipe = false; bool wants_reboot = false; @@ -1515,6 +1542,7 @@ int FastBootTool::Main(int argc, char* argv[]) { bool wants_set_active = false; bool skip_secondary = false; bool set_fbe_marker = false; + bool force_flash = false; int longindex; std::string slot_override; std::string next_active; @@ -1530,6 +1558,7 @@ int FastBootTool::Main(int argc, char* argv[]) { {"cmdline", required_argument, 0, 0}, {"disable-verification", no_argument, 0, 0}, {"disable-verity", no_argument, 0, 0}, + {"force", no_argument, 0, 0}, {"header-version", required_argument, 0, 0}, {"help", no_argument, 0, 'h'}, {"kernel-offset", required_argument, 0, 0}, @@ -1565,6 +1594,8 @@ int FastBootTool::Main(int argc, char* argv[]) { g_disable_verification = true; } else if (name == "disable-verity") { g_disable_verity = true; + } else if (name == "force") { + force_flash = true; } else if (name == "header-version") { g_boot_img_hdr.header_version = strtoul(optarg, nullptr, 0); } else if (name == "kernel-offset") { @@ -1779,6 +1810,16 @@ int FastBootTool::Main(int argc, char* argv[]) { if (fname.empty()) die("cannot determine image filename for '%s'", pname.c_str()); auto flash = [&](const std::string &partition) { + if (should_flash_in_userspace(partition) && !is_userspace_fastboot() && + !force_flash) { + die("The partition you are trying to flash is dynamic, and " + "should be flashed via fastbootd. Please run:\n" + "\n" + " fastboot reboot fastboot\n" + "\n" + "And try again. If you are intentionally trying to " + "overwrite a fixed partition, use --force."); + } do_flash(partition.c_str(), fname.c_str()); }; do_for_partitions(pname.c_str(), slot_override, flash, true); diff --git a/fastboot/fuzzy_fastboot/Android.bp b/fastboot/fuzzy_fastboot/Android.bp index 301534bfb..277cc3a9d 100644 --- a/fastboot/fuzzy_fastboot/Android.bp +++ b/fastboot/fuzzy_fastboot/Android.bp @@ -26,6 +26,9 @@ cc_test_host { "libadb_host", "libtinyxml2", "libsparse", + "liblp", + "libcrypto", + "libext4_utils", ], // Static libs (libfastboot2) shared library dependencies are not transitively included diff --git a/fs_mgr/liblp/images.cpp b/fs_mgr/liblp/images.cpp index cae93e8f0..5a498f975 100644 --- a/fs_mgr/liblp/images.cpp +++ b/fs_mgr/liblp/images.cpp @@ -67,10 +67,10 @@ std::unique_ptr<LpMetadata> ReadFromImageBlob(const void* data, size_t bytes) { return ParseMetadata(geometry, metadata_buffer, metadata_buffer_size); } -std::unique_ptr<LpMetadata> ReadFromImageFile(const char* file) { - unique_fd fd(open(file, O_RDONLY | O_CLOEXEC)); +std::unique_ptr<LpMetadata> ReadFromImageFile(const std::string& image_file) { + unique_fd fd(open(image_file.c_str(), O_RDONLY | O_CLOEXEC)); if (fd < 0) { - PERROR << __PRETTY_FUNCTION__ << " open failed: " << file; + PERROR << __PRETTY_FUNCTION__ << " open failed: " << image_file; return nullptr; } return ReadFromImageFile(fd); diff --git a/fs_mgr/liblp/include/liblp/liblp.h b/fs_mgr/liblp/include/liblp/liblp.h index 1af1e800d..6348f556f 100644 --- a/fs_mgr/liblp/include/liblp/liblp.h +++ b/fs_mgr/liblp/include/liblp/liblp.h @@ -75,7 +75,7 @@ std::unique_ptr<LpMetadata> ReadMetadata(const std::string& super_partition, uin bool WriteToSparseFile(const char* file, const LpMetadata& metadata, uint32_t block_size, const std::map<std::string, std::string>& images); bool WriteToImageFile(const char* file, const LpMetadata& metadata); -std::unique_ptr<LpMetadata> ReadFromImageFile(const char* file); +std::unique_ptr<LpMetadata> ReadFromImageFile(const std::string& image_file); std::unique_ptr<LpMetadata> ReadFromImageBlob(const void* data, size_t bytes); // Similar to WriteToSparseFile, this will generate an image that can be |