Commit 48730a9d authored by Igor Pylypiv's avatar Igor Pylypiv Committed by Wolfram Sang
Browse files

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: 97ca843f ("i2c: dev: Check for I2C_FUNC_I2C before calling i2c_transfer")
Signed-off-by: default avatarIgor Pylypiv <ipylypiv@google.com>
[wsa: replaced '== NULL' with '!']
Signed-off-by: default avatarWolfram Sang <wsa+renesas@sang-engineering.com>
parent 433c6916
Loading
Loading
Loading
Loading
+9 −8
Original line number Diff line number Diff line
@@ -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;