]> git.baikalelectronics.ru Git - kernel.git/commitdiff
platform/chrome: fix double-free in chromeos_laptop_prepare()
authorRustam Subkhankulov <subkhankulov@ispras.ru>
Sat, 13 Aug 2022 22:08:43 +0000 (01:08 +0300)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 26 Oct 2022 11:22:28 +0000 (13:22 +0200)
[ Upstream commit 66830c04e2f594310297ac6e05717490af6a8c2b ]

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: Rustam Subkhankulov <subkhankulov@ispras.ru>
Fixes: 89fd493f6384 ("platform/chrome: chromeos_laptop - supply properties for ACPI devices")
Reviewed-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Signed-off-by: Tzung-Bi Shih <tzungbi@kernel.org>
Link: https://lore.kernel.org/r/20220813220843.2373004-1-subkhankulov@ispras.ru
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/platform/chrome/chromeos_laptop.c

index 8723bcf10c9317af6659e421fd70d1c829e86918..954953133d56dd2086c0a424321744771c9777c9 100644 (file)
@@ -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,
-                                              src->num_i2c_peripherals *
-                                               sizeof(*src->i2c_peripherals),
-                                              GFP_KERNEL);
-       if (!cros_laptop->i2c_peripherals)
+       i2c_peripherals = kmemdup(src->i2c_peripherals,
+                                             src->num_i2c_peripherals *
+                                         sizeof(*src->i2c_peripherals),
+                                         GFP_KERNEL);
+       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;
 }