mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-08-23 18:56:40 -04:00
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>
This commit is contained in:
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user