diff options
author | Igor Pylypiv <ipylypiv@google.com> | 2024-11-08 00:15:42 +0000 |
---|---|---|
committer | Wolfram Sang <wsa+renesas@sang-engineering.com> | 2024-11-14 11:22:57 +0100 |
commit | 48730a9d04ffccda541602d722d1ff81920a85d8 (patch) | |
tree | 67049c6dad15e6bbf8f4947ed1783f5617c10aa0 /drivers/i2c/i2c-dev.c | |
parent | 433c6916628e5e2ba47e618d96c23e8a9c5a6b9e (diff) |
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: 97ca843f6ad3 ("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>
Diffstat (limited to 'drivers/i2c/i2c-dev.c')
-rw-r--r-- | drivers/i2c/i2c-dev.c | 17 |
1 files changed, 9 insertions, 8 deletions
diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c index 61f7c4003d2f..e9577f920286 100644 --- a/drivers/i2c/i2c-dev.c +++ b/drivers/i2c/i2c-dev.c @@ -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; |