summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorJack Wang <jinpu.wang@ionos.com>2026-01-20 11:24:56 +0100
committerSasha Levin <sashal@kernel.org>2026-03-04 07:20:49 -0500
commitd3af62411e19752c663fe4f424dbf49d95a4cc7c (patch)
tree2131fe674e6c1089ff2b35e0fc98b66462c0a526 /drivers
parent1c96c1acef4b4a1108fc13f84a8ac0b0633bbb46 (diff)
md/bitmap: fix GPF in write_page caused by resize race
[ Upstream commit 46ef85f854dfa9d5226b3c1c46493d79556c9589 ] A General Protection Fault occurs in write_page() during array resize: RIP: 0010:write_page+0x22b/0x3c0 [md_mod] This is a use-after-free race between bitmap_daemon_work() and __bitmap_resize(). The daemon iterates over `bitmap->storage.filemap` without locking, while the resize path frees that storage via md_bitmap_file_unmap(). `quiesce()` does not stop the md thread, allowing concurrent access to freed pages. Fix by holding `mddev->bitmap_info.mutex` during the bitmap update. Link: https://lore.kernel.org/linux-raid/20260120102456.25169-1-jinpu.wang@ionos.com Closes: https://lore.kernel.org/linux-raid/CAMGffE=Mbfp=7xD_hYxXk1PAaCZNSEAVeQGKGy7YF9f2S4=NEA@mail.gmail.com/T/#u Cc: stable@vger.kernel.org Fixes: d60b479d177a ("md/bitmap: add bitmap_resize function to allow bitmap resizing.") Signed-off-by: Jack Wang <jinpu.wang@ionos.com> Signed-off-by: Yu Kuai <yukuai@fnnas.com> Signed-off-by: Sasha Levin <sashal@kernel.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/md/md-bitmap.c3
1 files changed, 2 insertions, 1 deletions
diff --git a/drivers/md/md-bitmap.c b/drivers/md/md-bitmap.c
index 898ff417928f..2e73be016d3c 100644
--- a/drivers/md/md-bitmap.c
+++ b/drivers/md/md-bitmap.c
@@ -2134,6 +2134,7 @@ int md_bitmap_resize(struct bitmap *bitmap, sector_t blocks,
memcpy(page_address(store.sb_page),
page_address(bitmap->storage.sb_page),
sizeof(bitmap_super_t));
+ mutex_lock(&bitmap->mddev->bitmap_info.mutex);
spin_lock_irq(&bitmap->counts.lock);
md_bitmap_file_unmap(&bitmap->storage);
bitmap->storage = store;
@@ -2241,7 +2242,7 @@ int md_bitmap_resize(struct bitmap *bitmap, sector_t blocks,
set_page_attr(bitmap, i, BITMAP_PAGE_DIRTY);
}
spin_unlock_irq(&bitmap->counts.lock);
-
+ mutex_unlock(&bitmap->mddev->bitmap_info.mutex);
if (!init) {
md_bitmap_unplug(bitmap);
bitmap->mddev->pers->quiesce(bitmap->mddev, 0);