AMD General Applied. Thanks!
Alex ________________________________ From: Hari Mishal <[email protected]> Sent: Tuesday, September 15, 2026 9:15 AM To: Deucher, Alexander <[email protected]>; Koenig, Christian <[email protected]> Cc: [email protected] <[email protected]>; [email protected] <[email protected]>; Lazar, Lijo <[email protected]>; [email protected] <[email protected]>; [email protected] <[email protected]>; [email protected] <[email protected]>; [email protected] <[email protected]>; [email protected] <[email protected]>; Hari Mishal <[email protected]> Subject: [PATCH] drm/amdgpu/atom: bound the VBIOS date, part number, version and build getters atom_get_vbios_date(), atom_get_vbios_pn(), atom_get_vbios_version() and atom_get_vbios_build() all walk the BIOS image using offsets and counts taken from the image itself, checked only against each other and never against ctx->bios_size: - atom_get_vbios_date() reads 14 bytes at a fixed offset that check_atom_bios()'s minimum size (0x49) does not cover. - atom_get_vbios_pn() dereferences an image-supplied u16 string offset unchecked, then walks and copies from it with only a length cap, not an image cap. - atom_get_vbios_version() takes its search bounds from image u16s; atom_find_str_in_rom() already clamps the search itself, but the match is then advanced by a fixed 18 bytes and STRLEN_NORMAL bytes are copied from there with no check that this still lands inside the image. - atom_get_vbios_build() walks from an image-supplied config-string offset toward the ROM header; a config offset at or past the header makes the pointer difference negative, wrapping through the u16 'len' and passing strscpy() a bound far larger than the 32-byte destination. Bound each getter's reads, walks and copies to ctx->bios_size, falling back to an empty string on a malformed image. Fixes: 29b4c589b43d ("drm/amdgpu: Add vbios info ioctl interface") Fixes: d6fa80266178 ("drm/amdgpu: Add vbios build number interface") Assisted-by: gkh_clanker_t1000 Signed-off-by: Hari Mishal <[email protected]> --- drivers/gpu/drm/amd/amdgpu/atom.c | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/atom.c b/drivers/gpu/drm/amd/amdgpu/atom.c index e74253682929..fe9af26ccc11 100644 --- a/drivers/gpu/drm/amd/amdgpu/atom.c +++ b/drivers/gpu/drm/amd/amdgpu/atom.c @@ -1445,6 +1445,11 @@ static void atom_get_vbios_date(struct atom_context *ctx) p_rom = ctx->bios; + if (ctx->bios_size < OFFSET_TO_VBIOS_DATE + 14) { + ctx->date[0] = '\0'; + return; + } + date_in_rom = p_rom + OFFSET_TO_VBIOS_DATE; ctx->date[0] = '2'; @@ -1513,17 +1518,24 @@ static void atom_get_vbios_pn(struct atom_context *ctx) vbios_str = p_rom + OFFSET_TO_VBIOS_PART_NUMBER; } - if (*vbios_str == 0) { + if (vbios_str >= p_rom + ctx->bios_size) + vbios_str = NULL; + + if (vbios_str == NULL || *vbios_str == 0) { vbios_str = atom_find_str_in_rom(ctx, BIOS_ATOM_PREFIX, 3, 1024, 64); if (vbios_str) vbios_str += sizeof(BIOS_ATOM_PREFIX) - 1; + if (vbios_str >= p_rom + ctx->bios_size) + vbios_str = NULL; } if (vbios_str != NULL && *vbios_str == 0) vbios_str++; if (vbios_str != NULL) { count = 0; - while ((count < BIOS_STRING_LENGTH) && vbios_str[count] >= ' ' && + while ((count < BIOS_STRING_LENGTH) && + vbios_str + count < p_rom + ctx->bios_size && + vbios_str[count] >= ' ' && vbios_str[count] <= 'z') { ctx->vbios_pn[count] = vbios_str[count]; count++; @@ -1556,9 +1568,10 @@ static void atom_get_vbios_version(struct atom_context *ctx) /* find anchor ATOMBIOSBK-AMD */ vbios_ver = atom_find_str_in_rom(ctx, BIOS_VERSION_PREFIX, start, end, 64); - if (vbios_ver != NULL) { - /* skip ATOMBIOSBK-AMD VER */ - vbios_ver += 18; + if (vbios_ver != NULL) + vbios_ver += 18; /* skip ATOMBIOSBK-AMD VER */ + + if (vbios_ver != NULL && vbios_ver + STRLEN_NORMAL <= p_rom + ctx->bios_size) { memcpy(ctx->vbios_ver_str, vbios_ver, STRLEN_NORMAL); } else { ctx->vbios_ver_str[0] = '\0'; @@ -1574,7 +1587,13 @@ static void atom_get_vbios_build(struct atom_context *ctx) base = CU16(ATOM_ROM_TABLE_PTR); atom_rom_hdr = CSTR(base); + if ((uint32_t)base + ATOM_ROM_CFG_PTR + sizeof(uint16_t) > ctx->bios_size) + return; + str = CSTR(CU16(base + ATOM_ROM_CFG_PTR)); + if (str >= atom_rom_hdr) + return; + /* Skip config string */ while (str < atom_rom_hdr && *str++) ; -- 2.43.0
