VYPR
Unrated severityNVD Advisory· Published May 28, 2026

CVE-2026-46204

CVE-2026-46204

Description

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

drm/amdgpu/vcn4: Prevent OOB reads when parsing IB

Rewrite the IB parsing to use amdgpu_ib_get_value() which handles the bounds checks.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

A Linux kernel amdgpu VCN4 driver vulnerability allows out-of-bounds reads when parsing indirect buffers, fixed by using a bounds-checked accessor.

Vulnerability

The vulnerability resides in the indirect buffer (IB) parsing code of the drm/amdgpu/vcn4 driver in the Linux kernel. The original implementation did not validate indices when reading values from the IB, enabling out-of-bounds reads. The issue affects kernel versions prior to the inclusion of commit d0802a8877d7.

Exploitation

An attacker with the ability to submit crafted GPU commands to the VCN4 hardware—typically requiring local access or the capability to interact with the amdgpu driver—can trigger the out-of-bounds read by supplying a malicious IB with invalid indices.

Impact

Successful exploitation can lead to information disclosure (reading kernel memory beyond the IB buffer) or a system crash (denial of service). The attacker does not gain code execution directly from this read, but the leaked memory may contain sensitive data.

Mitigation

The fix is implemented in kernel commit d0802a8877d7, which rewrites the IB parsing to use amdgpu_ib_get_value() with proper bounds checks. Users should update to a kernel version containing this commit. No workaround is documented in the available references [1].

AI Insight generated on May 28, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected products

1

Patches

10
d0802a8877d7

drm/amdgpu/vcn4: Prevent OOB reads when parsing IB

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitBenjamin ChengMar 24, 2026Fixed in 6.12.90via kernel-cna
1 file changed · +12 12
  • drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c+12 12 modified
    diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
    index ae510fd9d29442..12da44342faf43 100644
    --- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
    +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
    @@ -1854,9 +1854,10 @@ out:
     static int vcn_v4_0_enc_find_ib_param(struct amdgpu_ib *ib, uint32_t id, int start)
     {
     	int i;
    +	uint32_t len;
     
    -	for (i = start; i < ib->length_dw && ib->ptr[i] >= 8; i += ib->ptr[i] / 4) {
    -		if (ib->ptr[i + 1] == id)
    +	for (i = start; (len = amdgpu_ib_get_value(ib, i)) >= 8; i += len / 4) {
    +		if (amdgpu_ib_get_value(ib, i + 1) == id)
     			return i;
     	}
     	return -1;
    @@ -1867,8 +1868,6 @@ static int vcn_v4_0_ring_patch_cs_in_place(struct amdgpu_cs_parser *p,
     					   struct amdgpu_ib *ib)
     {
     	struct amdgpu_ring *ring = amdgpu_job_ring(job);
    -	struct amdgpu_vcn_decode_buffer *decode_buffer;
    -	uint64_t addr;
     	uint32_t val;
     	int idx = 0, sidx;
     
    @@ -1879,20 +1878,22 @@ static int vcn_v4_0_ring_patch_cs_in_place(struct amdgpu_cs_parser *p,
     	while ((idx = vcn_v4_0_enc_find_ib_param(ib, RADEON_VCN_ENGINE_INFO, idx)) >= 0) {
     		val = amdgpu_ib_get_value(ib, idx + 2); /* RADEON_VCN_ENGINE_TYPE */
     		if (val == RADEON_VCN_ENGINE_TYPE_DECODE) {
    -			decode_buffer = (struct amdgpu_vcn_decode_buffer *)&ib->ptr[idx + 6];
    +			uint32_t valid_buf_flag = amdgpu_ib_get_value(ib, idx + 6);
    +			uint64_t msg_buffer_addr;
     
    -			if (!(decode_buffer->valid_buf_flag & 0x1))
    +			if (!(valid_buf_flag & 0x1))
     				return 0;
     
    -			addr = ((u64)decode_buffer->msg_buffer_address_hi) << 32 |
    -				decode_buffer->msg_buffer_address_lo;
    -			return vcn_v4_0_dec_msg(p, job, addr);
    +			msg_buffer_addr = ((u64)amdgpu_ib_get_value(ib, idx + 7)) << 32 |
    +				amdgpu_ib_get_value(ib, idx + 8);
    +			return vcn_v4_0_dec_msg(p, job, msg_buffer_addr);
     		} else if (val == RADEON_VCN_ENGINE_TYPE_ENCODE) {
     			sidx = vcn_v4_0_enc_find_ib_param(ib, RENCODE_IB_PARAM_SESSION_INIT, idx);
    -			if (sidx >= 0 && ib->ptr[sidx + 2] == RENCODE_ENCODE_STANDARD_AV1)
    +			if (sidx >= 0 &&
    +			    amdgpu_ib_get_value(ib, sidx + 2) == RENCODE_ENCODE_STANDARD_AV1)
     				return vcn_v4_0_limit_sched(p, job);
     		}
    -		idx += ib->ptr[idx] / 4;
    +		idx += amdgpu_ib_get_value(ib, idx) / 4;
     	}
     	return 0;
     }
    -- 
    cgit 1.3-korg
    
    
    
a6d5563ba1f0

drm/amdgpu/vcn4: Prevent OOB reads when parsing IB

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitBenjamin ChengMar 24, 2026Fixed in 6.18.32via kernel-cna
1 file changed · +12 12
  • drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c+12 12 modified
    diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
    index 3ae666522d570f..85a2c42ea691d9 100644
    --- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
    +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
    @@ -1912,9 +1912,10 @@ out:
     static int vcn_v4_0_enc_find_ib_param(struct amdgpu_ib *ib, uint32_t id, int start)
     {
     	int i;
    +	uint32_t len;
     
    -	for (i = start; i < ib->length_dw && ib->ptr[i] >= 8; i += ib->ptr[i] / 4) {
    -		if (ib->ptr[i + 1] == id)
    +	for (i = start; (len = amdgpu_ib_get_value(ib, i)) >= 8; i += len / 4) {
    +		if (amdgpu_ib_get_value(ib, i + 1) == id)
     			return i;
     	}
     	return -1;
    @@ -1925,8 +1926,6 @@ static int vcn_v4_0_ring_patch_cs_in_place(struct amdgpu_cs_parser *p,
     					   struct amdgpu_ib *ib)
     {
     	struct amdgpu_ring *ring = amdgpu_job_ring(job);
    -	struct amdgpu_vcn_decode_buffer *decode_buffer;
    -	uint64_t addr;
     	uint32_t val;
     	int idx = 0, sidx;
     
    @@ -1937,20 +1936,22 @@ static int vcn_v4_0_ring_patch_cs_in_place(struct amdgpu_cs_parser *p,
     	while ((idx = vcn_v4_0_enc_find_ib_param(ib, RADEON_VCN_ENGINE_INFO, idx)) >= 0) {
     		val = amdgpu_ib_get_value(ib, idx + 2); /* RADEON_VCN_ENGINE_TYPE */
     		if (val == RADEON_VCN_ENGINE_TYPE_DECODE) {
    -			decode_buffer = (struct amdgpu_vcn_decode_buffer *)&ib->ptr[idx + 6];
    +			uint32_t valid_buf_flag = amdgpu_ib_get_value(ib, idx + 6);
    +			uint64_t msg_buffer_addr;
     
    -			if (!(decode_buffer->valid_buf_flag & 0x1))
    +			if (!(valid_buf_flag & 0x1))
     				return 0;
     
    -			addr = ((u64)decode_buffer->msg_buffer_address_hi) << 32 |
    -				decode_buffer->msg_buffer_address_lo;
    -			return vcn_v4_0_dec_msg(p, job, addr);
    +			msg_buffer_addr = ((u64)amdgpu_ib_get_value(ib, idx + 7)) << 32 |
    +				amdgpu_ib_get_value(ib, idx + 8);
    +			return vcn_v4_0_dec_msg(p, job, msg_buffer_addr);
     		} else if (val == RADEON_VCN_ENGINE_TYPE_ENCODE) {
     			sidx = vcn_v4_0_enc_find_ib_param(ib, RENCODE_IB_PARAM_SESSION_INIT, idx);
    -			if (sidx >= 0 && ib->ptr[sidx + 2] == RENCODE_ENCODE_STANDARD_AV1)
    +			if (sidx >= 0 &&
    +			    amdgpu_ib_get_value(ib, sidx + 2) == RENCODE_ENCODE_STANDARD_AV1)
     				return vcn_v4_0_limit_sched(p, job);
     		}
    -		idx += ib->ptr[idx] / 4;
    +		idx += amdgpu_ib_get_value(ib, idx) / 4;
     	}
     	return 0;
     }
    -- 
    cgit 1.3-korg
    
    
    
5c3e8ebad0c9

drm/amdgpu/vcn4: Prevent OOB reads when parsing IB

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitBenjamin ChengMar 24, 2026Fixed in 7.0.9via kernel-cna
1 file changed · +12 12
  • drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c+12 12 modified
    diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
    index d17219be50f393..311b2479508abd 100644
    --- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
    +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
    @@ -1913,9 +1913,10 @@ out:
     static int vcn_v4_0_enc_find_ib_param(struct amdgpu_ib *ib, uint32_t id, int start)
     {
     	int i;
    +	uint32_t len;
     
    -	for (i = start; i < ib->length_dw && ib->ptr[i] >= 8; i += ib->ptr[i] / 4) {
    -		if (ib->ptr[i + 1] == id)
    +	for (i = start; (len = amdgpu_ib_get_value(ib, i)) >= 8; i += len / 4) {
    +		if (amdgpu_ib_get_value(ib, i + 1) == id)
     			return i;
     	}
     	return -1;
    @@ -1926,8 +1927,6 @@ static int vcn_v4_0_ring_patch_cs_in_place(struct amdgpu_cs_parser *p,
     					   struct amdgpu_ib *ib)
     {
     	struct amdgpu_ring *ring = amdgpu_job_ring(job);
    -	struct amdgpu_vcn_decode_buffer *decode_buffer;
    -	uint64_t addr;
     	uint32_t val;
     	int idx = 0, sidx;
     
    @@ -1938,20 +1937,22 @@ static int vcn_v4_0_ring_patch_cs_in_place(struct amdgpu_cs_parser *p,
     	while ((idx = vcn_v4_0_enc_find_ib_param(ib, RADEON_VCN_ENGINE_INFO, idx)) >= 0) {
     		val = amdgpu_ib_get_value(ib, idx + 2); /* RADEON_VCN_ENGINE_TYPE */
     		if (val == RADEON_VCN_ENGINE_TYPE_DECODE) {
    -			decode_buffer = (struct amdgpu_vcn_decode_buffer *)&ib->ptr[idx + 6];
    +			uint32_t valid_buf_flag = amdgpu_ib_get_value(ib, idx + 6);
    +			uint64_t msg_buffer_addr;
     
    -			if (!(decode_buffer->valid_buf_flag & 0x1))
    +			if (!(valid_buf_flag & 0x1))
     				return 0;
     
    -			addr = ((u64)decode_buffer->msg_buffer_address_hi) << 32 |
    -				decode_buffer->msg_buffer_address_lo;
    -			return vcn_v4_0_dec_msg(p, job, addr);
    +			msg_buffer_addr = ((u64)amdgpu_ib_get_value(ib, idx + 7)) << 32 |
    +				amdgpu_ib_get_value(ib, idx + 8);
    +			return vcn_v4_0_dec_msg(p, job, msg_buffer_addr);
     		} else if (val == RADEON_VCN_ENGINE_TYPE_ENCODE) {
     			sidx = vcn_v4_0_enc_find_ib_param(ib, RENCODE_IB_PARAM_SESSION_INIT, idx);
    -			if (sidx >= 0 && ib->ptr[sidx + 2] == RENCODE_ENCODE_STANDARD_AV1)
    +			if (sidx >= 0 &&
    +			    amdgpu_ib_get_value(ib, sidx + 2) == RENCODE_ENCODE_STANDARD_AV1)
     				return vcn_v4_0_limit_sched(p, job);
     		}
    -		idx += ib->ptr[idx] / 4;
    +		idx += amdgpu_ib_get_value(ib, idx) / 4;
     	}
     	return 0;
     }
    -- 
    cgit 1.3-korg
    
    
    
2444eb0ec828

drm/amdgpu/vcn4: Prevent OOB reads when parsing IB

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitBenjamin ChengMar 24, 2026Fixed in 7.1-rc1via kernel-cna
1 file changed · +12 12
  • drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c+12 12 modified
    diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
    index 1a1cdc14841a7c..5dec92691f73ee 100644
    --- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
    +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
    @@ -1928,9 +1928,10 @@ out:
     static int vcn_v4_0_enc_find_ib_param(struct amdgpu_ib *ib, uint32_t id, int start)
     {
     	int i;
    +	uint32_t len;
     
    -	for (i = start; i < ib->length_dw && ib->ptr[i] >= 8; i += ib->ptr[i] / 4) {
    -		if (ib->ptr[i + 1] == id)
    +	for (i = start; (len = amdgpu_ib_get_value(ib, i)) >= 8; i += len / 4) {
    +		if (amdgpu_ib_get_value(ib, i + 1) == id)
     			return i;
     	}
     	return -1;
    @@ -1941,8 +1942,6 @@ static int vcn_v4_0_ring_patch_cs_in_place(struct amdgpu_cs_parser *p,
     					   struct amdgpu_ib *ib)
     {
     	struct amdgpu_ring *ring = amdgpu_job_ring(job);
    -	struct amdgpu_vcn_decode_buffer *decode_buffer;
    -	uint64_t addr;
     	uint32_t val;
     	int idx = 0, sidx;
     
    @@ -1953,20 +1952,22 @@ static int vcn_v4_0_ring_patch_cs_in_place(struct amdgpu_cs_parser *p,
     	while ((idx = vcn_v4_0_enc_find_ib_param(ib, RADEON_VCN_ENGINE_INFO, idx)) >= 0) {
     		val = amdgpu_ib_get_value(ib, idx + 2); /* RADEON_VCN_ENGINE_TYPE */
     		if (val == RADEON_VCN_ENGINE_TYPE_DECODE) {
    -			decode_buffer = (struct amdgpu_vcn_decode_buffer *)&ib->ptr[idx + 6];
    +			uint32_t valid_buf_flag = amdgpu_ib_get_value(ib, idx + 6);
    +			uint64_t msg_buffer_addr;
     
    -			if (!(decode_buffer->valid_buf_flag & 0x1))
    +			if (!(valid_buf_flag & 0x1))
     				return 0;
     
    -			addr = ((u64)decode_buffer->msg_buffer_address_hi) << 32 |
    -				decode_buffer->msg_buffer_address_lo;
    -			return vcn_v4_0_dec_msg(p, job, addr);
    +			msg_buffer_addr = ((u64)amdgpu_ib_get_value(ib, idx + 7)) << 32 |
    +				amdgpu_ib_get_value(ib, idx + 8);
    +			return vcn_v4_0_dec_msg(p, job, msg_buffer_addr);
     		} else if (val == RADEON_VCN_ENGINE_TYPE_ENCODE) {
     			sidx = vcn_v4_0_enc_find_ib_param(ib, RENCODE_IB_PARAM_SESSION_INIT, idx);
    -			if (sidx >= 0 && ib->ptr[sidx + 2] == RENCODE_ENCODE_STANDARD_AV1)
    +			if (sidx >= 0 &&
    +			    amdgpu_ib_get_value(ib, sidx + 2) == RENCODE_ENCODE_STANDARD_AV1)
     				return vcn_v4_0_limit_sched(p, job);
     		}
    -		idx += ib->ptr[idx] / 4;
    +		idx += amdgpu_ib_get_value(ib, idx) / 4;
     	}
     	return 0;
     }
    -- 
    cgit 1.3-korg
    
    
    
1dc005775fb5

drm/amdgpu/vcn4: Prevent OOB reads when parsing IB

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitBenjamin ChengMar 24, 2026Fixed in 6.6.140via kernel-cna
1 file changed · +12 12
  • drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c+12 12 modified
    diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
    index 43249e9f66d74d..2a6c0fa682d794 100644
    --- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
    +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
    @@ -1755,9 +1755,10 @@ out:
     static int vcn_v4_0_enc_find_ib_param(struct amdgpu_ib *ib, uint32_t id, int start)
     {
     	int i;
    +	uint32_t len;
     
    -	for (i = start; i < ib->length_dw && ib->ptr[i] >= 8; i += ib->ptr[i] / 4) {
    -		if (ib->ptr[i + 1] == id)
    +	for (i = start; (len = amdgpu_ib_get_value(ib, i)) >= 8; i += len / 4) {
    +		if (amdgpu_ib_get_value(ib, i + 1) == id)
     			return i;
     	}
     	return -1;
    @@ -1768,8 +1769,6 @@ static int vcn_v4_0_ring_patch_cs_in_place(struct amdgpu_cs_parser *p,
     					   struct amdgpu_ib *ib)
     {
     	struct amdgpu_ring *ring = amdgpu_job_ring(job);
    -	struct amdgpu_vcn_decode_buffer *decode_buffer;
    -	uint64_t addr;
     	uint32_t val;
     	int idx = 0, sidx;
     
    @@ -1780,20 +1779,22 @@ static int vcn_v4_0_ring_patch_cs_in_place(struct amdgpu_cs_parser *p,
     	while ((idx = vcn_v4_0_enc_find_ib_param(ib, RADEON_VCN_ENGINE_INFO, idx)) >= 0) {
     		val = amdgpu_ib_get_value(ib, idx + 2); /* RADEON_VCN_ENGINE_TYPE */
     		if (val == RADEON_VCN_ENGINE_TYPE_DECODE) {
    -			decode_buffer = (struct amdgpu_vcn_decode_buffer *)&ib->ptr[idx + 6];
    +			uint32_t valid_buf_flag = amdgpu_ib_get_value(ib, idx + 6);
    +			uint64_t msg_buffer_addr;
     
    -			if (!(decode_buffer->valid_buf_flag & 0x1))
    +			if (!(valid_buf_flag & 0x1))
     				return 0;
     
    -			addr = ((u64)decode_buffer->msg_buffer_address_hi) << 32 |
    -				decode_buffer->msg_buffer_address_lo;
    -			return vcn_v4_0_dec_msg(p, job, addr);
    +			msg_buffer_addr = ((u64)amdgpu_ib_get_value(ib, idx + 7)) << 32 |
    +				amdgpu_ib_get_value(ib, idx + 8);
    +			return vcn_v4_0_dec_msg(p, job, msg_buffer_addr);
     		} else if (val == RADEON_VCN_ENGINE_TYPE_ENCODE) {
     			sidx = vcn_v4_0_enc_find_ib_param(ib, RENCODE_IB_PARAM_SESSION_INIT, idx);
    -			if (sidx >= 0 && ib->ptr[sidx + 2] == RENCODE_ENCODE_STANDARD_AV1)
    +			if (sidx >= 0 &&
    +			    amdgpu_ib_get_value(ib, sidx + 2) == RENCODE_ENCODE_STANDARD_AV1)
     				return vcn_v4_0_limit_sched(p, job);
     		}
    -		idx += ib->ptr[idx] / 4;
    +		idx += amdgpu_ib_get_value(ib, idx) / 4;
     	}
     	return 0;
     }
    -- 
    cgit 1.3-korg
    
    
    
2444eb0ec828

drm/amdgpu/vcn4: Prevent OOB reads when parsing IB

1 file changed · +12 12
  • drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c+12 12 modified
    diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
    index 1a1cdc14841a7c..5dec92691f73ee 100644
    --- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
    +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
    @@ -1928,9 +1928,10 @@ out:
     static int vcn_v4_0_enc_find_ib_param(struct amdgpu_ib *ib, uint32_t id, int start)
     {
     	int i;
    +	uint32_t len;
     
    -	for (i = start; i < ib->length_dw && ib->ptr[i] >= 8; i += ib->ptr[i] / 4) {
    -		if (ib->ptr[i + 1] == id)
    +	for (i = start; (len = amdgpu_ib_get_value(ib, i)) >= 8; i += len / 4) {
    +		if (amdgpu_ib_get_value(ib, i + 1) == id)
     			return i;
     	}
     	return -1;
    @@ -1941,8 +1942,6 @@ static int vcn_v4_0_ring_patch_cs_in_place(struct amdgpu_cs_parser *p,
     					   struct amdgpu_ib *ib)
     {
     	struct amdgpu_ring *ring = amdgpu_job_ring(job);
    -	struct amdgpu_vcn_decode_buffer *decode_buffer;
    -	uint64_t addr;
     	uint32_t val;
     	int idx = 0, sidx;
     
    @@ -1953,20 +1952,22 @@ static int vcn_v4_0_ring_patch_cs_in_place(struct amdgpu_cs_parser *p,
     	while ((idx = vcn_v4_0_enc_find_ib_param(ib, RADEON_VCN_ENGINE_INFO, idx)) >= 0) {
     		val = amdgpu_ib_get_value(ib, idx + 2); /* RADEON_VCN_ENGINE_TYPE */
     		if (val == RADEON_VCN_ENGINE_TYPE_DECODE) {
    -			decode_buffer = (struct amdgpu_vcn_decode_buffer *)&ib->ptr[idx + 6];
    +			uint32_t valid_buf_flag = amdgpu_ib_get_value(ib, idx + 6);
    +			uint64_t msg_buffer_addr;
     
    -			if (!(decode_buffer->valid_buf_flag & 0x1))
    +			if (!(valid_buf_flag & 0x1))
     				return 0;
     
    -			addr = ((u64)decode_buffer->msg_buffer_address_hi) << 32 |
    -				decode_buffer->msg_buffer_address_lo;
    -			return vcn_v4_0_dec_msg(p, job, addr);
    +			msg_buffer_addr = ((u64)amdgpu_ib_get_value(ib, idx + 7)) << 32 |
    +				amdgpu_ib_get_value(ib, idx + 8);
    +			return vcn_v4_0_dec_msg(p, job, msg_buffer_addr);
     		} else if (val == RADEON_VCN_ENGINE_TYPE_ENCODE) {
     			sidx = vcn_v4_0_enc_find_ib_param(ib, RENCODE_IB_PARAM_SESSION_INIT, idx);
    -			if (sidx >= 0 && ib->ptr[sidx + 2] == RENCODE_ENCODE_STANDARD_AV1)
    +			if (sidx >= 0 &&
    +			    amdgpu_ib_get_value(ib, sidx + 2) == RENCODE_ENCODE_STANDARD_AV1)
     				return vcn_v4_0_limit_sched(p, job);
     		}
    -		idx += ib->ptr[idx] / 4;
    +		idx += amdgpu_ib_get_value(ib, idx) / 4;
     	}
     	return 0;
     }
    -- 
    cgit 1.3-korg
    
    
    
a6d5563ba1f0

drm/amdgpu/vcn4: Prevent OOB reads when parsing IB

1 file changed · +12 12
  • drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c+12 12 modified
    diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
    index 3ae666522d570f..85a2c42ea691d9 100644
    --- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
    +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
    @@ -1912,9 +1912,10 @@ out:
     static int vcn_v4_0_enc_find_ib_param(struct amdgpu_ib *ib, uint32_t id, int start)
     {
     	int i;
    +	uint32_t len;
     
    -	for (i = start; i < ib->length_dw && ib->ptr[i] >= 8; i += ib->ptr[i] / 4) {
    -		if (ib->ptr[i + 1] == id)
    +	for (i = start; (len = amdgpu_ib_get_value(ib, i)) >= 8; i += len / 4) {
    +		if (amdgpu_ib_get_value(ib, i + 1) == id)
     			return i;
     	}
     	return -1;
    @@ -1925,8 +1926,6 @@ static int vcn_v4_0_ring_patch_cs_in_place(struct amdgpu_cs_parser *p,
     					   struct amdgpu_ib *ib)
     {
     	struct amdgpu_ring *ring = amdgpu_job_ring(job);
    -	struct amdgpu_vcn_decode_buffer *decode_buffer;
    -	uint64_t addr;
     	uint32_t val;
     	int idx = 0, sidx;
     
    @@ -1937,20 +1936,22 @@ static int vcn_v4_0_ring_patch_cs_in_place(struct amdgpu_cs_parser *p,
     	while ((idx = vcn_v4_0_enc_find_ib_param(ib, RADEON_VCN_ENGINE_INFO, idx)) >= 0) {
     		val = amdgpu_ib_get_value(ib, idx + 2); /* RADEON_VCN_ENGINE_TYPE */
     		if (val == RADEON_VCN_ENGINE_TYPE_DECODE) {
    -			decode_buffer = (struct amdgpu_vcn_decode_buffer *)&ib->ptr[idx + 6];
    +			uint32_t valid_buf_flag = amdgpu_ib_get_value(ib, idx + 6);
    +			uint64_t msg_buffer_addr;
     
    -			if (!(decode_buffer->valid_buf_flag & 0x1))
    +			if (!(valid_buf_flag & 0x1))
     				return 0;
     
    -			addr = ((u64)decode_buffer->msg_buffer_address_hi) << 32 |
    -				decode_buffer->msg_buffer_address_lo;
    -			return vcn_v4_0_dec_msg(p, job, addr);
    +			msg_buffer_addr = ((u64)amdgpu_ib_get_value(ib, idx + 7)) << 32 |
    +				amdgpu_ib_get_value(ib, idx + 8);
    +			return vcn_v4_0_dec_msg(p, job, msg_buffer_addr);
     		} else if (val == RADEON_VCN_ENGINE_TYPE_ENCODE) {
     			sidx = vcn_v4_0_enc_find_ib_param(ib, RENCODE_IB_PARAM_SESSION_INIT, idx);
    -			if (sidx >= 0 && ib->ptr[sidx + 2] == RENCODE_ENCODE_STANDARD_AV1)
    +			if (sidx >= 0 &&
    +			    amdgpu_ib_get_value(ib, sidx + 2) == RENCODE_ENCODE_STANDARD_AV1)
     				return vcn_v4_0_limit_sched(p, job);
     		}
    -		idx += ib->ptr[idx] / 4;
    +		idx += amdgpu_ib_get_value(ib, idx) / 4;
     	}
     	return 0;
     }
    -- 
    cgit 1.3-korg
    
    
    
1dc005775fb5

drm/amdgpu/vcn4: Prevent OOB reads when parsing IB

1 file changed · +12 12
  • drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c+12 12 modified
    diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
    index 43249e9f66d74d..2a6c0fa682d794 100644
    --- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
    +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
    @@ -1755,9 +1755,10 @@ out:
     static int vcn_v4_0_enc_find_ib_param(struct amdgpu_ib *ib, uint32_t id, int start)
     {
     	int i;
    +	uint32_t len;
     
    -	for (i = start; i < ib->length_dw && ib->ptr[i] >= 8; i += ib->ptr[i] / 4) {
    -		if (ib->ptr[i + 1] == id)
    +	for (i = start; (len = amdgpu_ib_get_value(ib, i)) >= 8; i += len / 4) {
    +		if (amdgpu_ib_get_value(ib, i + 1) == id)
     			return i;
     	}
     	return -1;
    @@ -1768,8 +1769,6 @@ static int vcn_v4_0_ring_patch_cs_in_place(struct amdgpu_cs_parser *p,
     					   struct amdgpu_ib *ib)
     {
     	struct amdgpu_ring *ring = amdgpu_job_ring(job);
    -	struct amdgpu_vcn_decode_buffer *decode_buffer;
    -	uint64_t addr;
     	uint32_t val;
     	int idx = 0, sidx;
     
    @@ -1780,20 +1779,22 @@ static int vcn_v4_0_ring_patch_cs_in_place(struct amdgpu_cs_parser *p,
     	while ((idx = vcn_v4_0_enc_find_ib_param(ib, RADEON_VCN_ENGINE_INFO, idx)) >= 0) {
     		val = amdgpu_ib_get_value(ib, idx + 2); /* RADEON_VCN_ENGINE_TYPE */
     		if (val == RADEON_VCN_ENGINE_TYPE_DECODE) {
    -			decode_buffer = (struct amdgpu_vcn_decode_buffer *)&ib->ptr[idx + 6];
    +			uint32_t valid_buf_flag = amdgpu_ib_get_value(ib, idx + 6);
    +			uint64_t msg_buffer_addr;
     
    -			if (!(decode_buffer->valid_buf_flag & 0x1))
    +			if (!(valid_buf_flag & 0x1))
     				return 0;
     
    -			addr = ((u64)decode_buffer->msg_buffer_address_hi) << 32 |
    -				decode_buffer->msg_buffer_address_lo;
    -			return vcn_v4_0_dec_msg(p, job, addr);
    +			msg_buffer_addr = ((u64)amdgpu_ib_get_value(ib, idx + 7)) << 32 |
    +				amdgpu_ib_get_value(ib, idx + 8);
    +			return vcn_v4_0_dec_msg(p, job, msg_buffer_addr);
     		} else if (val == RADEON_VCN_ENGINE_TYPE_ENCODE) {
     			sidx = vcn_v4_0_enc_find_ib_param(ib, RENCODE_IB_PARAM_SESSION_INIT, idx);
    -			if (sidx >= 0 && ib->ptr[sidx + 2] == RENCODE_ENCODE_STANDARD_AV1)
    +			if (sidx >= 0 &&
    +			    amdgpu_ib_get_value(ib, sidx + 2) == RENCODE_ENCODE_STANDARD_AV1)
     				return vcn_v4_0_limit_sched(p, job);
     		}
    -		idx += ib->ptr[idx] / 4;
    +		idx += amdgpu_ib_get_value(ib, idx) / 4;
     	}
     	return 0;
     }
    -- 
    cgit 1.3-korg
    
    
    
d0802a8877d7

drm/amdgpu/vcn4: Prevent OOB reads when parsing IB

1 file changed · +12 12
  • drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c+12 12 modified
    diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
    index ae510fd9d29442..12da44342faf43 100644
    --- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
    +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
    @@ -1854,9 +1854,10 @@ out:
     static int vcn_v4_0_enc_find_ib_param(struct amdgpu_ib *ib, uint32_t id, int start)
     {
     	int i;
    +	uint32_t len;
     
    -	for (i = start; i < ib->length_dw && ib->ptr[i] >= 8; i += ib->ptr[i] / 4) {
    -		if (ib->ptr[i + 1] == id)
    +	for (i = start; (len = amdgpu_ib_get_value(ib, i)) >= 8; i += len / 4) {
    +		if (amdgpu_ib_get_value(ib, i + 1) == id)
     			return i;
     	}
     	return -1;
    @@ -1867,8 +1868,6 @@ static int vcn_v4_0_ring_patch_cs_in_place(struct amdgpu_cs_parser *p,
     					   struct amdgpu_ib *ib)
     {
     	struct amdgpu_ring *ring = amdgpu_job_ring(job);
    -	struct amdgpu_vcn_decode_buffer *decode_buffer;
    -	uint64_t addr;
     	uint32_t val;
     	int idx = 0, sidx;
     
    @@ -1879,20 +1878,22 @@ static int vcn_v4_0_ring_patch_cs_in_place(struct amdgpu_cs_parser *p,
     	while ((idx = vcn_v4_0_enc_find_ib_param(ib, RADEON_VCN_ENGINE_INFO, idx)) >= 0) {
     		val = amdgpu_ib_get_value(ib, idx + 2); /* RADEON_VCN_ENGINE_TYPE */
     		if (val == RADEON_VCN_ENGINE_TYPE_DECODE) {
    -			decode_buffer = (struct amdgpu_vcn_decode_buffer *)&ib->ptr[idx + 6];
    +			uint32_t valid_buf_flag = amdgpu_ib_get_value(ib, idx + 6);
    +			uint64_t msg_buffer_addr;
     
    -			if (!(decode_buffer->valid_buf_flag & 0x1))
    +			if (!(valid_buf_flag & 0x1))
     				return 0;
     
    -			addr = ((u64)decode_buffer->msg_buffer_address_hi) << 32 |
    -				decode_buffer->msg_buffer_address_lo;
    -			return vcn_v4_0_dec_msg(p, job, addr);
    +			msg_buffer_addr = ((u64)amdgpu_ib_get_value(ib, idx + 7)) << 32 |
    +				amdgpu_ib_get_value(ib, idx + 8);
    +			return vcn_v4_0_dec_msg(p, job, msg_buffer_addr);
     		} else if (val == RADEON_VCN_ENGINE_TYPE_ENCODE) {
     			sidx = vcn_v4_0_enc_find_ib_param(ib, RENCODE_IB_PARAM_SESSION_INIT, idx);
    -			if (sidx >= 0 && ib->ptr[sidx + 2] == RENCODE_ENCODE_STANDARD_AV1)
    +			if (sidx >= 0 &&
    +			    amdgpu_ib_get_value(ib, sidx + 2) == RENCODE_ENCODE_STANDARD_AV1)
     				return vcn_v4_0_limit_sched(p, job);
     		}
    -		idx += ib->ptr[idx] / 4;
    +		idx += amdgpu_ib_get_value(ib, idx) / 4;
     	}
     	return 0;
     }
    -- 
    cgit 1.3-korg
    
    
    
5c3e8ebad0c9

drm/amdgpu/vcn4: Prevent OOB reads when parsing IB

1 file changed · +12 12
  • drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c+12 12 modified
    diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
    index d17219be50f393..311b2479508abd 100644
    --- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
    +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
    @@ -1913,9 +1913,10 @@ out:
     static int vcn_v4_0_enc_find_ib_param(struct amdgpu_ib *ib, uint32_t id, int start)
     {
     	int i;
    +	uint32_t len;
     
    -	for (i = start; i < ib->length_dw && ib->ptr[i] >= 8; i += ib->ptr[i] / 4) {
    -		if (ib->ptr[i + 1] == id)
    +	for (i = start; (len = amdgpu_ib_get_value(ib, i)) >= 8; i += len / 4) {
    +		if (amdgpu_ib_get_value(ib, i + 1) == id)
     			return i;
     	}
     	return -1;
    @@ -1926,8 +1927,6 @@ static int vcn_v4_0_ring_patch_cs_in_place(struct amdgpu_cs_parser *p,
     					   struct amdgpu_ib *ib)
     {
     	struct amdgpu_ring *ring = amdgpu_job_ring(job);
    -	struct amdgpu_vcn_decode_buffer *decode_buffer;
    -	uint64_t addr;
     	uint32_t val;
     	int idx = 0, sidx;
     
    @@ -1938,20 +1937,22 @@ static int vcn_v4_0_ring_patch_cs_in_place(struct amdgpu_cs_parser *p,
     	while ((idx = vcn_v4_0_enc_find_ib_param(ib, RADEON_VCN_ENGINE_INFO, idx)) >= 0) {
     		val = amdgpu_ib_get_value(ib, idx + 2); /* RADEON_VCN_ENGINE_TYPE */
     		if (val == RADEON_VCN_ENGINE_TYPE_DECODE) {
    -			decode_buffer = (struct amdgpu_vcn_decode_buffer *)&ib->ptr[idx + 6];
    +			uint32_t valid_buf_flag = amdgpu_ib_get_value(ib, idx + 6);
    +			uint64_t msg_buffer_addr;
     
    -			if (!(decode_buffer->valid_buf_flag & 0x1))
    +			if (!(valid_buf_flag & 0x1))
     				return 0;
     
    -			addr = ((u64)decode_buffer->msg_buffer_address_hi) << 32 |
    -				decode_buffer->msg_buffer_address_lo;
    -			return vcn_v4_0_dec_msg(p, job, addr);
    +			msg_buffer_addr = ((u64)amdgpu_ib_get_value(ib, idx + 7)) << 32 |
    +				amdgpu_ib_get_value(ib, idx + 8);
    +			return vcn_v4_0_dec_msg(p, job, msg_buffer_addr);
     		} else if (val == RADEON_VCN_ENGINE_TYPE_ENCODE) {
     			sidx = vcn_v4_0_enc_find_ib_param(ib, RENCODE_IB_PARAM_SESSION_INIT, idx);
    -			if (sidx >= 0 && ib->ptr[sidx + 2] == RENCODE_ENCODE_STANDARD_AV1)
    +			if (sidx >= 0 &&
    +			    amdgpu_ib_get_value(ib, sidx + 2) == RENCODE_ENCODE_STANDARD_AV1)
     				return vcn_v4_0_limit_sched(p, job);
     		}
    -		idx += ib->ptr[idx] / 4;
    +		idx += amdgpu_ib_get_value(ib, idx) / 4;
     	}
     	return 0;
     }
    -- 
    cgit 1.3-korg
    
    
    

Vulnerability mechanics

Root cause

"Missing bounds checks when directly indexing ib->ptr[] allows out-of-bounds reads during VCN4 IB parsing."

Attack vector

An attacker submits a crafted command buffer (IB) to the VCN4 hardware via the amdgpu DRM driver. The functions vcn_v4_0_enc_find_ib_param() and vcn_v4_0_ring_patch_cs_in_place() in drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c previously read ib->ptr[i], ib->ptr[i+1], ib->ptr[sidx+2], etc. without verifying that those indices fall within ib->length_dw. By supplying an IB with a short length or a manipulated length field, the attacker can cause the loop to advance past the buffer boundary, resulting in an out-of-bounds read [patch_id=2897785].

Affected code

The vulnerable functions are vcn_v4_0_enc_find_ib_param() and vcn_v4_0_ring_patch_cs_in_place() in drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c [patch_id=2897785]. The former iterates over IB entries using direct ib->ptr[] indexing without bounds checking beyond the initial length_dw comparison. The latter casts a pointer to struct amdgpu_vcn_decode_buffer at ib->ptr[idx+6] and reads its fields, again without verifying that idx+6, idx+7, or idx+8 are within bounds.

What the fix does

The patch replaces all direct ib->ptr[] accesses with calls to amdgpu_ib_get_value(), which performs internal bounds checking before returning a value [patch_id=2897785]. In vcn_v4_0_enc_find_ib_param(), the loop condition now uses amdgpu_ib_get_value(ib, i) to fetch the length and amdgpu_ib_get_value(ib, i+1) to compare the ID. In vcn_v4_0_ring_patch_cs_in_place(), the decode-buffer struct cast is removed; instead individual fields are read via amdgpu_ib_get_value() at offsets idx+6, idx+7, and idx+8. The encode-path check and the loop-advance step are similarly converted. These changes close the OOB read by ensuring every index is validated against the IB's actual length.

Preconditions

  • authThe attacker must be able to submit a command buffer (IB) to the VCN4 hardware through the amdgpu DRM device, which typically requires local access to the system or the ability to run unprivileged code that can open /dev/dri/renderD* and submit DRM_IOCTL_AMDGPU_CS.
  • configThe system must have an AMD GPU with VCN4 (Video Core Next 4) hardware and the amdgpu kernel driver loaded.
  • inputThe attacker crafts an IB with a manipulated length field or a short buffer such that the loop index advances past the allocated IB memory.

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.