VYPR
Unrated severityNVD Advisory· Published May 28, 2026

CVE-2026-46230

CVE-2026-46230

Description

In the Linux kernel, the following vulnerability has been resolved:

drm/amdgpu/vcn3: Prevent OOB reads when parsing dec msg

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

Affected products

2

Patches

10
e382e0b81a3e

drm/amdgpu/vcn3: Prevent OOB reads when parsing dec msg

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitBenjamin ChengMar 24, 2026Fixed in 7.0.9via kernel-cna
2 files changed · +38 10
  • drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c+19 5 modified
    diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
    index 02d5c5af65f232..6fb4fcdbba4f14 100644
    --- a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
    +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
    @@ -1909,7 +1909,7 @@ static int vcn_v3_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;
    @@ -1930,6 +1930,11 @@ static int vcn_v3_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);
    @@ -1946,8 +1951,8 @@ static int vcn_v3_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;
     	}
    @@ -1955,7 +1960,16 @@ static int vcn_v3_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;
     
    @@ -1965,14 +1979,15 @@ static int vcn_v3_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;
     		}
     
     		create = ptr + addr + offset - start;
     
    -		/* H246, HEVC and VP9 can run on any instance */
    +		/* H264, HEVC and VP9 can run on any instance */
     		if (create[0] == 0x7 || create[0] == 0x10 || create[0] == 0x11)
     			continue;
     
    -- 
    cgit 1.3-korg
    
    
    
  • drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c+19 5 modified
    diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
    index 02d5c5af65f232..6fb4fcdbba4f14 100644
    --- a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
    +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
    @@ -1909,7 +1909,7 @@ static int vcn_v3_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;
    @@ -1930,6 +1930,11 @@ static int vcn_v3_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);
    @@ -1946,8 +1951,8 @@ static int vcn_v3_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;
     	}
    @@ -1955,7 +1960,16 @@ static int vcn_v3_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;
     
    @@ -1965,14 +1979,15 @@ static int vcn_v3_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;
     		}
     
     		create = ptr + addr + offset - start;
     
    -		/* H246, HEVC and VP9 can run on any instance */
    +		/* H264, HEVC and VP9 can run on any instance */
     		if (create[0] == 0x7 || create[0] == 0x10 || create[0] == 0x11)
     			continue;
     
    -- 
    cgit 1.3-korg
    
    
    
638d3e0b9eb7

drm/amdgpu/vcn3: Prevent OOB reads when parsing dec msg

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitBenjamin ChengMar 24, 2026Fixed in 6.6.140via kernel-cna
2 files changed · +38 10
  • drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c+19 5 modified
    diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
    index 710328f12194d3..8d1b6a06194fb1 100644
    --- a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
    +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
    @@ -1789,7 +1789,7 @@ static int vcn_v3_0_dec_msg(struct amdgpu_cs_parser *p, struct amdgpu_job *job,
     {
     	struct ttm_operation_ctx ctx = { false, false };
     	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;
    @@ -1810,6 +1810,11 @@ static int vcn_v3_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);
    @@ -1826,8 +1831,8 @@ static int vcn_v3_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;
     	}
    @@ -1835,7 +1840,16 @@ static int vcn_v3_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;
     
    @@ -1845,14 +1859,15 @@ static int vcn_v3_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;
     		}
     
     		create = ptr + addr + offset - start;
     
    -		/* H246, HEVC and VP9 can run on any instance */
    +		/* H264, HEVC and VP9 can run on any instance */
     		if (create[0] == 0x7 || create[0] == 0x10 || create[0] == 0x11)
     			continue;
     
    -- 
    cgit 1.3-korg
    
    
    
  • drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c+19 5 modified
    diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
    index 710328f12194d3..8d1b6a06194fb1 100644
    --- a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
    +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
    @@ -1789,7 +1789,7 @@ static int vcn_v3_0_dec_msg(struct amdgpu_cs_parser *p, struct amdgpu_job *job,
     {
     	struct ttm_operation_ctx ctx = { false, false };
     	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;
    @@ -1810,6 +1810,11 @@ static int vcn_v3_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);
    @@ -1826,8 +1831,8 @@ static int vcn_v3_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;
     	}
    @@ -1835,7 +1840,16 @@ static int vcn_v3_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;
     
    @@ -1845,14 +1859,15 @@ static int vcn_v3_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;
     		}
     
     		create = ptr + addr + offset - start;
     
    -		/* H246, HEVC and VP9 can run on any instance */
    +		/* H264, HEVC and VP9 can run on any instance */
     		if (create[0] == 0x7 || create[0] == 0x10 || create[0] == 0x11)
     			continue;
     
    -- 
    cgit 1.3-korg
    
    
    
870c8738c377

drm/amdgpu/vcn3: Prevent OOB reads when parsing dec msg

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitBenjamin ChengMar 24, 2026Fixed in 6.12.90via kernel-cna
2 files changed · +38 10
  • drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c+19 5 modified
    diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
    index 4196bdece253b6..be9151bd2c7208 100644
    --- a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
    +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
    @@ -1843,7 +1843,7 @@ static int vcn_v3_0_dec_msg(struct amdgpu_cs_parser *p, struct amdgpu_job *job,
     {
     	struct ttm_operation_ctx ctx = { false, false };
     	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;
    @@ -1864,6 +1864,11 @@ static int vcn_v3_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);
    @@ -1880,8 +1885,8 @@ static int vcn_v3_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;
     	}
    @@ -1889,7 +1894,16 @@ static int vcn_v3_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;
     
    @@ -1899,14 +1913,15 @@ static int vcn_v3_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;
     		}
     
     		create = ptr + addr + offset - start;
     
    -		/* H246, HEVC and VP9 can run on any instance */
    +		/* H264, HEVC and VP9 can run on any instance */
     		if (create[0] == 0x7 || create[0] == 0x10 || create[0] == 0x11)
     			continue;
     
    -- 
    cgit 1.3-korg
    
    
    
  • drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c+19 5 modified
    diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
    index 4196bdece253b6..be9151bd2c7208 100644
    --- a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
    +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
    @@ -1843,7 +1843,7 @@ static int vcn_v3_0_dec_msg(struct amdgpu_cs_parser *p, struct amdgpu_job *job,
     {
     	struct ttm_operation_ctx ctx = { false, false };
     	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;
    @@ -1864,6 +1864,11 @@ static int vcn_v3_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);
    @@ -1880,8 +1885,8 @@ static int vcn_v3_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;
     	}
    @@ -1889,7 +1894,16 @@ static int vcn_v3_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;
     
    @@ -1899,14 +1913,15 @@ static int vcn_v3_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;
     		}
     
     		create = ptr + addr + offset - start;
     
    -		/* H246, HEVC and VP9 can run on any instance */
    +		/* H264, HEVC and VP9 can run on any instance */
     		if (create[0] == 0x7 || create[0] == 0x10 || create[0] == 0x11)
     			continue;
     
    -- 
    cgit 1.3-korg
    
    
    
b193019860d6

drm/amdgpu/vcn3: Prevent OOB reads when parsing dec msg

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitBenjamin ChengMar 24, 2026Fixed in 7.1-rc1via kernel-cna
2 files changed · +38 10
  • drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c+19 5 modified
    diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
    index 02d5c5af65f232..6fb4fcdbba4f14 100644
    --- a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
    +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
    @@ -1909,7 +1909,7 @@ static int vcn_v3_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;
    @@ -1930,6 +1930,11 @@ static int vcn_v3_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);
    @@ -1946,8 +1951,8 @@ static int vcn_v3_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;
     	}
    @@ -1955,7 +1960,16 @@ static int vcn_v3_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;
     
    @@ -1965,14 +1979,15 @@ static int vcn_v3_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;
     		}
     
     		create = ptr + addr + offset - start;
     
    -		/* H246, HEVC and VP9 can run on any instance */
    +		/* H264, HEVC and VP9 can run on any instance */
     		if (create[0] == 0x7 || create[0] == 0x10 || create[0] == 0x11)
     			continue;
     
    -- 
    cgit 1.3-korg
    
    
    
  • drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c+19 5 modified
    diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
    index 02d5c5af65f232..6fb4fcdbba4f14 100644
    --- a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
    +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
    @@ -1909,7 +1909,7 @@ static int vcn_v3_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;
    @@ -1930,6 +1930,11 @@ static int vcn_v3_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);
    @@ -1946,8 +1951,8 @@ static int vcn_v3_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;
     	}
    @@ -1955,7 +1960,16 @@ static int vcn_v3_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;
     
    @@ -1965,14 +1979,15 @@ static int vcn_v3_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;
     		}
     
     		create = ptr + addr + offset - start;
     
    -		/* H246, HEVC and VP9 can run on any instance */
    +		/* H264, HEVC and VP9 can run on any instance */
     		if (create[0] == 0x7 || create[0] == 0x10 || create[0] == 0x11)
     			continue;
     
    -- 
    cgit 1.3-korg
    
    
    
638e48ee39d0

drm/amdgpu/vcn3: Prevent OOB reads when parsing dec msg

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitBenjamin ChengMar 24, 2026Fixed in 6.18.32via kernel-cna
2 files changed · +38 10
  • drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c+19 5 modified
    diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
    index d9cf8f0feeb3e6..558d3bf7fc76ee 100644
    --- a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
    +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
    @@ -1908,7 +1908,7 @@ static int vcn_v3_0_dec_msg(struct amdgpu_cs_parser *p, struct amdgpu_job *job,
     {
     	struct ttm_operation_ctx ctx = { false, false };
     	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;
    @@ -1929,6 +1929,11 @@ static int vcn_v3_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);
    @@ -1945,8 +1950,8 @@ static int vcn_v3_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;
     	}
    @@ -1954,7 +1959,16 @@ static int vcn_v3_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;
     
    @@ -1964,14 +1978,15 @@ static int vcn_v3_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;
     		}
     
     		create = ptr + addr + offset - start;
     
    -		/* H246, HEVC and VP9 can run on any instance */
    +		/* H264, HEVC and VP9 can run on any instance */
     		if (create[0] == 0x7 || create[0] == 0x10 || create[0] == 0x11)
     			continue;
     
    -- 
    cgit 1.3-korg
    
    
    
  • drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c+19 5 modified
    diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
    index d9cf8f0feeb3e6..558d3bf7fc76ee 100644
    --- a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
    +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
    @@ -1908,7 +1908,7 @@ static int vcn_v3_0_dec_msg(struct amdgpu_cs_parser *p, struct amdgpu_job *job,
     {
     	struct ttm_operation_ctx ctx = { false, false };
     	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;
    @@ -1929,6 +1929,11 @@ static int vcn_v3_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);
    @@ -1945,8 +1950,8 @@ static int vcn_v3_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;
     	}
    @@ -1954,7 +1959,16 @@ static int vcn_v3_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;
     
    @@ -1964,14 +1978,15 @@ static int vcn_v3_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;
     		}
     
     		create = ptr + addr + offset - start;
     
    -		/* H246, HEVC and VP9 can run on any instance */
    +		/* H264, HEVC and VP9 can run on any instance */
     		if (create[0] == 0x7 || create[0] == 0x10 || create[0] == 0x11)
     			continue;
     
    -- 
    cgit 1.3-korg
    
    
    
638e48ee39d0

drm/amdgpu/vcn3: Prevent OOB reads when parsing dec msg

2 files changed · +38 10
  • drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c+19 5 modified
    diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
    index d9cf8f0feeb3e6..558d3bf7fc76ee 100644
    --- a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
    +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
    @@ -1908,7 +1908,7 @@ static int vcn_v3_0_dec_msg(struct amdgpu_cs_parser *p, struct amdgpu_job *job,
     {
     	struct ttm_operation_ctx ctx = { false, false };
     	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;
    @@ -1929,6 +1929,11 @@ static int vcn_v3_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);
    @@ -1945,8 +1950,8 @@ static int vcn_v3_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;
     	}
    @@ -1954,7 +1959,16 @@ static int vcn_v3_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;
     
    @@ -1964,14 +1978,15 @@ static int vcn_v3_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;
     		}
     
     		create = ptr + addr + offset - start;
     
    -		/* H246, HEVC and VP9 can run on any instance */
    +		/* H264, HEVC and VP9 can run on any instance */
     		if (create[0] == 0x7 || create[0] == 0x10 || create[0] == 0x11)
     			continue;
     
    -- 
    cgit 1.3-korg
    
    
    
  • drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c+19 5 modified
    diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
    index d9cf8f0feeb3e6..558d3bf7fc76ee 100644
    --- a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
    +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
    @@ -1908,7 +1908,7 @@ static int vcn_v3_0_dec_msg(struct amdgpu_cs_parser *p, struct amdgpu_job *job,
     {
     	struct ttm_operation_ctx ctx = { false, false };
     	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;
    @@ -1929,6 +1929,11 @@ static int vcn_v3_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);
    @@ -1945,8 +1950,8 @@ static int vcn_v3_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;
     	}
    @@ -1954,7 +1959,16 @@ static int vcn_v3_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;
     
    @@ -1964,14 +1978,15 @@ static int vcn_v3_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;
     		}
     
     		create = ptr + addr + offset - start;
     
    -		/* H246, HEVC and VP9 can run on any instance */
    +		/* H264, HEVC and VP9 can run on any instance */
     		if (create[0] == 0x7 || create[0] == 0x10 || create[0] == 0x11)
     			continue;
     
    -- 
    cgit 1.3-korg
    
    
    
e382e0b81a3e

drm/amdgpu/vcn3: Prevent OOB reads when parsing dec msg

2 files changed · +38 10
  • drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c+19 5 modified
    diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
    index 02d5c5af65f232..6fb4fcdbba4f14 100644
    --- a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
    +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
    @@ -1909,7 +1909,7 @@ static int vcn_v3_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;
    @@ -1930,6 +1930,11 @@ static int vcn_v3_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);
    @@ -1946,8 +1951,8 @@ static int vcn_v3_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;
     	}
    @@ -1955,7 +1960,16 @@ static int vcn_v3_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;
     
    @@ -1965,14 +1979,15 @@ static int vcn_v3_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;
     		}
     
     		create = ptr + addr + offset - start;
     
    -		/* H246, HEVC and VP9 can run on any instance */
    +		/* H264, HEVC and VP9 can run on any instance */
     		if (create[0] == 0x7 || create[0] == 0x10 || create[0] == 0x11)
     			continue;
     
    -- 
    cgit 1.3-korg
    
    
    
  • drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c+19 5 modified
    diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
    index 02d5c5af65f232..6fb4fcdbba4f14 100644
    --- a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
    +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
    @@ -1909,7 +1909,7 @@ static int vcn_v3_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;
    @@ -1930,6 +1930,11 @@ static int vcn_v3_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);
    @@ -1946,8 +1951,8 @@ static int vcn_v3_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;
     	}
    @@ -1955,7 +1960,16 @@ static int vcn_v3_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;
     
    @@ -1965,14 +1979,15 @@ static int vcn_v3_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;
     		}
     
     		create = ptr + addr + offset - start;
     
    -		/* H246, HEVC and VP9 can run on any instance */
    +		/* H264, HEVC and VP9 can run on any instance */
     		if (create[0] == 0x7 || create[0] == 0x10 || create[0] == 0x11)
     			continue;
     
    -- 
    cgit 1.3-korg
    
    
    
b193019860d6

drm/amdgpu/vcn3: Prevent OOB reads when parsing dec msg

2 files changed · +38 10
  • drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c+19 5 modified
    diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
    index 02d5c5af65f232..6fb4fcdbba4f14 100644
    --- a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
    +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
    @@ -1909,7 +1909,7 @@ static int vcn_v3_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;
    @@ -1930,6 +1930,11 @@ static int vcn_v3_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);
    @@ -1946,8 +1951,8 @@ static int vcn_v3_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;
     	}
    @@ -1955,7 +1960,16 @@ static int vcn_v3_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;
     
    @@ -1965,14 +1979,15 @@ static int vcn_v3_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;
     		}
     
     		create = ptr + addr + offset - start;
     
    -		/* H246, HEVC and VP9 can run on any instance */
    +		/* H264, HEVC and VP9 can run on any instance */
     		if (create[0] == 0x7 || create[0] == 0x10 || create[0] == 0x11)
     			continue;
     
    -- 
    cgit 1.3-korg
    
    
    
  • drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c+19 5 modified
    diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
    index 02d5c5af65f232..6fb4fcdbba4f14 100644
    --- a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
    +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
    @@ -1909,7 +1909,7 @@ static int vcn_v3_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;
    @@ -1930,6 +1930,11 @@ static int vcn_v3_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);
    @@ -1946,8 +1951,8 @@ static int vcn_v3_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;
     	}
    @@ -1955,7 +1960,16 @@ static int vcn_v3_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;
     
    @@ -1965,14 +1979,15 @@ static int vcn_v3_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;
     		}
     
     		create = ptr + addr + offset - start;
     
    -		/* H246, HEVC and VP9 can run on any instance */
    +		/* H264, HEVC and VP9 can run on any instance */
     		if (create[0] == 0x7 || create[0] == 0x10 || create[0] == 0x11)
     			continue;
     
    -- 
    cgit 1.3-korg
    
    
    
870c8738c377

drm/amdgpu/vcn3: Prevent OOB reads when parsing dec msg

2 files changed · +38 10
  • drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c+19 5 modified
    diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
    index 4196bdece253b6..be9151bd2c7208 100644
    --- a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
    +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
    @@ -1843,7 +1843,7 @@ static int vcn_v3_0_dec_msg(struct amdgpu_cs_parser *p, struct amdgpu_job *job,
     {
     	struct ttm_operation_ctx ctx = { false, false };
     	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;
    @@ -1864,6 +1864,11 @@ static int vcn_v3_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);
    @@ -1880,8 +1885,8 @@ static int vcn_v3_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;
     	}
    @@ -1889,7 +1894,16 @@ static int vcn_v3_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;
     
    @@ -1899,14 +1913,15 @@ static int vcn_v3_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;
     		}
     
     		create = ptr + addr + offset - start;
     
    -		/* H246, HEVC and VP9 can run on any instance */
    +		/* H264, HEVC and VP9 can run on any instance */
     		if (create[0] == 0x7 || create[0] == 0x10 || create[0] == 0x11)
     			continue;
     
    -- 
    cgit 1.3-korg
    
    
    
  • drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c+19 5 modified
    diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
    index 4196bdece253b6..be9151bd2c7208 100644
    --- a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
    +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
    @@ -1843,7 +1843,7 @@ static int vcn_v3_0_dec_msg(struct amdgpu_cs_parser *p, struct amdgpu_job *job,
     {
     	struct ttm_operation_ctx ctx = { false, false };
     	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;
    @@ -1864,6 +1864,11 @@ static int vcn_v3_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);
    @@ -1880,8 +1885,8 @@ static int vcn_v3_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;
     	}
    @@ -1889,7 +1894,16 @@ static int vcn_v3_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;
     
    @@ -1899,14 +1913,15 @@ static int vcn_v3_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;
     		}
     
     		create = ptr + addr + offset - start;
     
    -		/* H246, HEVC and VP9 can run on any instance */
    +		/* H264, HEVC and VP9 can run on any instance */
     		if (create[0] == 0x7 || create[0] == 0x10 || create[0] == 0x11)
     			continue;
     
    -- 
    cgit 1.3-korg
    
    
    
638d3e0b9eb7

drm/amdgpu/vcn3: Prevent OOB reads when parsing dec msg

2 files changed · +38 10
  • drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c+19 5 modified
    diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
    index 710328f12194d3..8d1b6a06194fb1 100644
    --- a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
    +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
    @@ -1789,7 +1789,7 @@ static int vcn_v3_0_dec_msg(struct amdgpu_cs_parser *p, struct amdgpu_job *job,
     {
     	struct ttm_operation_ctx ctx = { false, false };
     	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;
    @@ -1810,6 +1810,11 @@ static int vcn_v3_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);
    @@ -1826,8 +1831,8 @@ static int vcn_v3_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;
     	}
    @@ -1835,7 +1840,16 @@ static int vcn_v3_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;
     
    @@ -1845,14 +1859,15 @@ static int vcn_v3_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;
     		}
     
     		create = ptr + addr + offset - start;
     
    -		/* H246, HEVC and VP9 can run on any instance */
    +		/* H264, HEVC and VP9 can run on any instance */
     		if (create[0] == 0x7 || create[0] == 0x10 || create[0] == 0x11)
     			continue;
     
    -- 
    cgit 1.3-korg
    
    
    
  • drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c+19 5 modified
    diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
    index 710328f12194d3..8d1b6a06194fb1 100644
    --- a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
    +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
    @@ -1789,7 +1789,7 @@ static int vcn_v3_0_dec_msg(struct amdgpu_cs_parser *p, struct amdgpu_job *job,
     {
     	struct ttm_operation_ctx ctx = { false, false };
     	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;
    @@ -1810,6 +1810,11 @@ static int vcn_v3_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);
    @@ -1826,8 +1831,8 @@ static int vcn_v3_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;
     	}
    @@ -1835,7 +1840,16 @@ static int vcn_v3_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;
     
    @@ -1845,14 +1859,15 @@ static int vcn_v3_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;
     		}
     
     		create = ptr + addr + offset - start;
     
    -		/* H246, HEVC and VP9 can run on any instance */
    +		/* H264, HEVC and VP9 can run on any instance */
     		if (create[0] == 0x7 || create[0] == 0x10 || create[0] == 0x11)
     			continue;
     
    -- 
    cgit 1.3-korg
    
    
    

Vulnerability mechanics

Root cause

"Missing bounds checks when parsing a VCN decode message from a buffer object allow out-of-bounds reads."

Attack vector

An attacker with the ability to submit a crafted command submission (CS) to the AMDGPU VCN3 hardware decoder can supply a malicious decode message buffer object (BO) whose header fields claim a larger length or more buffers than the BO actually contains [patch_id=2897575]. The kernel driver then reads past the end of the BO when iterating over buffer descriptors and dereferencing `create[0]` for each buffer, resulting in an out-of-bounds read. No special privileges beyond local access to the DRM device are required.

Affected code

The vulnerability resides in the `vcn_v3_0_dec_msg` function within `drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c` [patch_id=2897575]. The function parses a decode message from a buffer object (BO) but lacked sufficient bounds checks before reading fields such as `msg[1]`, `msg[2]`, `msg[3]`, and the per-buffer `create[0]` values.

What the fix does

The patch adds four new bounds checks in `vcn_v3_0_dec_msg` [patch_id=2897575]. First, it verifies the BO has at least 16 bytes (4 DWORDs) before any header reads. Second, it checks that the claimed message length (`msg[1]`) does not exceed the BO's remaining size. Third, it computes `len_dw = msg[1] / 4` and validates that the number of buffers (`msg[2]`) and the required DWORDs (`6 + num_buffers * 4`) fit within `len_dw`. Fourth, in the per-buffer loop it ensures `size >= 4` and that `offset + size` does not exceed the BO's bounds (using `end - addr` instead of the raw `end` pointer). These changes close all out-of-bounds read paths by rejecting malformed messages early.

Preconditions

  • authLocal access to the AMD DRM device to submit command submissions to the VCN3 hardware decoder.
  • inputAbility to craft a buffer object (BO) with a decode message header containing manipulated length or buffer-count fields.

Generated on May 28, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

5

News mentions

0

No linked articles in our index yet.