Merge Android R (rvc-dev-plus-aosp-without-vendor@6692709)

Bug: 166295507
Merged-In: I29d286d476565af2af7cb6b5e2165ea8de2b2b69
Change-Id: Id72cfafe90e134554fab7d21fa0f94181d68e11d
diff --git a/libavb/avb_descriptor.c b/libavb/avb_descriptor.c
index 7030a40..222a616 100644
--- a/libavb/avb_descriptor.c
+++ b/libavb/avb_descriptor.c
@@ -48,6 +48,8 @@
   const uint8_t* desc_start;
   const uint8_t* desc_end;
   const uint8_t* p;
+  uint64_t desc_offset = 0;
+  uint64_t desc_size = 0;
 
   if (image_data == NULL) {
     avb_error("image_data is NULL\n.");
@@ -59,6 +61,9 @@
     goto out;
   }
 
+  /* The data is supposed to have been cryptographically verified at this point,
+   * This check is just adding defense in depth.
+   */
   if (image_size < sizeof(AvbVBMetaImageHeader)) {
     avb_error("Length is smaller than header.\n");
     goto out;
@@ -75,27 +80,50 @@
   header = (const AvbVBMetaImageHeader*)image_data;
   image_end = image_data + image_size;
 
-  desc_start = image_data + sizeof(AvbVBMetaImageHeader) +
-               avb_be64toh(header->authentication_data_block_size) +
-               avb_be64toh(header->descriptors_offset);
+  /* Since the data is supposed to have been cryptographically verified at this
+   * point, being overflow-safe is just for defense.
+   * The following lines are overflow-safe version of:
+   * desc_offset = sizeof(AvbVBMetaImageHeader) +
+   *               avb_be64toh(header->authentication_data_block_size)) +
+   *               avb_be64toh(header->descriptors_offset)
+   */
+  if (!avb_safe_add(&desc_offset,
+                    sizeof(AvbVBMetaImageHeader),
+                    avb_be64toh(header->authentication_data_block_size))) {
+    avb_error("Invalid authentication data block size.\n");
+    goto out;
+  }
+  if (!avb_safe_add_to(&desc_offset, avb_be64toh(header->descriptors_offset))) {
+    avb_error("Invalid descriptors offset.\n");
+    goto out;
+  }
 
-  desc_end = desc_start + avb_be64toh(header->descriptors_size);
-
-  if (desc_start < image_data || desc_start > image_end ||
-      desc_end < image_data || desc_end > image_end || desc_end < desc_start) {
+  if (desc_offset > (uint64_t)(image_end - image_data)) {
     avb_error("Descriptors not inside passed-in data.\n");
     goto out;
   }
 
+  desc_start = image_data + desc_offset;
+
+  desc_size = avb_be64toh(header->descriptors_size);
+  if (desc_size > (uint64_t)(image_end - desc_start)) {
+    avb_error("Descriptors not inside passed-in data.\n");
+    goto out;
+  }
+
+  desc_end = desc_start + desc_size;
+
   for (p = desc_start; p < desc_end;) {
     if (p + sizeof(AvbDescriptor) > desc_end) {
       avb_error("Invalid descriptor length.\n");
       goto out;
     }
     const AvbDescriptor* dh = (const AvbDescriptor*)p;
-    avb_assert_aligned(dh);
-    uint64_t nb_following = avb_be64toh(dh->num_bytes_following);
+    uint64_t nb_following;
     uint64_t nb_total = 0;
+    avb_assert_aligned(dh);
+    nb_following = avb_be64toh(dh->num_bytes_following);
+
     if (!avb_safe_add(&nb_total, sizeof(AvbDescriptor), nb_following)) {
       avb_error("Invalid descriptor length.\n");
       goto out;
@@ -106,7 +134,7 @@
       goto out;
     }
 
-    if (nb_total + p < desc_start || nb_total + p > desc_end) {
+    if (nb_total > (uint64_t)(desc_end - p)) {
       avb_error("Invalid data in descriptors array.\n");
       goto out;
     }
@@ -115,10 +143,7 @@
       goto out;
     }
 
-    if (!avb_safe_add_to((uint64_t*)(&p), nb_total)) {
-      avb_error("Invalid descriptor length.\n");
-      goto out;
-    }
+    p += nb_total;
   }
 
   ret = true;