Skip to content

Commit 77be00f

Browse files
Oleksandr Tyshchenkojgross1
authored andcommitted
xen/virtio: Fix potential deadlock when accessing xen_grant_dma_devices
As find_xen_grant_dma_data() is called from both interrupt and process contexts, the access to xen_grant_dma_devices XArray must be protected by xa_lock_irqsave to avoid deadlock scenario. As XArray API doesn't provide xa_store_irqsave helper, call lockless __xa_store directly and guard it externally. Also move the storage of the XArray's entry to a separate helper. Fixes: d6aca35 ("xen/grant-dma-ops: Add option to restrict memory access under Xen") Signed-off-by: Oleksandr Tyshchenko <[email protected]> Reviewed-by: Stefano Stabellini <[email protected]> Reviewed-by: Juergen Gross <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Juergen Gross <[email protected]>
1 parent e433715 commit 77be00f

File tree

1 file changed

+19
-5
lines changed

1 file changed

+19
-5
lines changed

drivers/xen/grant-dma-ops.c

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ struct xen_grant_dma_data {
2525
bool broken;
2626
};
2727

28-
static DEFINE_XARRAY(xen_grant_dma_devices);
28+
static DEFINE_XARRAY_FLAGS(xen_grant_dma_devices, XA_FLAGS_LOCK_IRQ);
2929

3030
#define XEN_GRANT_DMA_ADDR_OFF (1ULL << 63)
3131

@@ -42,14 +42,29 @@ static inline grant_ref_t dma_to_grant(dma_addr_t dma)
4242
static struct xen_grant_dma_data *find_xen_grant_dma_data(struct device *dev)
4343
{
4444
struct xen_grant_dma_data *data;
45+
unsigned long flags;
4546

46-
xa_lock(&xen_grant_dma_devices);
47+
xa_lock_irqsave(&xen_grant_dma_devices, flags);
4748
data = xa_load(&xen_grant_dma_devices, (unsigned long)dev);
48-
xa_unlock(&xen_grant_dma_devices);
49+
xa_unlock_irqrestore(&xen_grant_dma_devices, flags);
4950

5051
return data;
5152
}
5253

54+
static int store_xen_grant_dma_data(struct device *dev,
55+
struct xen_grant_dma_data *data)
56+
{
57+
unsigned long flags;
58+
int ret;
59+
60+
xa_lock_irqsave(&xen_grant_dma_devices, flags);
61+
ret = xa_err(__xa_store(&xen_grant_dma_devices, (unsigned long)dev, data,
62+
GFP_ATOMIC));
63+
xa_unlock_irqrestore(&xen_grant_dma_devices, flags);
64+
65+
return ret;
66+
}
67+
5368
/*
5469
* DMA ops for Xen frontends (e.g. virtio).
5570
*
@@ -338,8 +353,7 @@ void xen_grant_setup_dma_ops(struct device *dev)
338353
*/
339354
data->backend_domid = iommu_spec.args[0];
340355

341-
if (xa_err(xa_store(&xen_grant_dma_devices, (unsigned long)dev, data,
342-
GFP_KERNEL))) {
356+
if (store_xen_grant_dma_data(dev, data)) {
343357
dev_err(dev, "Cannot store Xen grant DMA data\n");
344358
goto err;
345359
}

0 commit comments

Comments
 (0)