← All writing
SecurityFabric▶ Interactive

The kernel can’t see your tensors: RDMA’s trust model

RDMA is fast because it takes the remote CPU and kernel out of the data path. That is also why every host-based security control you own goes blind the moment the gradients start moving.

Who touches the bytes: TCP vs one-sided RDMA Pick a datapath
Receiver-side controlTCPRDMA WRITE
Host firewall (netfilter / nftables)sees every packetnot on the data path
eBPF / XDP / tc hooks, host IDSsees every packetnot on the data path
Receiver CPU, per messageruns (syscalls, copies)never runs
Authorisation of the writesocket + app logicrkey + address match in the NIC
Confidentiality on the wireTLS, if you add itplaintext unless the NIC/fabric encrypts

What actually authorises a remote write

The receiver registers a memory region (for GPUDirect, a slice of GPU memory) under a protection domain, and gets back an rkey. It hands the peer an (address, rkey) pair. From then on, any RDMA WRITE that arrives on a queue pair in that protection domain, with a matching rkey and an address inside the region, is placed into memory by the NIC. No interrupt, no syscall, no policy check in software.

Three things follow. The rkey is a bearer capability: whoever holds it can write. It travels in plaintext in each WRITE packet’s RDMA extended transport header, so anyone who can observe the fabric learns it. And it is 32 bits, long-lived for as long as the region stays registered. For a KV-cache pool registered once at startup, as most disaggregated-inference transports do for speed, that is the life of the server.

How long does guessing an rkey take? Off-path attacker with a connection · closed-form
Expected time to first valid key
–
P(hit before key expires)
–
On-path attacker
0 guesses
reads the rkey off the wire

Reading the calculator

At full 32-bit entropy, a modest guess rate and a handful of long-lived regions, an off-path attacker gets there in days, and “registered at startup” means the key lives longer than that. Drop the effective entropy (key generation that is less random than it looks was one of ReDMArk’s findings) and it’s minutes. The lever that changes the shape of the curve is lifetime. A type-2 memory window, bound per transfer and invalidated when the transfer ends, turns a server-lifetime capability into a milliseconds-lifetime one.

That isn’t only a security property. It is the same mechanism that stops a delayed write from a timed-out transfer from landing in a KV block that has since been reused: the NIC rejects it with a remote access error. In kvwire this is ADR-0005: per-transfer memory windows are the first option for stale-write fencing, to be decided on measured bind cost. Correctness and security want the same thing here, which is the best kind of security control: it pays for itself.

The controls, at the layer that can enforce them

ControlWhat it stopsCost on the hot path
Protection domain + QP per tenanta tenant’s QP using another tenant’s rkeynone (setup only)
Partitions (IB partition keys) / VRF or VLAN per tenant (RoCE)packets from outside the tenant’s partition reaching its QPsnone (switch / NIC)
Type-2 memory windows, per transfer, invalidated on completion or abortlong-lived keys; late writes into reused memoryone bind per transfer (measure it)
Inline encryption (IPsec / MACsec offload on NICs that support it)reading rkeys and tensors off the wireNIC offload; verify line rate
Telemetry at the NIC / DPU (counters, flow records, access errors)blind spots: the host can’t see this trafficnone on the data path
No pickle or untyped RPC on the control pathRCE through the KV-transfer side channel (CVE-2025-32444)none

Notice the last column. None of these controls sits in software on the per-message path, which is what makes them deployable on a fabric whose whole reason to exist is microseconds.

Keep going

Next · interactive
Your prompt cache is a side channel
Repo
kvwire transport design: memory registration & fencing ↗