diff options
| author | Yang Wang <kevinyang.wang@amd.com> | 2026-06-23 00:04:33 +0800 |
|---|---|---|
| committer | Alex Deucher <alexander.deucher@amd.com> | 2026-07-01 11:23:35 -0400 |
| commit | a17e79d01f22182a9fcbe79fcbe2ad1477d43e0f (patch) | |
| tree | 6954202007286a9bfab57ef3b7188da559ddfe8f | |
| parent | d41624990ef66b410e95b7fc89b3727a0d297906 (diff) | |
| download | linux-stable-a17e79d01f22182a9fcbe79fcbe2ad1477d43e0f.tar.gz linux-stable-a17e79d01f22182a9fcbe79fcbe2ad1477d43e0f.zip | |
drm/amd/pm: Validate pp_table header before reading size
smu_sys_set_pp_table() reads usStructureSize from the uploaded
pp_table buffer before validating that the buffer contains a complete
ATOM_COMMON_TABLE_HEADER. A short write can therefore make the driver
read past the supplied sysfs buffer.
Reject empty or header-short uploads before dereferencing the header
pointer.
Keep the existing structure-size check for the full uploaded table.
Signed-off-by: Yang Wang <kevinyang.wang@amd.com>
Reviewed-by: Hawking Zhang <Hawking.Zhang@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
| -rw-r--r-- | drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c | 19 |
1 files changed, 11 insertions, 8 deletions
diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c index 5e73594efdf0..9abfac9f81d1 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c +++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c @@ -667,25 +667,28 @@ static int smu_sys_set_pp_table(void *handle, { struct smu_context *smu = handle; struct smu_table_context *smu_table = &smu->smu_table; - ATOM_COMMON_TABLE_HEADER *header = (ATOM_COMMON_TABLE_HEADER *)buf; + ATOM_COMMON_TABLE_HEADER *header; + void *hardcode_pptable; int ret = 0; if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) return -EOPNOTSUPP; + if (!buf || size < sizeof(*header)) + return -EINVAL; + + header = (ATOM_COMMON_TABLE_HEADER *)buf; if (header->usStructureSize != size) { dev_err(smu->adev->dev, "pp table size not matched !\n"); return -EIO; } - if (!smu_table->hardcode_pptable || smu_table->power_play_table_size < size) { - kfree(smu_table->hardcode_pptable); - smu_table->hardcode_pptable = kzalloc(size, GFP_KERNEL); - if (!smu_table->hardcode_pptable) - return -ENOMEM; - } + hardcode_pptable = kmemdup(buf, size, GFP_KERNEL); + if (!hardcode_pptable) + return -ENOMEM; - memcpy(smu_table->hardcode_pptable, buf, size); + kfree(smu_table->hardcode_pptable); + smu_table->hardcode_pptable = hardcode_pptable; smu_table->power_play_table = smu_table->hardcode_pptable; smu_table->power_play_table_size = size; |
