drm/amdgpu/vcn: fix integer overflow in dec_msg buffer count check

If the supplied msg[2] (num_buffers) is 0x3FFFFFFF, the expression
6 + num_buffers * 4 wraps to 2 and the bounds check passes, letting
the parser loop far past the end of the message BO. Triggering it
additionally requires a ~4GiB mapping so that msg[1] survives the
earlier "header does not fit in BO" check.

Rewrite the test in division form, which is overflow-free by
construction. Also update the message to reflect that msg is invalid.

Fixes: b193019860 ("drm/amdgpu/vcn3: Prevent OOB reads when parsing dec msg")
Fixes: 0a78f2bac1 ("drm/amdgpu/vcn4: Prevent OOB reads when parsing dec msg")
Cc: stable@vger.kernel.org
Signed-off-by: David (Ming Qiang) Wu <David.Wu3@amd.com>
Reviewed-by: Leo Liu <leo.liu@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
David (Ming Qiang) Wu 2026-08-07 15:12:14 -04:00 committed by Alex Deucher
parent 275c333258
commit 4d73905308
2 changed files with 14 additions and 6 deletions

View File

@ -1964,9 +1964,13 @@ static int vcn_v3_0_dec_msg(struct amdgpu_cs_parser *p, struct amdgpu_job *job,
len_dw = msg[1] / 4;
num_buffers = msg[2];
/* Verify that all indices fit within the claimed length. Each index is 4 DWORDs */
if (num_buffers > len_dw || 6 + num_buffers * 4 > len_dw) {
DRM_ERROR("VCN message has too many buffers!\n");
/* Verify that all indices fit within the claimed length.
* There are 6 dwords in the header before the first buffer.
* Each buffer has 4 dwords. Any trailing dwords after the
* last buffer are ignored.
*/
if (len_dw < 6 || num_buffers > (len_dw - 6) / 4) {
DRM_ERROR("Invalid VCN message!\n");
r = -EINVAL;
goto out;
}

View File

@ -1880,9 +1880,13 @@ static int vcn_v4_0_dec_msg(struct amdgpu_cs_parser *p, struct amdgpu_job *job,
len_dw = msg[1] / 4;
num_buffers = msg[2];
/* Verify that all indices fit within the claimed length. Each index is 4 DWORDs */
if (num_buffers > len_dw || 6 + num_buffers * 4 > len_dw) {
DRM_ERROR("VCN message has too many buffers!\n");
/* Verify that all indices fit within the claimed length.
* There are 6 dwords in the header before the first buffer.
* Each buffer has 4 dwords. Any trailing dwords after the
* last buffer are ignored.
*/
if (len_dw < 6 || num_buffers > (len_dw - 6) / 4) {
DRM_ERROR("Invalid VCN message!\n");
r = -EINVAL;
goto out;
}