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>
This commit is contained in:
David Francis 2026-07-06 10:19:04 -04:00 committed by Alex Deucher
parent 9d01579f3f
commit f19d8086f6
4 changed files with 27 additions and 8 deletions

View File

@ -3777,6 +3777,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

@ -335,6 +335,8 @@ bool kfd_dqm_is_queue_in_process(struct device_queue_manager *dqm,
int doorbell_off, u32 *queue_format);
int kfd_reset_queue_mes(struct device_queue_manager *dqm, int queue_type,
int pipe, int queue, unsigned int db);
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

@ -441,7 +441,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

@ -1003,6 +1003,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;
@ -1025,13 +1042,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]...