summaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorTrond Myklebust <trondmy@gmail.com>2019-09-16 15:12:19 +0200
committerAnna Schumaker <Anna.Schumaker@Netapp.com>2019-09-20 21:15:24 +0200
commit9ba828861c56a21d211d5d10f5643774b1ea330d (patch)
tree45468b00aca4baedcad2cbbd9c6ed5fba9c0bd21 /net
parentSUNRPC: Rename xdr_buf_read_netobj to xdr_buf_read_mic (diff)
downloadlinux-9ba828861c56a21d211d5d10f5643774b1ea330d.tar.xz
linux-9ba828861c56a21d211d5d10f5643774b1ea330d.zip
SUNRPC: Don't try to parse incomplete RPC messages
If the copy of the RPC reply into our buffers did not complete, and we could end up with a truncated message. In that case, just resend the call. Fixes: a0584ee9aed80 ("SUNRPC: Use struct xdr_stream when decoding...") Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com> Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
Diffstat (limited to 'net')
-rw-r--r--net/sunrpc/clnt.c14
1 files changed, 13 insertions, 1 deletions
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index 44d5cf318813..8b622ceb1158 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -2465,6 +2465,7 @@ call_decode(struct rpc_task *task)
struct rpc_clnt *clnt = task->tk_client;
struct rpc_rqst *req = task->tk_rqstp;
struct xdr_stream xdr;
+ int err;
dprint_status(task);
@@ -2487,6 +2488,15 @@ call_decode(struct rpc_task *task)
* before it changed req->rq_reply_bytes_recvd.
*/
smp_rmb();
+
+ /*
+ * Did we ever call xprt_complete_rqst()? If not, we should assume
+ * the message is incomplete.
+ */
+ err = -EAGAIN;
+ if (!req->rq_reply_bytes_recvd)
+ goto out;
+
req->rq_rcv_buf.len = req->rq_private_buf.len;
/* Check that the softirq receive buffer is valid */
@@ -2495,7 +2505,9 @@ call_decode(struct rpc_task *task)
xdr_init_decode(&xdr, &req->rq_rcv_buf,
req->rq_rcv_buf.head[0].iov_base, req);
- switch (rpc_decode_header(task, &xdr)) {
+ err = rpc_decode_header(task, &xdr);
+out:
+ switch (err) {
case 0:
task->tk_action = rpc_exit_task;
task->tk_status = rpcauth_unwrap_resp(task, &xdr);