Re: [PATCH 2/4] i2c: cgbc: Add virtual I2C bus support

Thomas Richard <[email protected]> Wed, 5 Aug 2026 10:37:20 +0200
Newsgroups dev.linux.lists.sashiko-reviews,dev.linux.lists.mfd
Message-ID <[email protected]>
On 8/4/26 5:43 PM, [email protected] wrote:
> Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
> 
> Pre-existing issues:
> - [High] Uninitialized stack variable `data` used as a denominator, leading to a potential division by zero panic.
> --
> 
> --- Patch [2]: [PATCH 2/4] i2c: cgbc: Add virtual I2C bus support ---
> commit 68db5c3b940f7f50540127b0266b86e6b3d69b22
> Author: Thomas Richard <[email protected]>
> 
> i2c: cgbc: Add virtual I2C bus support
> 
> Internally the Board Controller has a virtual I2C bus with some virtual
> storage devices on it. Add support for it by defining a i2c_adapter entry.
> This virtual bus has a fixed frequency that cannot be changed.
> 
>> diff --git a/drivers/i2c/busses/i2c-cgbc.c b/drivers/i2c/busses/i2c-cgbc.c
>> index 25a74fa51aa00..c3f1c83b105a8 100644
>> --- a/drivers/i2c/busses/i2c-cgbc.c
>> +++ b/drivers/i2c/busses/i2c-cgbc.c
> 
> [ ... ]
> 
>> @@ -147,11 +148,14 @@ static int cgbc_i2c_set_frequency(struct i2c_adapter *adap,
>>  	cmd[0] = CGBC_I2C_CMD_SPEED | algo_data->bus_id;
>>  	cmd[1] = cgbc_i2c_freq_to_reg(bus_frequency);
>>  
>> -	ret = cgbc_command(cgbc, &cmd, sizeof(cmd), &data, 1, NULL);
>> -	if (ret)
>> -		return dev_err_probe(i2c->dev, ret,
>> -				     "Failed to initialize I2C bus %s",
>> -				     adap->name);
>> +	/* Virtual bus has a fixed frequency */
>> +	if (algo_data->bus_id != CGBC_I2C_VIRTUAL_BUS_ID) {
>> +		ret = cgbc_command(cgbc, &cmd, sizeof(cmd), &data, 1, NULL);
>> +		if (ret)
>> +			return dev_err_probe(i2c->dev, ret,
>> +					     "Failed to initialize I2C bus %s",
>> +					     adap->name);
>> +	}
>>  
>>  	cmd[1] = 0x00;
> 
> [Severity: High]
> This is a pre-existing issue, but I noticed a potential problem in how
> cgbc_i2c_set_frequency() handles the data variable.
> 
> Could this lead to a division by zero panic? The data variable is allocated on
> the stack uninitialized:
> 
> drivers/i2c/busses/i2c-cgbc.c:cgbc_i2c_set_frequency() {
>     ...
>     u8 cmd[2], data;
>     ...
> }
> 
> When passed to cgbc_command(), if the board controller firmware returns a
> successful status but provides a zero byte count, cgbc_command() skips reading
> into data and returns 0:
> 
> drivers/mfd/cgbc-core.c:cgbc_command() {
>     ...
>     case CGBC_STATUS_DATA_READY:
>         if (istatus > data_size)
>             istatus = data_size;
>         for (i = 0; i < istatus; i++) {
>             _data[i] = ioread8(cgbc->io_cmd + CGBC_CMD_DATA + ((i + 1) % 4));
>     ...
> }
> 
> If istatus is 0, the loop is skipped and data remains untouched.
> 
> When execution continues in cgbc_i2c_set_frequency(), this uninitialized
> value is converted to a frequency:
> 
> drivers/i2c/busses/i2c-cgbc.c:cgbc_i2c_set_frequency() {
>     ...
>     ret = cgbc_command(cgbc, &cmd, sizeof(cmd), &data, 1, NULL);
>     if (ret)
>         return dev_err_probe(...);
> 
>     bus_frequency = cgbc_i2c_reg_to_freq(data);
>     ...
>     algo_data->read_maxtime_us = (BITS_PER_BYTE + 1) * CGBC_I2C_READ_MAX_LEN
>         * USEC_PER_SEC / bus_frequency;
>     ...
> }
> 
> If the uninitialized stack memory evaluates to 0, or if the hardware
> explicitly returns a frequency of 0, would this result in a division by zero
> during the read_maxtime_us calculation?

The answer is still no. If CGBC_I2C_CMD_SPEED succeeds (and we check
cgbc_command's return code), it returns exactly 1 byte. We provided a
data buffer with size 1 to cgbc_command, so there is no way for
uninitialized stack memory to be read if the command succeeded.

To prevent buffer overflow, cgbc_command verifies that the buffer is
large enough to hold all received data.

Best Regards,
Thomas