Skip to content

Commit 59f2394

Browse files
committed
vfio/pci: Lock external INTx masking ops
jira LE-1907 cve CVE-2024-26810 Rebuild_History Non-Buildable kernel-5.14.0-427.33.1.el9_4 commit-author Alex Williamson <alex.williamson@redhat.com> commit 810cd4b Mask operations through config space changes to DisINTx may race INTx configuration changes via ioctl. Create wrappers that add locking for paths outside of the core interrupt code. In particular, irq_type is updated holding igate, therefore testing is_intx() requires holding igate. For example clearing DisINTx from config space can otherwise race changes of the interrupt configuration. This aligns interfaces which may trigger the INTx eventfd into two camps, one side serialized by igate and the other only enabled while INTx is configured. A subsequent patch introduces synchronization for the latter flows. Cc: <stable@vger.kernel.org> Fixes: 89e1f7d ("vfio: Add PCI device driver") Reported-by: Reinette Chatre <reinette.chatre@intel.com> Reviewed-by: Kevin Tian <kevin.tian@intel.com> Reviewed-by: Reinette Chatre <reinette.chatre@intel.com> Reviewed-by: Eric Auger <eric.auger@redhat.com> Link: https://lore.kernel.org/r/20240308230557.805580-3-alex.williamson@redhat.com Signed-off-by: Alex Williamson <alex.williamson@redhat.com> (cherry picked from commit 810cd4b) Signed-off-by: Jonathan Maple <jmaple@ciq.com>
1 parent 21a858e commit 59f2394

File tree

1 file changed

+28
-6
lines changed

1 file changed

+28
-6
lines changed

drivers/vfio/pci/vfio_pci_intrs.c

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -99,13 +99,15 @@ static void vfio_send_intx_eventfd(void *opaque, void *unused)
9999
}
100100

101101
/* Returns true if the INTx vfio_pci_irq_ctx.masked value is changed. */
102-
bool vfio_pci_intx_mask(struct vfio_pci_core_device *vdev)
102+
static bool __vfio_pci_intx_mask(struct vfio_pci_core_device *vdev)
103103
{
104104
struct pci_dev *pdev = vdev->pdev;
105105
struct vfio_pci_irq_ctx *ctx;
106106
unsigned long flags;
107107
bool masked_changed = false;
108108

109+
lockdep_assert_held(&vdev->igate);
110+
109111
spin_lock_irqsave(&vdev->irqlock, flags);
110112

111113
/*
@@ -143,6 +145,17 @@ bool vfio_pci_intx_mask(struct vfio_pci_core_device *vdev)
143145
return masked_changed;
144146
}
145147

148+
bool vfio_pci_intx_mask(struct vfio_pci_core_device *vdev)
149+
{
150+
bool mask_changed;
151+
152+
mutex_lock(&vdev->igate);
153+
mask_changed = __vfio_pci_intx_mask(vdev);
154+
mutex_unlock(&vdev->igate);
155+
156+
return mask_changed;
157+
}
158+
146159
/*
147160
* If this is triggered by an eventfd, we can't call eventfd_signal
148161
* or else we'll deadlock on the eventfd wait queue. Return >0 when
@@ -194,12 +207,21 @@ static int vfio_pci_intx_unmask_handler(void *opaque, void *unused)
194207
return ret;
195208
}
196209

197-
void vfio_pci_intx_unmask(struct vfio_pci_core_device *vdev)
210+
static void __vfio_pci_intx_unmask(struct vfio_pci_core_device *vdev)
198211
{
212+
lockdep_assert_held(&vdev->igate);
213+
199214
if (vfio_pci_intx_unmask_handler(vdev, NULL) > 0)
200215
vfio_send_intx_eventfd(vdev, NULL);
201216
}
202217

218+
void vfio_pci_intx_unmask(struct vfio_pci_core_device *vdev)
219+
{
220+
mutex_lock(&vdev->igate);
221+
__vfio_pci_intx_unmask(vdev);
222+
mutex_unlock(&vdev->igate);
223+
}
224+
203225
static irqreturn_t vfio_intx_handler(int irq, void *dev_id)
204226
{
205227
struct vfio_pci_core_device *vdev = dev_id;
@@ -560,11 +582,11 @@ static int vfio_pci_set_intx_unmask(struct vfio_pci_core_device *vdev,
560582
return -EINVAL;
561583

562584
if (flags & VFIO_IRQ_SET_DATA_NONE) {
563-
vfio_pci_intx_unmask(vdev);
585+
__vfio_pci_intx_unmask(vdev);
564586
} else if (flags & VFIO_IRQ_SET_DATA_BOOL) {
565587
uint8_t unmask = *(uint8_t *)data;
566588
if (unmask)
567-
vfio_pci_intx_unmask(vdev);
589+
__vfio_pci_intx_unmask(vdev);
568590
} else if (flags & VFIO_IRQ_SET_DATA_EVENTFD) {
569591
struct vfio_pci_irq_ctx *ctx = vfio_irq_ctx_get(vdev, 0);
570592
int32_t fd = *(int32_t *)data;
@@ -591,11 +613,11 @@ static int vfio_pci_set_intx_mask(struct vfio_pci_core_device *vdev,
591613
return -EINVAL;
592614

593615
if (flags & VFIO_IRQ_SET_DATA_NONE) {
594-
vfio_pci_intx_mask(vdev);
616+
__vfio_pci_intx_mask(vdev);
595617
} else if (flags & VFIO_IRQ_SET_DATA_BOOL) {
596618
uint8_t mask = *(uint8_t *)data;
597619
if (mask)
598-
vfio_pci_intx_mask(vdev);
620+
__vfio_pci_intx_mask(vdev);
599621
} else if (flags & VFIO_IRQ_SET_DATA_EVENTFD) {
600622
return -ENOTTY; /* XXX implement me */
601623
}

0 commit comments

Comments
 (0)