[storage] Check for numeric overflow in VmoBuffer::Initialize.

Fixed: 66302
Change-Id: I6c5c55e8be6fc4f12c9abea491eb130eac0b7920
Reviewed-on: https://fuchsia-review.googlesource.com/c/fuchsia/+/476117
Reviewed-by: Vikram Auradkar <auradkar@google.com>
Commit-Queue: Chris Suter <csuter@google.com>
diff --git a/zircon/system/ulib/storage/buffer/BUILD.gn b/zircon/system/ulib/storage/buffer/BUILD.gn
index 6b0afd7..7e31e8d 100644
--- a/zircon/system/ulib/storage/buffer/BUILD.gn
+++ b/zircon/system/ulib/storage/buffer/BUILD.gn
@@ -43,6 +43,7 @@
 
       # TODO(fxbug.dev/38240): Clean up any remaining 'fs' dependencies. Only for fs/trace
       "//sdk/lib/syslog/cpp",
+      "//zircon/public/lib/safemath",
       "//zircon/public/lib/zx",
       "//zircon/system/ulib/fs",
       "//zircon/system/ulib/fzl",
diff --git a/zircon/system/ulib/storage/buffer/test/vmo_buffer_test.cc b/zircon/system/ulib/storage/buffer/test/vmo_buffer_test.cc
index 15e1e93..803c56f 100644
--- a/zircon/system/ulib/storage/buffer/test/vmo_buffer_test.cc
+++ b/zircon/system/ulib/storage/buffer/test/vmo_buffer_test.cc
@@ -182,5 +182,13 @@
   }
 }
 
+TEST(VmoBufferTest, TooManyBlocks) {
+  MockVmoidRegistry registry;
+  VmoBuffer buffer;
+  EXPECT_EQ(
+      buffer.Initialize(&registry, std::numeric_limits<size_t>::max(), kBlockSize, kGoldenLabel),
+      ZX_ERR_INVALID_ARGS);
+}
+
 }  // namespace
 }  // namespace storage
diff --git a/zircon/system/ulib/storage/buffer/vmo_buffer.cc b/zircon/system/ulib/storage/buffer/vmo_buffer.cc
index f8de6df..d780446 100644
--- a/zircon/system/ulib/storage/buffer/vmo_buffer.cc
+++ b/zircon/system/ulib/storage/buffer/vmo_buffer.cc
@@ -10,6 +10,8 @@
 
 #include <utility>
 
+#include <safemath/checked_math.h>
+
 namespace storage {
 
 VmoBuffer::VmoBuffer(VmoBuffer&& other)
@@ -53,7 +55,10 @@
                                   uint32_t block_size, const char* label) {
   ZX_DEBUG_ASSERT(!vmoid_.IsAttached());
   fzl::OwnedVmoMapper mapper;
-  zx_status_t status = mapper.CreateAndMap(blocks * block_size, label);
+  auto size = safemath::CheckMul(uint64_t{blocks}, block_size);
+  if (!size.IsValid())
+    return ZX_ERR_INVALID_ARGS;
+  zx_status_t status = mapper.CreateAndMap(size.ValueOrDie(), label);
   if (status != ZX_OK) {
     FX_LOGS(ERROR) << "VmoBuffer: Failed to create vmo " << label << ": "
                    << zx_status_get_string(status);