Skip to content

Commit d02f05d

Browse files
andmar-amdgregkh
authored andcommitted
drm/amdkfd: Fix buffer overflow in SDMA queue checkpoint/restore on GFX11
commit 352ea59 upstream. The v11 MQD manager incorrectly assigned the CP-compute variants of checkpoint_mqd/restore_mqd for KFD_MQD_TYPE_SDMA queues. These functions use sizeof(struct v11_compute_mqd) (2048 bytes) instead of sizeof(struct v11_sdma_mqd) (512 bytes), causing a 1536-byte overflow. During CRIU checkpoint of an SDMA queue on Navi3x: - checkpoint_mqd() reads 2048 bytes from a 512-byte SDMA MQD buffer, leaking 1536 bytes of adjacent GTT memory to userspace During CRIU restore: - restore_mqd() writes 2048 bytes into a 512-byte SDMA MQD buffer, corrupting 1536 bytes of adjacent GTT memory (often the ring buffer or neighboring MQDs) This is a copy-paste regression unique to v11. All other ASIC backends (cik, vi, v9, v10, v12) correctly use the SDMA-specific variants. Add checkpoint_mqd_sdma() and restore_mqd_sdma() functions that properly handle the smaller v11_sdma_mqd structure, matching the pattern used in other MQD managers. Fixes: cc009e6 ("drm/amdkfd: Add KFD support for soc21 v3") Assisted-by: Claude:Sonnet 4-5 Signed-off-by: Andrew Martin <andrew.martin@amd.com> Acked-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> (cherry picked from commit 6fa41db) Cc: stable@vger.kernel.org Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent e1965e8 commit d02f05d

1 file changed

Lines changed: 41 additions & 8 deletions

File tree

drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v11.c

Lines changed: 41 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -320,8 +320,7 @@ static void checkpoint_mqd(struct mqd_manager *mm, void *mqd, void *mqd_dst, voi
320320

321321
static void restore_mqd(struct mqd_manager *mm, void **mqd,
322322
struct kfd_mem_obj *mqd_mem_obj, uint64_t *gart_addr,
323-
struct queue_properties *qp,
324-
const void *mqd_src,
323+
struct queue_properties *qp, const void *mqd_src,
325324
const void *ctl_stack_src, const u32 ctl_stack_size)
326325
{
327326
uint64_t addr;
@@ -337,14 +336,48 @@ static void restore_mqd(struct mqd_manager *mm, void **mqd,
337336
*gart_addr = addr;
338337

339338
m->cp_hqd_pq_doorbell_control =
340-
qp->doorbell_off <<
341-
CP_HQD_PQ_DOORBELL_CONTROL__DOORBELL_OFFSET__SHIFT;
342-
pr_debug("cp_hqd_pq_doorbell_control 0x%x\n",
343-
m->cp_hqd_pq_doorbell_control);
339+
qp->doorbell_off << CP_HQD_PQ_DOORBELL_CONTROL__DOORBELL_OFFSET__SHIFT;
340+
pr_debug("cp_hqd_pq_doorbell_control 0x%x\n", m->cp_hqd_pq_doorbell_control);
344341

345342
qp->is_active = 0;
346343
}
347344

345+
static void checkpoint_mqd_sdma(struct mqd_manager *mm,
346+
void *mqd,
347+
void *mqd_dst,
348+
void *ctl_stack_dst)
349+
{
350+
struct v11_sdma_mqd *m;
351+
352+
m = get_sdma_mqd(mqd);
353+
354+
memcpy(mqd_dst, m, sizeof(struct v11_sdma_mqd));
355+
}
356+
357+
static void restore_mqd_sdma(struct mqd_manager *mm, void **mqd,
358+
struct kfd_mem_obj *mqd_mem_obj, uint64_t *gart_addr,
359+
struct queue_properties *qp,
360+
const void *mqd_src,
361+
const void *ctl_stack_src,
362+
const u32 ctl_stack_size)
363+
{
364+
uint64_t addr;
365+
struct v11_sdma_mqd *m;
366+
367+
m = (struct v11_sdma_mqd *) mqd_mem_obj->cpu_ptr;
368+
addr = mqd_mem_obj->gpu_addr;
369+
370+
memcpy(m, mqd_src, sizeof(*m));
371+
372+
m->sdmax_rlcx_doorbell_offset =
373+
qp->doorbell_off << SDMA0_QUEUE0_DOORBELL_OFFSET__OFFSET__SHIFT;
374+
375+
*mqd = m;
376+
if (gart_addr)
377+
*gart_addr = addr;
378+
379+
qp->is_active = 0;
380+
}
348381

349382
static void init_mqd_hiq(struct mqd_manager *mm, void **mqd,
350383
struct kfd_mem_obj *mqd_mem_obj, uint64_t *gart_addr,
@@ -529,8 +562,8 @@ struct mqd_manager *mqd_manager_init_v11(enum KFD_MQD_TYPE type,
529562
mqd->update_mqd = update_mqd_sdma;
530563
mqd->destroy_mqd = kfd_destroy_mqd_sdma;
531564
mqd->is_occupied = kfd_is_occupied_sdma;
532-
mqd->checkpoint_mqd = checkpoint_mqd;
533-
mqd->restore_mqd = restore_mqd;
565+
mqd->checkpoint_mqd = checkpoint_mqd_sdma;
566+
mqd->restore_mqd = restore_mqd_sdma;
534567
mqd->mqd_size = sizeof(struct v11_sdma_mqd);
535568
mqd->mqd_stride = kfd_mqd_stride;
536569
#if defined(CONFIG_DEBUG_FS)

0 commit comments

Comments
 (0)