[SRU][Disco][PATCH 2/2] SUNRPC: Fix a use after free when a server rejects the RPCSEC_GSS credential
Matthew Ruffell
matthew.ruffell at canonical.com
Wed Oct 30 03:50:06 UTC 2019
From: Trond Myklebust <trond.myklebust at hammerspace.com>
BugLink: https://bugs.launchpad.net/bugs/1842037
The addition of rpc_check_timeout() to call_decode causes an Oops
when the RPCSEC_GSS credential is rejected.
The reason is that rpc_decode_header() will call xprt_release() in
order to free task->tk_rqstp, which is needed by rpc_check_timeout()
to check whether or not we should exit due to a soft timeout.
The fix is to move the call to xprt_release() into call_decode() so
we can perform it after rpc_check_timeout().
Reported-by: Olga Kornievskaia <olga.kornievskaia at gmail.com>
Reported-by: Nick Bowler <nbowler at draconx.ca>
Fixes: cea57789e408 ("SUNRPC: Clean up")
Cc: stable at vger.kernel.org # v5.1+
Signed-off-by: Trond Myklebust <trond.myklebust at hammerspace.com>
Signed-off-by: Anna Schumaker <Anna.Schumaker at Netapp.com>
(backported from commit 7987b694ade8cc465ce10fb3dceaa614f13ceaf3)
[mruffell: rewrite goto error handling, medium context adjustments]
Signed-off-by: Matthew Ruffell <matthew.ruffell at canonical.com>
---
net/sunrpc/clnt.c | 30 ++++++++++++++++--------------
1 file changed, 16 insertions(+), 14 deletions(-)
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index f9568b0dc63e..5ea3c62fff9f 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -2303,6 +2303,8 @@ call_decode(struct rpc_task *task)
if (IS_ERR(p)) {
if (p == ERR_PTR(-EAGAIN))
goto out_retry;
+ if (p == ERR_PTR(-EKEYREJECTED))
+ goto out_key_rejected;
return;
}
task->tk_action = rpc_exit_task;
@@ -2315,17 +2317,21 @@ call_decode(struct rpc_task *task)
return;
out_retry:
task->tk_status = 0;
- /* Note: rpc_verify_header() may have freed the RPC slot */
- if (task->tk_rqstp == req) {
- xdr_free_bvec(&req->rq_rcv_buf);
- req->rq_reply_bytes_recvd = 0;
- req->rq_rcv_buf.len = 0;
- if (task->tk_client->cl_discrtry)
- xprt_conditional_disconnect(req->rq_xprt,
- req->rq_connect_cookie);
- }
+ xdr_free_bvec(&req->rq_rcv_buf);
+ req->rq_reply_bytes_recvd = 0;
+ req->rq_rcv_buf.len = 0;
+ if (task->tk_client->cl_discrtry)
+ xprt_conditional_disconnect(req->rq_xprt,
+ req->rq_connect_cookie);
task->tk_action = call_encode;
rpc_check_timeout(task);
+ return;
+out_key_rejected:
+ task->tk_action = call_reserve;
+ rpc_check_timeout(task);
+ rpcauth_invalcred(task);
+ /* Ensure we obtain a new XID if we retry! */
+ xprt_release(task);
}
static __be32 *
@@ -2413,11 +2419,7 @@ rpc_verify_header(struct rpc_task *task)
task->tk_cred_retry--;
dprintk("RPC: %5u %s: retry stale creds\n",
task->tk_pid, __func__);
- rpcauth_invalcred(task);
- /* Ensure we obtain a new XID! */
- xprt_release(task);
- task->tk_action = call_reserve;
- goto out_retry;
+ return ERR_PTR(-EKEYREJECTED);
case RPC_AUTH_BADCRED:
case RPC_AUTH_BADVERF:
/* possibly garbled cred/verf? */
--
2.20.1
More information about the kernel-team
mailing list