[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <6c4657d9cff0a0a00501a7b928297ac966e9ec9d.1670452419.git.reinette.chatre@intel.com>
Date: Wed, 7 Dec 2022 14:52:21 -0800
From: Reinette Chatre <reinette.chatre@...el.com>
To: fenghua.yu@...el.com, dave.jiang@...el.com, vkoul@...nel.org,
dmaengine@...r.kernel.org
Cc: linux-kernel@...r.kernel.org, stable@...r.kernel.org
Subject: [PATCH V2 2/3] dmaengine: idxd: Prevent use after free on completion memory
On driver unload any pending descriptors are flushed at the
time the interrupt is freed:
idxd_dmaengine_drv_remove() ->
drv_disable_wq() ->
idxd_wq_free_irq() ->
idxd_flush_pending_descs().
If there are any descriptors present that need to be flushed this
flow triggers a "not present" page fault as below:
BUG: unable to handle page fault for address: ff391c97c70c9040
#PF: supervisor read access in kernel mode
#PF: error_code(0x0000) - not-present page
The address that triggers the fault is the address of the
descriptor that was freed moments earlier via:
drv_disable_wq()->idxd_wq_free_resources()
Fix the use after free by freeing the descriptors after any possible
usage. This is done after idxd_wq_reset() to ensure that the memory
remains accessible during possible completion writes by the device.
Fixes: 63c14ae6c161 ("dmaengine: idxd: refactor wq driver enable/disable operations")
Suggested-by: Dave Jiang <dave.jiang@...el.com>
Signed-off-by: Reinette Chatre <reinette.chatre@...el.com>
Reviewed-by: Dave Jiang <dave.jiang@...el.com>
Reviewed-by: Fenghua Yu <fenghua.yu@...el.com>
Cc: stable@...r.kernel.org
---
Changes since V1:
- Add Dave and Fenghua's Reviewed-by tags.
- cc stable team (Fenghua).
drivers/dma/idxd/device.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/dma/idxd/device.c b/drivers/dma/idxd/device.c
index fcd03d29a941..b4d7bb923a40 100644
--- a/drivers/dma/idxd/device.c
+++ b/drivers/dma/idxd/device.c
@@ -1408,11 +1408,11 @@ void drv_disable_wq(struct idxd_wq *wq)
dev_warn(dev, "Clients has claim on wq %d: %d\n",
wq->id, idxd_wq_refcount(wq));
- idxd_wq_free_resources(wq);
idxd_wq_unmap_portal(wq);
idxd_wq_drain(wq);
idxd_wq_free_irq(wq);
idxd_wq_reset(wq);
+ idxd_wq_free_resources(wq);
percpu_ref_exit(&wq->wq_active);
wq->type = IDXD_WQT_NONE;
wq->client_count = 0;
--
2.34.1
Powered by blists - more mailing lists