drm/amdkfd: Check bounds on CRIU restore queue type and mqd size

We weren't checking whether the values provided in the private
data in kfd CRIU restore were within bounds.

For queue type, add a KFD_QUEUE_TYPE_MAX and ensure the provided
type is less than it.

For mqd_size, add new function mqd_size_from_queue_type and confirm
that the provided mqd_size matches expectations.

Reviewed-by: David Yat Sin <david.yatsin@amd.com>
Signed-off-by: David Francis <David.Francis@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
(cherry picked from commit f19d8086f6644083c913d70bfdeee20e1b6f46a5)
Cc: stable@vger.kernel.org
This commit is contained in:
David Francis 2026-07-06 10:19:04 -04:00 committed by Alex Deucher
parent e987eabc02
commit 47ea05f246
4 changed files with 27 additions and 8 deletions

View File

@ -3818,6 +3818,12 @@ bool kfd_dqm_is_queue_in_process(struct device_queue_manager *dqm,
dqm_unlock(dqm);
return r;
}
size_t mqd_size_from_queue_type(struct device_queue_manager *dqm, enum kfd_queue_type type)
{
return dqm->mqd_mgrs[get_mqd_type_from_queue_type(type)]->mqd_size;
}
#if defined(CONFIG_DEBUG_FS)
static void seq_reg_dump(struct seq_file *m,

View File

@ -333,6 +333,8 @@ int debug_refresh_runlist(struct device_queue_manager *dqm);
bool kfd_dqm_is_queue_in_process(struct device_queue_manager *dqm,
struct qcm_process_device *qpd,
int doorbell_off, u32 *queue_format);
size_t mqd_size_from_queue_type(struct device_queue_manager *dqm,
enum kfd_queue_type type);
static inline unsigned int get_sh_mem_bases_32(struct kfd_process_device *pdd)
{

View File

@ -440,7 +440,8 @@ enum kfd_queue_type {
KFD_QUEUE_TYPE_SDMA,
KFD_QUEUE_TYPE_HIQ,
KFD_QUEUE_TYPE_SDMA_XGMI,
KFD_QUEUE_TYPE_SDMA_BY_ENG_ID
KFD_QUEUE_TYPE_SDMA_BY_ENG_ID,
KFD_QUEUE_TYPE_MAX,
};
enum kfd_queue_format {

View File

@ -1008,6 +1008,23 @@ int kfd_criu_restore_queue(struct kfd_process *p,
goto exit;
}
pdd = kfd_process_device_data_by_id(p, q_data->gpu_id);
if (!pdd) {
pr_err("Failed to get pdd\n");
ret = -EINVAL;
goto exit;
}
if (q_data->type >= KFD_QUEUE_TYPE_MAX) {
ret = -EINVAL;
goto exit;
}
if (q_data->mqd_size != mqd_size_from_queue_type(pdd->dev->dqm, q_data->type)) {
ret = -EINVAL;
goto exit;
}
*priv_data_offset += sizeof(*q_data);
q_extra_data_size = (uint64_t)q_data->ctl_stack_size + q_data->mqd_size;
@ -1030,13 +1047,6 @@ int kfd_criu_restore_queue(struct kfd_process *p,
*priv_data_offset += q_extra_data_size;
pdd = kfd_process_device_data_by_id(p, q_data->gpu_id);
if (!pdd) {
pr_err("Failed to get pdd\n");
ret = -EINVAL;
goto exit;
}
/*
* data stored in this order:
* mqd[xcc0], mqd[xcc1],..., ctl_stack[xcc0], ctl_stack[xcc1]...