From dfc74e37bdb487eed5ad90d0eac4055f60217fb0 Mon Sep 17 00:00:00 2001 From: Srinivasan Shanmugam Date: Thu, 23 Oct 2025 19:54:16 +0530 Subject: drm/amdkfd: Fix use-after-free of HMM range in svm_range_validate_and_map() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The function svm_range_validate_and_map() was freeing `range` when amdgpu_hmm_range_get_pages() failed. But later, the code still used the same `range` pointer and freed it again. This could cause a use-after-free and double-free issue. The fix sets `range = NULL` right after it is freed and checks for `range` before using or freeing it again. v2: Removed duplicate !r check in the condition for clarity. v3: In amdgpu_hmm_range_get_pages(), when hmm_range_fault() fails, we kvfree(pfns) but leave the pointer in hmm_range->hmm_pfns still pointing to freed memory. The caller (or amdgpu_hmm_range_free(range)) may try to free range->hmm_range.hmm_pfns again, causing a double free, Setting hmm_range->hmm_pfns = NULL immediately after kvfree(pfns) prevents both double free. (Philip) In svm_range_validate_and_map(), When r == 0, it means success → range is not NULL. When r != 0, it means failure → already made range = NULL. So checking both (!r && range) is unnecessary because the moment r == 0, we automatically know range exists and is safe to use. (Philip) Fixes: 737da5363cc0 ("drm/amdgpu: update the functions to use amdgpu version of hmm") Reported by: Dan Carpenter Cc: Philip Yang Cc: Sunil Khatri Cc: Christian König Cc: Alex Deucher Signed-off-by: Srinivasan Shanmugam Reviewed-by: Philip Yang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_hmm.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_hmm.c') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_hmm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_hmm.c index 7e5a09b0bc78..518ca3f4db2b 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_hmm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_hmm.c @@ -221,6 +221,7 @@ retry: out_free_pfns: kvfree(pfns); + hmm_range->hmm_pfns = NULL; out_free_range: if (r == -EBUSY) r = -EAGAIN; -- cgit v1.2.3