[PATCH] media: flexcop-i2c: reject a zero length write message

From: Guo Zihao

Date: Thu Sep 17 2026 - 23:24:51 EST


flexcop_master_xfer() passes msgs[i].len - 1 as the transfer length for
a write, because the byte at buf[0] carries the register address and the
payload starts at buf[1]:

ret = i2c->fc->i2c_request(i2c, FC_WRITE, msgs[i].addr,
msgs[i].buf[0], &msgs[i].buf[1],
msgs[i].len - 1);

msgs[i].len is __u16, so a zero length write wraps the argument around
to 0xffff. flexcop_i2c_request() takes it as a u16 and copies it into
an int, so the loop

while (len != 0) {
bytes_to_transfer = len > 4 ? 4 : len;
...
p += bytes_to_transfer;
len -= bytes_to_transfer;
}

then walks 65535 bytes starting at &msgs[i].buf[1], reading past the end
of the userspace provided message, and issues roughly 16384 transfers to
the bus.

The zero length case cannot be handled inside flexcop_i2c_request(),
because the len == 0 branch there is a different operation: with
no_base_addr set it writes start_addr alone and is reached when the
caller passes buf = &addr, len = 0. A zero length write message means
msgs[i].len == 0 and the caller has nothing to send.

Reject it in flexcop_master_xfer() with -EINVAL instead. The else branch
is the only place that does arithmetic on the message length, so nothing
else in the function needs the same guard.

No Fixes tag. The len - 1 argument comes from the b2c2 driver
refactoring in 2add87a95068 (2005) and predates it in the skystar2
driver that was imported with the initial git history.

Reviewed-by: Liu Chao <liuc63@xxxxxxxxxxxx>
Signed-off-by: Guo Zihao <guozh23@xxxxxxxxxxxx>
---
A zero length write reaches this code from /dev/i2c-N: the i2c core only
rejects it when the adapter sets I2C_AQ_NO_ZERO_LEN_WRITE, and
flexcop-i2c.c does not set it. The same sequence in i2c-core-base.c
guards I2C_AQ_NO_ZERO_LEN_READ for reads.

The read path one line above is not affected: it forwards
msgs[i+1].len without arithmetic, so a zero length read stays zero.

drivers/media/common/b2c2/flexcop-i2c.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/drivers/media/common/b2c2/flexcop-i2c.c b/drivers/media/common/b2c2/flexcop-i2c.c
index 21edf870d..6171f7a2d 100644
--- a/drivers/media/common/b2c2/flexcop-i2c.c
+++ b/drivers/media/common/b2c2/flexcop-i2c.c
@@ -187,10 +187,16 @@ static int flexcop_master_xfer(struct i2c_adapter *i2c_adap,
msgs[i].buf[0], msgs[i+1].buf,
msgs[i+1].len);
i++; /* skip the following message */
- } else /* writing */
+ } else { /* writing */
+ if (msgs[i].len == 0) {
+ deb_i2c("zero-length write message");
+ ret = -EINVAL;
+ break;
+ }
ret = i2c->fc->i2c_request(i2c, FC_WRITE, msgs[i].addr,
msgs[i].buf[0], &msgs[i].buf[1],
msgs[i].len - 1);
+ }
if (ret < 0) {
deb_i2c("i2c master_xfer failed");
break;
--
2.50.1