Fix boot image parsing when input image is too small am: 010c6d1468 am: b78bfc3d3d

Original change: https://android-review.googlesource.com/c/platform/system/update_engine/+/2593466

Change-Id: If591071ecad4738955aa58a5d61863bb79fcc7ea
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/payload_generator/boot_img_filesystem.cc b/payload_generator/boot_img_filesystem.cc
index cad267e..3e324f1 100644
--- a/payload_generator/boot_img_filesystem.cc
+++ b/payload_generator/boot_img_filesystem.cc
@@ -16,10 +16,15 @@
 
 #include "update_engine/payload_generator/boot_img_filesystem.h"
 
+#include <array>
+
+#include <android-base/unique_fd.h>
+#include <android-base/file.h>
 #include <base/logging.h>
 #include <bootimg.h>
 #include <brillo/secure_blob.h>
 #include <puffin/utils.h>
+#include <sys/stat.h>
 
 #include "update_engine/common/utils.h"
 #include "update_engine/payload_generator/delta_diff_generator.h"
@@ -33,11 +38,26 @@
 
 unique_ptr<BootImgFilesystem> BootImgFilesystem::CreateFromFile(
     const string& filename) {
-  if (filename.empty())
+  if (filename.empty()) {
     return nullptr;
-
-  if (brillo::Blob header_magic;
-      !utils::ReadFileChunk(filename, 0, BOOT_MAGIC_SIZE, &header_magic) ||
+  }
+  android::base::unique_fd fd(open(filename.c_str(), O_RDONLY));
+  if (!fd.ok()) {
+    PLOG(ERROR) << "Failed to open " << filename;
+    return nullptr;
+  }
+  struct stat st {};
+  if (fstat(fd.get(), &st) < 0) {
+    return nullptr;
+  }
+  if (static_cast<size_t>(st.st_size) < sizeof(boot_img_hdr_v0)) {
+    LOG(INFO) << "Image " << filename
+              << " is too small to be a boot image. file size: " << st.st_size;
+    return nullptr;
+  }
+  std::array<char, BOOT_MAGIC_SIZE> header_magic{};
+  if (!android::base::ReadFullyAtOffset(
+          fd, header_magic.data(), BOOT_MAGIC_SIZE, 0) ||
       memcmp(header_magic.data(), BOOT_MAGIC, BOOT_MAGIC_SIZE) != 0) {
     return nullptr;
   }
@@ -48,11 +68,11 @@
   // See details in system/tools/mkbootimg/include/bootimg/bootimg.h
   constexpr size_t header_version_offset =
       BOOT_MAGIC_SIZE + 8 * sizeof(uint32_t);
-  brillo::Blob header_version_blob;
-  if (!utils::ReadFileChunk(filename,
-                            header_version_offset,
-                            sizeof(uint32_t),
-                            &header_version_blob)) {
+  std::array<char, sizeof(uint32_t)> header_version_blob{};
+  if (!android::base::ReadFullyAtOffset(fd,
+                                        header_version_blob.data(),
+                                        sizeof(uint32_t),
+                                        header_version_offset)) {
     return nullptr;
   }
   uint32_t header_version =
@@ -66,8 +86,8 @@
   // Read the bytes of boot image header based on the header version.
   size_t header_size =
       header_version == 3 ? sizeof(boot_img_hdr_v3) : sizeof(boot_img_hdr_v0);
-  brillo::Blob header_blob;
-  if (!utils::ReadFileChunk(filename, 0, header_size, &header_blob)) {
+  brillo::Blob header_blob(header_size);
+  if (!ReadFullyAtOffset(fd, header_blob.data(), header_size, 0)) {
     return nullptr;
   }
 
@@ -120,7 +140,8 @@
   file.extents = {ExtentForBytes(kBlockSize, offset, size)};
 
   brillo::Blob data;
-  if (utils::ReadFileChunk(filename_, offset, size, &data)) {
+  if (utils::ReadFileChunk(filename_, offset, size, &data) &&
+      data.size() == size) {
     constexpr size_t kGZipHeaderSize = 10;
     // Check GZip header magic.
     if (data.size() > kGZipHeaderSize && data[0] == 0x1F && data[1] == 0x8B) {