diff options
| -rw-r--r-- | drivers/i2c/i2c-dev.c | 30 |
1 files changed, 26 insertions, 4 deletions
diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c index 45048323b75e..5ec2261574ec 100644 --- a/drivers/i2c/i2c-dev.c +++ b/drivers/i2c/i2c-dev.c | |||
| @@ -265,19 +265,41 @@ static noinline int i2cdev_ioctl_rdrw(struct i2c_client *client, | |||
| 265 | 265 | ||
| 266 | res = 0; | 266 | res = 0; |
| 267 | for (i = 0; i < rdwr_arg.nmsgs; i++) { | 267 | for (i = 0; i < rdwr_arg.nmsgs; i++) { |
| 268 | /* Limit the size of the message to a sane amount; | 268 | /* Limit the size of the message to a sane amount */ |
| 269 | * and don't let length change either. */ | 269 | if (rdwr_pa[i].len > 8192) { |
| 270 | if ((rdwr_pa[i].len > 8192) || | ||
| 271 | (rdwr_pa[i].flags & I2C_M_RECV_LEN)) { | ||
| 272 | res = -EINVAL; | 270 | res = -EINVAL; |
| 273 | break; | 271 | break; |
| 274 | } | 272 | } |
| 273 | |||
| 275 | data_ptrs[i] = (u8 __user *)rdwr_pa[i].buf; | 274 | data_ptrs[i] = (u8 __user *)rdwr_pa[i].buf; |
| 276 | rdwr_pa[i].buf = memdup_user(data_ptrs[i], rdwr_pa[i].len); | 275 | rdwr_pa[i].buf = memdup_user(data_ptrs[i], rdwr_pa[i].len); |
| 277 | if (IS_ERR(rdwr_pa[i].buf)) { | 276 | if (IS_ERR(rdwr_pa[i].buf)) { |
| 278 | res = PTR_ERR(rdwr_pa[i].buf); | 277 | res = PTR_ERR(rdwr_pa[i].buf); |
| 279 | break; | 278 | break; |
| 280 | } | 279 | } |
| 280 | |||
| 281 | /* | ||
| 282 | * If the message length is received from the slave (similar | ||
| 283 | * to SMBus block read), we must ensure that the buffer will | ||
| 284 | * be large enough to cope with a message length of | ||
| 285 | * I2C_SMBUS_BLOCK_MAX as this is the maximum underlying bus | ||
| 286 | * drivers allow. The first byte in the buffer must be | ||
| 287 | * pre-filled with the number of extra bytes, which must be | ||
| 288 | * at least one to hold the message length, but can be | ||
| 289 | * greater (for example to account for a checksum byte at | ||
| 290 | * the end of the message.) | ||
| 291 | */ | ||
| 292 | if (rdwr_pa[i].flags & I2C_M_RECV_LEN) { | ||
| 293 | if (!(rdwr_pa[i].flags & I2C_M_RD) || | ||
| 294 | rdwr_pa[i].buf[0] < 1 || | ||
| 295 | rdwr_pa[i].len < rdwr_pa[i].buf[0] + | ||
| 296 | I2C_SMBUS_BLOCK_MAX) { | ||
| 297 | res = -EINVAL; | ||
| 298 | break; | ||
| 299 | } | ||
| 300 | |||
| 301 | rdwr_pa[i].len = rdwr_pa[i].buf[0]; | ||
| 302 | } | ||
| 281 | } | 303 | } |
| 282 | if (res < 0) { | 304 | if (res < 0) { |
| 283 | int j; | 305 | int j; |
