2023-11-22 19:27:44

by Brett Creeley

[permalink] [raw]
Subject: [PATCH v4 vfio 0/2] vfio/pds: Fixes for locking bugs

This series contains fixes for locking bugs in the recently introduced
pds-vfio-pci driver. There was an initial bug reported by Dan Carpenter
at:

https://lore.kernel.org/kvm/[email protected]/

However, more locking bugs were found when looking into the previously
mentioned issue. So, all fixes are included in this series.

v4:
- Drop patch 1/3 since it added a spinlock_init that was later replaced
by a mutex_init anyway

v3:
https://lore.kernel.org/kvm/[email protected]/
- Change reset lock from spinlock to mutex

v2:
https://lore.kernel.org/kvm/[email protected]/
- Trim the OOPs in the patch commit messages
- Rework patch 3/3 to only unlock the spinlock once
- Destroy the state_mutex in the driver specific vfio_device_ops.release
callback

v1:
https://lore.kernel.org/kvm/[email protected]/

Brett Creeley (2):
vfio/pds: Fix mutex lock->magic != lock warning
vfio/pds: Fix possible sleep while in atomic context

drivers/vfio/pci/pds/pci_drv.c | 4 ++--
drivers/vfio/pci/pds/vfio_dev.c | 30 +++++++++++++++++++++---------
drivers/vfio/pci/pds/vfio_dev.h | 2 +-
3 files changed, 24 insertions(+), 12 deletions(-)

--
2.17.1


2023-11-22 19:27:46

by Brett Creeley

[permalink] [raw]
Subject: [PATCH v4 vfio 2/2] vfio/pds: Fix possible sleep while in atomic context

The driver could possibly sleep while in atomic context resulting
in the following call trace while CONFIG_DEBUG_ATOMIC_SLEEP=y is
set:

BUG: sleeping function called from invalid context at kernel/locking/mutex.c:283
in_atomic(): 1, irqs_disabled(): 0, non_block: 0, pid: 2817, name: bash
preempt_count: 1, expected: 0
RCU nest depth: 0, expected: 0
Call Trace:
<TASK>
dump_stack_lvl+0x36/0x50
__might_resched+0x123/0x170
mutex_lock+0x1e/0x50
pds_vfio_put_lm_file+0x1e/0xa0 [pds_vfio_pci]
pds_vfio_put_save_file+0x19/0x30 [pds_vfio_pci]
pds_vfio_state_mutex_unlock+0x2e/0x80 [pds_vfio_pci]
pci_reset_function+0x4b/0x70
reset_store+0x5b/0xa0
kernfs_fop_write_iter+0x137/0x1d0
vfs_write+0x2de/0x410
ksys_write+0x5d/0xd0
do_syscall_64+0x3b/0x90
entry_SYSCALL_64_after_hwframe+0x6e/0xd8

This can happen if pds_vfio_put_restore_file() and/or
pds_vfio_put_save_file() grab the mutex_lock(&lm_file->lock)
while the spin_lock(&pds_vfio->reset_lock) is held, which can
happen during while calling pds_vfio_state_mutex_unlock().

Fix this by changing the reset_lock to reset_mutex so there are no such
conerns. Also, make sure to destroy the reset_mutex in the driver specific
VFIO device release function.

This also fixes a spinlock bad magic BUG that was caused
by not calling spinlock_init() on the reset_lock. Since, the lock is
being changed to a mutex, make sure to call mutex_init() on it.

Reported-by: Dan Carpenter <[email protected]>
Closes: https://lore.kernel.org/kvm/[email protected]/
Fixes: bb500dbe2ac6 ("vfio/pds: Add VFIO live migration support")
Signed-off-by: Brett Creeley <[email protected]>
Reviewed-by: Shannon Nelson <[email protected]>
---
drivers/vfio/pci/pds/pci_drv.c | 4 ++--
drivers/vfio/pci/pds/vfio_dev.c | 14 ++++++++------
drivers/vfio/pci/pds/vfio_dev.h | 2 +-
3 files changed, 11 insertions(+), 9 deletions(-)

diff --git a/drivers/vfio/pci/pds/pci_drv.c b/drivers/vfio/pci/pds/pci_drv.c
index ab4b5958e413..caffa1a2cf59 100644
--- a/drivers/vfio/pci/pds/pci_drv.c
+++ b/drivers/vfio/pci/pds/pci_drv.c
@@ -55,10 +55,10 @@ static void pds_vfio_recovery(struct pds_vfio_pci_device *pds_vfio)
* VFIO_DEVICE_STATE_RUNNING.
*/
if (deferred_reset_needed) {
- spin_lock(&pds_vfio->reset_lock);
+ mutex_lock(&pds_vfio->reset_mutex);
pds_vfio->deferred_reset = true;
pds_vfio->deferred_reset_state = VFIO_DEVICE_STATE_ERROR;
- spin_unlock(&pds_vfio->reset_lock);
+ mutex_unlock(&pds_vfio->reset_mutex);
}
}

diff --git a/drivers/vfio/pci/pds/vfio_dev.c b/drivers/vfio/pci/pds/vfio_dev.c
index 8c9fb87b13e1..4c351c59d05a 100644
--- a/drivers/vfio/pci/pds/vfio_dev.c
+++ b/drivers/vfio/pci/pds/vfio_dev.c
@@ -29,7 +29,7 @@ struct pds_vfio_pci_device *pds_vfio_pci_drvdata(struct pci_dev *pdev)
void pds_vfio_state_mutex_unlock(struct pds_vfio_pci_device *pds_vfio)
{
again:
- spin_lock(&pds_vfio->reset_lock);
+ mutex_lock(&pds_vfio->reset_mutex);
if (pds_vfio->deferred_reset) {
pds_vfio->deferred_reset = false;
if (pds_vfio->state == VFIO_DEVICE_STATE_ERROR) {
@@ -39,23 +39,23 @@ void pds_vfio_state_mutex_unlock(struct pds_vfio_pci_device *pds_vfio)
}
pds_vfio->state = pds_vfio->deferred_reset_state;
pds_vfio->deferred_reset_state = VFIO_DEVICE_STATE_RUNNING;
- spin_unlock(&pds_vfio->reset_lock);
+ mutex_unlock(&pds_vfio->reset_mutex);
goto again;
}
mutex_unlock(&pds_vfio->state_mutex);
- spin_unlock(&pds_vfio->reset_lock);
+ mutex_unlock(&pds_vfio->reset_mutex);
}

void pds_vfio_reset(struct pds_vfio_pci_device *pds_vfio)
{
- spin_lock(&pds_vfio->reset_lock);
+ mutex_lock(&pds_vfio->reset_mutex);
pds_vfio->deferred_reset = true;
pds_vfio->deferred_reset_state = VFIO_DEVICE_STATE_RUNNING;
if (!mutex_trylock(&pds_vfio->state_mutex)) {
- spin_unlock(&pds_vfio->reset_lock);
+ mutex_unlock(&pds_vfio->reset_mutex);
return;
}
- spin_unlock(&pds_vfio->reset_lock);
+ mutex_unlock(&pds_vfio->reset_mutex);
pds_vfio_state_mutex_unlock(pds_vfio);
}

@@ -156,6 +156,7 @@ static int pds_vfio_init_device(struct vfio_device *vdev)
pds_vfio->vf_id = vf_id;

mutex_init(&pds_vfio->state_mutex);
+ mutex_init(&pds_vfio->reset_mutex);

vdev->migration_flags = VFIO_MIGRATION_STOP_COPY | VFIO_MIGRATION_P2P;
vdev->mig_ops = &pds_vfio_lm_ops;
@@ -177,6 +178,7 @@ static void pds_vfio_release_device(struct vfio_device *vdev)
vfio_coredev.vdev);

mutex_destroy(&pds_vfio->state_mutex);
+ mutex_destroy(&pds_vfio->reset_mutex);
vfio_pci_core_release_dev(vdev);
}

diff --git a/drivers/vfio/pci/pds/vfio_dev.h b/drivers/vfio/pci/pds/vfio_dev.h
index b8f2d667608f..e7b01080a1ec 100644
--- a/drivers/vfio/pci/pds/vfio_dev.h
+++ b/drivers/vfio/pci/pds/vfio_dev.h
@@ -18,7 +18,7 @@ struct pds_vfio_pci_device {
struct pds_vfio_dirty dirty;
struct mutex state_mutex; /* protect migration state */
enum vfio_device_mig_state state;
- spinlock_t reset_lock; /* protect reset_done flow */
+ struct mutex reset_mutex; /* protect reset_done flow */
u8 deferred_reset;
enum vfio_device_mig_state deferred_reset_state;
struct notifier_block nb;
--
2.17.1

2023-11-27 18:09:14

by Alex Williamson

[permalink] [raw]
Subject: Re: [PATCH v4 vfio 0/2] vfio/pds: Fixes for locking bugs

On Wed, 22 Nov 2023 11:25:30 -0800
Brett Creeley <[email protected]> wrote:

> This series contains fixes for locking bugs in the recently introduced
> pds-vfio-pci driver. There was an initial bug reported by Dan Carpenter
> at:
>
> https://lore.kernel.org/kvm/[email protected]/
>
> However, more locking bugs were found when looking into the previously
> mentioned issue. So, all fixes are included in this series.
>
> v4:
> - Drop patch 1/3 since it added a spinlock_init that was later replaced
> by a mutex_init anyway
>
> v3:
> https://lore.kernel.org/kvm/[email protected]/
> - Change reset lock from spinlock to mutex
>
> v2:
> https://lore.kernel.org/kvm/[email protected]/
> - Trim the OOPs in the patch commit messages
> - Rework patch 3/3 to only unlock the spinlock once
> - Destroy the state_mutex in the driver specific vfio_device_ops.release
> callback
>
> v1:
> https://lore.kernel.org/kvm/[email protected]/
>
> Brett Creeley (2):
> vfio/pds: Fix mutex lock->magic != lock warning
> vfio/pds: Fix possible sleep while in atomic context
>
> drivers/vfio/pci/pds/pci_drv.c | 4 ++--
> drivers/vfio/pci/pds/vfio_dev.c | 30 +++++++++++++++++++++---------
> drivers/vfio/pci/pds/vfio_dev.h | 2 +-
> 3 files changed, 24 insertions(+), 12 deletions(-)
>

Applied to vfio for-linus branch for v6.7. Thanks,

Alex