amdxdna_drm_gem_mmap() can be called after drm_dev_unplug() during device
removal. In that case, the mmap path may access amdxdna_client after it
has been freed, leading to a use-after-free.
Guard the mmap path with drm_dev_enter()/drm_dev_exit() and return an
error if the device is already unplugged.
Fixes: 91f4da826c08 ("accel/amdxdna: Add command doorbell and wait support")
Signed-off-by: Lizhi Hou <[email protected]>
---
drivers/accel/amdxdna/amdxdna_pci_drv.c | 17 +++++++++++++----
1 file changed, 13 insertions(+), 4 deletions(-)
diff --git a/drivers/accel/amdxdna/amdxdna_pci_drv.c
b/drivers/accel/amdxdna/amdxdna_pci_drv.c
index a22c986f1b33..c18ddad9f645 100644
--- a/drivers/accel/amdxdna/amdxdna_pci_drv.c
+++ b/drivers/accel/amdxdna/amdxdna_pci_drv.c
@@ -253,15 +253,24 @@ static int amdxdna_drm_gem_mmap(struct file *filp, struct
vm_area_struct *vma)
{
struct drm_file *drm_filp = filp->private_data;
struct amdxdna_client *client = drm_filp->driver_priv;
- struct amdxdna_dev *xdna = client->xdna;
+ struct amdxdna_dev *xdna;
+ int ret, idx;
if (likely(vma->vm_pgoff >= DRM_FILE_PAGE_OFFSET_START))
return drm_gem_mmap(filp, vma);
- if (!xdna->dev_info->ops->mmap)
- return -EOPNOTSUPP;
+ if (!drm_dev_enter(drm_filp->minor->dev, &idx))
+ return -ENODEV;
- return xdna->dev_info->ops->mmap(client, vma);
+ xdna = client->xdna;
+ if (xdna->dev_info->ops->mmap)
+ ret = xdna->dev_info->ops->mmap(client, vma);
+ else
+ ret = -EOPNOTSUPP;
+
+ drm_dev_exit(idx);
+
+ return ret;
}
static const struct drm_ioctl_desc amdxdna_drm_ioctls[] = {
--
2.34.1