summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLijo Lazar <lijo.lazar@amd.com>2026-06-22 15:21:59 +0530
committerAlex Deucher <alexander.deucher@amd.com>2026-07-01 11:28:54 -0400
commit294403fde5ba8e972d1bab88ea56be0fa2ff1f3e (patch)
treefe15940202e1a9c0b79db7f93cf6284585e06230
parent6244eae22966350db52faf9c1369d3b2ffc5de4e (diff)
downloadlinux-stable-294403fde5ba8e972d1bab88ea56be0fa2ff1f3e.tar.gz
linux-stable-294403fde5ba8e972d1bab88ea56be0fa2ff1f3e.zip
drm/amdgpu: bounds check VBIOS name extraction
Bound atom_get_vbios_name() by the BIOS size to avoid out-of-bounds reads. Signed-off-by: Lijo Lazar <lijo.lazar@amd.com> Reviewed-by: Hawking Zhang <Hawking.Zhang@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
-rw-r--r--drivers/gpu/drm/amd/amdgpu/atom.c34
1 files changed, 22 insertions, 12 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/atom.c b/drivers/gpu/drm/amd/amdgpu/atom.c
index 23f5cd52f9fc..e0e585f280e2 100644
--- a/drivers/gpu/drm/amd/amdgpu/atom.c
+++ b/drivers/gpu/drm/amd/amdgpu/atom.c
@@ -1358,6 +1358,7 @@ static void atom_index_iio(struct atom_context *ctx, int base)
static void atom_get_vbios_name(struct atom_context *ctx)
{
unsigned char *p_rom;
+ unsigned char *p_end;
unsigned char str_num;
unsigned short off_to_vbios_str;
unsigned char *c_ptr;
@@ -1368,39 +1369,48 @@ static void atom_get_vbios_name(struct atom_context *ctx)
char *back;
p_rom = ctx->bios;
+ p_end = p_rom + ctx->bios_size;
+
+ if (p_rom + OFFSET_TO_GET_ATOMBIOS_STRING_START + 1 >= p_end)
+ goto no_name;
str_num = *(p_rom + OFFSET_TO_GET_ATOMBIOS_NUMBER_OF_STRINGS);
- if (str_num != 0) {
- off_to_vbios_str =
- *(unsigned short *)(p_rom + OFFSET_TO_GET_ATOMBIOS_STRING_START);
+ if (!str_num)
+ goto no_name;
- c_ptr = (unsigned char *)(p_rom + off_to_vbios_str);
- } else {
- /* do not know where to find name */
- memcpy(ctx->name, na, 7);
- ctx->name[7] = 0;
- return;
- }
+ off_to_vbios_str =
+ *(unsigned short *)(p_rom + OFFSET_TO_GET_ATOMBIOS_STRING_START);
+
+ c_ptr = (unsigned char *)(p_rom + off_to_vbios_str);
+ if (c_ptr >= p_end)
+ goto no_name;
/*
* skip the atombios strings, usually 4
* 1st is P/N, 2nd is ASIC, 3rd is PCI type, 4th is Memory type
*/
for (i = 0; i < str_num; i++) {
- while (*c_ptr != 0)
+ while (c_ptr < p_end && *c_ptr != 0)
c_ptr++;
c_ptr++;
}
/* skip the following 2 chars: 0x0D 0x0A */
c_ptr += 2;
+ if (c_ptr >= p_end)
+ goto no_name;
- name_size = strnlen(c_ptr, STRLEN_LONG - 1);
+ name_size = strnlen(c_ptr, min(STRLEN_LONG - 1, (int)(p_end - c_ptr)));
memcpy(ctx->name, c_ptr, name_size);
back = ctx->name + name_size;
while ((*--back) == ' ')
;
*(back + 1) = '\0';
+ return;
+
+no_name:
+ /* do not know where to find name */
+ strscpy(ctx->name, na, sizeof(ctx->name));
}
static void atom_get_vbios_date(struct atom_context *ctx)