From: Harry Wentland <[email protected]>

[Why]
dp_link_settings_read() passed strlen() of each format string as the size
argument to snprintf() and then advanced rd_buf_ptr by that same fixed amount.
The format-string length has no relation to the formatted output length, so
snprintf() truncated each field at a NUL it wrote inside the buffer while the
pointer was advanced past it. The result is a buffer peppered with embedded NUL
bytes and fields that are silently cut short, so the data read back from the
debugfs node does not reflect the actual link settings.

[How]
Use scnprintf() with the real remaining buffer size
(rd_buf_size - (rd_buf_ptr - rd_buf)) and advance rd_buf_ptr by its return
value, which is the number of characters actually written. This both bounds
each write to the space left in rd_buf and keeps the output a single,
properly terminated string. The now-unused str_len local is removed.

Fixes: 41db5f1931ec ("drm/amd/display: set-read link rate and lane count 
through debugfs")
Cc: [email protected]
Assisted-by: Copilot:claude-opus-4.8
Reviewed-by: Alex Hung <[email protected]>
Signed-off-by: Harry Wentland <[email protected]>
Signed-off-by: George Zhang <[email protected]>
---
 .../amd/display/amdgpu_dm/amdgpu_dm_debugfs.c | 20 ++++++++-----------
 1 file changed, 8 insertions(+), 12 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 1f5dde2bc74c..6b07982e3aa5 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
@@ -196,7 +196,6 @@ static ssize_t dp_link_settings_read(struct file *f, char 
__user *buf,
        char *rd_buf_ptr = NULL;
        const uint32_t rd_buf_size = 100;
        uint32_t result = 0;
-       uint8_t str_len = 0;
        int r;
 
        if (*pos & 3 || size & 3)
@@ -208,29 +207,26 @@ static ssize_t dp_link_settings_read(struct file *f, char 
__user *buf,
 
        rd_buf_ptr = rd_buf;
 
-       str_len = strlen("Current:  %d  0x%x  %d  ");
-       snprintf(rd_buf_ptr, str_len, "Current:  %d  0x%x  %d  ",
+       rd_buf_ptr += scnprintf(rd_buf_ptr, rd_buf_size - (rd_buf_ptr - rd_buf),
+                       "Current:  %d  0x%x  %d  ",
                        link->cur_link_settings.lane_count,
                        link->cur_link_settings.link_rate,
                        link->cur_link_settings.link_spread);
-       rd_buf_ptr += str_len;
 
-       str_len = strlen("Verified:  %d  0x%x  %d  ");
-       snprintf(rd_buf_ptr, str_len, "Verified:  %d  0x%x  %d  ",
+       rd_buf_ptr += scnprintf(rd_buf_ptr, rd_buf_size - (rd_buf_ptr - rd_buf),
+                       "Verified:  %d  0x%x  %d  ",
                        link->verified_link_cap.lane_count,
                        link->verified_link_cap.link_rate,
                        link->verified_link_cap.link_spread);
-       rd_buf_ptr += str_len;
 
-       str_len = strlen("Reported:  %d  0x%x  %d  ");
-       snprintf(rd_buf_ptr, str_len, "Reported:  %d  0x%x  %d  ",
+       rd_buf_ptr += scnprintf(rd_buf_ptr, rd_buf_size - (rd_buf_ptr - rd_buf),
+                       "Reported:  %d  0x%x  %d  ",
                        link->reported_link_cap.lane_count,
                        link->reported_link_cap.link_rate,
                        link->reported_link_cap.link_spread);
-       rd_buf_ptr += str_len;
 
-       str_len = strlen("Preferred:  %d  0x%x  %d  ");
-       snprintf(rd_buf_ptr, str_len, "Preferred:  %d  0x%x  %d\n",
+       rd_buf_ptr += scnprintf(rd_buf_ptr, rd_buf_size - (rd_buf_ptr - rd_buf),
+                       "Preferred:  %d  0x%x  %d\n",
                        link->preferred_link_setting.lane_count,
                        link->preferred_link_setting.link_rate,
                        link->preferred_link_setting.link_spread);
-- 
2.53.0

Reply via email to