On Tue, Apr 18, 2023 at 12:07:15PM +0200, Krzysztof Kozlowski wrote: > On 18/04/2023 10:47, Andi Shyti wrote: > > Hi Daniil, > > > > On Mon, Apr 17, 2023 at 11:55:21PM -0700, Daniil Dulov wrote: > >> Pointer mqd_mem_obj can be deallocated in kfd_gtt_sa_allocate(). > >> The function then returns non-zero value, which causes the second deallocation. > >> > >> Found by Linux Verification Center (linuxtesting.org) with SVACE. > >> > >> Fixes: d1f8f0d17d40 ("drm/amdkfd: Move non-sdma mqd allocation out of init_mqd") > >> Signed-off-by: Daniil Dulov <d.dulov@xxxxxxxxxx> > >> --- > >> drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v9.c | 3 ++- > >> 1 file changed, 2 insertions(+), 1 deletion(-) > >> > >> diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v9.c b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v9.c > >> index 3b6f5963180d..bce11c5b07d6 100644 > >> --- a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v9.c > >> +++ b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v9.c > >> @@ -119,7 +119,8 @@ static struct kfd_mem_obj *allocate_mqd(struct kfd_dev *kfd, > >> } > >> > >> if (retval) { > >> - kfree(mqd_mem_obj); > >> + if (mqd_mem_obj) > >> + kfree(mqd_mem_obj); > > > > I think this is not needed. kfree() returns immediately if > > mqd_mem_obj is NULL. > > > > Yep, the tool has to be fixed because such patch is just misleading. > However different point - the commit description actually describes > entirely different case: double free. Maybe the issue is true, just the > fix is wrong? Yes, indeed, the fix is wrong, but the bug exists. I'm pasting the original function: if (kfd->cwsr_enabled && (q->type == KFD_QUEUE_TYPE_COMPUTE)) { mqd_mem_obj = kzalloc(sizeof(struct kfd_mem_obj), GFP_KERNEL); if (!mqd_mem_obj) return NULL; ... } else { retval = kfd_gtt_sa_allocate(kfd, sizeof(struct v9_mqd), &mqd_mem_obj); } if (retval) { kfree(mqd_mem_obj); return NULL; } The "kfd_gtt_sa_allocate()" function allocates mqd_mem_obj and if an error occurs internally frees it, without setting it to NULL; retval is true and we kfree a memory that has already been freed. The real fix is to move the "if (retval)" inside the if. It would basically be: diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v9.c b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v9.c index fdbfd725841ff..31d47d687bd62 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v9.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v9.c @@ -115,18 +115,20 @@ static struct kfd_mem_obj *allocate_mqd(struct kfd_dev *kfd, &(mqd_mem_obj->gtt_mem), &(mqd_mem_obj->gpu_addr), (void *)&(mqd_mem_obj->cpu_ptr), true); + + if (retval) { + kfree(mqd_mem_obj); + return NULL; + } + } else { retval = kfd_gtt_sa_allocate(kfd, sizeof(struct v9_mqd), &mqd_mem_obj); - } - - if (retval) { - kfree(mqd_mem_obj); - return NULL; + if (retval) + return NULL; } return mqd_mem_obj; - } Maybe with some clever refactoring we could reduce some code duplication. Daniil will you look into this? Andi