summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMikulas Patocka <mpatocka@redhat.com>2024-09-05 20:27:25 +0200
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2024-09-18 19:24:07 +0200
commit9b27991f3fb77d51bf1baeeb722427a4706fb60f (patch)
tree259063d71ff445cc01de8ccaa8c7296878590253
parent4ec0d8dbd7025d0dd0e00ac8a4e0df3d02045e97 (diff)
dm-integrity: fix a race condition when accessing recalc_sector
commit f8e1ca92e35e9041cc0a1bc226ef07a853a22de4 upstream. There's a race condition when accessing the variable ic->sb->recalc_sector. The function integrity_recalc writes to this variable when it makes some progress and the function dm_integrity_map_continue may read this variable concurrently. One problem is that on 32-bit architectures the 64-bit variable is not read and written atomically - it may be possible to read garbage if read races with write. Another problem is that memory accesses to this variable are not guarded with memory barriers. This commit fixes the race - it moves reading ic->sb->recalc_sector to an earlier place where we hold &ic->endio_wait.lock. Signed-off-by: Mikulas Patocka <mpatocka@redhat.com> Cc: stable@vger.kernel.org Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/md/dm-integrity.c4
1 files changed, 3 insertions, 1 deletions
diff --git a/drivers/md/dm-integrity.c b/drivers/md/dm-integrity.c
index 470add73f7bd..a36dd749c688 100644
--- a/drivers/md/dm-integrity.c
+++ b/drivers/md/dm-integrity.c
@@ -2183,6 +2183,7 @@ static void dm_integrity_map_continue(struct dm_integrity_io *dio, bool from_map
struct bio *bio = dm_bio_from_per_bio_data(dio, sizeof(struct dm_integrity_io));
unsigned int journal_section, journal_entry;
unsigned int journal_read_pos;
+ sector_t recalc_sector;
struct completion read_comp;
bool discard_retried = false;
bool need_sync_io = ic->internal_hash && dio->op == REQ_OP_READ;
@@ -2323,6 +2324,7 @@ offload_to_thread:
goto lock_retry;
}
}
+ recalc_sector = le64_to_cpu(ic->sb->recalc_sector);
spin_unlock_irq(&ic->endio_wait.lock);
if (unlikely(journal_read_pos != NOT_FOUND)) {
@@ -2377,7 +2379,7 @@ offload_to_thread:
if (need_sync_io) {
wait_for_completion_io(&read_comp);
if (ic->sb->flags & cpu_to_le32(SB_FLAG_RECALCULATING) &&
- dio->range.logical_sector + dio->range.n_sectors > le64_to_cpu(ic->sb->recalc_sector))
+ dio->range.logical_sector + dio->range.n_sectors > recalc_sector)
goto skip_check;
if (ic->mode == 'B') {
if (!block_bitmap_op(ic, ic->recalc_bitmap, dio->range.logical_sector,