VYPR
Unrated severityNVD Advisory· Published Jun 8, 2026

CVE-2026-46298

CVE-2026-46298

Description

Linux kernel pseries/papr-hvpipe driver has a deadlock vulnerability due to a race condition with interrupt handlers.

AI Insight

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

Linux kernel pseries/papr-hvpipe driver has a deadlock vulnerability due to a race condition with interrupt handlers.

Vulnerability

A deadlock vulnerability exists in the Linux kernel's pseries/papr-hvpipe driver. This race condition occurs when an interrupt fires on the same CPU while the ->ioctl or ->release handlers are executing, leading to a deadlock. This issue affects versions of the kernel where this race condition is present.

Exploitation

An attacker could trigger this vulnerability by causing an interrupt to fire on the same CPU while the ->ioctl or ->release handlers are active. This race condition requires specific timing and execution paths within the kernel's interrupt handling and driver operations.

Impact

Successful exploitation of this vulnerability can lead to a deadlock within the kernel, potentially causing system instability or denial of service. The exact impact depends on the context in which the deadlock occurs.

Mitigation

This vulnerability has been resolved by taking the spin_lock_irq{save|restore} versions of the lock within both the ->ioctl and ->release handlers. The specific fixed version and release date are not detailed in the available references, but the patch is available at [1].

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

Affected products

1

Patches

4
7a4f0846ee6c

pseries/papr-hvpipe: Fix race with interrupt handler

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git"Ritesh Harjani (IBM)"Fixed in 7.1-rc3via kernel-cna
1 file changed · +11 10
  • arch/powerpc/platforms/pseries/papr-hvpipe.c+11 10 modified
    diff --git a/arch/powerpc/platforms/pseries/papr-hvpipe.c b/arch/powerpc/platforms/pseries/papr-hvpipe.c
    index 14ae480d060a4..c41d45e1986d1 100644
    --- a/arch/powerpc/platforms/pseries/papr-hvpipe.c
    +++ b/arch/powerpc/platforms/pseries/papr-hvpipe.c
    @@ -444,13 +444,14 @@ static int papr_hvpipe_handle_release(struct inode *inode,
     				struct file *file)
     {
     	struct hvpipe_source_info *src_info;
    +	unsigned long flags;
     
     	/*
     	 * Hold the lock, remove source from src_list, reset the
     	 * hvpipe status and release the lock to prevent any race
     	 * with message event IRQ.
     	 */
    -	spin_lock(&hvpipe_src_list_lock);
    +	spin_lock_irqsave(&hvpipe_src_list_lock, flags);
     	src_info = file->private_data;
     	list_del(&src_info->list);
     	file->private_data = NULL;
    @@ -461,10 +462,10 @@ static int papr_hvpipe_handle_release(struct inode *inode,
     	 */
     	if (src_info->hvpipe_status & HVPIPE_MSG_AVAILABLE) {
     		src_info->hvpipe_status = 0;
    -		spin_unlock(&hvpipe_src_list_lock);
    +		spin_unlock_irqrestore(&hvpipe_src_list_lock, flags);
     		hvpipe_rtas_recv_msg(NULL, 0);
     	} else
    -		spin_unlock(&hvpipe_src_list_lock);
    +		spin_unlock_irqrestore(&hvpipe_src_list_lock, flags);
     
     	kfree(src_info);
     	return 0;
    @@ -480,20 +481,21 @@ static const struct file_operations papr_hvpipe_handle_ops = {
     static int papr_hvpipe_dev_create_handle(u32 srcID)
     {
     	struct hvpipe_source_info *src_info __free(kfree) = NULL;
    +	unsigned long flags;
     
    -	spin_lock(&hvpipe_src_list_lock);
    +	spin_lock_irqsave(&hvpipe_src_list_lock, flags);
     	/*
     	 * Do not allow more than one process communicates with
     	 * each source.
     	 */
     	src_info = hvpipe_find_source(srcID);
     	if (src_info) {
    -		spin_unlock(&hvpipe_src_list_lock);
    +		spin_unlock_irqrestore(&hvpipe_src_list_lock, flags);
     		pr_err("pid(%d) is already using the source(%d)\n",
     				src_info->tsk->pid, srcID);
     		return -EALREADY;
     	}
    -	spin_unlock(&hvpipe_src_list_lock);
    +	spin_unlock_irqrestore(&hvpipe_src_list_lock, flags);
     
     	src_info = kzalloc_obj(*src_info, GFP_KERNEL_ACCOUNT);
     	if (!src_info)
    @@ -510,18 +512,18 @@ static int papr_hvpipe_dev_create_handle(u32 srcID)
     		return fdf.err;
     
     	retain_and_null_ptr(src_info);
    -	spin_lock(&hvpipe_src_list_lock);
    +	spin_lock_irqsave(&hvpipe_src_list_lock, flags);
     	/*
     	 * If two processes are executing ioctl() for the same
     	 * source ID concurrently, prevent the second process to
     	 * acquire FD.
     	 */
     	if (hvpipe_find_source(srcID)) {
    -		spin_unlock(&hvpipe_src_list_lock);
    +		spin_unlock_irqrestore(&hvpipe_src_list_lock, flags);
     		return -EALREADY;
     	}
     	list_add(&src_info->list, &hvpipe_src_list);
    -	spin_unlock(&hvpipe_src_list_lock);
    +	spin_unlock_irqrestore(&hvpipe_src_list_lock, flags);
     	return fd_publish(fdf);
     }
     
    -- 
    cgit 1.3-korg
    
    
    
342c966f81cf

pseries/papr-hvpipe: Fix race with interrupt handler

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git"Ritesh Harjani (IBM)"Fixed in 7.0.7via kernel-cna
1 file changed · +11 10
  • arch/powerpc/platforms/pseries/papr-hvpipe.c+11 10 modified
    diff --git a/arch/powerpc/platforms/pseries/papr-hvpipe.c b/arch/powerpc/platforms/pseries/papr-hvpipe.c
    index 14ae480d060a4..c41d45e1986d1 100644
    --- a/arch/powerpc/platforms/pseries/papr-hvpipe.c
    +++ b/arch/powerpc/platforms/pseries/papr-hvpipe.c
    @@ -444,13 +444,14 @@ static int papr_hvpipe_handle_release(struct inode *inode,
     				struct file *file)
     {
     	struct hvpipe_source_info *src_info;
    +	unsigned long flags;
     
     	/*
     	 * Hold the lock, remove source from src_list, reset the
     	 * hvpipe status and release the lock to prevent any race
     	 * with message event IRQ.
     	 */
    -	spin_lock(&hvpipe_src_list_lock);
    +	spin_lock_irqsave(&hvpipe_src_list_lock, flags);
     	src_info = file->private_data;
     	list_del(&src_info->list);
     	file->private_data = NULL;
    @@ -461,10 +462,10 @@ static int papr_hvpipe_handle_release(struct inode *inode,
     	 */
     	if (src_info->hvpipe_status & HVPIPE_MSG_AVAILABLE) {
     		src_info->hvpipe_status = 0;
    -		spin_unlock(&hvpipe_src_list_lock);
    +		spin_unlock_irqrestore(&hvpipe_src_list_lock, flags);
     		hvpipe_rtas_recv_msg(NULL, 0);
     	} else
    -		spin_unlock(&hvpipe_src_list_lock);
    +		spin_unlock_irqrestore(&hvpipe_src_list_lock, flags);
     
     	kfree(src_info);
     	return 0;
    @@ -480,20 +481,21 @@ static const struct file_operations papr_hvpipe_handle_ops = {
     static int papr_hvpipe_dev_create_handle(u32 srcID)
     {
     	struct hvpipe_source_info *src_info __free(kfree) = NULL;
    +	unsigned long flags;
     
    -	spin_lock(&hvpipe_src_list_lock);
    +	spin_lock_irqsave(&hvpipe_src_list_lock, flags);
     	/*
     	 * Do not allow more than one process communicates with
     	 * each source.
     	 */
     	src_info = hvpipe_find_source(srcID);
     	if (src_info) {
    -		spin_unlock(&hvpipe_src_list_lock);
    +		spin_unlock_irqrestore(&hvpipe_src_list_lock, flags);
     		pr_err("pid(%d) is already using the source(%d)\n",
     				src_info->tsk->pid, srcID);
     		return -EALREADY;
     	}
    -	spin_unlock(&hvpipe_src_list_lock);
    +	spin_unlock_irqrestore(&hvpipe_src_list_lock, flags);
     
     	src_info = kzalloc_obj(*src_info, GFP_KERNEL_ACCOUNT);
     	if (!src_info)
    @@ -510,18 +512,18 @@ static int papr_hvpipe_dev_create_handle(u32 srcID)
     		return fdf.err;
     
     	retain_and_null_ptr(src_info);
    -	spin_lock(&hvpipe_src_list_lock);
    +	spin_lock_irqsave(&hvpipe_src_list_lock, flags);
     	/*
     	 * If two processes are executing ioctl() for the same
     	 * source ID concurrently, prevent the second process to
     	 * acquire FD.
     	 */
     	if (hvpipe_find_source(srcID)) {
    -		spin_unlock(&hvpipe_src_list_lock);
    +		spin_unlock_irqrestore(&hvpipe_src_list_lock, flags);
     		return -EALREADY;
     	}
     	list_add(&src_info->list, &hvpipe_src_list);
    -	spin_unlock(&hvpipe_src_list_lock);
    +	spin_unlock_irqrestore(&hvpipe_src_list_lock, flags);
     	return fd_publish(fdf);
     }
     
    -- 
    cgit 1.3-korg
    
    
    
342c966f81cf

pseries/papr-hvpipe: Fix race with interrupt handler

1 file changed · +11 10
  • arch/powerpc/platforms/pseries/papr-hvpipe.c+11 10 modified
    diff --git a/arch/powerpc/platforms/pseries/papr-hvpipe.c b/arch/powerpc/platforms/pseries/papr-hvpipe.c
    index 14ae480d060a4..c41d45e1986d1 100644
    --- a/arch/powerpc/platforms/pseries/papr-hvpipe.c
    +++ b/arch/powerpc/platforms/pseries/papr-hvpipe.c
    @@ -444,13 +444,14 @@ static int papr_hvpipe_handle_release(struct inode *inode,
     				struct file *file)
     {
     	struct hvpipe_source_info *src_info;
    +	unsigned long flags;
     
     	/*
     	 * Hold the lock, remove source from src_list, reset the
     	 * hvpipe status and release the lock to prevent any race
     	 * with message event IRQ.
     	 */
    -	spin_lock(&hvpipe_src_list_lock);
    +	spin_lock_irqsave(&hvpipe_src_list_lock, flags);
     	src_info = file->private_data;
     	list_del(&src_info->list);
     	file->private_data = NULL;
    @@ -461,10 +462,10 @@ static int papr_hvpipe_handle_release(struct inode *inode,
     	 */
     	if (src_info->hvpipe_status & HVPIPE_MSG_AVAILABLE) {
     		src_info->hvpipe_status = 0;
    -		spin_unlock(&hvpipe_src_list_lock);
    +		spin_unlock_irqrestore(&hvpipe_src_list_lock, flags);
     		hvpipe_rtas_recv_msg(NULL, 0);
     	} else
    -		spin_unlock(&hvpipe_src_list_lock);
    +		spin_unlock_irqrestore(&hvpipe_src_list_lock, flags);
     
     	kfree(src_info);
     	return 0;
    @@ -480,20 +481,21 @@ static const struct file_operations papr_hvpipe_handle_ops = {
     static int papr_hvpipe_dev_create_handle(u32 srcID)
     {
     	struct hvpipe_source_info *src_info __free(kfree) = NULL;
    +	unsigned long flags;
     
    -	spin_lock(&hvpipe_src_list_lock);
    +	spin_lock_irqsave(&hvpipe_src_list_lock, flags);
     	/*
     	 * Do not allow more than one process communicates with
     	 * each source.
     	 */
     	src_info = hvpipe_find_source(srcID);
     	if (src_info) {
    -		spin_unlock(&hvpipe_src_list_lock);
    +		spin_unlock_irqrestore(&hvpipe_src_list_lock, flags);
     		pr_err("pid(%d) is already using the source(%d)\n",
     				src_info->tsk->pid, srcID);
     		return -EALREADY;
     	}
    -	spin_unlock(&hvpipe_src_list_lock);
    +	spin_unlock_irqrestore(&hvpipe_src_list_lock, flags);
     
     	src_info = kzalloc_obj(*src_info, GFP_KERNEL_ACCOUNT);
     	if (!src_info)
    @@ -510,18 +512,18 @@ static int papr_hvpipe_dev_create_handle(u32 srcID)
     		return fdf.err;
     
     	retain_and_null_ptr(src_info);
    -	spin_lock(&hvpipe_src_list_lock);
    +	spin_lock_irqsave(&hvpipe_src_list_lock, flags);
     	/*
     	 * If two processes are executing ioctl() for the same
     	 * source ID concurrently, prevent the second process to
     	 * acquire FD.
     	 */
     	if (hvpipe_find_source(srcID)) {
    -		spin_unlock(&hvpipe_src_list_lock);
    +		spin_unlock_irqrestore(&hvpipe_src_list_lock, flags);
     		return -EALREADY;
     	}
     	list_add(&src_info->list, &hvpipe_src_list);
    -	spin_unlock(&hvpipe_src_list_lock);
    +	spin_unlock_irqrestore(&hvpipe_src_list_lock, flags);
     	return fd_publish(fdf);
     }
     
    -- 
    cgit 1.3-korg
    
    
    
7a4f0846ee6c

pseries/papr-hvpipe: Fix race with interrupt handler

1 file changed · +11 10
  • arch/powerpc/platforms/pseries/papr-hvpipe.c+11 10 modified
    diff --git a/arch/powerpc/platforms/pseries/papr-hvpipe.c b/arch/powerpc/platforms/pseries/papr-hvpipe.c
    index 14ae480d060a4..c41d45e1986d1 100644
    --- a/arch/powerpc/platforms/pseries/papr-hvpipe.c
    +++ b/arch/powerpc/platforms/pseries/papr-hvpipe.c
    @@ -444,13 +444,14 @@ static int papr_hvpipe_handle_release(struct inode *inode,
     				struct file *file)
     {
     	struct hvpipe_source_info *src_info;
    +	unsigned long flags;
     
     	/*
     	 * Hold the lock, remove source from src_list, reset the
     	 * hvpipe status and release the lock to prevent any race
     	 * with message event IRQ.
     	 */
    -	spin_lock(&hvpipe_src_list_lock);
    +	spin_lock_irqsave(&hvpipe_src_list_lock, flags);
     	src_info = file->private_data;
     	list_del(&src_info->list);
     	file->private_data = NULL;
    @@ -461,10 +462,10 @@ static int papr_hvpipe_handle_release(struct inode *inode,
     	 */
     	if (src_info->hvpipe_status & HVPIPE_MSG_AVAILABLE) {
     		src_info->hvpipe_status = 0;
    -		spin_unlock(&hvpipe_src_list_lock);
    +		spin_unlock_irqrestore(&hvpipe_src_list_lock, flags);
     		hvpipe_rtas_recv_msg(NULL, 0);
     	} else
    -		spin_unlock(&hvpipe_src_list_lock);
    +		spin_unlock_irqrestore(&hvpipe_src_list_lock, flags);
     
     	kfree(src_info);
     	return 0;
    @@ -480,20 +481,21 @@ static const struct file_operations papr_hvpipe_handle_ops = {
     static int papr_hvpipe_dev_create_handle(u32 srcID)
     {
     	struct hvpipe_source_info *src_info __free(kfree) = NULL;
    +	unsigned long flags;
     
    -	spin_lock(&hvpipe_src_list_lock);
    +	spin_lock_irqsave(&hvpipe_src_list_lock, flags);
     	/*
     	 * Do not allow more than one process communicates with
     	 * each source.
     	 */
     	src_info = hvpipe_find_source(srcID);
     	if (src_info) {
    -		spin_unlock(&hvpipe_src_list_lock);
    +		spin_unlock_irqrestore(&hvpipe_src_list_lock, flags);
     		pr_err("pid(%d) is already using the source(%d)\n",
     				src_info->tsk->pid, srcID);
     		return -EALREADY;
     	}
    -	spin_unlock(&hvpipe_src_list_lock);
    +	spin_unlock_irqrestore(&hvpipe_src_list_lock, flags);
     
     	src_info = kzalloc_obj(*src_info, GFP_KERNEL_ACCOUNT);
     	if (!src_info)
    @@ -510,18 +512,18 @@ static int papr_hvpipe_dev_create_handle(u32 srcID)
     		return fdf.err;
     
     	retain_and_null_ptr(src_info);
    -	spin_lock(&hvpipe_src_list_lock);
    +	spin_lock_irqsave(&hvpipe_src_list_lock, flags);
     	/*
     	 * If two processes are executing ioctl() for the same
     	 * source ID concurrently, prevent the second process to
     	 * acquire FD.
     	 */
     	if (hvpipe_find_source(srcID)) {
    -		spin_unlock(&hvpipe_src_list_lock);
    +		spin_unlock_irqrestore(&hvpipe_src_list_lock, flags);
     		return -EALREADY;
     	}
     	list_add(&src_info->list, &hvpipe_src_list);
    -	spin_unlock(&hvpipe_src_list_lock);
    +	spin_unlock_irqrestore(&hvpipe_src_list_lock, flags);
     	return fd_publish(fdf);
     }
     
    -- 
    cgit 1.3-korg
    
    
    

Vulnerability mechanics

Root cause

"A race condition exists between the ioctl/release handlers and the interrupt handler on the same CPU, leading to a deadlock."

Attack vector

An attacker can trigger this vulnerability by concurrently executing the ioctl or release handlers while an interrupt occurs on the same CPU. This specific scenario can lead to a deadlock situation within the system. The vulnerability is present in the papr-hvpipe character driver.

Affected code

The vulnerability resides within the `arch/powerpc/platforms/pseries/papr-hvpipe.c` file. Specifically, the `papr_hvpipe_handle_release` and `papr_hvpipe_dev_create_handle` functions are affected, as they utilize spinlocks that do not disable interrupts.

What the fix does

The patch replaces the use of `spin_lock` and `spin_unlock` with `spin_lock_irqsave` and `spin_unlock_irqrestore` respectively in both the `papr_hvpipe_handle_release` and `papr_hvpipe_dev_create_handle` functions. This change ensures that interrupts are disabled on the local CPU while the spinlock is held, preventing the interrupt handler from acquiring the same lock and thus avoiding the deadlock condition [patch_id=5239577].

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

References

2

News mentions

1