Skip to contentSkip to conversation

svcrdma: silently discard undersized messages

PATCH In review Hyunsol Mun 3 participants 3 messages Oct 22

Subsystems (5)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 svcrdma: silently discard undersized messages

RFC 8166 requires an RPC-over-RDMA message shorter than the 28-byte minimum header to be silently discarded because its XID cannot be trusted.

svc_rdma_xdr_decode_req() instead returns -EINVAL when the fixed header cannot be decoded. svc_rdma_recvfrom() turns that into an RDMA_ERROR, whose encoder copies the first two words from rc_recv_buf without checking rc_byte_len. A zero- to seven-byte SEND can therefore return up to eight bytes that were not supplied by the peer.

Check the complete minimum header length before parsing and use the decoder's existing silent-drop return for undersized input. This keeps the error encoder from reading beyond the received message and follows the protocol requirement.

On an unpatched nfsd-testing kernel at 764ffa45f3f2, a two-VM Soft-iWARP test sent 128 complete 28-byte bad-version headers over connection A. After closing that connection, it sent 128 zero-byte SENDs over connection B. All 128 zero-byte requests received replies, and 56 of those replies contained the exact XID and version markers left by connection A. The test process ran as uid/gid 65534 with no effective capabilities and NoNewPrivs set.

With this patch applied, all eight complete 28-byte bad-version headers elicited replies. A zero-byte SEND and a 27-byte SEND each elicited no reply during a five-second observation interval. A normal NFSv4.1/RDMA mount, write, readback, and unmount completed successfully. The server remained running without an oops or panic. Both x86-64 kernels built with GCC 12.2 and CONFIG_WERROR=y without warnings.

The vulnerability research and validation were conducted by members of the Tobabz team as part of the Best of the Best 15th program.

Fixes f3ea53fb3bc3 ("svcrdma: Use correct XID in error replies")
Assisted-by LLM
---
 net/sunrpc/xprtrdma/svc_rdma_recvfrom.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)
net/sunrpc/xprtrdma/svc_rdma_recvfrom.c +4 -1
index ed5a83e9edd2..f2fbba4b30d4 100644
@@ -714,6 +714,9 @@ static int svc_rdma_xdr_decode_req(struct xdr_buf *rq_arg,
 	__be32 *p, *rdma_argp;
 	unsigned int hdr_len;
 
+	if (unlikely(rq_arg->len < RPCRDMA_HDRLEN_MIN))
+		goto out_short;
+
 	rdma_argp = rq_arg->head[0].iov_base;
 	xdr_init_decode(&rctxt->rc_stream, rq_arg, rdma_argp, NULL);
 
@@ -758,7 +761,7 @@ static int svc_rdma_xdr_decode_req(struct xdr_buf *rq_arg,
 
 out_short:
 	trace_svcrdma_decode_short_err(rctxt, rq_arg->len);
-	return -EINVAL;
+	return 0;
 
 out_version:
 	trace_svcrdma_decode_badvers_err(rctxt, rdma_argp);

base-commit: 764ffa45f3f2189cd86ec6d46d248fc0440507b6

Signature · 1 line
2.50.1 (Apple Git-155)
#1 lore raw
Sashiko has reviewed this patch and found no issues.
Quoted 15 lines

RFC 8166 requires an RPC-over-RDMA message shorter than the 28-byte minimum header to be silently discarded because its XID cannot be trusted.

svc_rdma_xdr_decode_req() instead returns -EINVAL when the fixed header cannot be decoded. svc_rdma_recvfrom() turns that into an RDMA_ERROR, whose encoder copies the first two words from rc_recv_buf without checking rc_byte_len. A zero- to seven-byte SEND can therefore return up to eight bytes that were not supplied by the peer.

Check the complete minimum header length before parsing and use the decoder's existing silent-drop return for undersized input. This keeps the error encoder from reading beyond the received message and follows the protocol requirement.

Quoted 6 lines

[ ... ]

Fixes f3ea53fb3bc3 ("svcrdma: Use correct XID in error replies")
Assisted-by LLM

Sashiko has reviewed this patch and found no issues.

Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=1
maintainer
#2 lore raw
In reply to Hyunsol Mun
Quoted 11 lines · Hyunsol Mun

RFC 8166 requires an RPC-over-RDMA message shorter than the 28-byte minimum header to be silently discarded because its XID cannot be trusted.

svc_rdma_xdr_decode_req() instead returns -EINVAL when the fixed header cannot be decoded. svc_rdma_recvfrom() turns that into an RDMA_ERROR, whose encoder copies the first two words from rc_recv_buf without checking rc_byte_len. A zero- to seven-byte SEND can therefore return up to eight bytes that were not supplied by the peer.

[...]

Applied to nfsd-testing, thanks!

[1/1] svcrdma: silently discard undersized messages

      commit: 667147c17f15824c00a5b2fcfdb66283c3f4cad6

--
Chuck Lever