Skip to content

Commit eb8d3a2

Browse files
neilbrownchucklever
authored andcommitted
SUNRPC: double free xprt_ctxt while still in use
When an RPC request is deferred, the rq_xprt_ctxt pointer is moved out of the svc_rqst into the svc_deferred_req. When the deferred request is revisited, the pointer is copied into the new svc_rqst - and also remains in the svc_deferred_req. In the (rare?) case that the request is deferred a second time, the old svc_deferred_req is reused - it still has all the correct content. However in that case the rq_xprt_ctxt pointer is NOT cleared so that when xpo_release_xprt is called, the ctxt is freed (UDP) or possible added to a free list (RDMA). When the deferred request is revisited for a second time, it will reference this ctxt which may be invalid, and the free the object a second time which is likely to oops. So change svc_defer() to *always* clear rq_xprt_ctxt, and assert that the value is now stored in the svc_deferred_req. Fixes: 773f91b ("SUNRPC: Fix NFSD's request deferral on RDMA transports") Signed-off-by: NeilBrown <[email protected]> Reviewed-by: Jeff Layton <[email protected]> Signed-off-by: Chuck Lever <[email protected]>
1 parent 319050d commit eb8d3a2

File tree

1 file changed

+2
-1
lines changed

1 file changed

+2
-1
lines changed

net/sunrpc/svc_xprt.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1223,13 +1223,14 @@ static struct cache_deferred_req *svc_defer(struct cache_req *req)
12231223
dr->daddr = rqstp->rq_daddr;
12241224
dr->argslen = rqstp->rq_arg.len >> 2;
12251225
dr->xprt_ctxt = rqstp->rq_xprt_ctxt;
1226-
rqstp->rq_xprt_ctxt = NULL;
12271226

12281227
/* back up head to the start of the buffer and copy */
12291228
skip = rqstp->rq_arg.len - rqstp->rq_arg.head[0].iov_len;
12301229
memcpy(dr->args, rqstp->rq_arg.head[0].iov_base - skip,
12311230
dr->argslen << 2);
12321231
}
1232+
WARN_ON_ONCE(rqstp->rq_xprt_ctxt != dr->xprt_ctxt);
1233+
rqstp->rq_xprt_ctxt = NULL;
12331234
trace_svc_defer(rqstp);
12341235
svc_xprt_get(rqstp->rq_xprt);
12351236
dr->xprt = rqstp->rq_xprt;

0 commit comments

Comments
 (0)