CVE-2026-93287: i2c: smbus: reject oversized block transfers in the common path
In the Linux kernel, the following vulnerability has been resolved:
i2c: smbus: reject oversized block transfers in the common path
The SMBus block transfer length data->block[0] is validated in i2csmbusxferemulated() but that check runs too late for tracepoints and is skipped entirely when the adapter provides a native smbusxfer implementation. This allows user-controlled oversized block lengths to reach tracepoint memcpy calls and driver callbacks unchecked.
Add an early validation in i2csmbusxfer() that rejects block transfers whose caller-supplied length is zero or exceeds I2CSMBUSBLOCKMAX before any tracepoint fires or driver callback runs. data->block[0] is filled in by the device on SMBus block reads, so the check is scoped to operations where the length is actually supplied by the caller. This is consistent with the existing -EINVAL convention in the emulated path and protects all downstream consumers at once: the smbuswrite tracepoint, all native smbusxfer driver implementations, and the emulated path.
Two distinct bugs are fixed by this change:
Bug 1: smbuswrite tracepoint OOB (include/trace/events/smbus.h) tracesmbuswrite() fires before any validation and copies data->block[0]+1 bytes into a 34-byte event buffer. With block[0]=0xfe the tracepoint copies 255 bytes, overflowing by 221.
BUG: KASAN: stack-out-of-bounds in traceeventraweventsmbuswrite+0x27c/0x530 Read of size 255 at addr ffff88800d98fcf8 by task pocsmbus/91 Call Trace: <TASK> asanmemcpy+0x23/0x80 traceeventraweventsmbuswrite+0x27c/0x530 i2csmbusxfer+0x43a/0xa40 i2csmbusxfer+0x19e/0x340 i2cdevioctlsmbus+0x38f/0x7f0 i2cdevioctl+0x35e/0x680 x64sysioctl+0x147/0x1e0 dosyscall64+0xcf/0x15a0 entrySYSCALL64afterhwframe+0x76/0x7e </TASK>
Bug 2: i2c-stub I2CSMBUSI2CBLOCKDATA OOB (drivers/i2c/i2c-stub.c) stubxfer() implements .smbusxfer directly and only clamps block[0] against 256-command, not I2CSMBUSBLOCKMAX. With block[0]=0xff and command=0 the loop accesses block[1+i] for i up to 254, far past the 34-byte union.
UBSAN: array-index-out-of-bounds in drivers/i2c/i2c-stub.c:223:44 index 34 is out of range for type 'u8 [34]' Call Trace: <TASK> ubsanhandleoutofbounds+0xd7/0x120 stubxfer+0x1971/0x198f [i2cstub] i2csmbusxfer+0x306/0xa40 i2csmbusxfer+0x19e/0x340 i2cdevioctlsmbus+0x38f/0x7f0 i2cdevioctl+0x35e/0x680 x64sysioctl+0x147/0x1e0 dosyscall64+0xcf/0x15a0 entrySYSCALL64afterhwframe+0x76/0x7e </TASK>
Both traces reproduced on v7.0-rc6+i2c/for-current with KASAN+UBSAN.
Affected Software
Remediation
Recommended actions to resolve this vulnerability, in priority order.
- Compensating control
Add early validation in __i2c_smbus_xfer() for caller-supplied SMBus block-transfer lengths, rejecting transfers whose length is zero or exceeds I2C_SMBUS_BLOCK_MAX with -EINVAL before any tracepoint fires or driver callback runs; apply this in the common path to protect both native and emulated implementations.
Event History
Frequently Asked Questions
Who is exposed to this issue?
Systems running affected Linux kernel code are exposed when SMBus block-transfer operations accept caller-supplied block lengths. The affected downstream paths include the SMBus write tracepoint, native smbus_xfer adapter-driver implementations, and the emulated SMBus path.
What does an attacker need to trigger the vulnerable behavior?
An attacker needs a way to issue an SMBus block transfer with a caller-controlled length of zero or greater than I2C_SMBUS_BLOCK_MAX. The vulnerable paths allow that unvalidated length to reach tracepoint memcpy operations or adapter driver callbacks.
Are SMBus block reads covered by the new validation?
The validation is scoped to operations where the caller supplies the block length. For SMBus block reads, data->block[0] is filled in by the device, so those operations are not the target of this check.
How can I tell whether a system has the fix?
The fix adds validation in __i2c_smbus_xfer() before tracepoints fire or driver callbacks run, rejecting caller-supplied block lengths of zero or above I2C_SMBUS_BLOCK_MAX with -EINVAL. Check whether the deployed kernel includes one of the referenced stable commits or equivalent code.