Commit 67891a7f authored by Huisong Li's avatar Huisong Li Committed by Lifeng Zheng
Browse files

hwmon: (acpi_power_meter) Fix uninitialized variables

mainline inclusion
from mainline-v6.13-rc2
commit 7532e68f5d8f05353765d7585a791a14985d68b7
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/IBVB4K
CVE: NA

Reference: https://web.git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=7532e68f5d8f05353765d7585a791a14985d68b7



---------------------------------------------------------------------

The 'power1_alarm' attribute uses the 'power' and 'cap' in the
acpi_power_meter_resource structure. Currently, these two fields are just
updated when user query 'power' and 'cap' attribute. If user directly query
the 'power1_alarm' attribute without queryng above two attributes, driver
will use uninitialized variables to judge.

So this patch adds the setting of alarm state and update 'cap' in the
notification callback and update 'power' and 'cap' if needed to show the
real alarm state.

Signed-off-by: default avatarHuisong Li <lihuisong@huawei.com>
Link: https://lore.kernel.org/r/20250109081708.27366-2-lihuisong@huawei.com


Signed-off-by: default avatarGuenter Roeck <linux@roeck-us.net>
Signed-off-by: default avatarXinghai Cen <cenxinghai@h-partners.com>
parent fe05ca53
Loading
Loading
Loading
Loading
+23 −4
Original line number Diff line number Diff line
@@ -84,6 +84,7 @@ struct acpi_power_meter_resource {
	u64		power;
	u64		cap;
	u64		avg_interval;
	bool		power_alarm;
	int			sensors_valid;
	unsigned long		sensors_last_updated;
	struct sensor_device_attribute	sensors[NUM_SENSORS];
@@ -396,6 +397,9 @@ static ssize_t show_val(struct device *dev,
	struct acpi_device *acpi_dev = to_acpi_device(dev);
	struct acpi_power_meter_resource *resource = acpi_dev->driver_data;
	u64 val = 0;
	int ret;

	guard(mutex)(&resource->lock);

	switch (attr->index) {
	case 0:
@@ -423,10 +427,17 @@ static ssize_t show_val(struct device *dev,
			val = 0;
		break;
	case 6:
		if (resource->power > resource->cap)
			val = 1;
		else
			val = 0;
		ret = update_meter(resource);
		if (ret)
			return ret;
		/* need to update cap if not to support the notification. */
		if (!(resource->caps.flags & POWER_METER_CAN_NOTIFY)) {
			ret = update_cap(resource);
			if (ret)
				return ret;
		}
		val = resource->power_alarm || resource->power > resource->cap;
		resource->power_alarm = resource->power > resource->cap;
		break;
	case 7:
	case 8:
@@ -848,12 +859,20 @@ static void acpi_power_meter_notify(struct acpi_device *device, u32 event)
		sysfs_notify(&device->dev.kobj, NULL, POWER_AVERAGE_NAME);
		break;
	case METER_NOTIFY_CAP:
		mutex_lock(&resource->lock);
		res = update_cap(resource);
		if (res)
			dev_err_once(&device->dev, "update cap failed when capping value is changed.\n");
		mutex_unlock(&resource->lock);
		sysfs_notify(&device->dev.kobj, NULL, POWER_CAP_NAME);
		break;
	case METER_NOTIFY_INTERVAL:
		sysfs_notify(&device->dev.kobj, NULL, POWER_AVG_INTERVAL_NAME);
		break;
	case METER_NOTIFY_CAPPING:
		mutex_lock(&resource->lock);
		resource->power_alarm = true;
		mutex_unlock(&resource->lock);
		sysfs_notify(&device->dev.kobj, NULL, POWER_ALARM_NAME);
		dev_info(&device->dev, "Capping in progress.\n");
		break;