]> www.infradead.org Git - users/hch/misc.git/commitdiff
HID: cp2112: Add parameter validation to data length
authorDeepak Sharma <deepak.sharma.472935@gmail.com>
Fri, 26 Sep 2025 14:58:11 +0000 (20:28 +0530)
committerJiri Kosina <jkosina@suse.com>
Tue, 14 Oct 2025 09:46:49 +0000 (11:46 +0200)
Syzkaller reported a stack OOB access in cp2112_write_req caused by lack
of parameter validation for the user input in I2C SMBUS ioctl in cp2112
driver

Add the parameter validation for the data->block[0] to be bounded by
I2C_SMBUS_BLOCK_MAX + the additional compatibility padding

[jkosina@suse.com: fix whitespace damage]
Reported-by: syzbot+7617e19c8a59edfbd879@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=7617e19c8a59edfbd879
Tested-by: syzbot+7617e19c8a59edfbd879@syzkaller.appspotmail.com
Signed-off-by: Deepak Sharma <deepak.sharma.472935@gmail.com>
Signed-off-by: Jiri Kosina <jkosina@suse.com>
drivers/hid/hid-cp2112.c

index 5a95ea3bec9805453712b7b9e3d3fefec2351822..803b883ae8750f39e9748f4f89b37c5971b4cbec 100644 (file)
@@ -689,7 +689,14 @@ static int cp2112_xfer(struct i2c_adapter *adap, u16 addr,
                        count = cp2112_write_read_req(buf, addr, read_length,
                                                      command, NULL, 0);
                } else {
-                       count = cp2112_write_req(buf, addr, command,
+                       /* Copy starts from data->block[1] so the length can
+                        * be at max I2C_SMBUS_CLOCK_MAX + 1
+                        */
+
+                       if (data->block[0] > I2C_SMBUS_BLOCK_MAX + 1)
+                               count = -EINVAL;
+                       else
+                               count = cp2112_write_req(buf, addr, command,
                                                 data->block + 1,
                                                 data->block[0]);
                }
@@ -700,7 +707,14 @@ static int cp2112_xfer(struct i2c_adapter *adap, u16 addr,
                                                      I2C_SMBUS_BLOCK_MAX,
                                                      command, NULL, 0);
                } else {
-                       count = cp2112_write_req(buf, addr, command,
+                       /* data_length here is data->block[0] + 1
+                        * so make sure that the data->block[0] is
+                        * less than or equals I2C_SMBUS_BLOCK_MAX + 1
+                       */
+                       if (data->block[0] > I2C_SMBUS_BLOCK_MAX + 1)
+                               count = -EINVAL;
+                       else
+                               count = cp2112_write_req(buf, addr, command,
                                                 data->block,
                                                 data->block[0] + 1);
                }
@@ -709,7 +723,14 @@ static int cp2112_xfer(struct i2c_adapter *adap, u16 addr,
                size = I2C_SMBUS_BLOCK_DATA;
                read_write = I2C_SMBUS_READ;
 
-               count = cp2112_write_read_req(buf, addr, I2C_SMBUS_BLOCK_MAX,
+               /* data_length is data->block[0] + 1, so
+                * so data->block[0] should be less than or
+                * equal to the I2C_SMBUS_BLOCK_MAX + 1
+               */
+               if (data->block[0] > I2C_SMBUS_BLOCK_MAX + 1)
+                       count = -EINVAL;
+               else
+                       count = cp2112_write_read_req(buf, addr, I2C_SMBUS_BLOCK_MAX,
                                              command, data->block,
                                              data->block[0] + 1);
                break;