diff options
author | Chuck Lever <chuck.lever@oracle.com> | 2015-02-12 18:14:51 +0300 |
---|---|---|
committer | Anna Schumaker <Anna.Schumaker@Netapp.com> | 2015-02-24 00:54:04 +0300 |
commit | 9b1dcbc8cf4679ecf090b343ac31bda6e55ddabe (patch) | |
tree | a79e05a22da80e9ffb0318e215a4fdccb0a7493c /net/sunrpc | |
parent | b625a61698619c7af652de2701a2fb17c5c5d66e (diff) | |
download | linux-9b1dcbc8cf4679ecf090b343ac31bda6e55ddabe.tar.xz |
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/sunrpc')
-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) struct rpc_xprt *xprt = rep->rr_xprt; struct rpcrdma_xprt *r_xprt = rpcx_to_rdmax(xprt); __be32 *iptr; - int credits, rdmalen, status; + int rdmalen, status; unsigned long cwnd; + u32 credits; /* Check status. If bad, signal disconnect and return rep to pool */ 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) */ struct rpcrdma_buffer { spinlock_t rb_lock; /* protects indexes */ - int rb_max_requests;/* client max requests */ + u32 rb_max_requests;/* client max requests */ struct list_head rb_mws; /* optional memory windows/fmrs/frmrs */ struct list_head rb_all; int rb_send_index; |