diff options
author | Chuck Lever <chuck.lever@oracle.com> | 2015-02-12 10:14:51 -0500 |
---|---|---|
committer | Anna Schumaker <Anna.Schumaker@Netapp.com> | 2015-02-23 16:54:04 -0500 |
commit | 9b1dcbc8cf4679ecf090b343ac31bda6e55ddabe (patch) | |
tree | a79e05a22da80e9ffb0318e215a4fdccb0a7493c /net | |
parent | b625a61698619c7af652de2701a2fb17c5c5d66e (diff) |
xprtrdma: Store RDMA credits in unsigned variables
Dan Carpenter's static checker pointed out:
net/sunrpc/xprtrdma/rpc_rdma.c:879 rpcrdma_reply_handler()
warn: can 'credits' be negative?
"credits" is defined as an int. The credits value comes from the
server as a 32-bit unsigned integer.
A malicious or broken server can plant a large unsigned integer in
that field which would result in an underflow in the following
logic, potentially triggering a deadlock of the mount point by
blocking the client from issuing more RPC requests.
net/sunrpc/xprtrdma/rpc_rdma.c:
876 credits = be32_to_cpu(headerp->rm_credit);
877 if (credits == 0)
878 credits = 1; /* don't deadlock */
879 else if (credits > r_xprt->rx_buf.rb_max_requests)
880 credits = r_xprt->rx_buf.rb_max_requests;
881
882 cwnd = xprt->cwnd;
883 xprt->cwnd = credits << RPC_CWNDSHIFT;
884 if (xprt->cwnd > cwnd)
885 xprt_release_rqst_cong(rqst->rq_task);
Reported-by: Dan Carpenter <dan.carpenter@oracle.com>
Fixes: eba8ff660b2d ("xprtrdma: Move credit update to RPC . . .")
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
Diffstat (limited to 'net')
-rw-r--r-- | net/sunrpc/xprtrdma/rpc_rdma.c | 3 | ||||
-rw-r--r-- | net/sunrpc/xprtrdma/xprt_rdma.h | 2 |
2 files changed, 3 insertions, 2 deletions
diff --git a/net/sunrpc/xprtrdma/rpc_rdma.c b/net/sunrpc/xprtrdma/rpc_rdma.c index 7e9acd9361c5..91ffde82fa0c 100644 --- a/net/sunrpc/xprtrdma/rpc_rdma.c +++ b/net/sunrpc/xprtrdma/rpc_rdma.c | |||
@@ -738,8 +738,9 @@ rpcrdma_reply_handler(struct rpcrdma_rep *rep) | |||
738 | struct rpc_xprt *xprt = rep->rr_xprt; | 738 | struct rpc_xprt *xprt = rep->rr_xprt; |
739 | struct rpcrdma_xprt *r_xprt = rpcx_to_rdmax(xprt); | 739 | struct rpcrdma_xprt *r_xprt = rpcx_to_rdmax(xprt); |
740 | __be32 *iptr; | 740 | __be32 *iptr; |
741 | int credits, rdmalen, status; | 741 | int rdmalen, status; |
742 | unsigned long cwnd; | 742 | unsigned long cwnd; |
743 | u32 credits; | ||
743 | 744 | ||
744 | /* Check status. If bad, signal disconnect and return rep to pool */ | 745 | /* Check status. If bad, signal disconnect and return rep to pool */ |
745 | if (rep->rr_len == ~0U) { | 746 | if (rep->rr_len == ~0U) { |
diff --git a/net/sunrpc/xprtrdma/xprt_rdma.h b/net/sunrpc/xprtrdma/xprt_rdma.h index d1b70397c60f..0a16fb6f0885 100644 --- a/net/sunrpc/xprtrdma/xprt_rdma.h +++ b/net/sunrpc/xprtrdma/xprt_rdma.h | |||
@@ -285,7 +285,7 @@ rpcr_to_rdmar(struct rpc_rqst *rqst) | |||
285 | */ | 285 | */ |
286 | struct rpcrdma_buffer { | 286 | struct rpcrdma_buffer { |
287 | spinlock_t rb_lock; /* protects indexes */ | 287 | spinlock_t rb_lock; /* protects indexes */ |
288 | int rb_max_requests;/* client max requests */ | 288 | u32 rb_max_requests;/* client max requests */ |
289 | struct list_head rb_mws; /* optional memory windows/fmrs/frmrs */ | 289 | struct list_head rb_mws; /* optional memory windows/fmrs/frmrs */ |
290 | struct list_head rb_all; | 290 | struct list_head rb_all; |
291 | int rb_send_index; | 291 | int rb_send_index; |