[PATCH v4 2/2] hwmon: (powerz) Fix missing usb_kill_urb() on signal interrupt

From: Pradhan, Sanman

Date: Thu Apr 09 2026 - 20:26:33 EST


From: Sanman Pradhan <psanman@xxxxxxxxxxx>

wait_for_completion_interruptible_timeout() returns -ERESTARTSYS when
interrupted. This needs to abort the URB and return an error. No data
has been received from the device so any reads from the transfer
buffer are invalid.

The original code tests !ret, which only catches the timeout case (0).
On signal delivery (-ERESTARTSYS), !ret is false so the function skips
usb_kill_urb() and falls through to read from the unfilled transfer
buffer.

Fix by capturing the return value into a long (matching the function
return type) and handling signal (negative) and timeout (zero) cases
with separate checks that both call usb_kill_urb() before returning.

Fixes: 4381a36abdf1c ("hwmon: add POWER-Z driver")
Cc: stable@xxxxxxxxxxxxxxx
Signed-off-by: Sanman Pradhan <psanman@xxxxxxxxxxx>
---
v4:
- Split from combined patch into standalone signal fix
- Use long type for wait_for_completion return value
- Split ret <= 0 check into separate if (ret < 0) and
if (ret == 0) blocks per review feedback
- Reword commit message per review feedback
v1-v3:
- Part of combined patch "Fix use-after-free and signal
handling on USB disconnect"

drivers/hwmon/powerz.c | 11 +++++++++--
1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/drivers/hwmon/powerz.c b/drivers/hwmon/powerz.c
index a75b941bd6e2..96438f5f05d4 100644
--- a/drivers/hwmon/powerz.c
+++ b/drivers/hwmon/powerz.c
@@ -106,6 +106,7 @@ static void powerz_usb_cmd_complete(struct urb *urb)

static int powerz_read_data(struct usb_device *udev, struct powerz_priv *priv)
{
+ long rc;
int ret;

if (!priv->urb)
@@ -127,8 +128,14 @@ static int powerz_read_data(struct usb_device *udev, struct powerz_priv *priv)
if (ret)
return ret;

- if (!wait_for_completion_interruptible_timeout
- (&priv->completion, msecs_to_jiffies(5))) {
+ rc = wait_for_completion_interruptible_timeout(&priv->completion,
+ msecs_to_jiffies(5));
+ if (rc < 0) {
+ usb_kill_urb(priv->urb);
+ return rc;
+ }
+
+ if (rc == 0) {
usb_kill_urb(priv->urb);
return -EIO;
}
--
2.34.1