| From d76e99b1f3bd524a34fe3905d019c4dc437821cc Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Tue, 21 Apr 2026 16:22:10 +0300 |
| Subject: drm/amd/display: Fix memory leak |
| |
| From: Yongzhi Liu <lyz_cs@pku.edu.cn> |
| |
| commit 5d5c6dba2b43e28845d7d7ed32a36802329a5f52 upstream. |
| |
| [why] |
| Resource release is needed on the error handling path |
| to prevent memory leak. |
| |
| [how] |
| Fix this by adding kfree on the error handling path. |
| |
| Reviewed-by: Harry Wentland <harry.wentland@amd.com> |
| Signed-off-by: Yongzhi Liu <lyz_cs@pku.edu.cn> |
| Signed-off-by: Alex Deucher <alexander.deucher@amd.com> |
| Fixes: f8ac2cf78f27 ("drm/amd/display: Linux set/read lane settings through debugfs") |
| Fixes: c06e09b76639 ("drm/amd/display: Add DSC parameters logging to debugfs") |
| [ kovalev: bp to fix CVE-2022-49135; added Fixes tags ] |
| Signed-off-by: Vasiliy Kovalev <kovalev@altlinux.org> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| .../amd/display/amdgpu_dm/amdgpu_dm_debugfs.c | 72 ++++++++++++++----- |
| 1 file changed, 54 insertions(+), 18 deletions(-) |
| |
| diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c |
| index 6914738f0275a..f4a1ad8959b7d 100644 |
| --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c |
| +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c |
| @@ -229,8 +229,10 @@ static ssize_t dp_link_settings_read(struct file *f, char __user *buf, |
| break; |
| |
| r = put_user(*(rd_buf + result), buf); |
| - if (r) |
| + if (r) { |
| + kfree(rd_buf); |
| return r; /* r = -EFAULT */ |
| + } |
| |
| buf += 1; |
| size -= 1; |
| @@ -388,8 +390,10 @@ static ssize_t dp_phy_settings_read(struct file *f, char __user *buf, |
| break; |
| |
| r = put_user((*(rd_buf + result)), buf); |
| - if (r) |
| + if (r) { |
| + kfree(rd_buf); |
| return r; /* r = -EFAULT */ |
| + } |
| |
| buf += 1; |
| size -= 1; |
| @@ -1195,8 +1199,10 @@ static ssize_t dp_dsc_clock_en_read(struct file *f, char __user *buf, |
| break; |
| } |
| |
| - if (!pipe_ctx) |
| + if (!pipe_ctx) { |
| + kfree(rd_buf); |
| return -ENXIO; |
| + } |
| |
| dsc = pipe_ctx->stream_res.dsc; |
| if (dsc) |
| @@ -1212,8 +1218,10 @@ static ssize_t dp_dsc_clock_en_read(struct file *f, char __user *buf, |
| break; |
| |
| r = put_user(*(rd_buf + result), buf); |
| - if (r) |
| + if (r) { |
| + kfree(rd_buf); |
| return r; /* r = -EFAULT */ |
| + } |
| |
| buf += 1; |
| size -= 1; |
| @@ -1351,8 +1359,10 @@ static ssize_t dp_dsc_slice_width_read(struct file *f, char __user *buf, |
| break; |
| } |
| |
| - if (!pipe_ctx) |
| + if (!pipe_ctx) { |
| + kfree(rd_buf); |
| return -ENXIO; |
| + } |
| |
| dsc = pipe_ctx->stream_res.dsc; |
| if (dsc) |
| @@ -1368,8 +1378,10 @@ static ssize_t dp_dsc_slice_width_read(struct file *f, char __user *buf, |
| break; |
| |
| r = put_user(*(rd_buf + result), buf); |
| - if (r) |
| + if (r) { |
| + kfree(rd_buf); |
| return r; /* r = -EFAULT */ |
| + } |
| |
| buf += 1; |
| size -= 1; |
| @@ -1505,8 +1517,10 @@ static ssize_t dp_dsc_slice_height_read(struct file *f, char __user *buf, |
| break; |
| } |
| |
| - if (!pipe_ctx) |
| + if (!pipe_ctx) { |
| + kfree(rd_buf); |
| return -ENXIO; |
| + } |
| |
| dsc = pipe_ctx->stream_res.dsc; |
| if (dsc) |
| @@ -1522,8 +1536,10 @@ static ssize_t dp_dsc_slice_height_read(struct file *f, char __user *buf, |
| break; |
| |
| r = put_user(*(rd_buf + result), buf); |
| - if (r) |
| + if (r) { |
| + kfree(rd_buf); |
| return r; /* r = -EFAULT */ |
| + } |
| |
| buf += 1; |
| size -= 1; |
| @@ -1655,8 +1671,10 @@ static ssize_t dp_dsc_bits_per_pixel_read(struct file *f, char __user *buf, |
| break; |
| } |
| |
| - if (!pipe_ctx) |
| + if (!pipe_ctx) { |
| + kfree(rd_buf); |
| return -ENXIO; |
| + } |
| |
| dsc = pipe_ctx->stream_res.dsc; |
| if (dsc) |
| @@ -1672,8 +1690,10 @@ static ssize_t dp_dsc_bits_per_pixel_read(struct file *f, char __user *buf, |
| break; |
| |
| r = put_user(*(rd_buf + result), buf); |
| - if (r) |
| + if (r) { |
| + kfree(rd_buf); |
| return r; /* r = -EFAULT */ |
| + } |
| |
| buf += 1; |
| size -= 1; |
| @@ -1800,8 +1820,10 @@ static ssize_t dp_dsc_pic_width_read(struct file *f, char __user *buf, |
| break; |
| } |
| |
| - if (!pipe_ctx) |
| + if (!pipe_ctx) { |
| + kfree(rd_buf); |
| return -ENXIO; |
| + } |
| |
| dsc = pipe_ctx->stream_res.dsc; |
| if (dsc) |
| @@ -1817,8 +1839,10 @@ static ssize_t dp_dsc_pic_width_read(struct file *f, char __user *buf, |
| break; |
| |
| r = put_user(*(rd_buf + result), buf); |
| - if (r) |
| + if (r) { |
| + kfree(rd_buf); |
| return r; /* r = -EFAULT */ |
| + } |
| |
| buf += 1; |
| size -= 1; |
| @@ -1857,8 +1881,10 @@ static ssize_t dp_dsc_pic_height_read(struct file *f, char __user *buf, |
| break; |
| } |
| |
| - if (!pipe_ctx) |
| + if (!pipe_ctx) { |
| + kfree(rd_buf); |
| return -ENXIO; |
| + } |
| |
| dsc = pipe_ctx->stream_res.dsc; |
| if (dsc) |
| @@ -1874,8 +1900,10 @@ static ssize_t dp_dsc_pic_height_read(struct file *f, char __user *buf, |
| break; |
| |
| r = put_user(*(rd_buf + result), buf); |
| - if (r) |
| + if (r) { |
| + kfree(rd_buf); |
| return r; /* r = -EFAULT */ |
| + } |
| |
| buf += 1; |
| size -= 1; |
| @@ -1929,8 +1957,10 @@ static ssize_t dp_dsc_chunk_size_read(struct file *f, char __user *buf, |
| break; |
| } |
| |
| - if (!pipe_ctx) |
| + if (!pipe_ctx) { |
| + kfree(rd_buf); |
| return -ENXIO; |
| + } |
| |
| dsc = pipe_ctx->stream_res.dsc; |
| if (dsc) |
| @@ -1946,8 +1976,10 @@ static ssize_t dp_dsc_chunk_size_read(struct file *f, char __user *buf, |
| break; |
| |
| r = put_user(*(rd_buf + result), buf); |
| - if (r) |
| + if (r) { |
| + kfree(rd_buf); |
| return r; /* r = -EFAULT */ |
| + } |
| |
| buf += 1; |
| size -= 1; |
| @@ -2001,8 +2033,10 @@ static ssize_t dp_dsc_slice_bpg_offset_read(struct file *f, char __user *buf, |
| break; |
| } |
| |
| - if (!pipe_ctx) |
| + if (!pipe_ctx) { |
| + kfree(rd_buf); |
| return -ENXIO; |
| + } |
| |
| dsc = pipe_ctx->stream_res.dsc; |
| if (dsc) |
| @@ -2018,8 +2052,10 @@ static ssize_t dp_dsc_slice_bpg_offset_read(struct file *f, char __user *buf, |
| break; |
| |
| r = put_user(*(rd_buf + result), buf); |
| - if (r) |
| + if (r) { |
| + kfree(rd_buf); |
| return r; /* r = -EFAULT */ |
| + } |
| |
| buf += 1; |
| size -= 1; |
| -- |
| 2.53.0 |
| |