Bound atom_get_vbios_name() by the BIOS size to avoid out-of-bounds reads.
Signed-off-by: Lijo Lazar <[email protected]>
---
drivers/gpu/drm/amd/amdgpu/atom.c | 34 ++++++++++++++++++++-----------
1 file changed, 22 insertions(+), 12 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/atom.c
b/drivers/gpu/drm/amd/amdgpu/atom.c
index d4a652d2b453..ebb4ac279393 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)
--
2.49.0