[PATCH 08/11] drm/amdgpu/vce: Check maximum ucode size in amdgpu_vce_resume()

Timur Kristóf
2026-04-23T01:16:31Z

Verify that the ucode fits the part of the BO that is
specifically meant for it to avoid overflowing it.

Signed-off-by: Timur Kristóf <timur.kristof@gmail.com>
---
drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c | 5 ++++-
drivers/gpu/drm/amd/amdgpu/amdgpu_vce.h | 2 +-
drivers/gpu/drm/amd/amdgpu/vce_v2_0.c | 4 ++--
drivers/gpu/drm/amd/amdgpu/vce_v3_0.c | 4 ++--
drivers/gpu/drm/amd/amdgpu/vce_v4_0.c | 4 ++--
5 files changed, 11 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c
index efdebd9c0a1f3..8c620254f0374 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c
@@ -324,7 +324,7 @@ int amdgpu_vce_suspend(struct amdgpu_device *adev)
* @adev: amdgpu_device pointer
*
*/
-int amdgpu_vce_resume(struct amdgpu_device *adev)
+int amdgpu_vce_resume(struct amdgpu_device *adev, const unsigned long max_size)
{
const struct common_firmware_header *hdr;
unsigned int offset;
@@ -336,6 +336,9 @@ int amdgpu_vce_resume(struct amdgpu_device *adev)
hdr = (const struct common_firmware_header *)adev->vce.fw->data;
offset = le32_to_cpu(hdr->ucode_array_offset_bytes);

+ if (adev->vce.fw->size - offset > max_size)
+ return -EINVAL;
+
if (drm_dev_enter(adev_to_drm(adev), &idx)) {
memset_io(adev->vce.cpu_addr, 0, amdgpu_bo_size(adev->vce.vcpu_bo));
memcpy_toio(adev->vce.cpu_addr, adev->vce.fw->data + offset,
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.h
index 778c714c8385d..a57e2f6f5f930 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.h
@@ -60,7 +60,7 @@ int amdgpu_vce_sw_init(struct amdgpu_device *adev, unsigned long size);
int amdgpu_vce_sw_fini(struct amdgpu_device *adev);
int amdgpu_vce_entity_init(struct amdgpu_device *adev, struct amdgpu_ring *ring);
int amdgpu_vce_suspend(struct amdgpu_device *adev);
-int amdgpu_vce_resume(struct amdgpu_device *adev);
+int amdgpu_vce_resume(struct amdgpu_device *adev, const unsigned long max_size);
void amdgpu_vce_free_handles(struct amdgpu_device *adev, struct drm_file *filp);
int amdgpu_vce_ring_parse_cs(struct amdgpu_cs_parser *p, struct amdgpu_job *job,
struct amdgpu_ib *ib);
diff --git a/drivers/gpu/drm/amd/amdgpu/vce_v2_0.c b/drivers/gpu/drm/amd/amdgpu/vce_v2_0.c
index db149eda62044..00b4037d4bc89 100644
--- a/drivers/gpu/drm/amd/amdgpu/vce_v2_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/vce_v2_0.c
@@ -437,7 +437,7 @@ static int vce_v2_0_sw_init(struct amdgpu_ip_block *ip_block)
if (r)
return r;

- r = amdgpu_vce_resume(adev);
+ r = amdgpu_vce_resume(adev, VCE_V2_0_FW_SIZE);
if (r)
return r;

@@ -533,7 +533,7 @@ static int vce_v2_0_resume(struct amdgpu_ip_block *ip_block)
{
int r;

- r = amdgpu_vce_resume(ip_block->adev);
+ r = amdgpu_vce_resume(ip_block->adev, VCE_V2_0_FW_SIZE);
if (r)
return r;

diff --git a/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c b/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c
index 03d79e464f04f..2e97376ff30e5 100644
--- a/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c
@@ -440,7 +440,7 @@ static int vce_v3_0_sw_init(struct amdgpu_ip_block *ip_block)
if (adev->vce.fw_version < FW_52_8_3)
adev->vce.num_rings = 2;

- r = amdgpu_vce_resume(adev);
+ r = amdgpu_vce_resume(adev, VCE_V3_0_FW_SIZE);
if (r)
return r;

@@ -544,7 +544,7 @@ static int vce_v3_0_resume(struct amdgpu_ip_block *ip_block)
{
int r;

- r = amdgpu_vce_resume(ip_block->adev);
+ r = amdgpu_vce_resume(ip_block->adev, VCE_V3_0_FW_SIZE);
if (r)
return r;

diff --git a/drivers/gpu/drm/amd/amdgpu/vce_v4_0.c b/drivers/gpu/drm/amd/amdgpu/vce_v4_0.c
index ee445d8abe474..3309e7b8f2a2e 100644
--- a/drivers/gpu/drm/amd/amdgpu/vce_v4_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/vce_v4_0.c
@@ -462,7 +462,7 @@ static int vce_v4_0_sw_init(struct amdgpu_ip_block *ip_block)
ALIGN(le32_to_cpu(hdr->ucode_size_bytes), PAGE_SIZE);
drm_info(adev_to_drm(adev), "PSP loading VCE firmware\n");
} else {
- r = amdgpu_vce_resume(adev);
+ r = amdgpu_vce_resume(adev, VCE_V4_0_FW_SIZE);
if (r)
return r;
}
@@ -624,7 +624,7 @@ static int vce_v4_0_resume(struct amdgpu_ip_block *ip_block)
drm_dev_exit(idx);
}
} else {
- r = amdgpu_vce_resume(adev);
+ r = amdgpu_vce_resume(adev, VCE_V4_0_FW_SIZE);
if (r)
return r;
}
--
2.53.0