Re: [PATCH] hwmon: (sg2042-mcu) reject short uptime reads
Guenter Roeck <[email protected]> Sun, 2 Aug 2026 08:00:15 -0700
| Newsgroups | org.kernel.vger.linux-hwmon,org.kernel.vger.linux-kernel,org.kernel.vger.stable |
|---|---|
| Message-ID | <[email protected]> |
On 8/2/26 06:07, Ali Ahmet Memis wrote:
> uptime_show() asks for two bytes and only rejects a negative return:
>
> u8 time_val[2];
>
> ret = i2c_smbus_read_i2c_block_data(mcu->client, REG_UPTIME,
> sizeof(time_val), time_val);
> if (ret < 0)
> return ret;
>
> return sprintf(buf, "%d\n",
> (time_val[0]) | (time_val[1] << 8));
>
> i2c_smbus_read_i2c_block_data() returns the number of bytes the transfer
> actually produced, which the device supplies and which can be shorter
> than the length asked for:
>
> memcpy(values, &data.block[1], data.block[0]);
> return data.block[0];
>
> time_val is not initialised, so a reply of one byte leaves the high half
> of the reported uptime as whatever was on the stack, and a reply of zero
> bytes leaks both halves. Either way the value ends up in sysfs.
>
> Require the full two bytes. The other registers this driver reads go
> through i2c_smbus_read_byte_data(), which returns the byte itself, so
> the existing negative-only checks are right there.
>
I ended up asking AI:
Does i2c_smbus_read_i2c_block_data() in ./drivers/i2c/i2c-core-smbus.c ever return less than the requested number of bytes unless there is an error ?
Here is what it tells me:
No, as long as the requested length is <= I2C_SMBUS_BLOCK_MAX (32 bytes), i2c-core-smbus.c will never return fewer
bytes than requested unless a negative error code is returned.
The only scenario where it returns a positive byte count less than the caller's requested length is if the caller
passes length > 32, because the function clamps the request to I2C_SMBUS_BLOCK_MAX.
### Why this is the case
1. No Count Byte in I2C Block Read (I2C_SMBUS_I2C_BLOCK_DATA):
Unlike an SMBus Block Read (smbus-protocol.rst), where the slave device sends a length/count byte as the first byte of
data transferred, an I2C Block Read does not include a length byte from the target
device. The master reads a fixed number of bytes determined by the caller.
2. In i2c-core-smbus.c:
if (length > I2C_SMBUS_BLOCK_MAX)
length = I2C_SMBUS_BLOCK_MAX;
data.block[0] = length;
status = i2c_smbus_xfer(client->adapter, client->addr, client->flags,
I2C_SMBUS_READ, command,
I2C_SMBUS_I2C_BLOCK_DATA, &data);
if (status < 0)
return status;
memcpy(values, &data.block[1], data.block[0]);
return data.block[0];
Before calling i2c_smbus_xfer(), data.block[0] is initialized to the requested length (clamped to 32). Upon success
(status >= 0), it returns data.block[0].
3. In I2C Emulation (i2c-core-smbus.c):
• The read message is set up for exactly data->block[0] bytes (msg[1].len = data->block[0];).
• Unlike SMBus Block Data, it does not set I2C_M_RECV_LEN.
• When copying the buffer back upon completion (i2c-core-smbus.c), data->block[0] is never modified and remains
exactly equal to the requested length.
4. In Native Adapter Drivers (adapter->algo->smbus_xfer):
• None of the bus drivers in drivers/i2c/busses/ implementing I2C_SMBUS_I2C_BLOCK_DATA (i2c-i801, i2c-viapro,
i2c-amd8111, i2c-ismt, i2c-mlxbf, etc.) modify data->block[0] to a smaller value on success.
• If a target device NAKs before the requested length bytes are read, the controller driver fails the transaction
and returns a negative errno (e.g., -ENXIO, -EIO, or -EPROTO).
Consequently, any successful call such as i2c_smbus_read_i2c_block_data(client, reg, I2C_SMBUS_BLOCK_MAX, buf) will
always return exactly 32 (I2C_SMBUS_BLOCK_MAX) on success.
Please refrain from sending fixes for non-issues.
Thanks,
Guenter