]> git.hungrycats.org Git - linux/commitdiff
drm/amdgpu: bounds check VBIOS name extraction
authorLijo Lazar <lijo.lazar@amd.com>
Mon, 22 Jun 2026 09:51:59 +0000 (15:21 +0530)
committerAlex Deucher <alexander.deucher@amd.com>
Wed, 1 Jul 2026 15:28:54 +0000 (11:28 -0400)
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>
drivers/gpu/drm/amd/amdgpu/atom.c

index 23f5cd52f9fcb8b3dbbb262e7f71c47dd272c853..e0e585f280e21841cf05ff7e5d83a54e3d2f4557 100644 (file)
@@ -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)