On Fri, Jun 12, 2026 at 10:29 PM Mario Limonciello
<[email protected]> wrote:
>
> The cleanup tail of kfd_criu_resume_svm() walks
> svms->criu_svm_metadata_list and kfree()s each struct criu_svm_metadata
> without removing it from the list. The list head is left pointing at
> freed kmalloc-96 objects.
>
> A second AMDKFD_IOC_CRIU_OP from the same process re-enters: list_empty()
> reads the dangling ->next (use-after-free), the loop walks freed entries,
> and each is kfree()'d again (double-free). This is reachable by an
> unprivileged render-group user via /dev/kfd with no capabilities required.
>
> Add list_del() before the kfree() so the list is properly emptied. The
> list_for_each_entry_safe() iterator already caches the next pointer, so
> unlinking during the walk is safe.
>
> Fixes: 2a909ae71871 ("drm/amdkfd: CRIU resume shared virtual memory ranges")
> Signed-off-by: Mario Limonciello <[email protected]>

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

> ---
>  drivers/gpu/drm/amd/amdkfd/kfd_svm.c | 1 +
>  1 file changed, 1 insertion(+)
>
> diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c 
> b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
> index 8d241ad760f19..df7fca65e9a21 100644
> --- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
> +++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
> @@ -4115,6 +4115,7 @@ int kfd_criu_resume_svm(struct kfd_process *p)
>         list_for_each_entry_safe(criu_svm_md, next, 
> &svms->criu_svm_metadata_list, list) {
>                 pr_debug("freeing criu_svm_md[]\n\tstart: 0x%llx\n",
>                                                 criu_svm_md->data.start_addr);
> +               list_del(&criu_svm_md->list);
>                 kfree(criu_svm_md);
>         }
>
> --
> 2.43.0
>

Reply via email to