Public

> -----Original Message-----
> From: Irshad, Luqmaan <[email protected]>
> Sent: Thursday, October 8, 2026 3:28 PM
> To: [email protected]
> Cc: Deucher, Alexander <[email protected]>; Koenig, Christian
> <[email protected]>; Li, Yunxiang (Teddy) <[email protected]>;
> Irshad, Luqmaan <[email protected]>
> Subject: [PATCH v2] drm/amdgpu: defer XCP DRM device free until primary
> release
>
> XCP unplug currently restores the partition minors' device pointers to the
> synthetic p_ddev and frees that device while files opened through those
> minors may still be active. Those files acquired drm_device references on the
> primary ddev because the minors were redirected at XCP allocation time. After
> unplug reverses the redirection, close paths operate on the already-freed
> p_ddev, causing a use-after-free and p_ddev refcount underflow while leaking
> the matching primary-device references.
>
> Split teardown into two phases. amdgpu_xcp_dev_unplug() only calls
> drm_dev_unplug() so new opens fail, leaving minor->dev pointing at the
> primary device. amdgpu_xcp_dev_fini() restores the partition device pointers
> and frees p_ddev from amdgpu_driver_release_kms(), when the primary
> drm_device reaches final release and all references held by redirected files 
> have
> been dropped.
>
> Signed-off-by: Luqmaan Irshad <[email protected]>

Reviewed-by: Alex Deucher <[email protected]>

> ---
>  drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c |  1 +
> drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.c | 40
> ++++++++++++++++++++-----
> drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.h |  1 +
>  3 files changed, 35 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
> b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
> index f2f179421c4d..f4bc9e6eb97b 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
> @@ -1638,6 +1638,7 @@ void amdgpu_driver_release_kms(struct
> drm_device *dev)  {
>       struct amdgpu_device *adev = drm_to_adev(dev);
>
> +     amdgpu_xcp_dev_fini(adev);
>       amdgpu_device_fini_sw(adev);
>       pci_set_drvdata(adev->pdev, NULL);
>  }
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.c
> b/drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.c
> index a8c79a66df1d..c780d6794b89 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.c
> @@ -412,7 +412,6 @@ int amdgpu_xcp_dev_register(struct amdgpu_device
> *adev,
>
>  void amdgpu_xcp_dev_unplug(struct amdgpu_device *adev)  {
> -     struct drm_device *p_ddev;
>       int i;
>
>       if (!adev->xcp_mgr)
> @@ -422,12 +421,39 @@ void amdgpu_xcp_dev_unplug(struct
> amdgpu_device *adev)
>               if (!adev->xcp_mgr->xcp[i].ddev)
>                       break;
>
> -             p_ddev = adev->xcp_mgr->xcp[i].ddev;
> -             drm_dev_unplug(p_ddev);
> -             p_ddev->render->dev = adev->xcp_mgr->xcp[i].rdev;
> -             p_ddev->primary->dev = adev->xcp_mgr->xcp[i].pdev;
> -             p_ddev->driver =  adev->xcp_mgr->xcp[i].driver;
> -             p_ddev->vma_offset_manager = adev->xcp_mgr-
> >xcp[i].vma_offset_manager;
> +             drm_dev_unplug(adev->xcp_mgr->xcp[i].ddev);
> +     }
> +}
> +
> +void amdgpu_xcp_dev_fini(struct amdgpu_device *adev) {
> +     struct amdgpu_xcp *xcp;
> +     struct drm_device *p_ddev;
> +     int i;
> +
> +     if (!adev->xcp_mgr)
> +             return;
> +
> +     for (i = 1; i < MAX_XCP; i++) {
> +             xcp = &adev->xcp_mgr->xcp[i];
> +             if (!xcp->ddev)
> +                     break;
> +
> +             p_ddev = xcp->ddev;
> +
> +             /* Unregister devices on paths that did not unplug them
> earlier. */
> +             if (p_ddev->registered)
> +                     drm_dev_unplug(p_ddev);
> +
> +             /*
> +              * All XCP minor files have been released, so it is now safe to
> +              * restore the partition device and free it.
> +              */
> +             p_ddev->render->dev = xcp->rdev;
> +             p_ddev->primary->dev = xcp->pdev;
> +             p_ddev->driver = xcp->driver;
> +             p_ddev->vma_offset_manager = xcp->vma_offset_manager;
> +             xcp->ddev = NULL;
>               amdgpu_xcp_drm_dev_free(p_ddev);
>       }
>  }
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.h
> b/drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.h
> index 33157409eda0..e2fd32af9932 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.h
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.h
> @@ -181,6 +181,7 @@ int amdgpu_xcp_get_inst_details(struct amdgpu_xcp
> *xcp,  int amdgpu_xcp_dev_register(struct amdgpu_device *adev,
>                               const struct pci_device_id *ent);
>  void amdgpu_xcp_dev_unplug(struct amdgpu_device *adev);
> +void amdgpu_xcp_dev_fini(struct amdgpu_device *adev);
>  int amdgpu_xcp_open_device(struct amdgpu_device *adev,
>                          struct amdgpu_fpriv *fpriv,
>                          struct drm_file *file_priv);
> --
> 2.53.0

Reply via email to