]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
i2c: dev: Fix memory leak when underlying adapter does not support I2C
authorIgor Pylypiv <ipylypiv@google.com>
Fri, 8 Nov 2024 00:15:42 +0000 (00:15 +0000)
committerWolfram Sang <wsa+renesas@sang-engineering.com>
Thu, 14 Nov 2024 10:22:57 +0000 (11:22 +0100)
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>
drivers/i2c/i2c-dev.c

index 61f7c4003d2ff732d4b29a5a5dd2837797bb1c43..e9577f920286d094efd42e613b9aa93ae3d1da2b 100644 (file)
@@ -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;