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

CVE-2026-45910

CVE-2026-45910

Description

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

RDMA/rxe: Fix race condition in QP timer handlers

I encontered the following warning: WARNING: drivers/infiniband/sw/rxe/rxe_task.c:249 at rxe_sched_task+0x1c8/0x238 [rdma_rxe], CPU#0: swapper/0/0 ... libsha1 [last unloaded: ip6_udp_tunnel] CPU: 0 UID: 0 PID: 0 Comm: swapper/0 Tainted: G C 6.19.0-rc5-64k-v8+ #37 PREEMPT Tainted: [C]=CRAP Hardware name: Raspberry Pi 4 Model B Rev 1.2 Call trace: rxe_sched_task+0x1c8/0x238 [rdma_rxe] (P) retransmit_timer+0x130/0x188 [rdma_rxe] call_timer_fn+0x68/0x4d0 __run_timers+0x630/0x888 ... WARNING: drivers/infiniband/sw/rxe/rxe_task.c:38 at rxe_sched_task+0x1c0/0x238 [rdma_rxe], CPU#0: swapper/0/0 ... WARNING: drivers/infiniband/sw/rxe/rxe_task.c:111 at do_work+0x488/0x5c8 [rdma_rxe], CPU#3: kworker/u17:4/93400 ... refcount_t: underflow; use-after-free. WARNING: lib/refcount.c:28 at refcount_warn_saturate+0x138/0x1a0, CPU#3: kworker/u17:4/93400

The issue is caused by a race condition between retransmit_timer() and rxe_destroy_qp, leading to the Queue Pair's (QP) reference count dropping to zero during timer handler execution.

It seems this warning is harmless because rxe_qp_do_cleanup() will flush all pending timers and requests.

Example of flow causing the issue:

CPU0 CPU1 retransmit_timer() { spin_lock_irqsave rxe_destroy_qp() __rxe_cleanup() __rxe_put() // qp->ref_count decrease to 0 rxe_qp_do_cleanup() { if (qp->valid) { rxe_sched_task() { WARN_ON(rxe_read(task->qp) <= 0); } } spin_unlock_irqrestore } spin_lock_irqsave qp->valid = 0 spin_unlock_irqrestore }

Ensure the QP's reference count is maintained and its validity is checked within the timer callbacks by adding calls to rxe_get(qp) and corresponding rxe_put(qp) after use.

AI Insight

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

A race condition in the Linux kernel's RDMA/rxe QP timer handlers can cause a use-after-free when destroying a queue pair.

Vulnerability

The vulnerability is a race condition in the RDMA/rxe (Soft RoCE) driver in the Linux kernel. The retransmit_timer() function can execute concurrently with rxe_destroy_qp(), leading to the QP's reference count dropping to zero while the timer handler is still running. This can trigger a use-after-free condition. The affected versions are those prior to the commit that fixes it, including kernel 6.19.0-rc5 and earlier [1].

Exploitation

An attacker would need to be able to trigger the creation and destruction of RDMA queue pairs, which typically requires local access or the ability to interact with the RDMA subsystem. The race window is between the timer callback and the QP cleanup. The attacker would need to cause the QP to be destroyed while a timer is about to fire or is executing. This could be achieved by repeatedly creating and destroying QPs under specific timing conditions.

Impact

Successful exploitation could lead to a use-after-free, potentially allowing an attacker to corrupt kernel memory or cause a denial of service (system crash). The warning messages indicate a reference count underflow, which is a precursor to use-after-free. The impact is limited to the RDMA subsystem, but could be leveraged for privilege escalation if combined with other vulnerabilities.

Mitigation

The fix is included in the Linux kernel commit [1]. Users should update to a kernel version that includes this commit. The commit ensures that the QP's reference count is maintained and its validity is checked within the timer callbacks. If a patch is not yet available, there is no known workaround. The vulnerability is not listed on the CISA KEV as of the publication date.

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

2

Patches

10
87bf64692143

RDMA/rxe: Fix race condition in QP timer handlers

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitLi ZhijianJan 20, 2026Fixed in 7.0via kernel-cna
4 files changed · +12 2
  • drivers/infiniband/sw/rxe/rxe_comp.c+3 0 modified
    diff --git a/drivers/infiniband/sw/rxe/rxe_comp.c b/drivers/infiniband/sw/rxe/rxe_comp.c
    index a5b2b62f596b05..1390e861bd1d74 100644
    --- a/drivers/infiniband/sw/rxe/rxe_comp.c
    +++ b/drivers/infiniband/sw/rxe/rxe_comp.c
    @@ -119,12 +119,15 @@ void retransmit_timer(struct timer_list *t)
     
     	rxe_dbg_qp(qp, "retransmit timer fired\n");
     
    +	if (!rxe_get(qp))
    +		return;
     	spin_lock_irqsave(&qp->state_lock, flags);
     	if (qp->valid) {
     		qp->comp.timeout = 1;
     		rxe_sched_task(&qp->send_task);
     	}
     	spin_unlock_irqrestore(&qp->state_lock, flags);
    +	rxe_put(qp);
     }
     
     void rxe_comp_queue_pkt(struct rxe_qp *qp, struct sk_buff *skb)
    
  • drivers/infiniband/sw/rxe/rxe_comp.c+3 0 modified
    diff --git a/drivers/infiniband/sw/rxe/rxe_comp.c b/drivers/infiniband/sw/rxe/rxe_comp.c
    index a5b2b62f596b05..1390e861bd1d74 100644
    --- a/drivers/infiniband/sw/rxe/rxe_comp.c
    +++ b/drivers/infiniband/sw/rxe/rxe_comp.c
    @@ -119,12 +119,15 @@ void retransmit_timer(struct timer_list *t)
     
     	rxe_dbg_qp(qp, "retransmit timer fired\n");
     
    +	if (!rxe_get(qp))
    +		return;
     	spin_lock_irqsave(&qp->state_lock, flags);
     	if (qp->valid) {
     		qp->comp.timeout = 1;
     		rxe_sched_task(&qp->send_task);
     	}
     	spin_unlock_irqrestore(&qp->state_lock, flags);
    +	rxe_put(qp);
     }
     
     void rxe_comp_queue_pkt(struct rxe_qp *qp, struct sk_buff *skb)
    
  • drivers/infiniband/sw/rxe/rxe_req.c+3 1 modified
    diff --git a/drivers/infiniband/sw/rxe/rxe_req.c b/drivers/infiniband/sw/rxe/rxe_req.c
    index 373b03f223bebc..12d03f390b0978 100644
    --- a/drivers/infiniband/sw/rxe/rxe_req.c
    +++ b/drivers/infiniband/sw/rxe/rxe_req.c
    @@ -102,6 +102,8 @@ void rnr_nak_timer(struct timer_list *t)
     
     	rxe_dbg_qp(qp, "nak timer fired\n");
     
    +	if (!rxe_get(qp))
    +		return;
     	spin_lock_irqsave(&qp->state_lock, flags);
     	if (qp->valid) {
     		/* request a send queue retry */
    @@ -110,6 +112,7 @@ void rnr_nak_timer(struct timer_list *t)
     		rxe_sched_task(&qp->send_task);
     	}
     	spin_unlock_irqrestore(&qp->state_lock, flags);
    +	rxe_put(qp);
     }
     
     static void req_check_sq_drain_done(struct rxe_qp *qp)
    -- 
    cgit 1.3-korg
    
    
    
  • drivers/infiniband/sw/rxe/rxe_req.c+3 1 modified
    diff --git a/drivers/infiniband/sw/rxe/rxe_req.c b/drivers/infiniband/sw/rxe/rxe_req.c
    index 373b03f223bebc..12d03f390b0978 100644
    --- a/drivers/infiniband/sw/rxe/rxe_req.c
    +++ b/drivers/infiniband/sw/rxe/rxe_req.c
    @@ -102,6 +102,8 @@ void rnr_nak_timer(struct timer_list *t)
     
     	rxe_dbg_qp(qp, "nak timer fired\n");
     
    +	if (!rxe_get(qp))
    +		return;
     	spin_lock_irqsave(&qp->state_lock, flags);
     	if (qp->valid) {
     		/* request a send queue retry */
    @@ -110,6 +112,7 @@ void rnr_nak_timer(struct timer_list *t)
     		rxe_sched_task(&qp->send_task);
     	}
     	spin_unlock_irqrestore(&qp->state_lock, flags);
    +	rxe_put(qp);
     }
     
     static void req_check_sq_drain_done(struct rxe_qp *qp)
    -- 
    cgit 1.3-korg
    
    
    
756c93d6df7c

RDMA/rxe: Fix race condition in QP timer handlers

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitLi ZhijianJan 20, 2026Fixed in 6.6.128via kernel-cna
4 files changed · +12 2
  • drivers/infiniband/sw/rxe/rxe_comp.c+3 0 modified
    diff --git a/drivers/infiniband/sw/rxe/rxe_comp.c b/drivers/infiniband/sw/rxe/rxe_comp.c
    index c997b7cbf2a9e8..81b645c727a17c 100644
    --- a/drivers/infiniband/sw/rxe/rxe_comp.c
    +++ b/drivers/infiniband/sw/rxe/rxe_comp.c
    @@ -119,12 +119,15 @@ void retransmit_timer(struct timer_list *t)
     
     	rxe_dbg_qp(qp, "retransmit timer fired\n");
     
    +	if (!rxe_get(qp))
    +		return;
     	spin_lock_irqsave(&qp->state_lock, flags);
     	if (qp->valid) {
     		qp->comp.timeout = 1;
     		rxe_sched_task(&qp->comp.task);
     	}
     	spin_unlock_irqrestore(&qp->state_lock, flags);
    +	rxe_put(qp);
     }
     
     void rxe_comp_queue_pkt(struct rxe_qp *qp, struct sk_buff *skb)
    
  • drivers/infiniband/sw/rxe/rxe_comp.c+3 0 modified
    diff --git a/drivers/infiniband/sw/rxe/rxe_comp.c b/drivers/infiniband/sw/rxe/rxe_comp.c
    index c997b7cbf2a9e8..81b645c727a17c 100644
    --- a/drivers/infiniband/sw/rxe/rxe_comp.c
    +++ b/drivers/infiniband/sw/rxe/rxe_comp.c
    @@ -119,12 +119,15 @@ void retransmit_timer(struct timer_list *t)
     
     	rxe_dbg_qp(qp, "retransmit timer fired\n");
     
    +	if (!rxe_get(qp))
    +		return;
     	spin_lock_irqsave(&qp->state_lock, flags);
     	if (qp->valid) {
     		qp->comp.timeout = 1;
     		rxe_sched_task(&qp->comp.task);
     	}
     	spin_unlock_irqrestore(&qp->state_lock, flags);
    +	rxe_put(qp);
     }
     
     void rxe_comp_queue_pkt(struct rxe_qp *qp, struct sk_buff *skb)
    
  • drivers/infiniband/sw/rxe/rxe_req.c+3 1 modified
    diff --git a/drivers/infiniband/sw/rxe/rxe_req.c b/drivers/infiniband/sw/rxe/rxe_req.c
    index 7ff152ffe15b9f..4d550ac0dac5ad 100644
    --- a/drivers/infiniband/sw/rxe/rxe_req.c
    +++ b/drivers/infiniband/sw/rxe/rxe_req.c
    @@ -103,6 +103,8 @@ void rnr_nak_timer(struct timer_list *t)
     
     	rxe_dbg_qp(qp, "nak timer fired\n");
     
    +	if (!rxe_get(qp))
    +		return;
     	spin_lock_irqsave(&qp->state_lock, flags);
     	if (qp->valid) {
     		/* request a send queue retry */
    @@ -111,6 +113,7 @@ void rnr_nak_timer(struct timer_list *t)
     		rxe_sched_task(&qp->req.task);
     	}
     	spin_unlock_irqrestore(&qp->state_lock, flags);
    +	rxe_put(qp);
     }
     
     static void req_check_sq_drain_done(struct rxe_qp *qp)
    -- 
    cgit 1.3-korg
    
    
    
  • drivers/infiniband/sw/rxe/rxe_req.c+3 1 modified
    diff --git a/drivers/infiniband/sw/rxe/rxe_req.c b/drivers/infiniband/sw/rxe/rxe_req.c
    index 7ff152ffe15b9f..4d550ac0dac5ad 100644
    --- a/drivers/infiniband/sw/rxe/rxe_req.c
    +++ b/drivers/infiniband/sw/rxe/rxe_req.c
    @@ -103,6 +103,8 @@ void rnr_nak_timer(struct timer_list *t)
     
     	rxe_dbg_qp(qp, "nak timer fired\n");
     
    +	if (!rxe_get(qp))
    +		return;
     	spin_lock_irqsave(&qp->state_lock, flags);
     	if (qp->valid) {
     		/* request a send queue retry */
    @@ -111,6 +113,7 @@ void rnr_nak_timer(struct timer_list *t)
     		rxe_sched_task(&qp->req.task);
     	}
     	spin_unlock_irqrestore(&qp->state_lock, flags);
    +	rxe_put(qp);
     }
     
     static void req_check_sq_drain_done(struct rxe_qp *qp)
    -- 
    cgit 1.3-korg
    
    
    
3c2ae79fb19d

RDMA/rxe: Fix race condition in QP timer handlers

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitLi ZhijianJan 20, 2026Fixed in 6.12.75via kernel-cna
4 files changed · +12 2
  • drivers/infiniband/sw/rxe/rxe_comp.c+3 0 modified
    diff --git a/drivers/infiniband/sw/rxe/rxe_comp.c b/drivers/infiniband/sw/rxe/rxe_comp.c
    index d48af218074588..e02c5df0bef14c 100644
    --- a/drivers/infiniband/sw/rxe/rxe_comp.c
    +++ b/drivers/infiniband/sw/rxe/rxe_comp.c
    @@ -119,12 +119,15 @@ void retransmit_timer(struct timer_list *t)
     
     	rxe_dbg_qp(qp, "retransmit timer fired\n");
     
    +	if (!rxe_get(qp))
    +		return;
     	spin_lock_irqsave(&qp->state_lock, flags);
     	if (qp->valid) {
     		qp->comp.timeout = 1;
     		rxe_sched_task(&qp->send_task);
     	}
     	spin_unlock_irqrestore(&qp->state_lock, flags);
    +	rxe_put(qp);
     }
     
     void rxe_comp_queue_pkt(struct rxe_qp *qp, struct sk_buff *skb)
    
  • drivers/infiniband/sw/rxe/rxe_comp.c+3 0 modified
    diff --git a/drivers/infiniband/sw/rxe/rxe_comp.c b/drivers/infiniband/sw/rxe/rxe_comp.c
    index d48af218074588..e02c5df0bef14c 100644
    --- a/drivers/infiniband/sw/rxe/rxe_comp.c
    +++ b/drivers/infiniband/sw/rxe/rxe_comp.c
    @@ -119,12 +119,15 @@ void retransmit_timer(struct timer_list *t)
     
     	rxe_dbg_qp(qp, "retransmit timer fired\n");
     
    +	if (!rxe_get(qp))
    +		return;
     	spin_lock_irqsave(&qp->state_lock, flags);
     	if (qp->valid) {
     		qp->comp.timeout = 1;
     		rxe_sched_task(&qp->send_task);
     	}
     	spin_unlock_irqrestore(&qp->state_lock, flags);
    +	rxe_put(qp);
     }
     
     void rxe_comp_queue_pkt(struct rxe_qp *qp, struct sk_buff *skb)
    
  • drivers/infiniband/sw/rxe/rxe_req.c+3 1 modified
    diff --git a/drivers/infiniband/sw/rxe/rxe_req.c b/drivers/infiniband/sw/rxe/rxe_req.c
    index 87a02f0deb0001..d08ebb048cb0f3 100644
    --- a/drivers/infiniband/sw/rxe/rxe_req.c
    +++ b/drivers/infiniband/sw/rxe/rxe_req.c
    @@ -103,6 +103,8 @@ void rnr_nak_timer(struct timer_list *t)
     
     	rxe_dbg_qp(qp, "nak timer fired\n");
     
    +	if (!rxe_get(qp))
    +		return;
     	spin_lock_irqsave(&qp->state_lock, flags);
     	if (qp->valid) {
     		/* request a send queue retry */
    @@ -111,6 +113,7 @@ void rnr_nak_timer(struct timer_list *t)
     		rxe_sched_task(&qp->send_task);
     	}
     	spin_unlock_irqrestore(&qp->state_lock, flags);
    +	rxe_put(qp);
     }
     
     static void req_check_sq_drain_done(struct rxe_qp *qp)
    -- 
    cgit 1.3-korg
    
    
    
  • drivers/infiniband/sw/rxe/rxe_req.c+3 1 modified
    diff --git a/drivers/infiniband/sw/rxe/rxe_req.c b/drivers/infiniband/sw/rxe/rxe_req.c
    index 87a02f0deb0001..d08ebb048cb0f3 100644
    --- a/drivers/infiniband/sw/rxe/rxe_req.c
    +++ b/drivers/infiniband/sw/rxe/rxe_req.c
    @@ -103,6 +103,8 @@ void rnr_nak_timer(struct timer_list *t)
     
     	rxe_dbg_qp(qp, "nak timer fired\n");
     
    +	if (!rxe_get(qp))
    +		return;
     	spin_lock_irqsave(&qp->state_lock, flags);
     	if (qp->valid) {
     		/* request a send queue retry */
    @@ -111,6 +113,7 @@ void rnr_nak_timer(struct timer_list *t)
     		rxe_sched_task(&qp->send_task);
     	}
     	spin_unlock_irqrestore(&qp->state_lock, flags);
    +	rxe_put(qp);
     }
     
     static void req_check_sq_drain_done(struct rxe_qp *qp)
    -- 
    cgit 1.3-korg
    
    
    
5ae9da022ee3

RDMA/rxe: Fix race condition in QP timer handlers

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitLi ZhijianJan 20, 2026Fixed in 6.18.14via kernel-cna
4 files changed · +12 2
  • drivers/infiniband/sw/rxe/rxe_comp.c+3 0 modified
    diff --git a/drivers/infiniband/sw/rxe/rxe_comp.c b/drivers/infiniband/sw/rxe/rxe_comp.c
    index a5b2b62f596b05..1390e861bd1d74 100644
    --- a/drivers/infiniband/sw/rxe/rxe_comp.c
    +++ b/drivers/infiniband/sw/rxe/rxe_comp.c
    @@ -119,12 +119,15 @@ void retransmit_timer(struct timer_list *t)
     
     	rxe_dbg_qp(qp, "retransmit timer fired\n");
     
    +	if (!rxe_get(qp))
    +		return;
     	spin_lock_irqsave(&qp->state_lock, flags);
     	if (qp->valid) {
     		qp->comp.timeout = 1;
     		rxe_sched_task(&qp->send_task);
     	}
     	spin_unlock_irqrestore(&qp->state_lock, flags);
    +	rxe_put(qp);
     }
     
     void rxe_comp_queue_pkt(struct rxe_qp *qp, struct sk_buff *skb)
    
  • drivers/infiniband/sw/rxe/rxe_comp.c+3 0 modified
    diff --git a/drivers/infiniband/sw/rxe/rxe_comp.c b/drivers/infiniband/sw/rxe/rxe_comp.c
    index a5b2b62f596b05..1390e861bd1d74 100644
    --- a/drivers/infiniband/sw/rxe/rxe_comp.c
    +++ b/drivers/infiniband/sw/rxe/rxe_comp.c
    @@ -119,12 +119,15 @@ void retransmit_timer(struct timer_list *t)
     
     	rxe_dbg_qp(qp, "retransmit timer fired\n");
     
    +	if (!rxe_get(qp))
    +		return;
     	spin_lock_irqsave(&qp->state_lock, flags);
     	if (qp->valid) {
     		qp->comp.timeout = 1;
     		rxe_sched_task(&qp->send_task);
     	}
     	spin_unlock_irqrestore(&qp->state_lock, flags);
    +	rxe_put(qp);
     }
     
     void rxe_comp_queue_pkt(struct rxe_qp *qp, struct sk_buff *skb)
    
  • drivers/infiniband/sw/rxe/rxe_req.c+3 1 modified
    diff --git a/drivers/infiniband/sw/rxe/rxe_req.c b/drivers/infiniband/sw/rxe/rxe_req.c
    index 373b03f223bebc..12d03f390b0978 100644
    --- a/drivers/infiniband/sw/rxe/rxe_req.c
    +++ b/drivers/infiniband/sw/rxe/rxe_req.c
    @@ -102,6 +102,8 @@ void rnr_nak_timer(struct timer_list *t)
     
     	rxe_dbg_qp(qp, "nak timer fired\n");
     
    +	if (!rxe_get(qp))
    +		return;
     	spin_lock_irqsave(&qp->state_lock, flags);
     	if (qp->valid) {
     		/* request a send queue retry */
    @@ -110,6 +112,7 @@ void rnr_nak_timer(struct timer_list *t)
     		rxe_sched_task(&qp->send_task);
     	}
     	spin_unlock_irqrestore(&qp->state_lock, flags);
    +	rxe_put(qp);
     }
     
     static void req_check_sq_drain_done(struct rxe_qp *qp)
    -- 
    cgit 1.3-korg
    
    
    
  • drivers/infiniband/sw/rxe/rxe_req.c+3 1 modified
    diff --git a/drivers/infiniband/sw/rxe/rxe_req.c b/drivers/infiniband/sw/rxe/rxe_req.c
    index 373b03f223bebc..12d03f390b0978 100644
    --- a/drivers/infiniband/sw/rxe/rxe_req.c
    +++ b/drivers/infiniband/sw/rxe/rxe_req.c
    @@ -102,6 +102,8 @@ void rnr_nak_timer(struct timer_list *t)
     
     	rxe_dbg_qp(qp, "nak timer fired\n");
     
    +	if (!rxe_get(qp))
    +		return;
     	spin_lock_irqsave(&qp->state_lock, flags);
     	if (qp->valid) {
     		/* request a send queue retry */
    @@ -110,6 +112,7 @@ void rnr_nak_timer(struct timer_list *t)
     		rxe_sched_task(&qp->send_task);
     	}
     	spin_unlock_irqrestore(&qp->state_lock, flags);
    +	rxe_put(qp);
     }
     
     static void req_check_sq_drain_done(struct rxe_qp *qp)
    -- 
    cgit 1.3-korg
    
    
    
da379ca16af3

RDMA/rxe: Fix race condition in QP timer handlers

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitLi ZhijianJan 20, 2026Fixed in 6.19.4via kernel-cna
4 files changed · +12 2
  • drivers/infiniband/sw/rxe/rxe_comp.c+3 0 modified
    diff --git a/drivers/infiniband/sw/rxe/rxe_comp.c b/drivers/infiniband/sw/rxe/rxe_comp.c
    index a5b2b62f596b05..1390e861bd1d74 100644
    --- a/drivers/infiniband/sw/rxe/rxe_comp.c
    +++ b/drivers/infiniband/sw/rxe/rxe_comp.c
    @@ -119,12 +119,15 @@ void retransmit_timer(struct timer_list *t)
     
     	rxe_dbg_qp(qp, "retransmit timer fired\n");
     
    +	if (!rxe_get(qp))
    +		return;
     	spin_lock_irqsave(&qp->state_lock, flags);
     	if (qp->valid) {
     		qp->comp.timeout = 1;
     		rxe_sched_task(&qp->send_task);
     	}
     	spin_unlock_irqrestore(&qp->state_lock, flags);
    +	rxe_put(qp);
     }
     
     void rxe_comp_queue_pkt(struct rxe_qp *qp, struct sk_buff *skb)
    
  • drivers/infiniband/sw/rxe/rxe_comp.c+3 0 modified
    diff --git a/drivers/infiniband/sw/rxe/rxe_comp.c b/drivers/infiniband/sw/rxe/rxe_comp.c
    index a5b2b62f596b05..1390e861bd1d74 100644
    --- a/drivers/infiniband/sw/rxe/rxe_comp.c
    +++ b/drivers/infiniband/sw/rxe/rxe_comp.c
    @@ -119,12 +119,15 @@ void retransmit_timer(struct timer_list *t)
     
     	rxe_dbg_qp(qp, "retransmit timer fired\n");
     
    +	if (!rxe_get(qp))
    +		return;
     	spin_lock_irqsave(&qp->state_lock, flags);
     	if (qp->valid) {
     		qp->comp.timeout = 1;
     		rxe_sched_task(&qp->send_task);
     	}
     	spin_unlock_irqrestore(&qp->state_lock, flags);
    +	rxe_put(qp);
     }
     
     void rxe_comp_queue_pkt(struct rxe_qp *qp, struct sk_buff *skb)
    
  • drivers/infiniband/sw/rxe/rxe_req.c+3 1 modified
    diff --git a/drivers/infiniband/sw/rxe/rxe_req.c b/drivers/infiniband/sw/rxe/rxe_req.c
    index 373b03f223bebc..12d03f390b0978 100644
    --- a/drivers/infiniband/sw/rxe/rxe_req.c
    +++ b/drivers/infiniband/sw/rxe/rxe_req.c
    @@ -102,6 +102,8 @@ void rnr_nak_timer(struct timer_list *t)
     
     	rxe_dbg_qp(qp, "nak timer fired\n");
     
    +	if (!rxe_get(qp))
    +		return;
     	spin_lock_irqsave(&qp->state_lock, flags);
     	if (qp->valid) {
     		/* request a send queue retry */
    @@ -110,6 +112,7 @@ void rnr_nak_timer(struct timer_list *t)
     		rxe_sched_task(&qp->send_task);
     	}
     	spin_unlock_irqrestore(&qp->state_lock, flags);
    +	rxe_put(qp);
     }
     
     static void req_check_sq_drain_done(struct rxe_qp *qp)
    -- 
    cgit 1.3-korg
    
    
    
  • drivers/infiniband/sw/rxe/rxe_req.c+3 1 modified
    diff --git a/drivers/infiniband/sw/rxe/rxe_req.c b/drivers/infiniband/sw/rxe/rxe_req.c
    index 373b03f223bebc..12d03f390b0978 100644
    --- a/drivers/infiniband/sw/rxe/rxe_req.c
    +++ b/drivers/infiniband/sw/rxe/rxe_req.c
    @@ -102,6 +102,8 @@ void rnr_nak_timer(struct timer_list *t)
     
     	rxe_dbg_qp(qp, "nak timer fired\n");
     
    +	if (!rxe_get(qp))
    +		return;
     	spin_lock_irqsave(&qp->state_lock, flags);
     	if (qp->valid) {
     		/* request a send queue retry */
    @@ -110,6 +112,7 @@ void rnr_nak_timer(struct timer_list *t)
     		rxe_sched_task(&qp->send_task);
     	}
     	spin_unlock_irqrestore(&qp->state_lock, flags);
    +	rxe_put(qp);
     }
     
     static void req_check_sq_drain_done(struct rxe_qp *qp)
    -- 
    cgit 1.3-korg
    
    
    
3c2ae79fb19d

RDMA/rxe: Fix race condition in QP timer handlers

4 files changed · +12 2
  • drivers/infiniband/sw/rxe/rxe_comp.c+3 0 modified
    diff --git a/drivers/infiniband/sw/rxe/rxe_comp.c b/drivers/infiniband/sw/rxe/rxe_comp.c
    index d48af218074588..e02c5df0bef14c 100644
    --- a/drivers/infiniband/sw/rxe/rxe_comp.c
    +++ b/drivers/infiniband/sw/rxe/rxe_comp.c
    @@ -119,12 +119,15 @@ void retransmit_timer(struct timer_list *t)
     
     	rxe_dbg_qp(qp, "retransmit timer fired\n");
     
    +	if (!rxe_get(qp))
    +		return;
     	spin_lock_irqsave(&qp->state_lock, flags);
     	if (qp->valid) {
     		qp->comp.timeout = 1;
     		rxe_sched_task(&qp->send_task);
     	}
     	spin_unlock_irqrestore(&qp->state_lock, flags);
    +	rxe_put(qp);
     }
     
     void rxe_comp_queue_pkt(struct rxe_qp *qp, struct sk_buff *skb)
    
  • drivers/infiniband/sw/rxe/rxe_comp.c+3 0 modified
    diff --git a/drivers/infiniband/sw/rxe/rxe_comp.c b/drivers/infiniband/sw/rxe/rxe_comp.c
    index d48af218074588..e02c5df0bef14c 100644
    --- a/drivers/infiniband/sw/rxe/rxe_comp.c
    +++ b/drivers/infiniband/sw/rxe/rxe_comp.c
    @@ -119,12 +119,15 @@ void retransmit_timer(struct timer_list *t)
     
     	rxe_dbg_qp(qp, "retransmit timer fired\n");
     
    +	if (!rxe_get(qp))
    +		return;
     	spin_lock_irqsave(&qp->state_lock, flags);
     	if (qp->valid) {
     		qp->comp.timeout = 1;
     		rxe_sched_task(&qp->send_task);
     	}
     	spin_unlock_irqrestore(&qp->state_lock, flags);
    +	rxe_put(qp);
     }
     
     void rxe_comp_queue_pkt(struct rxe_qp *qp, struct sk_buff *skb)
    
  • drivers/infiniband/sw/rxe/rxe_req.c+3 1 modified
    diff --git a/drivers/infiniband/sw/rxe/rxe_req.c b/drivers/infiniband/sw/rxe/rxe_req.c
    index 87a02f0deb0001..d08ebb048cb0f3 100644
    --- a/drivers/infiniband/sw/rxe/rxe_req.c
    +++ b/drivers/infiniband/sw/rxe/rxe_req.c
    @@ -103,6 +103,8 @@ void rnr_nak_timer(struct timer_list *t)
     
     	rxe_dbg_qp(qp, "nak timer fired\n");
     
    +	if (!rxe_get(qp))
    +		return;
     	spin_lock_irqsave(&qp->state_lock, flags);
     	if (qp->valid) {
     		/* request a send queue retry */
    @@ -111,6 +113,7 @@ void rnr_nak_timer(struct timer_list *t)
     		rxe_sched_task(&qp->send_task);
     	}
     	spin_unlock_irqrestore(&qp->state_lock, flags);
    +	rxe_put(qp);
     }
     
     static void req_check_sq_drain_done(struct rxe_qp *qp)
    -- 
    cgit 1.3-korg
    
    
    
  • drivers/infiniband/sw/rxe/rxe_req.c+3 1 modified
    diff --git a/drivers/infiniband/sw/rxe/rxe_req.c b/drivers/infiniband/sw/rxe/rxe_req.c
    index 87a02f0deb0001..d08ebb048cb0f3 100644
    --- a/drivers/infiniband/sw/rxe/rxe_req.c
    +++ b/drivers/infiniband/sw/rxe/rxe_req.c
    @@ -103,6 +103,8 @@ void rnr_nak_timer(struct timer_list *t)
     
     	rxe_dbg_qp(qp, "nak timer fired\n");
     
    +	if (!rxe_get(qp))
    +		return;
     	spin_lock_irqsave(&qp->state_lock, flags);
     	if (qp->valid) {
     		/* request a send queue retry */
    @@ -111,6 +113,7 @@ void rnr_nak_timer(struct timer_list *t)
     		rxe_sched_task(&qp->send_task);
     	}
     	spin_unlock_irqrestore(&qp->state_lock, flags);
    +	rxe_put(qp);
     }
     
     static void req_check_sq_drain_done(struct rxe_qp *qp)
    -- 
    cgit 1.3-korg
    
    
    
5ae9da022ee3

RDMA/rxe: Fix race condition in QP timer handlers

4 files changed · +12 2
  • drivers/infiniband/sw/rxe/rxe_comp.c+3 0 modified
    diff --git a/drivers/infiniband/sw/rxe/rxe_comp.c b/drivers/infiniband/sw/rxe/rxe_comp.c
    index a5b2b62f596b05..1390e861bd1d74 100644
    --- a/drivers/infiniband/sw/rxe/rxe_comp.c
    +++ b/drivers/infiniband/sw/rxe/rxe_comp.c
    @@ -119,12 +119,15 @@ void retransmit_timer(struct timer_list *t)
     
     	rxe_dbg_qp(qp, "retransmit timer fired\n");
     
    +	if (!rxe_get(qp))
    +		return;
     	spin_lock_irqsave(&qp->state_lock, flags);
     	if (qp->valid) {
     		qp->comp.timeout = 1;
     		rxe_sched_task(&qp->send_task);
     	}
     	spin_unlock_irqrestore(&qp->state_lock, flags);
    +	rxe_put(qp);
     }
     
     void rxe_comp_queue_pkt(struct rxe_qp *qp, struct sk_buff *skb)
    
  • drivers/infiniband/sw/rxe/rxe_comp.c+3 0 modified
    diff --git a/drivers/infiniband/sw/rxe/rxe_comp.c b/drivers/infiniband/sw/rxe/rxe_comp.c
    index a5b2b62f596b05..1390e861bd1d74 100644
    --- a/drivers/infiniband/sw/rxe/rxe_comp.c
    +++ b/drivers/infiniband/sw/rxe/rxe_comp.c
    @@ -119,12 +119,15 @@ void retransmit_timer(struct timer_list *t)
     
     	rxe_dbg_qp(qp, "retransmit timer fired\n");
     
    +	if (!rxe_get(qp))
    +		return;
     	spin_lock_irqsave(&qp->state_lock, flags);
     	if (qp->valid) {
     		qp->comp.timeout = 1;
     		rxe_sched_task(&qp->send_task);
     	}
     	spin_unlock_irqrestore(&qp->state_lock, flags);
    +	rxe_put(qp);
     }
     
     void rxe_comp_queue_pkt(struct rxe_qp *qp, struct sk_buff *skb)
    
  • drivers/infiniband/sw/rxe/rxe_req.c+3 1 modified
    diff --git a/drivers/infiniband/sw/rxe/rxe_req.c b/drivers/infiniband/sw/rxe/rxe_req.c
    index 373b03f223bebc..12d03f390b0978 100644
    --- a/drivers/infiniband/sw/rxe/rxe_req.c
    +++ b/drivers/infiniband/sw/rxe/rxe_req.c
    @@ -102,6 +102,8 @@ void rnr_nak_timer(struct timer_list *t)
     
     	rxe_dbg_qp(qp, "nak timer fired\n");
     
    +	if (!rxe_get(qp))
    +		return;
     	spin_lock_irqsave(&qp->state_lock, flags);
     	if (qp->valid) {
     		/* request a send queue retry */
    @@ -110,6 +112,7 @@ void rnr_nak_timer(struct timer_list *t)
     		rxe_sched_task(&qp->send_task);
     	}
     	spin_unlock_irqrestore(&qp->state_lock, flags);
    +	rxe_put(qp);
     }
     
     static void req_check_sq_drain_done(struct rxe_qp *qp)
    -- 
    cgit 1.3-korg
    
    
    
  • drivers/infiniband/sw/rxe/rxe_req.c+3 1 modified
    diff --git a/drivers/infiniband/sw/rxe/rxe_req.c b/drivers/infiniband/sw/rxe/rxe_req.c
    index 373b03f223bebc..12d03f390b0978 100644
    --- a/drivers/infiniband/sw/rxe/rxe_req.c
    +++ b/drivers/infiniband/sw/rxe/rxe_req.c
    @@ -102,6 +102,8 @@ void rnr_nak_timer(struct timer_list *t)
     
     	rxe_dbg_qp(qp, "nak timer fired\n");
     
    +	if (!rxe_get(qp))
    +		return;
     	spin_lock_irqsave(&qp->state_lock, flags);
     	if (qp->valid) {
     		/* request a send queue retry */
    @@ -110,6 +112,7 @@ void rnr_nak_timer(struct timer_list *t)
     		rxe_sched_task(&qp->send_task);
     	}
     	spin_unlock_irqrestore(&qp->state_lock, flags);
    +	rxe_put(qp);
     }
     
     static void req_check_sq_drain_done(struct rxe_qp *qp)
    -- 
    cgit 1.3-korg
    
    
    
756c93d6df7c

RDMA/rxe: Fix race condition in QP timer handlers

4 files changed · +12 2
  • drivers/infiniband/sw/rxe/rxe_comp.c+3 0 modified
    diff --git a/drivers/infiniband/sw/rxe/rxe_comp.c b/drivers/infiniband/sw/rxe/rxe_comp.c
    index c997b7cbf2a9e8..81b645c727a17c 100644
    --- a/drivers/infiniband/sw/rxe/rxe_comp.c
    +++ b/drivers/infiniband/sw/rxe/rxe_comp.c
    @@ -119,12 +119,15 @@ void retransmit_timer(struct timer_list *t)
     
     	rxe_dbg_qp(qp, "retransmit timer fired\n");
     
    +	if (!rxe_get(qp))
    +		return;
     	spin_lock_irqsave(&qp->state_lock, flags);
     	if (qp->valid) {
     		qp->comp.timeout = 1;
     		rxe_sched_task(&qp->comp.task);
     	}
     	spin_unlock_irqrestore(&qp->state_lock, flags);
    +	rxe_put(qp);
     }
     
     void rxe_comp_queue_pkt(struct rxe_qp *qp, struct sk_buff *skb)
    
  • drivers/infiniband/sw/rxe/rxe_comp.c+3 0 modified
    diff --git a/drivers/infiniband/sw/rxe/rxe_comp.c b/drivers/infiniband/sw/rxe/rxe_comp.c
    index c997b7cbf2a9e8..81b645c727a17c 100644
    --- a/drivers/infiniband/sw/rxe/rxe_comp.c
    +++ b/drivers/infiniband/sw/rxe/rxe_comp.c
    @@ -119,12 +119,15 @@ void retransmit_timer(struct timer_list *t)
     
     	rxe_dbg_qp(qp, "retransmit timer fired\n");
     
    +	if (!rxe_get(qp))
    +		return;
     	spin_lock_irqsave(&qp->state_lock, flags);
     	if (qp->valid) {
     		qp->comp.timeout = 1;
     		rxe_sched_task(&qp->comp.task);
     	}
     	spin_unlock_irqrestore(&qp->state_lock, flags);
    +	rxe_put(qp);
     }
     
     void rxe_comp_queue_pkt(struct rxe_qp *qp, struct sk_buff *skb)
    
  • drivers/infiniband/sw/rxe/rxe_req.c+3 1 modified
    diff --git a/drivers/infiniband/sw/rxe/rxe_req.c b/drivers/infiniband/sw/rxe/rxe_req.c
    index 7ff152ffe15b9f..4d550ac0dac5ad 100644
    --- a/drivers/infiniband/sw/rxe/rxe_req.c
    +++ b/drivers/infiniband/sw/rxe/rxe_req.c
    @@ -103,6 +103,8 @@ void rnr_nak_timer(struct timer_list *t)
     
     	rxe_dbg_qp(qp, "nak timer fired\n");
     
    +	if (!rxe_get(qp))
    +		return;
     	spin_lock_irqsave(&qp->state_lock, flags);
     	if (qp->valid) {
     		/* request a send queue retry */
    @@ -111,6 +113,7 @@ void rnr_nak_timer(struct timer_list *t)
     		rxe_sched_task(&qp->req.task);
     	}
     	spin_unlock_irqrestore(&qp->state_lock, flags);
    +	rxe_put(qp);
     }
     
     static void req_check_sq_drain_done(struct rxe_qp *qp)
    -- 
    cgit 1.3-korg
    
    
    
  • drivers/infiniband/sw/rxe/rxe_req.c+3 1 modified
    diff --git a/drivers/infiniband/sw/rxe/rxe_req.c b/drivers/infiniband/sw/rxe/rxe_req.c
    index 7ff152ffe15b9f..4d550ac0dac5ad 100644
    --- a/drivers/infiniband/sw/rxe/rxe_req.c
    +++ b/drivers/infiniband/sw/rxe/rxe_req.c
    @@ -103,6 +103,8 @@ void rnr_nak_timer(struct timer_list *t)
     
     	rxe_dbg_qp(qp, "nak timer fired\n");
     
    +	if (!rxe_get(qp))
    +		return;
     	spin_lock_irqsave(&qp->state_lock, flags);
     	if (qp->valid) {
     		/* request a send queue retry */
    @@ -111,6 +113,7 @@ void rnr_nak_timer(struct timer_list *t)
     		rxe_sched_task(&qp->req.task);
     	}
     	spin_unlock_irqrestore(&qp->state_lock, flags);
    +	rxe_put(qp);
     }
     
     static void req_check_sq_drain_done(struct rxe_qp *qp)
    -- 
    cgit 1.3-korg
    
    
    
87bf64692143

RDMA/rxe: Fix race condition in QP timer handlers

4 files changed · +12 2
  • drivers/infiniband/sw/rxe/rxe_comp.c+3 0 modified
    diff --git a/drivers/infiniband/sw/rxe/rxe_comp.c b/drivers/infiniband/sw/rxe/rxe_comp.c
    index a5b2b62f596b05..1390e861bd1d74 100644
    --- a/drivers/infiniband/sw/rxe/rxe_comp.c
    +++ b/drivers/infiniband/sw/rxe/rxe_comp.c
    @@ -119,12 +119,15 @@ void retransmit_timer(struct timer_list *t)
     
     	rxe_dbg_qp(qp, "retransmit timer fired\n");
     
    +	if (!rxe_get(qp))
    +		return;
     	spin_lock_irqsave(&qp->state_lock, flags);
     	if (qp->valid) {
     		qp->comp.timeout = 1;
     		rxe_sched_task(&qp->send_task);
     	}
     	spin_unlock_irqrestore(&qp->state_lock, flags);
    +	rxe_put(qp);
     }
     
     void rxe_comp_queue_pkt(struct rxe_qp *qp, struct sk_buff *skb)
    
  • drivers/infiniband/sw/rxe/rxe_comp.c+3 0 modified
    diff --git a/drivers/infiniband/sw/rxe/rxe_comp.c b/drivers/infiniband/sw/rxe/rxe_comp.c
    index a5b2b62f596b05..1390e861bd1d74 100644
    --- a/drivers/infiniband/sw/rxe/rxe_comp.c
    +++ b/drivers/infiniband/sw/rxe/rxe_comp.c
    @@ -119,12 +119,15 @@ void retransmit_timer(struct timer_list *t)
     
     	rxe_dbg_qp(qp, "retransmit timer fired\n");
     
    +	if (!rxe_get(qp))
    +		return;
     	spin_lock_irqsave(&qp->state_lock, flags);
     	if (qp->valid) {
     		qp->comp.timeout = 1;
     		rxe_sched_task(&qp->send_task);
     	}
     	spin_unlock_irqrestore(&qp->state_lock, flags);
    +	rxe_put(qp);
     }
     
     void rxe_comp_queue_pkt(struct rxe_qp *qp, struct sk_buff *skb)
    
  • drivers/infiniband/sw/rxe/rxe_req.c+3 1 modified
    diff --git a/drivers/infiniband/sw/rxe/rxe_req.c b/drivers/infiniband/sw/rxe/rxe_req.c
    index 373b03f223bebc..12d03f390b0978 100644
    --- a/drivers/infiniband/sw/rxe/rxe_req.c
    +++ b/drivers/infiniband/sw/rxe/rxe_req.c
    @@ -102,6 +102,8 @@ void rnr_nak_timer(struct timer_list *t)
     
     	rxe_dbg_qp(qp, "nak timer fired\n");
     
    +	if (!rxe_get(qp))
    +		return;
     	spin_lock_irqsave(&qp->state_lock, flags);
     	if (qp->valid) {
     		/* request a send queue retry */
    @@ -110,6 +112,7 @@ void rnr_nak_timer(struct timer_list *t)
     		rxe_sched_task(&qp->send_task);
     	}
     	spin_unlock_irqrestore(&qp->state_lock, flags);
    +	rxe_put(qp);
     }
     
     static void req_check_sq_drain_done(struct rxe_qp *qp)
    -- 
    cgit 1.3-korg
    
    
    
  • drivers/infiniband/sw/rxe/rxe_req.c+3 1 modified
    diff --git a/drivers/infiniband/sw/rxe/rxe_req.c b/drivers/infiniband/sw/rxe/rxe_req.c
    index 373b03f223bebc..12d03f390b0978 100644
    --- a/drivers/infiniband/sw/rxe/rxe_req.c
    +++ b/drivers/infiniband/sw/rxe/rxe_req.c
    @@ -102,6 +102,8 @@ void rnr_nak_timer(struct timer_list *t)
     
     	rxe_dbg_qp(qp, "nak timer fired\n");
     
    +	if (!rxe_get(qp))
    +		return;
     	spin_lock_irqsave(&qp->state_lock, flags);
     	if (qp->valid) {
     		/* request a send queue retry */
    @@ -110,6 +112,7 @@ void rnr_nak_timer(struct timer_list *t)
     		rxe_sched_task(&qp->send_task);
     	}
     	spin_unlock_irqrestore(&qp->state_lock, flags);
    +	rxe_put(qp);
     }
     
     static void req_check_sq_drain_done(struct rxe_qp *qp)
    -- 
    cgit 1.3-korg
    
    
    
da379ca16af3

RDMA/rxe: Fix race condition in QP timer handlers

4 files changed · +12 2
  • drivers/infiniband/sw/rxe/rxe_comp.c+3 0 modified
    diff --git a/drivers/infiniband/sw/rxe/rxe_comp.c b/drivers/infiniband/sw/rxe/rxe_comp.c
    index a5b2b62f596b05..1390e861bd1d74 100644
    --- a/drivers/infiniband/sw/rxe/rxe_comp.c
    +++ b/drivers/infiniband/sw/rxe/rxe_comp.c
    @@ -119,12 +119,15 @@ void retransmit_timer(struct timer_list *t)
     
     	rxe_dbg_qp(qp, "retransmit timer fired\n");
     
    +	if (!rxe_get(qp))
    +		return;
     	spin_lock_irqsave(&qp->state_lock, flags);
     	if (qp->valid) {
     		qp->comp.timeout = 1;
     		rxe_sched_task(&qp->send_task);
     	}
     	spin_unlock_irqrestore(&qp->state_lock, flags);
    +	rxe_put(qp);
     }
     
     void rxe_comp_queue_pkt(struct rxe_qp *qp, struct sk_buff *skb)
    
  • drivers/infiniband/sw/rxe/rxe_comp.c+3 0 modified
    diff --git a/drivers/infiniband/sw/rxe/rxe_comp.c b/drivers/infiniband/sw/rxe/rxe_comp.c
    index a5b2b62f596b05..1390e861bd1d74 100644
    --- a/drivers/infiniband/sw/rxe/rxe_comp.c
    +++ b/drivers/infiniband/sw/rxe/rxe_comp.c
    @@ -119,12 +119,15 @@ void retransmit_timer(struct timer_list *t)
     
     	rxe_dbg_qp(qp, "retransmit timer fired\n");
     
    +	if (!rxe_get(qp))
    +		return;
     	spin_lock_irqsave(&qp->state_lock, flags);
     	if (qp->valid) {
     		qp->comp.timeout = 1;
     		rxe_sched_task(&qp->send_task);
     	}
     	spin_unlock_irqrestore(&qp->state_lock, flags);
    +	rxe_put(qp);
     }
     
     void rxe_comp_queue_pkt(struct rxe_qp *qp, struct sk_buff *skb)
    
  • drivers/infiniband/sw/rxe/rxe_req.c+3 1 modified
    diff --git a/drivers/infiniband/sw/rxe/rxe_req.c b/drivers/infiniband/sw/rxe/rxe_req.c
    index 373b03f223bebc..12d03f390b0978 100644
    --- a/drivers/infiniband/sw/rxe/rxe_req.c
    +++ b/drivers/infiniband/sw/rxe/rxe_req.c
    @@ -102,6 +102,8 @@ void rnr_nak_timer(struct timer_list *t)
     
     	rxe_dbg_qp(qp, "nak timer fired\n");
     
    +	if (!rxe_get(qp))
    +		return;
     	spin_lock_irqsave(&qp->state_lock, flags);
     	if (qp->valid) {
     		/* request a send queue retry */
    @@ -110,6 +112,7 @@ void rnr_nak_timer(struct timer_list *t)
     		rxe_sched_task(&qp->send_task);
     	}
     	spin_unlock_irqrestore(&qp->state_lock, flags);
    +	rxe_put(qp);
     }
     
     static void req_check_sq_drain_done(struct rxe_qp *qp)
    -- 
    cgit 1.3-korg
    
    
    
  • drivers/infiniband/sw/rxe/rxe_req.c+3 1 modified
    diff --git a/drivers/infiniband/sw/rxe/rxe_req.c b/drivers/infiniband/sw/rxe/rxe_req.c
    index 373b03f223bebc..12d03f390b0978 100644
    --- a/drivers/infiniband/sw/rxe/rxe_req.c
    +++ b/drivers/infiniband/sw/rxe/rxe_req.c
    @@ -102,6 +102,8 @@ void rnr_nak_timer(struct timer_list *t)
     
     	rxe_dbg_qp(qp, "nak timer fired\n");
     
    +	if (!rxe_get(qp))
    +		return;
     	spin_lock_irqsave(&qp->state_lock, flags);
     	if (qp->valid) {
     		/* request a send queue retry */
    @@ -110,6 +112,7 @@ void rnr_nak_timer(struct timer_list *t)
     		rxe_sched_task(&qp->send_task);
     	}
     	spin_unlock_irqrestore(&qp->state_lock, flags);
    +	rxe_put(qp);
     }
     
     static void req_check_sq_drain_done(struct rxe_qp *qp)
    -- 
    cgit 1.3-korg
    
    
    

Vulnerability mechanics

Root cause

"Missing reference-count protection in timer callbacks allows a Queue Pair's refcount to drop to zero while a timer handler is still executing."

Attack vector

An attacker (or local user) triggers destruction of a QP via rxe_destroy_qp() while a retransmit_timer or rnr_nak_timer callback is already running on another CPU. Because the timer handlers did not hold a reference on the QP, the destruction path can decrement the refcount to zero and begin cleanup while the timer handler still accesses the QP. This race manifests as kernel warnings ("refcount_t: underflow; use-after-free") and can lead to a use-after-free condition on the QP object.

Affected code

The vulnerable functions are retransmit_timer() in drivers/infiniband/sw/rxe/rxe_comp.c and rnr_nak_timer() in drivers/infiniband/sw/rxe/rxe_req.c. Both are timer callbacks that accessed the QP without holding a reference count.

What the fix does

The patch adds rxe_get(qp) / rxe_put(qp) pairs to both retransmit_timer() (in rxe_comp.c) and rnr_nak_timer() (in rxe_req.c). Before any work is done, rxe_get(qp) attempts to increment the QP's reference count; if it fails (returns false) the handler returns immediately because the QP is already being torn down. After the handler finishes, rxe_put(qp) releases the reference. This ensures the QP cannot be freed while a timer callback is in progress, closing the race with rxe_destroy_qp().

Preconditions

  • inputThe attacker must be able to trigger QP destruction (rxe_destroy_qp) on a different CPU while a retransmit or RNR-NAK timer is firing for the same QP.
  • configThe RDMA/rxe driver must be loaded and a QP must have active timers (e.g., retransmit timer armed).

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

References

5

News mentions

0

No linked articles in our index yet.