FAILED: patch "[PATCH] drm/amd/pm: fix pptable use-after-free" failed to apply to 6.6-stable tree
[email protected]
maintainerThe patch below does not apply to the 6.6-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
To reproduce the conflict and resubmit, you may use the following commands:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-6.6.y
git checkout FETCH_HEAD
git cherry-pick -x bb493058c35c8676e48269ab6732688ea733d23c
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '2026080537-trace-quake-d688@gregkh' --subject-prefix 'PATCH 6.6.y' 'HEAD^..'
Possible dependencies:
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From bb493058c35c8676e48269ab6732688ea733d23c Mon Sep 17 00:00:00 2001
From: Yang Wang <[email protected]>
Date: Fri, 24 Jul 2026 07:41:29 +0800
Subject: [PATCH] drm/amd/pm: fix pptable use-after-free
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.
drivers/gpu/drm/amd/pm/amdgpu_dpm.c +11 -3
@@ -1183,12 +1183,14 @@ 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) +if ((!table && size) || (table && !size))return -EINVAL ;if (amdgpu_sriov_vf (adev) || !pp_funcs->get_pp_table || adev->scpm_enabled)
@@ -1196,7 +1198,13 @@ int amdgpu_dpm_get_pp_table(struct amdgpu_device *adev, char **table)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;
drivers/gpu/drm/amd/pm/amdgpu_pm.c +3 -10
@@ -564,25 +564,19 @@ 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; ret =amdgpu_pm_get_access_if_active (adev);if (ret)return ret; - size =amdgpu_dpm_get_pp_table (adev, &table); + size =amdgpu_dpm_get_pp_table (adev, buf,PAGE_SIZE -1 );amdgpu_pm_put_access (adev);if (size <=0 )return size; -if (size >=PAGE_SIZE ) - size =PAGE_SIZE -1 ; - -memcpy (buf, table, size); -return size; }
@@ -2726,10 +2720,9 @@ static int default_attr_update(struct amdgpu_device *adev, struct amdgpu_device_ *states =ATTR_STATE_UNSUPPORTED ; }else if (DEVICE_ATTR_IS (pp_table)) {int ret; -char *tmp =NULL ; - ret =amdgpu_dpm_get_pp_table (adev, &tmp); -if (ret == -EOPNOTSUPP || !tmp) + ret =amdgpu_dpm_get_pp_table (adev,NULL ,0 ); +if (ret <=0 ) *states =ATTR_STATE_UNSUPPORTED ;else *states =ATTR_STATE_SUPPORTED ;
drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h +2 -1
@@ -487,7 +487,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,
Sasha Levin
maintainerPATCH 1/1 drm/amd/pm: fix pptable use-after-free
From: Yang Wang <[email protected]>
[ 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.
--- 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(-)
drivers/gpu/drm/amd/pm/amdgpu_dpm.c +13 -2
@@ -996,17 +996,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;
drivers/gpu/drm/amd/pm/amdgpu_pm.c +1 -7
@@ -496,7 +496,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))
@@ -510,7 +509,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);
@@ -518,11 +517,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; }
drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h +2 -1
@@ -463,7 +463,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,
Signature · 1 line
2.53.0