Commit 0218354c authored by Mikulas Patocka's avatar Mikulas Patocka Committed by Wen Zhiwei
Browse files

dm-integrity: fix a race condition when accessing recalc_sector

stable inclusion
from stable-v6.6.52
commit 9b27991f3fb77d51bf1baeeb722427a4706fb60f
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/IAYXOD

Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=9b27991f3fb77d51bf1baeeb722427a4706fb60f



--------------------------------

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: default avatarMikulas Patocka <mpatocka@redhat.com>
Cc: stable@vger.kernel.org
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: default avatarWen Zhiwei <wenzhiwei@kylinos.cn>
parent 01157f0f
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -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 @@ static void dm_integrity_map_continue(struct dm_integrity_io *dio, bool from_map
			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 @@ static void dm_integrity_map_continue(struct dm_integrity_io *dio, bool from_map
	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,