Check bounds against the end of the BO whenever we access the msg.

Signed-off-by: Benjamin Cheng <[email protected]>
Reviewed-by: Christian König <[email protected]>
Reviewed-by: Ruijing Dong <[email protected]>
---
 drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c | 21 ++++++++++++++++++---
 1 file changed, 18 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c 
b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
index d17219be50f3..1a1cdc14841a 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
@@ -1826,7 +1826,7 @@ static int vcn_v4_0_dec_msg(struct amdgpu_cs_parser *p, 
struct amdgpu_job *job,
        struct ttm_operation_ctx ctx = { false, false };
        struct amdgpu_device *adev = p->adev;
        struct amdgpu_bo_va_mapping *map;
-       uint32_t *msg, num_buffers;
+       uint32_t *msg, num_buffers, len_dw;
        struct amdgpu_bo *bo;
        uint64_t start, end;
        unsigned int i;
@@ -1847,6 +1847,11 @@ static int vcn_v4_0_dec_msg(struct amdgpu_cs_parser *p, 
struct amdgpu_job *job,
                return -EINVAL;
        }
 
+       if (end - addr < 16) {
+               DRM_ERROR("VCN messages must be at least 4 DWORDs!\n");
+               return -EINVAL;
+       }
+
        bo->flags |= AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED;
        amdgpu_bo_placement_from_domain(bo, bo->allowed_domains);
        r = ttm_bo_validate(&bo->tbo, &bo->placement, &ctx);
@@ -1863,8 +1868,8 @@ static int vcn_v4_0_dec_msg(struct amdgpu_cs_parser *p, 
struct amdgpu_job *job,
 
        msg = ptr + addr - start;
 
-       /* Check length */
        if (msg[1] > end - addr) {
+               DRM_ERROR("VCN message header does not fit in BO!\n");
                r = -EINVAL;
                goto out;
        }
@@ -1872,7 +1877,16 @@ static int vcn_v4_0_dec_msg(struct amdgpu_cs_parser *p, 
struct amdgpu_job *job,
        if (msg[3] != RDECODE_MSG_CREATE)
                goto out;
 
+       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) {
+               DRM_ERROR("VCN message has too many buffers!\n");
+               r = -EINVAL;
+               goto out;
+       }
+
        for (i = 0, msg = &msg[6]; i < num_buffers; ++i, msg += 4) {
                uint32_t offset, size, *create;
 
@@ -1882,7 +1896,8 @@ static int vcn_v4_0_dec_msg(struct amdgpu_cs_parser *p, 
struct amdgpu_job *job,
                offset = msg[1];
                size = msg[2];
 
-               if (offset + size > end) {
+               if (size < 4 || offset + size > end - addr) {
+                       DRM_ERROR("VCN message buffer exceeds BO bounds!\n");
                        r = -EINVAL;
                        goto out;
                }
-- 
2.53.0

Reply via email to