VYPR
Unrated severityNVD Advisory· Published May 28, 2026

CVE-2026-46114

CVE-2026-46114

Description

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

RDMA/rxe: Reject non-8-byte ATOMIC_WRITE payloads

atomic_write_reply() at drivers/infiniband/sw/rxe/rxe_resp.c unconditionally dereferences 8 bytes at payload_addr(pkt):

value = *(u64 *)payload_addr(pkt);

check_rkey() previously accepted an ATOMIC_WRITE request with pktlen == resid == 0 because the length validation only compared pktlen against resid. A remote initiator that sets the RETH length to 0 therefore reaches atomic_write_reply() with a zero-byte logical payload, and the responder reads sizeof(u64) bytes from past the logical end of the packet into skb->head tailroom, then writes those 8 bytes into the attacker's MR via rxe_mr_do_atomic_write(). That is a remote disclosure of 4 bytes of kernel tailroom per probe (the other 4 bytes are the packet's own trailing ICRC).

IBA oA19-28 defines ATOMIC_WRITE as exactly 8 bytes. Anything else is protocol-invalid. Hoist a strict length check into check_rkey() so the responder never reaches the unchecked dereference, and keep the existing WRITE-family length logic for the normal RDMA WRITE path.

Reproduced on mainline with an unmodified rxe driver: a sustained zero-length ATOMIC_WRITE probe repeatedly leaks adjacent skb head-buffer bytes into the attacker's MR, including recognisable kernel strings and partial kernel-direct-map pointer words. With this patch applied the responder rejects the PDU and the MR stays all-zero.

AI Insight

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

Linux kernel RDMA/rxe driver improperly accepts zero-length ATOMIC_WRITE requests, leaking up to 4 bytes of kernel tailroom per probe into an attacker-controlled MR.

Vulnerability

In the Linux kernel RDMA/rxe driver, the atomic_write_reply() function in drivers/infiniband/sw/rxe/rxe_resp.c unconditionally reads 8 bytes from the packet payload via *(u64 *)payload_addr(pkt). The check_rkey() function earlier accepts an ATOMIC_WRITE request with pktlen == resid == 0 because the length validation only compares pktlen against resid. A remote initiator can set the RETH length to 0, reaching the unchecked dereference with a zero-byte logical payload. This affects all kernel versions with the rxe driver enabled before the fix [1].

Exploitation

An attacker on the RDMA network sends a crafted ATOMIC_WRITE request with a zero payload length. No authentication is needed beyond RDMA access to the target. The request bypasses the length check in check_rkey(), and the responder reads 8 bytes from past the logical end of the packet, into the skb->head tailroom. Four of those bytes come from adjacent kernel tailroom (the other four are the packet's ICRC). The responder then writes those 8 bytes into the attacker's Memory Region (MR) via rxe_mr_do_atomic_write(), effectively leaking the tailroom contents to the attacker.

Impact

Successful exploitation leaks up to 4 bytes of kernel heap tailroom per probe. The leaked data can include recognizable kernel strings and partial kernel-direct-map pointer words. Repeated probes can amass significant information, aiding further attacks. The attacker gains unauthorized read of kernel memory, breaching confidentiality. No modification or denial of service is described.

Mitigation

The fix is commit 1114c87aa6f195cf07da55a27b2122ae26557b26 in the Linux kernel stable tree, released on or after 2026-05-28. Users should apply this kernel update. No workaround is available other than disabling the rxe module (modprobe -r rdma_rxe) if the system cannot be immediately patched. The vulnerability is not listed on CISA KEV as of the publication date.

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

Affected products

1

Patches

10
1114c87aa6f1

RDMA/rxe: Reject non-8-byte ATOMIC_WRITE payloads

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitMichael BommaritoApr 18, 2026Fixed in 7.1-rc3via kernel-cna
1 file changed · +13 2
  • drivers/infiniband/sw/rxe/rxe_resp.c+13 2 modified
    diff --git a/drivers/infiniband/sw/rxe/rxe_resp.c b/drivers/infiniband/sw/rxe/rxe_resp.c
    index 9faf8c09aa8e42..9cb2f6fbf2dd6a 100644
    --- a/drivers/infiniband/sw/rxe/rxe_resp.c
    +++ b/drivers/infiniband/sw/rxe/rxe_resp.c
    @@ -540,7 +540,19 @@ static enum resp_states check_rkey(struct rxe_qp *qp,
     	}
     
     skip_check_range:
    -	if (pkt->mask & (RXE_WRITE_MASK | RXE_ATOMIC_WRITE_MASK)) {
    +	if (pkt->mask & RXE_ATOMIC_WRITE_MASK) {
    +		/* IBA oA19-28: ATOMIC_WRITE payload is exactly 8 bytes.
    +		 * Reject any other length before the responder reads
    +		 * sizeof(u64) bytes from payload_addr(pkt); a shorter
    +		 * payload would read past the logical end of the packet
    +		 * into skb->head tailroom.
    +		 */
    +		if (resid != sizeof(u64) || pktlen != sizeof(u64) ||
    +		    bth_pad(pkt)) {
    +			state = RESPST_ERR_LENGTH;
    +			goto err;
    +		}
    +	} else if (pkt->mask & RXE_WRITE_MASK) {
     		if (resid > mtu) {
     			if (pktlen != mtu || bth_pad(pkt)) {
     				state = RESPST_ERR_LENGTH;
    -- 
    cgit 1.3-korg
    
    
    
7ec1ed4747f5

RDMA/rxe: Reject non-8-byte ATOMIC_WRITE payloads

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitMichael BommaritoApr 18, 2026Fixed in 7.0.7via kernel-cna
2 files changed · +26 4
  • drivers/infiniband/sw/rxe/rxe_resp.c+13 2 modified
    diff --git a/drivers/infiniband/sw/rxe/rxe_resp.c b/drivers/infiniband/sw/rxe/rxe_resp.c
    index 711f73e0bbb1c3..09ba21d0f3c4fe 100644
    --- a/drivers/infiniband/sw/rxe/rxe_resp.c
    +++ b/drivers/infiniband/sw/rxe/rxe_resp.c
    @@ -526,7 +526,19 @@ static enum resp_states check_rkey(struct rxe_qp *qp,
     	}
     
     skip_check_range:
    -	if (pkt->mask & (RXE_WRITE_MASK | RXE_ATOMIC_WRITE_MASK)) {
    +	if (pkt->mask & RXE_ATOMIC_WRITE_MASK) {
    +		/* IBA oA19-28: ATOMIC_WRITE payload is exactly 8 bytes.
    +		 * Reject any other length before the responder reads
    +		 * sizeof(u64) bytes from payload_addr(pkt); a shorter
    +		 * payload would read past the logical end of the packet
    +		 * into skb->head tailroom.
    +		 */
    +		if (resid != sizeof(u64) || pktlen != sizeof(u64) ||
    +		    bth_pad(pkt)) {
    +			state = RESPST_ERR_LENGTH;
    +			goto err;
    +		}
    +	} else if (pkt->mask & RXE_WRITE_MASK) {
     		if (resid > mtu) {
     			if (pktlen != mtu || bth_pad(pkt)) {
     				state = RESPST_ERR_LENGTH;
    -- 
    cgit 1.3-korg
    
    
    
  • drivers/infiniband/sw/rxe/rxe_resp.c+13 2 modified
    diff --git a/drivers/infiniband/sw/rxe/rxe_resp.c b/drivers/infiniband/sw/rxe/rxe_resp.c
    index 711f73e0bbb1c3..09ba21d0f3c4fe 100644
    --- a/drivers/infiniband/sw/rxe/rxe_resp.c
    +++ b/drivers/infiniband/sw/rxe/rxe_resp.c
    @@ -526,7 +526,19 @@ static enum resp_states check_rkey(struct rxe_qp *qp,
     	}
     
     skip_check_range:
    -	if (pkt->mask & (RXE_WRITE_MASK | RXE_ATOMIC_WRITE_MASK)) {
    +	if (pkt->mask & RXE_ATOMIC_WRITE_MASK) {
    +		/* IBA oA19-28: ATOMIC_WRITE payload is exactly 8 bytes.
    +		 * Reject any other length before the responder reads
    +		 * sizeof(u64) bytes from payload_addr(pkt); a shorter
    +		 * payload would read past the logical end of the packet
    +		 * into skb->head tailroom.
    +		 */
    +		if (resid != sizeof(u64) || pktlen != sizeof(u64) ||
    +		    bth_pad(pkt)) {
    +			state = RESPST_ERR_LENGTH;
    +			goto err;
    +		}
    +	} else if (pkt->mask & RXE_WRITE_MASK) {
     		if (resid > mtu) {
     			if (pktlen != mtu || bth_pad(pkt)) {
     				state = RESPST_ERR_LENGTH;
    -- 
    cgit 1.3-korg
    
    
    
105bf79a23b8

RDMA/rxe: Reject non-8-byte ATOMIC_WRITE payloads

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitMichael BommaritoApr 18, 2026Fixed in 6.18.30via kernel-cna
2 files changed · +26 4
  • drivers/infiniband/sw/rxe/rxe_resp.c+13 2 modified
    diff --git a/drivers/infiniband/sw/rxe/rxe_resp.c b/drivers/infiniband/sw/rxe/rxe_resp.c
    index 711f73e0bbb1c3..09ba21d0f3c4fe 100644
    --- a/drivers/infiniband/sw/rxe/rxe_resp.c
    +++ b/drivers/infiniband/sw/rxe/rxe_resp.c
    @@ -526,7 +526,19 @@ static enum resp_states check_rkey(struct rxe_qp *qp,
     	}
     
     skip_check_range:
    -	if (pkt->mask & (RXE_WRITE_MASK | RXE_ATOMIC_WRITE_MASK)) {
    +	if (pkt->mask & RXE_ATOMIC_WRITE_MASK) {
    +		/* IBA oA19-28: ATOMIC_WRITE payload is exactly 8 bytes.
    +		 * Reject any other length before the responder reads
    +		 * sizeof(u64) bytes from payload_addr(pkt); a shorter
    +		 * payload would read past the logical end of the packet
    +		 * into skb->head tailroom.
    +		 */
    +		if (resid != sizeof(u64) || pktlen != sizeof(u64) ||
    +		    bth_pad(pkt)) {
    +			state = RESPST_ERR_LENGTH;
    +			goto err;
    +		}
    +	} else if (pkt->mask & RXE_WRITE_MASK) {
     		if (resid > mtu) {
     			if (pktlen != mtu || bth_pad(pkt)) {
     				state = RESPST_ERR_LENGTH;
    -- 
    cgit 1.3-korg
    
    
    
  • drivers/infiniband/sw/rxe/rxe_resp.c+13 2 modified
    diff --git a/drivers/infiniband/sw/rxe/rxe_resp.c b/drivers/infiniband/sw/rxe/rxe_resp.c
    index 711f73e0bbb1c3..09ba21d0f3c4fe 100644
    --- a/drivers/infiniband/sw/rxe/rxe_resp.c
    +++ b/drivers/infiniband/sw/rxe/rxe_resp.c
    @@ -526,7 +526,19 @@ static enum resp_states check_rkey(struct rxe_qp *qp,
     	}
     
     skip_check_range:
    -	if (pkt->mask & (RXE_WRITE_MASK | RXE_ATOMIC_WRITE_MASK)) {
    +	if (pkt->mask & RXE_ATOMIC_WRITE_MASK) {
    +		/* IBA oA19-28: ATOMIC_WRITE payload is exactly 8 bytes.
    +		 * Reject any other length before the responder reads
    +		 * sizeof(u64) bytes from payload_addr(pkt); a shorter
    +		 * payload would read past the logical end of the packet
    +		 * into skb->head tailroom.
    +		 */
    +		if (resid != sizeof(u64) || pktlen != sizeof(u64) ||
    +		    bth_pad(pkt)) {
    +			state = RESPST_ERR_LENGTH;
    +			goto err;
    +		}
    +	} else if (pkt->mask & RXE_WRITE_MASK) {
     		if (resid > mtu) {
     			if (pktlen != mtu || bth_pad(pkt)) {
     				state = RESPST_ERR_LENGTH;
    -- 
    cgit 1.3-korg
    
    
    
d415fce3fcde

RDMA/rxe: Reject non-8-byte ATOMIC_WRITE payloads

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitMichael BommaritoApr 18, 2026Fixed in 6.12.88via kernel-cna
2 files changed · +26 4
  • drivers/infiniband/sw/rxe/rxe_resp.c+13 2 modified
    diff --git a/drivers/infiniband/sw/rxe/rxe_resp.c b/drivers/infiniband/sw/rxe/rxe_resp.c
    index c11ab280551a86..29e32b91d74b88 100644
    --- a/drivers/infiniband/sw/rxe/rxe_resp.c
    +++ b/drivers/infiniband/sw/rxe/rxe_resp.c
    @@ -526,7 +526,19 @@ static enum resp_states check_rkey(struct rxe_qp *qp,
     	}
     
     skip_check_range:
    -	if (pkt->mask & (RXE_WRITE_MASK | RXE_ATOMIC_WRITE_MASK)) {
    +	if (pkt->mask & RXE_ATOMIC_WRITE_MASK) {
    +		/* IBA oA19-28: ATOMIC_WRITE payload is exactly 8 bytes.
    +		 * Reject any other length before the responder reads
    +		 * sizeof(u64) bytes from payload_addr(pkt); a shorter
    +		 * payload would read past the logical end of the packet
    +		 * into skb->head tailroom.
    +		 */
    +		if (resid != sizeof(u64) || pktlen != sizeof(u64) ||
    +		    bth_pad(pkt)) {
    +			state = RESPST_ERR_LENGTH;
    +			goto err;
    +		}
    +	} else if (pkt->mask & RXE_WRITE_MASK) {
     		if (resid > mtu) {
     			if (pktlen != mtu || bth_pad(pkt)) {
     				state = RESPST_ERR_LENGTH;
    -- 
    cgit 1.3-korg
    
    
    
  • drivers/infiniband/sw/rxe/rxe_resp.c+13 2 modified
    diff --git a/drivers/infiniband/sw/rxe/rxe_resp.c b/drivers/infiniband/sw/rxe/rxe_resp.c
    index c11ab280551a86..29e32b91d74b88 100644
    --- a/drivers/infiniband/sw/rxe/rxe_resp.c
    +++ b/drivers/infiniband/sw/rxe/rxe_resp.c
    @@ -526,7 +526,19 @@ static enum resp_states check_rkey(struct rxe_qp *qp,
     	}
     
     skip_check_range:
    -	if (pkt->mask & (RXE_WRITE_MASK | RXE_ATOMIC_WRITE_MASK)) {
    +	if (pkt->mask & RXE_ATOMIC_WRITE_MASK) {
    +		/* IBA oA19-28: ATOMIC_WRITE payload is exactly 8 bytes.
    +		 * Reject any other length before the responder reads
    +		 * sizeof(u64) bytes from payload_addr(pkt); a shorter
    +		 * payload would read past the logical end of the packet
    +		 * into skb->head tailroom.
    +		 */
    +		if (resid != sizeof(u64) || pktlen != sizeof(u64) ||
    +		    bth_pad(pkt)) {
    +			state = RESPST_ERR_LENGTH;
    +			goto err;
    +		}
    +	} else if (pkt->mask & RXE_WRITE_MASK) {
     		if (resid > mtu) {
     			if (pktlen != mtu || bth_pad(pkt)) {
     				state = RESPST_ERR_LENGTH;
    -- 
    cgit 1.3-korg
    
    
    
539cabb7b2d8

RDMA/rxe: Reject non-8-byte ATOMIC_WRITE payloads

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitMichael BommaritoApr 18, 2026Fixed in 6.6.140via kernel-cna
2 files changed · +26 4
  • drivers/infiniband/sw/rxe/rxe_resp.c+13 2 modified
    diff --git a/drivers/infiniband/sw/rxe/rxe_resp.c b/drivers/infiniband/sw/rxe/rxe_resp.c
    index fa2b87c7492920..70e9bf3a704225 100644
    --- a/drivers/infiniband/sw/rxe/rxe_resp.c
    +++ b/drivers/infiniband/sw/rxe/rxe_resp.c
    @@ -536,7 +536,19 @@ static enum resp_states check_rkey(struct rxe_qp *qp,
     	}
     
     skip_check_range:
    -	if (pkt->mask & (RXE_WRITE_MASK | RXE_ATOMIC_WRITE_MASK)) {
    +	if (pkt->mask & RXE_ATOMIC_WRITE_MASK) {
    +		/* IBA oA19-28: ATOMIC_WRITE payload is exactly 8 bytes.
    +		 * Reject any other length before the responder reads
    +		 * sizeof(u64) bytes from payload_addr(pkt); a shorter
    +		 * payload would read past the logical end of the packet
    +		 * into skb->head tailroom.
    +		 */
    +		if (resid != sizeof(u64) || pktlen != sizeof(u64) ||
    +		    bth_pad(pkt)) {
    +			state = RESPST_ERR_LENGTH;
    +			goto err;
    +		}
    +	} else if (pkt->mask & RXE_WRITE_MASK) {
     		if (resid > mtu) {
     			if (pktlen != mtu || bth_pad(pkt)) {
     				state = RESPST_ERR_LENGTH;
    -- 
    cgit 1.3-korg
    
    
    
  • drivers/infiniband/sw/rxe/rxe_resp.c+13 2 modified
    diff --git a/drivers/infiniband/sw/rxe/rxe_resp.c b/drivers/infiniband/sw/rxe/rxe_resp.c
    index fa2b87c7492920..70e9bf3a704225 100644
    --- a/drivers/infiniband/sw/rxe/rxe_resp.c
    +++ b/drivers/infiniband/sw/rxe/rxe_resp.c
    @@ -536,7 +536,19 @@ static enum resp_states check_rkey(struct rxe_qp *qp,
     	}
     
     skip_check_range:
    -	if (pkt->mask & (RXE_WRITE_MASK | RXE_ATOMIC_WRITE_MASK)) {
    +	if (pkt->mask & RXE_ATOMIC_WRITE_MASK) {
    +		/* IBA oA19-28: ATOMIC_WRITE payload is exactly 8 bytes.
    +		 * Reject any other length before the responder reads
    +		 * sizeof(u64) bytes from payload_addr(pkt); a shorter
    +		 * payload would read past the logical end of the packet
    +		 * into skb->head tailroom.
    +		 */
    +		if (resid != sizeof(u64) || pktlen != sizeof(u64) ||
    +		    bth_pad(pkt)) {
    +			state = RESPST_ERR_LENGTH;
    +			goto err;
    +		}
    +	} else if (pkt->mask & RXE_WRITE_MASK) {
     		if (resid > mtu) {
     			if (pktlen != mtu || bth_pad(pkt)) {
     				state = RESPST_ERR_LENGTH;
    -- 
    cgit 1.3-korg
    
    
    
7ec1ed4747f5

RDMA/rxe: Reject non-8-byte ATOMIC_WRITE payloads

2 files changed · +26 4
  • drivers/infiniband/sw/rxe/rxe_resp.c+13 2 modified
    diff --git a/drivers/infiniband/sw/rxe/rxe_resp.c b/drivers/infiniband/sw/rxe/rxe_resp.c
    index 711f73e0bbb1c3..09ba21d0f3c4fe 100644
    --- a/drivers/infiniband/sw/rxe/rxe_resp.c
    +++ b/drivers/infiniband/sw/rxe/rxe_resp.c
    @@ -526,7 +526,19 @@ static enum resp_states check_rkey(struct rxe_qp *qp,
     	}
     
     skip_check_range:
    -	if (pkt->mask & (RXE_WRITE_MASK | RXE_ATOMIC_WRITE_MASK)) {
    +	if (pkt->mask & RXE_ATOMIC_WRITE_MASK) {
    +		/* IBA oA19-28: ATOMIC_WRITE payload is exactly 8 bytes.
    +		 * Reject any other length before the responder reads
    +		 * sizeof(u64) bytes from payload_addr(pkt); a shorter
    +		 * payload would read past the logical end of the packet
    +		 * into skb->head tailroom.
    +		 */
    +		if (resid != sizeof(u64) || pktlen != sizeof(u64) ||
    +		    bth_pad(pkt)) {
    +			state = RESPST_ERR_LENGTH;
    +			goto err;
    +		}
    +	} else if (pkt->mask & RXE_WRITE_MASK) {
     		if (resid > mtu) {
     			if (pktlen != mtu || bth_pad(pkt)) {
     				state = RESPST_ERR_LENGTH;
    -- 
    cgit 1.3-korg
    
    
    
  • drivers/infiniband/sw/rxe/rxe_resp.c+13 2 modified
    diff --git a/drivers/infiniband/sw/rxe/rxe_resp.c b/drivers/infiniband/sw/rxe/rxe_resp.c
    index 711f73e0bbb1c3..09ba21d0f3c4fe 100644
    --- a/drivers/infiniband/sw/rxe/rxe_resp.c
    +++ b/drivers/infiniband/sw/rxe/rxe_resp.c
    @@ -526,7 +526,19 @@ static enum resp_states check_rkey(struct rxe_qp *qp,
     	}
     
     skip_check_range:
    -	if (pkt->mask & (RXE_WRITE_MASK | RXE_ATOMIC_WRITE_MASK)) {
    +	if (pkt->mask & RXE_ATOMIC_WRITE_MASK) {
    +		/* IBA oA19-28: ATOMIC_WRITE payload is exactly 8 bytes.
    +		 * Reject any other length before the responder reads
    +		 * sizeof(u64) bytes from payload_addr(pkt); a shorter
    +		 * payload would read past the logical end of the packet
    +		 * into skb->head tailroom.
    +		 */
    +		if (resid != sizeof(u64) || pktlen != sizeof(u64) ||
    +		    bth_pad(pkt)) {
    +			state = RESPST_ERR_LENGTH;
    +			goto err;
    +		}
    +	} else if (pkt->mask & RXE_WRITE_MASK) {
     		if (resid > mtu) {
     			if (pktlen != mtu || bth_pad(pkt)) {
     				state = RESPST_ERR_LENGTH;
    -- 
    cgit 1.3-korg
    
    
    
539cabb7b2d8

RDMA/rxe: Reject non-8-byte ATOMIC_WRITE payloads

2 files changed · +26 4
  • drivers/infiniband/sw/rxe/rxe_resp.c+13 2 modified
    diff --git a/drivers/infiniband/sw/rxe/rxe_resp.c b/drivers/infiniband/sw/rxe/rxe_resp.c
    index fa2b87c7492920..70e9bf3a704225 100644
    --- a/drivers/infiniband/sw/rxe/rxe_resp.c
    +++ b/drivers/infiniband/sw/rxe/rxe_resp.c
    @@ -536,7 +536,19 @@ static enum resp_states check_rkey(struct rxe_qp *qp,
     	}
     
     skip_check_range:
    -	if (pkt->mask & (RXE_WRITE_MASK | RXE_ATOMIC_WRITE_MASK)) {
    +	if (pkt->mask & RXE_ATOMIC_WRITE_MASK) {
    +		/* IBA oA19-28: ATOMIC_WRITE payload is exactly 8 bytes.
    +		 * Reject any other length before the responder reads
    +		 * sizeof(u64) bytes from payload_addr(pkt); a shorter
    +		 * payload would read past the logical end of the packet
    +		 * into skb->head tailroom.
    +		 */
    +		if (resid != sizeof(u64) || pktlen != sizeof(u64) ||
    +		    bth_pad(pkt)) {
    +			state = RESPST_ERR_LENGTH;
    +			goto err;
    +		}
    +	} else if (pkt->mask & RXE_WRITE_MASK) {
     		if (resid > mtu) {
     			if (pktlen != mtu || bth_pad(pkt)) {
     				state = RESPST_ERR_LENGTH;
    -- 
    cgit 1.3-korg
    
    
    
  • drivers/infiniband/sw/rxe/rxe_resp.c+13 2 modified
    diff --git a/drivers/infiniband/sw/rxe/rxe_resp.c b/drivers/infiniband/sw/rxe/rxe_resp.c
    index fa2b87c7492920..70e9bf3a704225 100644
    --- a/drivers/infiniband/sw/rxe/rxe_resp.c
    +++ b/drivers/infiniband/sw/rxe/rxe_resp.c
    @@ -536,7 +536,19 @@ static enum resp_states check_rkey(struct rxe_qp *qp,
     	}
     
     skip_check_range:
    -	if (pkt->mask & (RXE_WRITE_MASK | RXE_ATOMIC_WRITE_MASK)) {
    +	if (pkt->mask & RXE_ATOMIC_WRITE_MASK) {
    +		/* IBA oA19-28: ATOMIC_WRITE payload is exactly 8 bytes.
    +		 * Reject any other length before the responder reads
    +		 * sizeof(u64) bytes from payload_addr(pkt); a shorter
    +		 * payload would read past the logical end of the packet
    +		 * into skb->head tailroom.
    +		 */
    +		if (resid != sizeof(u64) || pktlen != sizeof(u64) ||
    +		    bth_pad(pkt)) {
    +			state = RESPST_ERR_LENGTH;
    +			goto err;
    +		}
    +	} else if (pkt->mask & RXE_WRITE_MASK) {
     		if (resid > mtu) {
     			if (pktlen != mtu || bth_pad(pkt)) {
     				state = RESPST_ERR_LENGTH;
    -- 
    cgit 1.3-korg
    
    
    
105bf79a23b8

RDMA/rxe: Reject non-8-byte ATOMIC_WRITE payloads

2 files changed · +26 4
  • drivers/infiniband/sw/rxe/rxe_resp.c+13 2 modified
    diff --git a/drivers/infiniband/sw/rxe/rxe_resp.c b/drivers/infiniband/sw/rxe/rxe_resp.c
    index 711f73e0bbb1c3..09ba21d0f3c4fe 100644
    --- a/drivers/infiniband/sw/rxe/rxe_resp.c
    +++ b/drivers/infiniband/sw/rxe/rxe_resp.c
    @@ -526,7 +526,19 @@ static enum resp_states check_rkey(struct rxe_qp *qp,
     	}
     
     skip_check_range:
    -	if (pkt->mask & (RXE_WRITE_MASK | RXE_ATOMIC_WRITE_MASK)) {
    +	if (pkt->mask & RXE_ATOMIC_WRITE_MASK) {
    +		/* IBA oA19-28: ATOMIC_WRITE payload is exactly 8 bytes.
    +		 * Reject any other length before the responder reads
    +		 * sizeof(u64) bytes from payload_addr(pkt); a shorter
    +		 * payload would read past the logical end of the packet
    +		 * into skb->head tailroom.
    +		 */
    +		if (resid != sizeof(u64) || pktlen != sizeof(u64) ||
    +		    bth_pad(pkt)) {
    +			state = RESPST_ERR_LENGTH;
    +			goto err;
    +		}
    +	} else if (pkt->mask & RXE_WRITE_MASK) {
     		if (resid > mtu) {
     			if (pktlen != mtu || bth_pad(pkt)) {
     				state = RESPST_ERR_LENGTH;
    -- 
    cgit 1.3-korg
    
    
    
  • drivers/infiniband/sw/rxe/rxe_resp.c+13 2 modified
    diff --git a/drivers/infiniband/sw/rxe/rxe_resp.c b/drivers/infiniband/sw/rxe/rxe_resp.c
    index 711f73e0bbb1c3..09ba21d0f3c4fe 100644
    --- a/drivers/infiniband/sw/rxe/rxe_resp.c
    +++ b/drivers/infiniband/sw/rxe/rxe_resp.c
    @@ -526,7 +526,19 @@ static enum resp_states check_rkey(struct rxe_qp *qp,
     	}
     
     skip_check_range:
    -	if (pkt->mask & (RXE_WRITE_MASK | RXE_ATOMIC_WRITE_MASK)) {
    +	if (pkt->mask & RXE_ATOMIC_WRITE_MASK) {
    +		/* IBA oA19-28: ATOMIC_WRITE payload is exactly 8 bytes.
    +		 * Reject any other length before the responder reads
    +		 * sizeof(u64) bytes from payload_addr(pkt); a shorter
    +		 * payload would read past the logical end of the packet
    +		 * into skb->head tailroom.
    +		 */
    +		if (resid != sizeof(u64) || pktlen != sizeof(u64) ||
    +		    bth_pad(pkt)) {
    +			state = RESPST_ERR_LENGTH;
    +			goto err;
    +		}
    +	} else if (pkt->mask & RXE_WRITE_MASK) {
     		if (resid > mtu) {
     			if (pktlen != mtu || bth_pad(pkt)) {
     				state = RESPST_ERR_LENGTH;
    -- 
    cgit 1.3-korg
    
    
    
d415fce3fcde

RDMA/rxe: Reject non-8-byte ATOMIC_WRITE payloads

2 files changed · +26 4
  • drivers/infiniband/sw/rxe/rxe_resp.c+13 2 modified
    diff --git a/drivers/infiniband/sw/rxe/rxe_resp.c b/drivers/infiniband/sw/rxe/rxe_resp.c
    index c11ab280551a86..29e32b91d74b88 100644
    --- a/drivers/infiniband/sw/rxe/rxe_resp.c
    +++ b/drivers/infiniband/sw/rxe/rxe_resp.c
    @@ -526,7 +526,19 @@ static enum resp_states check_rkey(struct rxe_qp *qp,
     	}
     
     skip_check_range:
    -	if (pkt->mask & (RXE_WRITE_MASK | RXE_ATOMIC_WRITE_MASK)) {
    +	if (pkt->mask & RXE_ATOMIC_WRITE_MASK) {
    +		/* IBA oA19-28: ATOMIC_WRITE payload is exactly 8 bytes.
    +		 * Reject any other length before the responder reads
    +		 * sizeof(u64) bytes from payload_addr(pkt); a shorter
    +		 * payload would read past the logical end of the packet
    +		 * into skb->head tailroom.
    +		 */
    +		if (resid != sizeof(u64) || pktlen != sizeof(u64) ||
    +		    bth_pad(pkt)) {
    +			state = RESPST_ERR_LENGTH;
    +			goto err;
    +		}
    +	} else if (pkt->mask & RXE_WRITE_MASK) {
     		if (resid > mtu) {
     			if (pktlen != mtu || bth_pad(pkt)) {
     				state = RESPST_ERR_LENGTH;
    -- 
    cgit 1.3-korg
    
    
    
  • drivers/infiniband/sw/rxe/rxe_resp.c+13 2 modified
    diff --git a/drivers/infiniband/sw/rxe/rxe_resp.c b/drivers/infiniband/sw/rxe/rxe_resp.c
    index c11ab280551a86..29e32b91d74b88 100644
    --- a/drivers/infiniband/sw/rxe/rxe_resp.c
    +++ b/drivers/infiniband/sw/rxe/rxe_resp.c
    @@ -526,7 +526,19 @@ static enum resp_states check_rkey(struct rxe_qp *qp,
     	}
     
     skip_check_range:
    -	if (pkt->mask & (RXE_WRITE_MASK | RXE_ATOMIC_WRITE_MASK)) {
    +	if (pkt->mask & RXE_ATOMIC_WRITE_MASK) {
    +		/* IBA oA19-28: ATOMIC_WRITE payload is exactly 8 bytes.
    +		 * Reject any other length before the responder reads
    +		 * sizeof(u64) bytes from payload_addr(pkt); a shorter
    +		 * payload would read past the logical end of the packet
    +		 * into skb->head tailroom.
    +		 */
    +		if (resid != sizeof(u64) || pktlen != sizeof(u64) ||
    +		    bth_pad(pkt)) {
    +			state = RESPST_ERR_LENGTH;
    +			goto err;
    +		}
    +	} else if (pkt->mask & RXE_WRITE_MASK) {
     		if (resid > mtu) {
     			if (pktlen != mtu || bth_pad(pkt)) {
     				state = RESPST_ERR_LENGTH;
    -- 
    cgit 1.3-korg
    
    
    
1114c87aa6f1

RDMA/rxe: Reject non-8-byte ATOMIC_WRITE payloads

2 files changed · +26 4
  • drivers/infiniband/sw/rxe/rxe_resp.c+13 2 modified
    diff --git a/drivers/infiniband/sw/rxe/rxe_resp.c b/drivers/infiniband/sw/rxe/rxe_resp.c
    index 9faf8c09aa8e42..9cb2f6fbf2dd6a 100644
    --- a/drivers/infiniband/sw/rxe/rxe_resp.c
    +++ b/drivers/infiniband/sw/rxe/rxe_resp.c
    @@ -540,7 +540,19 @@ static enum resp_states check_rkey(struct rxe_qp *qp,
     	}
     
     skip_check_range:
    -	if (pkt->mask & (RXE_WRITE_MASK | RXE_ATOMIC_WRITE_MASK)) {
    +	if (pkt->mask & RXE_ATOMIC_WRITE_MASK) {
    +		/* IBA oA19-28: ATOMIC_WRITE payload is exactly 8 bytes.
    +		 * Reject any other length before the responder reads
    +		 * sizeof(u64) bytes from payload_addr(pkt); a shorter
    +		 * payload would read past the logical end of the packet
    +		 * into skb->head tailroom.
    +		 */
    +		if (resid != sizeof(u64) || pktlen != sizeof(u64) ||
    +		    bth_pad(pkt)) {
    +			state = RESPST_ERR_LENGTH;
    +			goto err;
    +		}
    +	} else if (pkt->mask & RXE_WRITE_MASK) {
     		if (resid > mtu) {
     			if (pktlen != mtu || bth_pad(pkt)) {
     				state = RESPST_ERR_LENGTH;
    -- 
    cgit 1.3-korg
    
    
    
  • drivers/infiniband/sw/rxe/rxe_resp.c+13 2 modified
    diff --git a/drivers/infiniband/sw/rxe/rxe_resp.c b/drivers/infiniband/sw/rxe/rxe_resp.c
    index 9faf8c09aa8e42..9cb2f6fbf2dd6a 100644
    --- a/drivers/infiniband/sw/rxe/rxe_resp.c
    +++ b/drivers/infiniband/sw/rxe/rxe_resp.c
    @@ -540,7 +540,19 @@ static enum resp_states check_rkey(struct rxe_qp *qp,
     	}
     
     skip_check_range:
    -	if (pkt->mask & (RXE_WRITE_MASK | RXE_ATOMIC_WRITE_MASK)) {
    +	if (pkt->mask & RXE_ATOMIC_WRITE_MASK) {
    +		/* IBA oA19-28: ATOMIC_WRITE payload is exactly 8 bytes.
    +		 * Reject any other length before the responder reads
    +		 * sizeof(u64) bytes from payload_addr(pkt); a shorter
    +		 * payload would read past the logical end of the packet
    +		 * into skb->head tailroom.
    +		 */
    +		if (resid != sizeof(u64) || pktlen != sizeof(u64) ||
    +		    bth_pad(pkt)) {
    +			state = RESPST_ERR_LENGTH;
    +			goto err;
    +		}
    +	} else if (pkt->mask & RXE_WRITE_MASK) {
     		if (resid > mtu) {
     			if (pktlen != mtu || bth_pad(pkt)) {
     				state = RESPST_ERR_LENGTH;
    -- 
    cgit 1.3-korg
    
    
    

Vulnerability mechanics

Root cause

"Missing payload-length validation for ATOMIC_WRITE requests allows a zero-length packet to reach an unchecked 8-byte read past the logical end of the packet buffer."

Attack vector

A remote RDMA initiator sends an ATOMIC_WRITE request with the RETH length field set to 0. The `check_rkey()` function previously only compared `pktlen` against `resid`, so a zero-length payload passed validation. The responder then reaches `atomic_write_reply()`, which reads `sizeof(u64)` bytes from `payload_addr(pkt)` — past the logical end of the packet into the `skb->head` tailroom. Those 8 bytes (4 bytes of kernel tailroom plus the packet's own trailing ICRC) are written into the attacker's MR via `rxe_mr_do_atomic_write()`, leaking kernel memory [patch_id=2898595].

Affected code

The vulnerable code is in `drivers/infiniband/sw/rxe/rxe_resp.c`, in the `check_rkey()` function. The function `atomic_write_reply()` unconditionally dereferences 8 bytes via `*(u64 *)payload_addr(pkt)` without first verifying the payload length [patch_id=2898595].

What the fix does

The patch separates the ATOMIC_WRITE length check from the normal WRITE path in `check_rkey()`. It adds a strict check that `resid == sizeof(u64)`, `pktlen == sizeof(u64)`, and `bth_pad(pkt)` is zero for ATOMIC_WRITE packets, rejecting any non-8-byte payload with `RESPST_ERR_LENGTH`. This ensures the responder never reaches the unchecked `*(u64 *)payload_addr(pkt)` dereference in `atomic_write_reply()` with a short payload [patch_id=2898595].

Preconditions

  • networkThe attacker must be able to send RDMA ATOMIC_WRITE requests to a target running the rxe (soft-RoCE) driver.
  • inputThe attacker must know or guess a valid rkey (remote key) for a registered memory region on the responder.

Generated on May 28, 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.