Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 783c1c50 authored by Rustam Subkhankulov's avatar Rustam Subkhankulov Committed by Greg Kroah-Hartman
Browse files

platform/chrome: fix double-free in chromeos_laptop_prepare()



[ Upstream commit 6ad4194d6a1e1d11b285989cd648ef695b4a93c0 ]

If chromeos_laptop_prepare_i2c_peripherals() fails after allocating memory
for 'cros_laptop->i2c_peripherals', this memory is freed at 'err_out' label
and nonzero value is returned. Then chromeos_laptop_destroy() is called,
resulting in double-free error.

Found by Linux Verification Center (linuxtesting.org) with SVACE.

Signed-off-by: default avatarRustam Subkhankulov <subkhankulov@ispras.ru>
Fixes: 5020cd29 ("platform/chrome: chromeos_laptop - supply properties for ACPI devices")
Reviewed-by: default avatarDmitry Torokhov <dmitry.torokhov@gmail.com>
Signed-off-by: default avatarTzung-Bi Shih <tzungbi@kernel.org>
Link: https://lore.kernel.org/r/20220813220843.2373004-1-subkhankulov@ispras.ru


Signed-off-by: default avatarSasha Levin <sashal@kernel.org>
parent 8242167c
Loading
Loading
Loading
Loading
+13 −11
Original line number Diff line number Diff line
@@ -716,6 +716,7 @@ static int __init
chromeos_laptop_prepare_i2c_peripherals(struct chromeos_laptop *cros_laptop,
					const struct chromeos_laptop *src)
{
	struct i2c_peripheral *i2c_peripherals;
	struct i2c_peripheral *i2c_dev;
	struct i2c_board_info *info;
	int i;
@@ -724,17 +725,15 @@ chromeos_laptop_prepare_i2c_peripherals(struct chromeos_laptop *cros_laptop,
	if (!src->num_i2c_peripherals)
		return 0;

	cros_laptop->i2c_peripherals = kmemdup(src->i2c_peripherals,
	i2c_peripherals = kmemdup(src->i2c_peripherals,
					      src->num_i2c_peripherals *
					  sizeof(*src->i2c_peripherals),
					  GFP_KERNEL);
	if (!cros_laptop->i2c_peripherals)
	if (!i2c_peripherals)
		return -ENOMEM;

	cros_laptop->num_i2c_peripherals = src->num_i2c_peripherals;

	for (i = 0; i < cros_laptop->num_i2c_peripherals; i++) {
		i2c_dev = &cros_laptop->i2c_peripherals[i];
	for (i = 0; i < src->num_i2c_peripherals; i++) {
		i2c_dev = &i2c_peripherals[i];
		info = &i2c_dev->board_info;

		error = chromeos_laptop_setup_irq(i2c_dev);
@@ -752,16 +751,19 @@ chromeos_laptop_prepare_i2c_peripherals(struct chromeos_laptop *cros_laptop,
		}
	}

	cros_laptop->i2c_peripherals = i2c_peripherals;
	cros_laptop->num_i2c_peripherals = src->num_i2c_peripherals;

	return 0;

err_out:
	while (--i >= 0) {
		i2c_dev = &cros_laptop->i2c_peripherals[i];
		i2c_dev = &i2c_peripherals[i];
		info = &i2c_dev->board_info;
		if (info->properties)
			property_entries_free(info->properties);
	}
	kfree(cros_laptop->i2c_peripherals);
	kfree(i2c_peripherals);
	return error;
}