aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2019-03-16 15:28:18 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2019-03-16 15:28:18 -0400
commit465c209db83e2cdaeb4a52f4e107a9fc636704db (patch)
tree626cf4c456967059cac08b3297afc58e794fe61d
parenta9c55d58bc36b5a0ef7021772fc2508e693ed534 (diff)
parent5e3863fd597eba8c6679de805681631b1aad9bdb (diff)
Merge tag 'nfs-for-5.1-2' of git://git.linux-nfs.org/projects/trondmy/linux-nfs
Pull NFS client bugfixes from Trond Myklebust: "Highlights include: Bugfixes: - Fix an Oops in SUNRPC back channel tracepoints - Fix a SUNRPC client regression when handling oversized replies - Fix the minimal size for SUNRPC reply buffer allocation - rpc_decode_header() must always return a non-zero value on error - Fix a typo in pnfs_update_layout() Cleanup: - Remove redundant check for the reply length in call_decode()" * tag 'nfs-for-5.1-2' of git://git.linux-nfs.org/projects/trondmy/linux-nfs: SUNRPC: Remove redundant check for the reply length in call_decode() SUNRPC: Handle the SYSTEM_ERR rpc error SUNRPC: rpc_decode_header() must always return a non-zero value on error SUNRPC: Use the ENOTCONN error on socket disconnect SUNRPC: Fix the minimal size for reply buffer allocation SUNRPC: Fix a client regression when handling oversized replies pNFS: Fix a typo in pnfs_update_layout fix null pointer deref in tracepoints in back channel
-rw-r--r--fs/nfs/pnfs.c2
-rw-r--r--include/trace/events/sunrpc.h6
-rw-r--r--net/sunrpc/clnt.c32
-rw-r--r--net/sunrpc/xprt.c2
-rw-r--r--net/sunrpc/xprtsock.c2
5 files changed, 21 insertions, 23 deletions
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c
index 8247bd1634cb..7066cd7c7aff 100644
--- a/fs/nfs/pnfs.c
+++ b/fs/nfs/pnfs.c
@@ -1889,7 +1889,7 @@ lookup_again:
1889 atomic_read(&lo->plh_outstanding) != 0) { 1889 atomic_read(&lo->plh_outstanding) != 0) {
1890 spin_unlock(&ino->i_lock); 1890 spin_unlock(&ino->i_lock);
1891 lseg = ERR_PTR(wait_var_event_killable(&lo->plh_outstanding, 1891 lseg = ERR_PTR(wait_var_event_killable(&lo->plh_outstanding,
1892 atomic_read(&lo->plh_outstanding))); 1892 !atomic_read(&lo->plh_outstanding)));
1893 if (IS_ERR(lseg) || !list_empty(&lo->plh_segs)) 1893 if (IS_ERR(lseg) || !list_empty(&lo->plh_segs))
1894 goto out_put_layout_hdr; 1894 goto out_put_layout_hdr;
1895 pnfs_put_layout_hdr(lo); 1895 pnfs_put_layout_hdr(lo);
diff --git a/include/trace/events/sunrpc.h b/include/trace/events/sunrpc.h
index 8451f30c6a0f..7e899e635d33 100644
--- a/include/trace/events/sunrpc.h
+++ b/include/trace/events/sunrpc.h
@@ -712,7 +712,8 @@ TRACE_EVENT(xprt_transmit,
712 712
713 TP_fast_assign( 713 TP_fast_assign(
714 __entry->task_id = rqst->rq_task->tk_pid; 714 __entry->task_id = rqst->rq_task->tk_pid;
715 __entry->client_id = rqst->rq_task->tk_client->cl_clid; 715 __entry->client_id = rqst->rq_task->tk_client ?
716 rqst->rq_task->tk_client->cl_clid : -1;
716 __entry->xid = be32_to_cpu(rqst->rq_xid); 717 __entry->xid = be32_to_cpu(rqst->rq_xid);
717 __entry->seqno = rqst->rq_seqno; 718 __entry->seqno = rqst->rq_seqno;
718 __entry->status = status; 719 __entry->status = status;
@@ -742,7 +743,8 @@ TRACE_EVENT(xprt_enq_xmit,
742 743
743 TP_fast_assign( 744 TP_fast_assign(
744 __entry->task_id = task->tk_pid; 745 __entry->task_id = task->tk_pid;
745 __entry->client_id = task->tk_client->cl_clid; 746 __entry->client_id = task->tk_client ?
747 task->tk_client->cl_clid : -1;
746 __entry->xid = be32_to_cpu(task->tk_rqstp->rq_xid); 748 __entry->xid = be32_to_cpu(task->tk_rqstp->rq_xid);
747 __entry->seqno = task->tk_rqstp->rq_seqno; 749 __entry->seqno = task->tk_rqstp->rq_seqno;
748 __entry->stage = stage; 750 __entry->stage = stage;
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index 4216fe33204a..228970e6e52b 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -1730,7 +1730,12 @@ call_allocate(struct rpc_task *task)
1730 req->rq_callsize = RPC_CALLHDRSIZE + (auth->au_cslack << 1) + 1730 req->rq_callsize = RPC_CALLHDRSIZE + (auth->au_cslack << 1) +
1731 proc->p_arglen; 1731 proc->p_arglen;
1732 req->rq_callsize <<= 2; 1732 req->rq_callsize <<= 2;
1733 req->rq_rcvsize = RPC_REPHDRSIZE + auth->au_rslack + proc->p_replen; 1733 /*
1734 * Note: the reply buffer must at minimum allocate enough space
1735 * for the 'struct accepted_reply' from RFC5531.
1736 */
1737 req->rq_rcvsize = RPC_REPHDRSIZE + auth->au_rslack + \
1738 max_t(size_t, proc->p_replen, 2);
1734 req->rq_rcvsize <<= 2; 1739 req->rq_rcvsize <<= 2;
1735 1740
1736 status = xprt->ops->buf_alloc(task); 1741 status = xprt->ops->buf_alloc(task);
@@ -2387,9 +2392,6 @@ call_decode(struct rpc_task *task)
2387 WARN_ON(memcmp(&req->rq_rcv_buf, &req->rq_private_buf, 2392 WARN_ON(memcmp(&req->rq_rcv_buf, &req->rq_private_buf,
2388 sizeof(req->rq_rcv_buf)) != 0); 2393 sizeof(req->rq_rcv_buf)) != 0);
2389 2394
2390 if (req->rq_rcv_buf.len < 12)
2391 goto out_retry;
2392
2393 xdr_init_decode(&xdr, &req->rq_rcv_buf, 2395 xdr_init_decode(&xdr, &req->rq_rcv_buf,
2394 req->rq_rcv_buf.head[0].iov_base, req); 2396 req->rq_rcv_buf.head[0].iov_base, req);
2395 switch (rpc_decode_header(task, &xdr)) { 2397 switch (rpc_decode_header(task, &xdr)) {
@@ -2400,7 +2402,6 @@ call_decode(struct rpc_task *task)
2400 task->tk_pid, __func__, task->tk_status); 2402 task->tk_pid, __func__, task->tk_status);
2401 return; 2403 return;
2402 case -EAGAIN: 2404 case -EAGAIN:
2403out_retry:
2404 task->tk_status = 0; 2405 task->tk_status = 0;
2405 /* Note: rpc_decode_header() may have freed the RPC slot */ 2406 /* Note: rpc_decode_header() may have freed the RPC slot */
2406 if (task->tk_rqstp == req) { 2407 if (task->tk_rqstp == req) {
@@ -2449,7 +2450,7 @@ static noinline int
2449rpc_decode_header(struct rpc_task *task, struct xdr_stream *xdr) 2450rpc_decode_header(struct rpc_task *task, struct xdr_stream *xdr)
2450{ 2451{
2451 struct rpc_clnt *clnt = task->tk_client; 2452 struct rpc_clnt *clnt = task->tk_client;
2452 int error = -EACCES; 2453 int error;
2453 __be32 *p; 2454 __be32 *p;
2454 2455
2455 /* RFC-1014 says that the representation of XDR data must be a 2456 /* RFC-1014 says that the representation of XDR data must be a
@@ -2458,7 +2459,7 @@ rpc_decode_header(struct rpc_task *task, struct xdr_stream *xdr)
2458 * undefined results 2459 * undefined results
2459 */ 2460 */
2460 if (task->tk_rqstp->rq_rcv_buf.len & 3) 2461 if (task->tk_rqstp->rq_rcv_buf.len & 3)
2461 goto out_badlen; 2462 goto out_unparsable;
2462 2463
2463 p = xdr_inline_decode(xdr, 3 * sizeof(*p)); 2464 p = xdr_inline_decode(xdr, 3 * sizeof(*p));
2464 if (!p) 2465 if (!p)
@@ -2492,10 +2493,12 @@ rpc_decode_header(struct rpc_task *task, struct xdr_stream *xdr)
2492 error = -EOPNOTSUPP; 2493 error = -EOPNOTSUPP;
2493 goto out_err; 2494 goto out_err;
2494 case rpc_garbage_args: 2495 case rpc_garbage_args:
2496 case rpc_system_err:
2495 trace_rpc__garbage_args(task); 2497 trace_rpc__garbage_args(task);
2498 error = -EIO;
2496 break; 2499 break;
2497 default: 2500 default:
2498 trace_rpc__unparsable(task); 2501 goto out_unparsable;
2499 } 2502 }
2500 2503
2501out_garbage: 2504out_garbage:
@@ -2509,11 +2512,6 @@ out_err:
2509 rpc_exit(task, error); 2512 rpc_exit(task, error);
2510 return error; 2513 return error;
2511 2514
2512out_badlen:
2513 trace_rpc__unparsable(task);
2514 error = -EIO;
2515 goto out_err;
2516
2517out_unparsable: 2515out_unparsable:
2518 trace_rpc__unparsable(task); 2516 trace_rpc__unparsable(task);
2519 error = -EIO; 2517 error = -EIO;
@@ -2524,6 +2522,7 @@ out_verifier:
2524 goto out_garbage; 2522 goto out_garbage;
2525 2523
2526out_msg_denied: 2524out_msg_denied:
2525 error = -EACCES;
2527 p = xdr_inline_decode(xdr, sizeof(*p)); 2526 p = xdr_inline_decode(xdr, sizeof(*p));
2528 if (!p) 2527 if (!p)
2529 goto out_unparsable; 2528 goto out_unparsable;
@@ -2535,9 +2534,7 @@ out_msg_denied:
2535 error = -EPROTONOSUPPORT; 2534 error = -EPROTONOSUPPORT;
2536 goto out_err; 2535 goto out_err;
2537 default: 2536 default:
2538 trace_rpc__unparsable(task); 2537 goto out_unparsable;
2539 error = -EIO;
2540 goto out_err;
2541 } 2538 }
2542 2539
2543 p = xdr_inline_decode(xdr, sizeof(*p)); 2540 p = xdr_inline_decode(xdr, sizeof(*p));
@@ -2572,8 +2569,7 @@ out_msg_denied:
2572 task->tk_xprt->servername); 2569 task->tk_xprt->servername);
2573 break; 2570 break;
2574 default: 2571 default:
2575 trace_rpc__unparsable(task); 2572 goto out_unparsable;
2576 error = -EIO;
2577 } 2573 }
2578 goto out_err; 2574 goto out_err;
2579} 2575}
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
index e096c5a725df..d7117d241460 100644
--- a/net/sunrpc/xprt.c
+++ b/net/sunrpc/xprt.c
@@ -664,7 +664,7 @@ void xprt_disconnect_done(struct rpc_xprt *xprt)
664 spin_lock_bh(&xprt->transport_lock); 664 spin_lock_bh(&xprt->transport_lock);
665 xprt_clear_connected(xprt); 665 xprt_clear_connected(xprt);
666 xprt_clear_write_space_locked(xprt); 666 xprt_clear_write_space_locked(xprt);
667 xprt_wake_pending_tasks(xprt, -EAGAIN); 667 xprt_wake_pending_tasks(xprt, -ENOTCONN);
668 spin_unlock_bh(&xprt->transport_lock); 668 spin_unlock_bh(&xprt->transport_lock);
669} 669}
670EXPORT_SYMBOL_GPL(xprt_disconnect_done); 670EXPORT_SYMBOL_GPL(xprt_disconnect_done);
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index 42f45d33dc56..9359539907ba 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -453,7 +453,7 @@ xs_read_xdr_buf(struct socket *sock, struct msghdr *msg, int flags,
453 goto out; 453 goto out;
454 if (ret != want) 454 if (ret != want)
455 goto out; 455 goto out;
456 } else 456 } else if (offset < seek_init)
457 offset = seek_init; 457 offset = seek_init;
458 ret = -EMSGSIZE; 458 ret = -EMSGSIZE;
459out: 459out: