VYPR
Unrated severityNVD Advisory· Published May 27, 2026· Updated May 27, 2026

CVE-2026-46073

CVE-2026-46073

Description

In the Linux kernel, the following vulnerability has been resolved:

hwmon: (powerz) Fix missing usb_kill_urb() on signal interrupt

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.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

A missing usb_kill_urb() call in the powerz hwmon driver when a signal interrupts wait_for_completion_interruptible_timeout() can lead to a read from an unfilled transfer buffer.

Vulnerability

In the Linux kernel's powerz hwmon driver, a bug exists in the handling of wait_for_completion_interruptible_timeout(). This function returns -ERESTARTSYS when a signal interrupts the wait, 0 on timeout, or a positive value on success. The original code only tested !ret, which catches timeout (0) but not signal interruption. On signal delivery, !ret is false, so the code skips usb_kill_urb() and falls through to read from the unfilled transfer buffer. This affects all versions of the kernel containing this driver before the fix commit 8b51277eec43[1].

Exploitation

An attacker would need to be able to send a signal to the process or thread that is performing a USB read via the powerz driver, such that wait_for_completion_interruptible_timeout() returns -ERESTARTSYS. This requires local access to send signals (e.g., via kill or from a user-space process in the same session). The attacker's signal must be delivered at the precise moment the driver is waiting for a USB transfer to complete, interrupting the wait. After the signal, the code does not cancel the URB, but continues reading the transfer buffer which may contain uninitialized or stale data.

Impact

On successful exploitation, the driver reads from a buffer that has not been properly filled by the USB device, potentially leaking stale kernel memory data to user space via the hwmon interface. This can lead to information disclosure of sensitive kernel data. The attacker gains no code execution, but can exfiltrate kernel memory contents, which may include cryptographic keys or other secrets.

Mitigation

The fix is included in Linux kernel stable commit 8b51277eec433d4e724b273a5a5c64e8acfbe405[1]. The fix modifies the error handling by capturing the return value and adding separate checks for signal (negative) and timeout (zero) cases, ensuring usb_kill_urb() is called in both error paths. Users should apply the latest stable kernel updates that include this commit. If patching is not immediately possible, the workaround is to ensure that no signals are sent to processes using the powerz hwmon driver, or to avoid using this driver version.

AI Insight generated on May 27, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected products

3

Patches

8
b6cb07f02253

hwmon: (powerz) Fix missing usb_kill_urb() on signal interrupt

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitSanman PradhanApr 10, 2026Fixed in 6.18.27via kernel-cna
2 files changed · +18 6
  • drivers/hwmon/powerz.c+9 3 modified
    diff --git a/drivers/hwmon/powerz.c b/drivers/hwmon/powerz.c
    index a75b941bd6e2fc..96438f5f05d489 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;
     	}
    -- 
    cgit 1.3-korg
    
    
    
  • drivers/hwmon/powerz.c+9 3 modified
    diff --git a/drivers/hwmon/powerz.c b/drivers/hwmon/powerz.c
    index a75b941bd6e2fc..96438f5f05d489 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;
     	}
    -- 
    cgit 1.3-korg
    
    
    
d64458784036

hwmon: (powerz) Fix missing usb_kill_urb() on signal interrupt

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitSanman PradhanApr 10, 2026Fixed in 7.0.4via kernel-cna
2 files changed · +18 6
  • drivers/hwmon/powerz.c+9 3 modified
    diff --git a/drivers/hwmon/powerz.c b/drivers/hwmon/powerz.c
    index a75b941bd6e2fc..96438f5f05d489 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;
     	}
    -- 
    cgit 1.3-korg
    
    
    
  • drivers/hwmon/powerz.c+9 3 modified
    diff --git a/drivers/hwmon/powerz.c b/drivers/hwmon/powerz.c
    index a75b941bd6e2fc..96438f5f05d489 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;
     	}
    -- 
    cgit 1.3-korg
    
    
    
b66437cb20a2

hwmon: (powerz) Fix missing usb_kill_urb() on signal interrupt

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitSanman PradhanApr 10, 2026Fixed in 7.1-rc1via kernel-cna
2 files changed · +18 6
  • drivers/hwmon/powerz.c+9 3 modified
    diff --git a/drivers/hwmon/powerz.c b/drivers/hwmon/powerz.c
    index a75b941bd6e2fc..96438f5f05d489 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;
     	}
    -- 
    cgit 1.3-korg
    
    
    
  • drivers/hwmon/powerz.c+9 3 modified
    diff --git a/drivers/hwmon/powerz.c b/drivers/hwmon/powerz.c
    index a75b941bd6e2fc..96438f5f05d489 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;
     	}
    -- 
    cgit 1.3-korg
    
    
    
8b51277eec43

hwmon: (powerz) Fix missing usb_kill_urb() on signal interrupt

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitSanman PradhanApr 10, 2026Fixed in 6.12.86via kernel-cna
2 files changed · +18 6
  • drivers/hwmon/powerz.c+9 3 modified
    diff --git a/drivers/hwmon/powerz.c b/drivers/hwmon/powerz.c
    index 9e1dfe59aa561e..da6dd48ac67c5a 100644
    --- a/drivers/hwmon/powerz.c
    +++ b/drivers/hwmon/powerz.c
    @@ -112,6 +112,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)
    @@ -133,8 +134,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;
     	}
    -- 
    cgit 1.3-korg
    
    
    
  • drivers/hwmon/powerz.c+9 3 modified
    diff --git a/drivers/hwmon/powerz.c b/drivers/hwmon/powerz.c
    index 9e1dfe59aa561e..da6dd48ac67c5a 100644
    --- a/drivers/hwmon/powerz.c
    +++ b/drivers/hwmon/powerz.c
    @@ -112,6 +112,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)
    @@ -133,8 +134,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;
     	}
    -- 
    cgit 1.3-korg
    
    
    
b66437cb20a2

hwmon: (powerz) Fix missing usb_kill_urb() on signal interrupt

2 files changed · +18 6
  • drivers/hwmon/powerz.c+9 3 modified
    diff --git a/drivers/hwmon/powerz.c b/drivers/hwmon/powerz.c
    index a75b941bd6e2fc..96438f5f05d489 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;
     	}
    -- 
    cgit 1.3-korg
    
    
    
  • drivers/hwmon/powerz.c+9 3 modified
    diff --git a/drivers/hwmon/powerz.c b/drivers/hwmon/powerz.c
    index a75b941bd6e2fc..96438f5f05d489 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;
     	}
    -- 
    cgit 1.3-korg
    
    
    
b6cb07f02253

hwmon: (powerz) Fix missing usb_kill_urb() on signal interrupt

2 files changed · +18 6
  • drivers/hwmon/powerz.c+9 3 modified
    diff --git a/drivers/hwmon/powerz.c b/drivers/hwmon/powerz.c
    index a75b941bd6e2fc..96438f5f05d489 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;
     	}
    -- 
    cgit 1.3-korg
    
    
    
  • drivers/hwmon/powerz.c+9 3 modified
    diff --git a/drivers/hwmon/powerz.c b/drivers/hwmon/powerz.c
    index a75b941bd6e2fc..96438f5f05d489 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;
     	}
    -- 
    cgit 1.3-korg
    
    
    
8b51277eec43

hwmon: (powerz) Fix missing usb_kill_urb() on signal interrupt

2 files changed · +18 6
  • drivers/hwmon/powerz.c+9 3 modified
    diff --git a/drivers/hwmon/powerz.c b/drivers/hwmon/powerz.c
    index 9e1dfe59aa561e..da6dd48ac67c5a 100644
    --- a/drivers/hwmon/powerz.c
    +++ b/drivers/hwmon/powerz.c
    @@ -112,6 +112,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)
    @@ -133,8 +134,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;
     	}
    -- 
    cgit 1.3-korg
    
    
    
  • drivers/hwmon/powerz.c+9 3 modified
    diff --git a/drivers/hwmon/powerz.c b/drivers/hwmon/powerz.c
    index 9e1dfe59aa561e..da6dd48ac67c5a 100644
    --- a/drivers/hwmon/powerz.c
    +++ b/drivers/hwmon/powerz.c
    @@ -112,6 +112,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)
    @@ -133,8 +134,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;
     	}
    -- 
    cgit 1.3-korg
    
    
    
d64458784036

hwmon: (powerz) Fix missing usb_kill_urb() on signal interrupt

2 files changed · +18 6
  • drivers/hwmon/powerz.c+9 3 modified
    diff --git a/drivers/hwmon/powerz.c b/drivers/hwmon/powerz.c
    index a75b941bd6e2fc..96438f5f05d489 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;
     	}
    -- 
    cgit 1.3-korg
    
    
    
  • drivers/hwmon/powerz.c+9 3 modified
    diff --git a/drivers/hwmon/powerz.c b/drivers/hwmon/powerz.c
    index a75b941bd6e2fc..96438f5f05d489 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;
     	}
    -- 
    cgit 1.3-korg
    
    
    

Vulnerability mechanics

Root cause

"Missing error handling for signal interrupt in powerz_read_data() — when wait_for_completion_interruptible_timeout() returns -ERESTARTSYS, the original code does not call usb_kill_urb() and proceeds to read from an unfilled transfer buffer."

Attack vector

An attacker with local access can send a signal (e.g. SIGINT) to a process that is reading hwmon data from a POWER-Z USB device via the powerz driver. The signal causes wait_for_completion_interruptible_timeout() in powerz_read_data() to return -ERESTARTSYS. Because the original code only checked for timeout (return value 0) via the !ret test, the negative return value is not caught, usb_kill_urb() is skipped, and the function falls through to read stale or uninitialized data from the transfer buffer [patch_id=2659933].

Affected code

The vulnerable function is powerz_read_data() in drivers/hwmon/powerz.c. The original code at the wait_for_completion_interruptible_timeout() call site used a single !ret check that only handled the timeout case (0), missing the signal-interrupt case (-ERESTARTSYS) [patch_id=2659933].

What the fix does

The patch captures the return value of wait_for_completion_interruptible_timeout() into a long variable 'rc' and adds two explicit checks: if rc &lt; 0 (signal interrupt), call usb_kill_urb() and return rc; if rc == 0 (timeout), call usb_kill_urb() and return -EIO [patch_id=2659933]. This ensures that on signal delivery the URB is properly killed and the function returns an error instead of reading from the unfilled transfer buffer.

Preconditions

  • configThe POWER-Z USB device must be connected and the powerz hwmon driver must be loaded.
  • inputA process must be performing a read from the hwmon sysfs interface (triggering powerz_read_data()).
  • authThe attacker must be able to deliver a signal (e.g. SIGINT) to that process.

Generated on May 27, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

4

News mentions

0

No linked articles in our index yet.