Re: [PATCH] drm/radeon: Bound GPIO I2C table entry count from VBIOS
From: Alex Deucher
Date: Wed Nov 11 2026 - 12:42:04 EST
Reviewed and applied. Thanks!
On Tue, Nov 10, 2026 at 3:41 AM Andrey Misiurov
<amisiurov@xxxxxxxxxxxxxx> wrote:
>
> radeon_atombios_i2c_init() derives the number of GPIO I2C entries from
> the size field of the VBIOS GPIO_I2C_Info table and stores a bus for
> every valid entry in rdev->i2c_bus[i], which has RADEON_MAX_I2C_BUS
> (16) slots. A table that claims more than 16 entries makes it write
> past the end of the array into the rest of struct radeon_device. A
> size smaller than the common header wraps the subtraction and the loop
> walks far past the table. radeon_lookup_i2c_gpio() uses the same
> calculation.
>
> Reject undersized tables and cap the entry count at
> RADEON_MAX_I2C_BUS.
>
> Fixes: f376b94fbc0a ("drm/radeon/kms: unify i2c handling")
> Cc: stable@xxxxxxxxxxxxxxx
> Signed-off-by: Andrey Misiurov <amisiurov@xxxxxxxxxxxxxx>
> ---
> Found by code inspection. Not reproduced at runtime; it needs a VBIOS
> with a malformed GPIO_I2C_Info table.
>
> drivers/gpu/drm/radeon/radeon_atombios.c | 22 ++++++++++++++++++----
> 1 file changed, 18 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c
> index 3dd9724..c4e1272 100644
> --- a/drivers/gpu/drm/radeon/radeon_atombios.c
> +++ b/drivers/gpu/drm/radeon/radeon_atombios.c
> @@ -125,6 +125,22 @@ static struct radeon_i2c_bus_rec radeon_get_bus_rec_for_i2c_gpio(ATOM_GPIO_I2C_A
> return i2c;
> }
>
> +/*
> + * The VBIOS table size is not checked against the image; cap the
> + * entry count to RADEON_MAX_I2C_BUS, the size of rdev->i2c_bus[].
> + */
> +static int radeon_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 min_t(u32, bytes / sizeof(ATOM_GPIO_I2C_ASSIGMENT),
> + RADEON_MAX_I2C_BUS);
> +}
> +
> static struct radeon_i2c_bus_rec radeon_lookup_i2c_gpio(struct radeon_device *rdev,
> uint8_t id)
> {
> @@ -142,8 +158,7 @@ static struct radeon_i2c_bus_rec radeon_lookup_i2c_gpio(struct radeon_device *rd
> if (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 = radeon_atombios_gpio_i2c_num_entries(size);
>
> gpio = &i2c_info->asGPIO_Info[0];
> for (i = 0; i < num_indices; i++) {
> @@ -176,8 +191,7 @@ void radeon_atombios_i2c_init(struct radeon_device *rdev)
> if (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 = radeon_atombios_gpio_i2c_num_entries(size);
>
> gpio = &i2c_info->asGPIO_Info[0];
> for (i = 0; i < num_indices; i++) {
> --
> 2.43.7
>