Skip to content

Commit ac4436a

Browse files
a3frafaeljw
authored andcommitted
thermal: of: fix double-free on unregistration
Since commit 3d439b1 ("thermal/core: Alloc-copy-free the thermal zone parameters structure"), thermal_zone_device_register() allocates a copy of the tzp argument and frees it when unregistering, so thermal_of_zone_register() now ends up leaking its original tzp and double-freeing the tzp copy. Fix this by locating tzp on stack instead. Fixes: 3d439b1 ("thermal/core: Alloc-copy-free the thermal zone parameters structure") Signed-off-by: Ahmad Fatoum <[email protected]> Acked-by: Daniel Lezcano <[email protected]> Cc: 6.4+ <[email protected]> # 6.4+: 8bcbb18: thermal: core: constify params in thermal_zone_device_register Signed-off-by: Rafael J. Wysocki <[email protected]>
1 parent 80ddce5 commit ac4436a

File tree

1 file changed

+6
-21
lines changed

1 file changed

+6
-21
lines changed

drivers/thermal/thermal_of.c

Lines changed: 6 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -238,17 +238,13 @@ static int thermal_of_monitor_init(struct device_node *np, int *delay, int *pdel
238238
return 0;
239239
}
240240

241-
static struct thermal_zone_params *thermal_of_parameters_init(struct device_node *np)
241+
static void thermal_of_parameters_init(struct device_node *np,
242+
struct thermal_zone_params *tzp)
242243
{
243-
struct thermal_zone_params *tzp;
244244
int coef[2];
245245
int ncoef = ARRAY_SIZE(coef);
246246
int prop, ret;
247247

248-
tzp = kzalloc(sizeof(*tzp), GFP_KERNEL);
249-
if (!tzp)
250-
return ERR_PTR(-ENOMEM);
251-
252248
tzp->no_hwmon = true;
253249

254250
if (!of_property_read_u32(np, "sustainable-power", &prop))
@@ -267,8 +263,6 @@ static struct thermal_zone_params *thermal_of_parameters_init(struct device_node
267263

268264
tzp->slope = coef[0];
269265
tzp->offset = coef[1];
270-
271-
return tzp;
272266
}
273267

274268
static struct device_node *thermal_of_zone_get_by_name(struct thermal_zone_device *tz)
@@ -442,13 +436,11 @@ static int thermal_of_unbind(struct thermal_zone_device *tz,
442436
static void thermal_of_zone_unregister(struct thermal_zone_device *tz)
443437
{
444438
struct thermal_trip *trips = tz->trips;
445-
struct thermal_zone_params *tzp = tz->tzp;
446439
struct thermal_zone_device_ops *ops = tz->ops;
447440

448441
thermal_zone_device_disable(tz);
449442
thermal_zone_device_unregister(tz);
450443
kfree(trips);
451-
kfree(tzp);
452444
kfree(ops);
453445
}
454446

@@ -477,7 +469,7 @@ static struct thermal_zone_device *thermal_of_zone_register(struct device_node *
477469
{
478470
struct thermal_zone_device *tz;
479471
struct thermal_trip *trips;
480-
struct thermal_zone_params *tzp;
472+
struct thermal_zone_params tzp = {};
481473
struct thermal_zone_device_ops *of_ops;
482474
struct device_node *np;
483475
int delay, pdelay;
@@ -509,25 +501,20 @@ static struct thermal_zone_device *thermal_of_zone_register(struct device_node *
509501
goto out_kfree_trips;
510502
}
511503

512-
tzp = thermal_of_parameters_init(np);
513-
if (IS_ERR(tzp)) {
514-
ret = PTR_ERR(tzp);
515-
pr_err("Failed to initialize parameter from %pOFn: %d\n", np, ret);
516-
goto out_kfree_trips;
517-
}
504+
thermal_of_parameters_init(np, &tzp);
518505

519506
of_ops->bind = thermal_of_bind;
520507
of_ops->unbind = thermal_of_unbind;
521508

522509
mask = GENMASK_ULL((ntrips) - 1, 0);
523510

524511
tz = thermal_zone_device_register_with_trips(np->name, trips, ntrips,
525-
mask, data, of_ops, tzp,
512+
mask, data, of_ops, &tzp,
526513
pdelay, delay);
527514
if (IS_ERR(tz)) {
528515
ret = PTR_ERR(tz);
529516
pr_err("Failed to register thermal zone %pOFn: %d\n", np, ret);
530-
goto out_kfree_tzp;
517+
goto out_kfree_trips;
531518
}
532519

533520
ret = thermal_zone_device_enable(tz);
@@ -540,8 +527,6 @@ static struct thermal_zone_device *thermal_of_zone_register(struct device_node *
540527

541528
return tz;
542529

543-
out_kfree_tzp:
544-
kfree(tzp);
545530
out_kfree_trips:
546531
kfree(trips);
547532
out_kfree_of_ops:

0 commit comments

Comments
 (0)