Reject undersized tables and cap the derived entry count
to AMDGPU_MAX_I2C_BUS so we do not overrun adev->i2c_bus[]
or walk an absurd number of entries on corrupt size fields.

Signed-off-by: Candice Li <[email protected]>
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c | 24 +++++++++++++++-----
 1 file changed, 18 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c
index 956eb33008f85d..ca65e6ebdb25e6 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c
@@ -36,6 +36,21 @@
 #include "atombios_encoders.h"
 #include "bif/bif_4_1_d.h"
 
+/* VBIOS-reported table size is unchecked against the image; cap iterations and
+ * adev->i2c_bus[] indexing to AMDGPU_MAX_I2C_BUS.
+ */
+static int amdgpu_atombios_gpio_i2c_num_entries(uint16_t size)
+{
+       u32 bytes;
+
+       if (size < sizeof(ATOM_COMMON_TABLE_HEADER))
+               return 0;
+
+       bytes = size - sizeof(ATOM_COMMON_TABLE_HEADER);
+       return (int)min_t(u32, bytes / sizeof(ATOM_GPIO_I2C_ASSIGMENT),
+                         AMDGPU_MAX_I2C_BUS);
+}
+
 static struct amdgpu_i2c_bus_rec 
amdgpu_atombios_get_bus_rec_for_i2c_gpio(ATOM_GPIO_I2C_ASSIGMENT *gpio)
 {
        struct amdgpu_i2c_bus_rec i2c;
@@ -96,8 +111,7 @@ struct amdgpu_i2c_bus_rec 
amdgpu_atombios_lookup_i2c_gpio(struct amdgpu_device *
        if (amdgpu_atom_parse_data_header(ctx, index, &size, NULL, NULL, 
&data_offset)) {
                i2c_info = (struct _ATOM_GPIO_I2C_INFO *)(ctx->bios + 
data_offset);
 
-               num_indices = (size - sizeof(ATOM_COMMON_TABLE_HEADER)) /
-                       sizeof(ATOM_GPIO_I2C_ASSIGMENT);
+               num_indices = amdgpu_atombios_gpio_i2c_num_entries(size);
 
                gpio = &i2c_info->asGPIO_Info[0];
                for (i = 0; i < num_indices; i++) {
@@ -127,8 +141,7 @@ void amdgpu_atombios_i2c_init(struct amdgpu_device *adev)
        if (amdgpu_atom_parse_data_header(ctx, index, &size, NULL, NULL, 
&data_offset)) {
                i2c_info = (struct _ATOM_GPIO_I2C_INFO *)(ctx->bios + 
data_offset);
 
-               num_indices = (size - sizeof(ATOM_COMMON_TABLE_HEADER)) /
-                       sizeof(ATOM_GPIO_I2C_ASSIGMENT);
+               num_indices = amdgpu_atombios_gpio_i2c_num_entries(size);
 
                gpio = &i2c_info->asGPIO_Info[0];
                for (i = 0; i < num_indices; i++) {
@@ -158,8 +171,7 @@ void amdgpu_atombios_oem_i2c_init(struct amdgpu_device 
*adev, u8 i2c_id)
        if (amdgpu_atom_parse_data_header(ctx, index, &size, NULL, NULL, 
&data_offset)) {
                i2c_info = (struct _ATOM_GPIO_I2C_INFO *)(ctx->bios + 
data_offset);
 
-               num_indices = (size - sizeof(ATOM_COMMON_TABLE_HEADER)) /
-                       sizeof(ATOM_GPIO_I2C_ASSIGMENT);
+               num_indices = amdgpu_atombios_gpio_i2c_num_entries(size);
 
                gpio = &i2c_info->asGPIO_Info[0];
                for (i = 0; i < num_indices; i++) {
-- 
2.25.1

Reply via email to