if supplied msg[2] in the header is too large, 4 times
of this unsigned 32 bit value will overflow and the test could pass.

v3: Using two-helper form is heavier than needed.
    Since len_dw is a plain u32, a division-based test is
    overflow-free by construction.

Fixes: b193019860d6 ("drm/amdgpu/vcn3: Prevent OOB reads when parsing dec msg")
Fixes: 0a78f2bac142 ("drm/amdgpu/vcn4: Prevent OOB reads when parsing dec msg")

Signed-off-by: David (Ming Qiang) Wu <[email protected]>
Cc: [email protected]
---
 drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c | 8 ++++++--
 drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c | 8 ++++++--
 2 files changed, 12 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c 
b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
index 81bba3ec2a93..686f5f758cb1 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
@@ -1964,8 +1964,12 @@ static int vcn_v3_0_dec_msg(struct amdgpu_cs_parser *p, 
struct amdgpu_job *job,
        len_dw = msg[1] / 4;
        num_buffers = msg[2];
 
-       /* Verify that all indices fit within the claimed length. Each index is 
4 DWORDs */
-       if (num_buffers > len_dw || 6 + num_buffers * 4 > len_dw) {
+       /* Verify that all indices fit within the claimed length.
+        * There are 6 dwords in the header before the first buffer.
+        * Each buffer has 4 dwords. Extra dwords will be ignored
+        * at the end of the last buffer.
+        */
+       if (len_dw < 6 || num_buffers > (len_dw - 6) / 4) {
                DRM_ERROR("VCN message has too many buffers!\n");
                r = -EINVAL;
                goto out;
diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c 
b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
index 0cce78b205a8..6f0a51c436db 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
@@ -1880,8 +1880,12 @@ static int vcn_v4_0_dec_msg(struct amdgpu_cs_parser *p, 
struct amdgpu_job *job,
        len_dw = msg[1] / 4;
        num_buffers = msg[2];
 
-       /* Verify that all indices fit within the claimed length. Each index is 
4 DWORDs */
-       if (num_buffers > len_dw || 6 + num_buffers * 4 > len_dw) {
+       /* Verify that all indices fit within the claimed length.
+        * There are 6 dwords in the header before the first buffer.
+        * Each buffer has 4 dwords. Extra dwords will be ignored
+        * at the end of the last buffer.
+        */
+       if (len_dw < 6 || num_buffers > (len_dw - 6) / 4) {
                DRM_ERROR("VCN message has too many buffers!\n");
                r = -EINVAL;
                goto out;
-- 
2.43.0

Reply via email to