mirror of https://github.com/torvalds/linux.git
i2c: dev: Fix memory leak when underlying adapter does not support I2C
Early return in i2cdev_ioctl_rdwr() failed to free the memory allocated
by the caller. Move freeing the memory to the function where it has been
allocated to prevent similar leaks in the future.
Fixes: 97ca843f6a ("i2c: dev: Check for I2C_FUNC_I2C before calling i2c_transfer")
Signed-off-by: Igor Pylypiv <ipylypiv@google.com>
[wsa: replaced '== NULL' with '!']
Signed-off-by: Wolfram Sang <wsa+renesas@sang-engineering.com>
This commit is contained in:
parent
433c691662
commit
48730a9d04
|
|
@ -251,10 +251,8 @@ static noinline int i2cdev_ioctl_rdwr(struct i2c_client *client,
|
|||
return -EOPNOTSUPP;
|
||||
|
||||
data_ptrs = kmalloc_array(nmsgs, sizeof(u8 __user *), GFP_KERNEL);
|
||||
if (data_ptrs == NULL) {
|
||||
kfree(msgs);
|
||||
if (!data_ptrs)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
res = 0;
|
||||
for (i = 0; i < nmsgs; i++) {
|
||||
|
|
@ -302,7 +300,6 @@ static noinline int i2cdev_ioctl_rdwr(struct i2c_client *client,
|
|||
for (j = 0; j < i; ++j)
|
||||
kfree(msgs[j].buf);
|
||||
kfree(data_ptrs);
|
||||
kfree(msgs);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
|
@ -316,7 +313,6 @@ static noinline int i2cdev_ioctl_rdwr(struct i2c_client *client,
|
|||
kfree(msgs[i].buf);
|
||||
}
|
||||
kfree(data_ptrs);
|
||||
kfree(msgs);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
|
@ -446,6 +442,7 @@ static long i2cdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
|||
case I2C_RDWR: {
|
||||
struct i2c_rdwr_ioctl_data rdwr_arg;
|
||||
struct i2c_msg *rdwr_pa;
|
||||
int res;
|
||||
|
||||
if (copy_from_user(&rdwr_arg,
|
||||
(struct i2c_rdwr_ioctl_data __user *)arg,
|
||||
|
|
@ -467,7 +464,9 @@ static long i2cdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
|||
if (IS_ERR(rdwr_pa))
|
||||
return PTR_ERR(rdwr_pa);
|
||||
|
||||
return i2cdev_ioctl_rdwr(client, rdwr_arg.nmsgs, rdwr_pa);
|
||||
res = i2cdev_ioctl_rdwr(client, rdwr_arg.nmsgs, rdwr_pa);
|
||||
kfree(rdwr_pa);
|
||||
return res;
|
||||
}
|
||||
|
||||
case I2C_SMBUS: {
|
||||
|
|
@ -540,7 +539,7 @@ static long compat_i2cdev_ioctl(struct file *file, unsigned int cmd, unsigned lo
|
|||
struct i2c_rdwr_ioctl_data32 rdwr_arg;
|
||||
struct i2c_msg32 __user *p;
|
||||
struct i2c_msg *rdwr_pa;
|
||||
int i;
|
||||
int i, res;
|
||||
|
||||
if (copy_from_user(&rdwr_arg,
|
||||
(struct i2c_rdwr_ioctl_data32 __user *)arg,
|
||||
|
|
@ -573,7 +572,9 @@ static long compat_i2cdev_ioctl(struct file *file, unsigned int cmd, unsigned lo
|
|||
};
|
||||
}
|
||||
|
||||
return i2cdev_ioctl_rdwr(client, rdwr_arg.nmsgs, rdwr_pa);
|
||||
res = i2cdev_ioctl_rdwr(client, rdwr_arg.nmsgs, rdwr_pa);
|
||||
kfree(rdwr_pa);
|
||||
return res;
|
||||
}
|
||||
case I2C_SMBUS: {
|
||||
struct i2c_smbus_ioctl_data32 data32;
|
||||
|
|
|
|||
Loading…
Reference in New Issue