summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Anderson <dvander@google.com>2018-11-16 15:53:35 -0800
committerDavid Anderson <dvander@google.com>2018-11-20 12:10:16 -0800
commit8956964ee2f211ea7792832582b8c0d139260cb0 (patch)
tree26100530302eef9c7d2426add5fe005d787f7c43
parenta3c47e63a659515d457e1a0509171b586a236e44 (diff)
downloadsystem_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.bp8
-rw-r--r--fastboot/fastboot.cpp41
-rw-r--r--fastboot/fuzzy_fastboot/Android.bp3
-rw-r--r--fs_mgr/liblp/images.cpp6
-rw-r--r--fs_mgr/liblp/include/liblp/liblp.h2
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