Commit 6ad4194d authored by Rustam Subkhankulov's avatar Rustam Subkhankulov Committed by Tzung-Bi Shih

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

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
parent 1a8912ca
...@@ -740,6 +740,7 @@ static int __init ...@@ -740,6 +740,7 @@ static int __init
chromeos_laptop_prepare_i2c_peripherals(struct chromeos_laptop *cros_laptop, chromeos_laptop_prepare_i2c_peripherals(struct chromeos_laptop *cros_laptop,
const struct chromeos_laptop *src) const struct chromeos_laptop *src)
{ {
struct i2c_peripheral *i2c_peripherals;
struct i2c_peripheral *i2c_dev; struct i2c_peripheral *i2c_dev;
struct i2c_board_info *info; struct i2c_board_info *info;
int i; int i;
...@@ -748,17 +749,15 @@ chromeos_laptop_prepare_i2c_peripherals(struct chromeos_laptop *cros_laptop, ...@@ -748,17 +749,15 @@ chromeos_laptop_prepare_i2c_peripherals(struct chromeos_laptop *cros_laptop,
if (!src->num_i2c_peripherals) if (!src->num_i2c_peripherals)
return 0; return 0;
cros_laptop->i2c_peripherals = kmemdup(src->i2c_peripherals, i2c_peripherals = kmemdup(src->i2c_peripherals,
src->num_i2c_peripherals * src->num_i2c_peripherals *
sizeof(*src->i2c_peripherals), sizeof(*src->i2c_peripherals),
GFP_KERNEL); GFP_KERNEL);
if (!cros_laptop->i2c_peripherals) if (!i2c_peripherals)
return -ENOMEM; return -ENOMEM;
cros_laptop->num_i2c_peripherals = src->num_i2c_peripherals; for (i = 0; i < src->num_i2c_peripherals; i++) {
i2c_dev = &i2c_peripherals[i];
for (i = 0; i < cros_laptop->num_i2c_peripherals; i++) {
i2c_dev = &cros_laptop->i2c_peripherals[i];
info = &i2c_dev->board_info; info = &i2c_dev->board_info;
error = chromeos_laptop_setup_irq(i2c_dev); error = chromeos_laptop_setup_irq(i2c_dev);
...@@ -775,16 +774,19 @@ chromeos_laptop_prepare_i2c_peripherals(struct chromeos_laptop *cros_laptop, ...@@ -775,16 +774,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; return 0;
err_out: err_out:
while (--i >= 0) { while (--i >= 0) {
i2c_dev = &cros_laptop->i2c_peripherals[i]; i2c_dev = &i2c_peripherals[i];
info = &i2c_dev->board_info; info = &i2c_dev->board_info;
if (!IS_ERR_OR_NULL(info->fwnode)) if (!IS_ERR_OR_NULL(info->fwnode))
fwnode_remove_software_node(info->fwnode); fwnode_remove_software_node(info->fwnode);
} }
kfree(cros_laptop->i2c_peripherals); kfree(i2c_peripherals);
return error; return error;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment