[PATCH] platform/x86/amd/hsmp: Reject negative power cap writes in hwmon

Hemanth Selam <[email protected]>
Newsgroups org.kernel.vger.platform-driver-x86,org.kernel.vger.linux-kernel
Message-ID <[email protected]>
hsmp_hwmon_write() takes the user-supplied hwmon value as a signed long
and assigns "val / MICROWATT_PER_MILLIWATT" to msg.args[0], which is a
__u32.  MICROWATT_PER_MILLIWATT is an unsigned long, so a negative write
to power1_cap (e.g. "echo -1 > power1_cap") is first converted to a huge
unsigned value by the division and then stored into the u32 argument.

As a result a nonsensical, multi-gigawatt socket power limit is sent to
the SMU via HSMP_SET_SOCKET_POWER_LIMIT instead of the write being
rejected.

Reject negative values with -EINVAL before the conversion.

Tested with HSMP enabled:

  CAP=$(dirname $(grep -l amd_hsmp_hwmon \
        /sys/class/hwmon/hwmon*/name | head -1))/power1_cap

  # negative write
  echo -1000000 > $CAP ; echo "ret=$?"
  # valid positive write must still work
  echo 400000000 > $CAP ; echo "ret=$?"

Before:
  # echo -1000000 > $CAP ; echo "ret=$?"
  ret=0                             <- accepted; bogus limit sent to SMU
  # echo 400000000 > $CAP ; echo "ret=$?"
  ret=0

After:
  # echo -1000000 > $CAP ; echo "ret=$?"
  bash: echo: write error: Invalid argument
  ret=1                             <- rejected with -EINVAL
  # echo 400000000 > $CAP ; echo "ret=$?"
  ret=0                             <- valid write still works

Fixes: 92c025db52bb ("platform/x86/amd/hsmp: Report power via hwmon sensors")
Signed-off-by: Hemanth Selam <[email protected]>
---
 drivers/platform/x86/amd/hsmp/hwmon.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/platform/x86/amd/hsmp/hwmon.c b/drivers/platform/x86/amd/hsmp/hwmon.c
index 0cc9a742497f..c8314eee06f4 100644
--- a/drivers/platform/x86/amd/hsmp/hwmon.c
+++ b/drivers/platform/x86/amd/hsmp/hwmon.c
@@ -31,6 +31,9 @@ static int hsmp_hwmon_write(struct device *dev, enum hwmon_sensor_types type,
 	if (attr != hwmon_power_cap)
 		return -EOPNOTSUPP;
 
+	if (val < 0)
+		return -EINVAL;
+
 	msg.num_args = 1;
 	msg.args[0] = val / MICROWATT_PER_MILLIWATT;
 	msg.msg_id = HSMP_SET_SOCKET_POWER_LIMIT;
-- 
2.43.7
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.