|
Coly Li |
2bbfc4 |
From 3d32aaa7e66d5c1479a3c31d6c2c5d45dd0d3b89 Mon Sep 17 00:00:00 2001
|
|
Coly Li |
2bbfc4 |
From: Mike Snitzer <snitzer@kernel.org>
|
|
Coly Li |
2bbfc4 |
Date: Mon, 17 Apr 2023 11:59:56 -0400
|
|
Coly Li |
2bbfc4 |
Subject: [PATCH] dm ioctl: fix nested locking in table_clear() to remove
|
|
Coly Li |
2bbfc4 |
deadlock concern
|
|
Coly Li |
2bbfc4 |
Git-commit: 3d32aaa7e66d5c1479a3c31d6c2c5d45dd0d3b89
|
|
Coly Li |
2bbfc4 |
Patch-mainline: v6.4-rc1
|
|
Coly Li |
2bbfc4 |
References: bsc#1210806, CVE-2023-2269
|
|
Coly Li |
2bbfc4 |
|
|
Coly Li |
2bbfc4 |
syzkaller found the following problematic rwsem locking (with write
|
|
Coly Li |
2bbfc4 |
lock already held):
|
|
Coly Li |
2bbfc4 |
|
|
Coly Li |
2bbfc4 |
down_read+0x9d/0x450 kernel/locking/rwsem.c:1509
|
|
Coly Li |
2bbfc4 |
dm_get_inactive_table+0x2b/0xc0 drivers/md/dm-ioctl.c:773
|
|
Coly Li |
2bbfc4 |
__dev_status+0x4fd/0x7c0 drivers/md/dm-ioctl.c:844
|
|
Coly Li |
2bbfc4 |
table_clear+0x197/0x280 drivers/md/dm-ioctl.c:1537
|
|
Coly Li |
2bbfc4 |
|
|
Coly Li |
2bbfc4 |
In table_clear, it first acquires a write lock
|
|
Coly Li |
2bbfc4 |
https://elixir.bootlin.com/linux/v6.2/source/drivers/md/dm-ioctl.c#L1520
|
|
Coly Li |
2bbfc4 |
down_write(&_hash_lock);
|
|
Coly Li |
2bbfc4 |
|
|
Coly Li |
2bbfc4 |
Then before the lock is released at L1539, there is a path shown above:
|
|
Coly Li |
2bbfc4 |
table_clear -> __dev_status -> dm_get_inactive_table -> down_read
|
|
Coly Li |
2bbfc4 |
https://elixir.bootlin.com/linux/v6.2/source/drivers/md/dm-ioctl.c#L773
|
|
Coly Li |
2bbfc4 |
down_read(&_hash_lock);
|
|
Coly Li |
2bbfc4 |
|
|
Coly Li |
2bbfc4 |
It tries to acquire the same read lock again, resulting in the deadlock
|
|
Coly Li |
2bbfc4 |
problem.
|
|
Coly Li |
2bbfc4 |
|
|
Coly Li |
2bbfc4 |
Fix this by moving table_clear()'s __dev_status() call to after its
|
|
Coly Li |
2bbfc4 |
up_write(&_hash_lock);
|
|
Coly Li |
2bbfc4 |
|
|
Coly Li |
2bbfc4 |
Cc: stable@vger.kernel.org
|
|
Coly Li |
2bbfc4 |
Reported-by: Zheng Zhang <zheng.zhang@email.ucr.edu>
|
|
Coly Li |
2bbfc4 |
Signed-off-by: Mike Snitzer <snitzer@kernel.org>
|
|
Coly Li |
2bbfc4 |
Signed-off-by: Coly Li <colyli@suse.de>
|
|
Coly Li |
2bbfc4 |
---
|
|
Coly Li |
2bbfc4 |
drivers/md/dm-ioctl.c | 7 ++++---
|
|
Coly Li |
2bbfc4 |
1 file changed, 4 insertions(+), 3 deletions(-)
|
|
Coly Li |
2bbfc4 |
|
|
Coly Li |
2bbfc4 |
--- a/drivers/md/dm-ioctl.c
|
|
Coly Li |
2bbfc4 |
+++ b/drivers/md/dm-ioctl.c
|
|
Coly Li |
2bbfc4 |
@@ -1512,11 +1512,12 @@ static int table_clear(struct file *filp
|
|
Coly Li |
2bbfc4 |
hc->new_map = NULL;
|
|
Coly Li |
2bbfc4 |
}
|
|
Coly Li |
2bbfc4 |
|
|
Coly Li |
2bbfc4 |
- param->flags &= ~DM_INACTIVE_PRESENT_FLAG;
|
|
Coly Li |
2bbfc4 |
-
|
|
Coly Li |
2bbfc4 |
- __dev_status(hc->md, param);
|
|
Coly Li |
2bbfc4 |
md = hc->md;
|
|
Coly Li |
2bbfc4 |
up_write(&_hash_lock);
|
|
Coly Li |
2bbfc4 |
+
|
|
Coly Li |
2bbfc4 |
+ param->flags &= ~DM_INACTIVE_PRESENT_FLAG;
|
|
Coly Li |
2bbfc4 |
+ __dev_status(md, param);
|
|
Coly Li |
2bbfc4 |
+
|
|
Coly Li |
2bbfc4 |
if (old_map) {
|
|
Coly Li |
2bbfc4 |
dm_sync_table(md);
|
|
Coly Li |
2bbfc4 |
dm_table_destroy(old_map);
|