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
