From: Sasha Levin <sashal@kernel.org>
To: stable@vger.kernel.org
Cc: Yang Wang <kevinyang.wang@amd.com>,
Kenneth Feng <kenneth.feng@amd.com>,
Alex Deucher <alexander.deucher@amd.com>,
Sasha Levin <sashal@kernel.org>
Subject: [PATCH 6.1.y] drm/amd/pm: fix pptable use-after-free
Date: Fri, 14 Aug 2026 13:24:54 -0400 [thread overview]
Message-ID: <20260814172454.176686-1-sashal@kernel.org> (raw)
In-Reply-To: <2026080538-overrate-sinuous-c96e@gregkh>
From: Yang Wang <kevinyang.wang@amd.com>
[ Upstream commit bb493058c35c8676e48269ab6732688ea733d23c ]
amdgpu_dpm_get_pp_table() returns a pointer to a driver-owned power table
after dropping adev->pm.mutex. The sysfs path then copies from that pointer.
A concurrent pp_table write can replace and free the allocation during the
copy, causing a use-after-free.
Change the DPM interface to copy into caller-provided storage while the mutex
is held. Keep the size-only query for attribute discovery without exposing
the driver-owned pointer.
Fixes: 1684d3ba4885 ("drm/amd/amdgpu: change pptable output format from ASCII to binary")
Signed-off-by: Yang Wang <kevinyang.wang@amd.com>
Reviewed-by: Kenneth Feng <kenneth.feng@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
(cherry picked from commit f6eed7acfd30099ef7baeb6ba45bb59daad80631)
Cc: stable@vger.kernel.org
[ kept 6.18's existing `if (!pp_funcs->get_pp_table) return 0;` guard instead of upstream's SR-IOV/SCPM `-EOPNOTSUPP` guard and dropped the `default_attr_update()` hunk whose `pp_table` branch doesn't exist yet ]
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/gpu/drm/amd/pm/amdgpu_dpm.c | 15 +++++++++++++--
drivers/gpu/drm/amd/pm/amdgpu_pm.c | 8 +-------
drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h | 3 ++-
3 files changed, 16 insertions(+), 10 deletions(-)
diff --git a/drivers/gpu/drm/amd/pm/amdgpu_dpm.c b/drivers/gpu/drm/amd/pm/amdgpu_dpm.c
index 69b51612c39a5..77dda3239c21c 100644
--- a/drivers/gpu/drm/amd/pm/amdgpu_dpm.c
+++ b/drivers/gpu/drm/amd/pm/amdgpu_dpm.c
@@ -950,17 +950,28 @@ int amdgpu_dpm_dispatch_task(struct amdgpu_device *adev,
return ret;
}
-int amdgpu_dpm_get_pp_table(struct amdgpu_device *adev, char **table)
+int amdgpu_dpm_get_pp_table(struct amdgpu_device *adev, char *table,
+ size_t size)
{
const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
+ char *pptable = NULL;
int ret = 0;
+ if ((!table && size) || (table && !size))
+ return -EINVAL;
+
if (!pp_funcs->get_pp_table)
return 0;
mutex_lock(&adev->pm.mutex);
ret = pp_funcs->get_pp_table(adev->powerplay.pp_handle,
- table);
+ &pptable);
+ if (ret > 0 && !pptable) {
+ ret = -EINVAL;
+ } else if (ret > 0 && table) {
+ ret = min_t(size_t, ret, size);
+ memcpy(table, pptable, ret);
+ }
mutex_unlock(&adev->pm.mutex);
return ret;
diff --git a/drivers/gpu/drm/amd/pm/amdgpu_pm.c b/drivers/gpu/drm/amd/pm/amdgpu_pm.c
index cdb406690b7e7..229049f21a89b 100644
--- a/drivers/gpu/drm/amd/pm/amdgpu_pm.c
+++ b/drivers/gpu/drm/amd/pm/amdgpu_pm.c
@@ -532,7 +532,6 @@ static ssize_t amdgpu_get_pp_table(struct device *dev,
{
struct drm_device *ddev = dev_get_drvdata(dev);
struct amdgpu_device *adev = drm_to_adev(ddev);
- char *table = NULL;
int size, ret;
if (amdgpu_in_reset(adev))
@@ -546,7 +545,7 @@ static ssize_t amdgpu_get_pp_table(struct device *dev,
return ret;
}
- size = amdgpu_dpm_get_pp_table(adev, &table);
+ size = amdgpu_dpm_get_pp_table(adev, buf, PAGE_SIZE - 1);
pm_runtime_mark_last_busy(ddev->dev);
pm_runtime_put_autosuspend(ddev->dev);
@@ -554,11 +553,6 @@ static ssize_t amdgpu_get_pp_table(struct device *dev,
if (size <= 0)
return size;
- if (size >= PAGE_SIZE)
- size = PAGE_SIZE - 1;
-
- memcpy(buf, table, size);
-
return size;
}
diff --git a/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h b/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h
index 338fce249f5ab..a97c27ae9702c 100644
--- a/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h
+++ b/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h
@@ -459,7 +459,8 @@ int amdgpu_dpm_get_pp_num_states(struct amdgpu_device *adev,
int amdgpu_dpm_dispatch_task(struct amdgpu_device *adev,
enum amd_pp_task task_id,
enum amd_pm_state_type *user_state);
-int amdgpu_dpm_get_pp_table(struct amdgpu_device *adev, char **table);
+int amdgpu_dpm_get_pp_table(struct amdgpu_device *adev, char *table,
+ size_t size);
int amdgpu_dpm_set_fine_grain_clk_vol(struct amdgpu_device *adev,
uint32_t type,
long *input,
--
2.53.0
prev parent reply other threads:[~2026-08-14 17:24 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-05 11:59 FAILED: patch "[PATCH] drm/amd/pm: fix pptable use-after-free" failed to apply to 6.1-stable tree gregkh
2026-08-14 17:24 ` [PATCH 6.1.y] drm/amd/pm: fix pptable use-after-free Sasha Levin
2026-08-14 17:24 ` Sasha Levin [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260814172454.176686-1-sashal@kernel.org \
--to=sashal@kernel.org \
--cc=alexander.deucher@amd.com \
--cc=kenneth.feng@amd.com \
--cc=kevinyang.wang@amd.com \
--cc=stable@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox