Skip to content

Commit c408b3d

Browse files
vireshkrafaeljw
authored andcommitted
thermal: Validate new state in cur_state_store()
In cur_state_store(), the new state of the cooling device is received from user-space and is not validated by the thermal core but the same is left for the individual drivers to take care of. Apart from duplicating the code it leaves possibility for introducing bugs where a driver may not do it right. Lets make the thermal core check the new state itself and store the max value in the cooling device structure. Link: https://lore.kernel.org/all/Y0ltRJRjO7AkawvE@kili/ Reported-by: Dan Carpenter <[email protected]> Signed-off-by: Viresh Kumar <[email protected]> Signed-off-by: Rafael J. Wysocki <[email protected]>
1 parent 247f34f commit c408b3d

File tree

4 files changed

+14
-19
lines changed

4 files changed

+14
-19
lines changed

drivers/thermal/gov_fair_share.c

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -49,11 +49,7 @@ static int get_trip_level(struct thermal_zone_device *tz)
4949
static long get_target_state(struct thermal_zone_device *tz,
5050
struct thermal_cooling_device *cdev, int percentage, int level)
5151
{
52-
unsigned long max_state;
53-
54-
cdev->ops->get_max_state(cdev, &max_state);
55-
56-
return (long)(percentage * level * max_state) / (100 * tz->num_trips);
52+
return (long)(percentage * level * cdev->max_state) / (100 * tz->num_trips);
5753
}
5854

5955
/**

drivers/thermal/thermal_core.c

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -603,8 +603,7 @@ int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz,
603603
struct thermal_instance *pos;
604604
struct thermal_zone_device *pos1;
605605
struct thermal_cooling_device *pos2;
606-
unsigned long max_state;
607-
int result, ret;
606+
int result;
608607

609608
if (trip >= tz->num_trips || trip < 0)
610609
return -EINVAL;
@@ -621,15 +620,11 @@ int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz,
621620
if (tz != pos1 || cdev != pos2)
622621
return -EINVAL;
623622

624-
ret = cdev->ops->get_max_state(cdev, &max_state);
625-
if (ret)
626-
return ret;
627-
628623
/* lower default 0, upper default max_state */
629624
lower = lower == THERMAL_NO_LIMIT ? 0 : lower;
630-
upper = upper == THERMAL_NO_LIMIT ? max_state : upper;
625+
upper = upper == THERMAL_NO_LIMIT ? cdev->max_state : upper;
631626

632-
if (lower > upper || upper > max_state)
627+
if (lower > upper || upper > cdev->max_state)
633628
return -EINVAL;
634629

635630
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
@@ -900,6 +895,10 @@ __thermal_cooling_device_register(struct device_node *np,
900895
cdev->updated = false;
901896
cdev->device.class = &thermal_class;
902897
cdev->devdata = devdata;
898+
899+
if (cdev->ops->get_max_state(cdev, &cdev->max_state))
900+
goto out_kfree_type;
901+
903902
thermal_cooling_device_setup_sysfs(cdev);
904903
ret = device_register(&cdev->device);
905904
if (ret)

drivers/thermal/thermal_sysfs.c

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -589,13 +589,8 @@ static ssize_t max_state_show(struct device *dev, struct device_attribute *attr,
589589
char *buf)
590590
{
591591
struct thermal_cooling_device *cdev = to_cooling_device(dev);
592-
unsigned long state;
593-
int ret;
594592

595-
ret = cdev->ops->get_max_state(cdev, &state);
596-
if (ret)
597-
return ret;
598-
return sprintf(buf, "%ld\n", state);
593+
return sprintf(buf, "%ld\n", cdev->max_state);
599594
}
600595

601596
static ssize_t cur_state_show(struct device *dev, struct device_attribute *attr,
@@ -625,6 +620,10 @@ cur_state_store(struct device *dev, struct device_attribute *attr,
625620
if ((long)state < 0)
626621
return -EINVAL;
627622

623+
/* Requested state should be less than max_state + 1 */
624+
if (state > cdev->max_state)
625+
return -EINVAL;
626+
628627
mutex_lock(&cdev->lock);
629628

630629
result = cdev->ops->set_cur_state(cdev, state);

include/linux/thermal.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ struct thermal_cooling_device_ops {
100100
struct thermal_cooling_device {
101101
int id;
102102
char *type;
103+
unsigned long max_state;
103104
struct device device;
104105
struct device_node *np;
105106
void *devdata;

0 commit comments

Comments
 (0)