Check for corrupted delta lists sizes that overflow the
memory available for the delta_lists. An overflow can
cause the delta list data to be written outside the
reserved delta memory space.

Signed-off-by: Matthew Sakai <[email protected]>
---
 drivers/md/dm-vdo/indexer/delta-index.c | 17 ++++++++++++++---
 1 file changed, 14 insertions(+), 3 deletions(-)

diff --git a/drivers/md/dm-vdo/indexer/delta-index.c 
b/drivers/md/dm-vdo/indexer/delta-index.c
index b288749067de..257612b81a9d 100644
--- a/drivers/md/dm-vdo/indexer/delta-index.c
+++ b/drivers/md/dm-vdo/indexer/delta-index.c
@@ -800,7 +800,7 @@ static void compute_new_list_offsets(struct delta_zone 
*delta_zone, u32 growing_
                (delta_zone->size * BITS_PER_BYTE - 
delta_lists[tail_guard_index].size);
 }
 
-static void rebalance_lists(struct delta_zone *delta_zone)
+static int rebalance_lists(struct delta_zone *delta_zone)
 {
        struct delta_list *delta_lists;
        u32 i;
@@ -811,9 +811,17 @@ static void rebalance_lists(struct delta_zone *delta_zone)
        for (i = 0; i <= delta_zone->list_count + 1; i++)
                used_space += get_delta_list_byte_size(&delta_lists[i]);
 
+       if (delta_zone->size < used_space) {
+               return vdo_log_warning_strerror(UDS_CORRUPT_DATA,
+                                               "delta zone lists overflow zone 
size %zu",
+                                               delta_zone->size);
+       }
+
        compute_new_list_offsets(delta_zone, 0, 0, used_space);
        for (i = 1; i <= delta_zone->list_count + 1; i++)
                delta_lists[i].start = delta_zone->new_offsets[i];
+
+       return UDS_SUCCESS;
 }
 
 /* Start restoring a delta index from multiple input streams. */
@@ -941,8 +949,11 @@ int uds_start_restoring_delta_index(struct delta_index 
*delta_index,
        }
 
        /* Prepare each zone to start receiving the delta list data. */
-       for (z = 0; z < delta_index->zone_count; z++)
-               rebalance_lists(&delta_index->delta_zones[z]);
+       for (z = 0; z < delta_index->zone_count; z++) {
+               result = rebalance_lists(&delta_index->delta_zones[z]);
+               if (result != UDS_SUCCESS)
+                       return result;
+       }
 
        return UDS_SUCCESS;
 }
-- 
2.53.0


Reply via email to