summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYang Wang <kevinyang.wang@amd.com>2026-06-23 00:04:33 +0800
committerAlex Deucher <alexander.deucher@amd.com>2026-07-01 11:23:35 -0400
commita17e79d01f22182a9fcbe79fcbe2ad1477d43e0f (patch)
tree6954202007286a9bfab57ef3b7188da559ddfe8f
parentd41624990ef66b410e95b7fc89b3727a0d297906 (diff)
downloadlinux-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.c19
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;