From 671249a3d22ea36be4f8edba368f2cdf0e22f905 Mon Sep 17 00:00:00 2001 From: Bowgo Tsai Date: Tue, 10 Aug 2021 16:32:37 +0800 Subject: [PATCH] fastboot: fix --disable-verifiation error message There is an unclear error message if we run `fastboot --disable-verification flash boot boot.img` on a AVB-disabled device without a /vbmeta partition. Error message: terminating with uncaught exception of type std::out_of_range: basic_string Aborted This is because the buf->fd of the loaded boot.img is not reset, before returning from function copy_boot_avb_footer(). Also reset some changes in copy_boot_avb_footer() from commit If83f785e235569ee8ef0de2b37f11dbd2a9a71f4, to prevent the unnecessary read of the boot vbmeta if no need to copy the boot image avb footer. Bug: 191903922 Test: `fastboot --disable-verification flash boot boot.img` on a device without /vbmeta and without setting BOARD_AVB_ENABLE to true. Change-Id: If84f08f1b2e12c4c6ded5cafda2bd1d30e75c662 --- fastboot/fastboot.cpp | 31 +++++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/fastboot/fastboot.cpp b/fastboot/fastboot.cpp index c87ce606f..532b52490 100644 --- a/fastboot/fastboot.cpp +++ b/fastboot/fastboot.cpp @@ -941,7 +941,8 @@ static void rewrite_vbmeta_buffer(struct fastboot_buffer* buf, bool vbmeta_in_bo // Tries to locate top-level vbmeta from boot.img footer. uint64_t footer_offset = buf->sz - AVB_FOOTER_SIZE; if (0 != data.compare(footer_offset, AVB_FOOTER_MAGIC_LEN, AVB_FOOTER_MAGIC)) { - die("Failed to find AVB_FOOTER at offset: %" PRId64, footer_offset); + die("Failed to find AVB_FOOTER at offset: %" PRId64 ", is BOARD_AVB_ENABLE true?", + footer_offset); } const AvbFooter* footer = reinterpret_cast(data.c_str() + footer_offset); vbmeta_offset = be64toh(footer->vbmeta_offset); @@ -1021,6 +1022,24 @@ static void copy_boot_avb_footer(const std::string& partition, struct fastboot_b return; } + // If overflows and negative, it should be < buf->sz. + int64_t partition_size = static_cast(get_partition_size(partition)); + + if (partition_size == buf->sz) { + return; + } + // Some device bootloaders might not implement `fastboot getvar partition-size:boot[_a|_b]`. + // In this case, partition_size will be zero. + if (partition_size < buf->sz) { + fprintf(stderr, + "Warning: skip copying boot image avb footer" + " (boot partition size: %" PRId64 ", boot image size: %" PRId64 ").\n", + partition_size, buf->sz); + return; + } + + // IMPORTANT: after the following read, we need to reset buf->fd before return (if not die). + // Because buf->fd will still be used afterwards. std::string data; if (!android::base::ReadFdToString(buf->fd, &data)) { die("Failed reading from boot"); @@ -1028,17 +1047,9 @@ static void copy_boot_avb_footer(const std::string& partition, struct fastboot_b uint64_t footer_offset = buf->sz - AVB_FOOTER_SIZE; if (0 != data.compare(footer_offset, AVB_FOOTER_MAGIC_LEN, AVB_FOOTER_MAGIC)) { + lseek(buf->fd.get(), 0, SEEK_SET); // IMPORTANT: resets buf->fd before return. return; } - // If overflows and negative, it should be < buf->sz. - int64_t partition_size = static_cast(get_partition_size(partition)); - - if (partition_size == buf->sz) { - return; - } - if (partition_size < buf->sz) { - die("boot partition is smaller than boot image"); - } unique_fd fd(make_temporary_fd("boot rewriting")); if (!android::base::WriteStringToFd(data, fd)) {