mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-08-30 07:39:12 -04:00
block: mtip32xx: synchronize ioctls with device removal
The ioctl handlers only test REMOVE_PENDING before entering
mtip_hw_ioctl(). Removal can set that bit immediately afterwards and free
dd->port in mtip_hw_exit() while an ioctl still dereferences it. An already
open block device can reach the handlers while del_gendisk() is in
progress.
Serialize both native and compat ioctls with removal. Set REMOVE_PENDING
before taking the mutex so new callers fail after an in-flight ioctl has
drained, and hold the mutex until the port has been torn down.
Fixes: 88523a6155 ("block: Add driver for Micron RealSSD pcie flash cards")
Signed-off-by: Hongyan Xu <getshell@seu.edu.cn>
Link: https://patch.msgid.link/20260806060441.676-1-getshell@seu.edu.cn
Signed-off-by: Jens Axboe <axboe@kernel.dk>
This commit is contained in:
@@ -3048,6 +3048,8 @@ static int mtip_block_ioctl(struct block_device *dev,
|
||||
if (!dd)
|
||||
return -ENOTTY;
|
||||
|
||||
guard(mutex)(&dd->ioctl_mutex);
|
||||
|
||||
if (unlikely(test_bit(MTIP_DDF_REMOVE_PENDING_BIT, &dd->dd_flag)))
|
||||
return -ENOTTY;
|
||||
|
||||
@@ -3086,6 +3088,8 @@ static int mtip_block_compat_ioctl(struct block_device *dev,
|
||||
if (!dd)
|
||||
return -ENOTTY;
|
||||
|
||||
guard(mutex)(&dd->ioctl_mutex);
|
||||
|
||||
if (unlikely(test_bit(MTIP_DDF_REMOVE_PENDING_BIT, &dd->dd_flag)))
|
||||
return -ENOTTY;
|
||||
|
||||
@@ -3721,6 +3725,7 @@ static int mtip_pci_probe(struct pci_dev *pdev,
|
||||
dd = kzalloc_node(sizeof(struct driver_data), GFP_KERNEL, my_node);
|
||||
if (!dd)
|
||||
return -ENOMEM;
|
||||
mutex_init(&dd->ioctl_mutex);
|
||||
|
||||
/* Attach the private data to this PCI device. */
|
||||
pci_set_drvdata(pdev, dd);
|
||||
@@ -3887,6 +3892,7 @@ static void mtip_pci_remove(struct pci_dev *pdev)
|
||||
}
|
||||
|
||||
set_bit(MTIP_DDF_REMOVE_PENDING_BIT, &dd->dd_flag);
|
||||
mutex_lock(&dd->ioctl_mutex);
|
||||
|
||||
if (test_bit(MTIP_DDF_INIT_DONE_BIT, &dd->dd_flag))
|
||||
del_gendisk(dd->disk);
|
||||
@@ -3915,6 +3921,7 @@ static void mtip_pci_remove(struct pci_dev *pdev)
|
||||
|
||||
/* De-initialize the protocol layer. */
|
||||
mtip_hw_exit(dd);
|
||||
mutex_unlock(&dd->ioctl_mutex);
|
||||
|
||||
if (dd->isr_workq) {
|
||||
destroy_workqueue(dd->isr_workq);
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#define __MTIP32XX_H__
|
||||
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/rwsem.h>
|
||||
#include <linux/ata.h>
|
||||
#include <linux/interrupt.h>
|
||||
@@ -432,6 +433,7 @@ struct driver_data {
|
||||
struct request_queue *queue; /* Our request queue. */
|
||||
|
||||
struct blk_mq_tag_set tags; /* blk_mq tags */
|
||||
struct mutex ioctl_mutex;
|
||||
|
||||
struct mtip_port *port; /* Pointer to the port data structure. */
|
||||
|
||||
|
||||
Reference in New Issue
Block a user