aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDan Carpenter <dan.carpenter@oracle.com>2013-07-12 02:39:03 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-08-04 04:50:57 -0400
commita4208aa227113be2e0ea81613c4f15d3bc2fc768 (patch)
tree9d98b27bdf13260e7d7a153269b1e1fb61e79023
parent2794edb180b726d9d8aedcc6c7034e2d877489fc (diff)
svcrdma: underflow issue in decode_write_list()
commit b2781e1021525649c0b33fffd005ef219da33926 upstream. My static checker marks everything from ntohl() as untrusted and it complains we could have an underflow problem doing: return (u32 *)&ary->wc_array[nchunks]; Also on 32 bit systems the upper bound check could overflow. Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com> Signed-off-by: J. Bruce Fields <bfields@redhat.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--net/sunrpc/xprtrdma/svc_rdma_marshal.c20
1 files changed, 14 insertions, 6 deletions
diff --git a/net/sunrpc/xprtrdma/svc_rdma_marshal.c b/net/sunrpc/xprtrdma/svc_rdma_marshal.c
index 8d2edddf48cf..65b146297f5a 100644
--- a/net/sunrpc/xprtrdma/svc_rdma_marshal.c
+++ b/net/sunrpc/xprtrdma/svc_rdma_marshal.c
@@ -98,6 +98,7 @@ void svc_rdma_rcl_chunk_counts(struct rpcrdma_read_chunk *ch,
98 */ 98 */
99static u32 *decode_write_list(u32 *va, u32 *vaend) 99static u32 *decode_write_list(u32 *va, u32 *vaend)
100{ 100{
101 unsigned long start, end;
101 int nchunks; 102 int nchunks;
102 103
103 struct rpcrdma_write_array *ary = 104 struct rpcrdma_write_array *ary =
@@ -113,9 +114,12 @@ static u32 *decode_write_list(u32 *va, u32 *vaend)
113 return NULL; 114 return NULL;
114 } 115 }
115 nchunks = ntohl(ary->wc_nchunks); 116 nchunks = ntohl(ary->wc_nchunks);
116 if (((unsigned long)&ary->wc_array[0] + 117
117 (sizeof(struct rpcrdma_write_chunk) * nchunks)) > 118 start = (unsigned long)&ary->wc_array[0];
118 (unsigned long)vaend) { 119 end = (unsigned long)vaend;
120 if (nchunks < 0 ||
121 nchunks > (SIZE_MAX - start) / sizeof(struct rpcrdma_write_chunk) ||
122 (start + (sizeof(struct rpcrdma_write_chunk) * nchunks)) > end) {
119 dprintk("svcrdma: ary=%p, wc_nchunks=%d, vaend=%p\n", 123 dprintk("svcrdma: ary=%p, wc_nchunks=%d, vaend=%p\n",
120 ary, nchunks, vaend); 124 ary, nchunks, vaend);
121 return NULL; 125 return NULL;
@@ -129,6 +133,7 @@ static u32 *decode_write_list(u32 *va, u32 *vaend)
129 133
130static u32 *decode_reply_array(u32 *va, u32 *vaend) 134static u32 *decode_reply_array(u32 *va, u32 *vaend)
131{ 135{
136 unsigned long start, end;
132 int nchunks; 137 int nchunks;
133 struct rpcrdma_write_array *ary = 138 struct rpcrdma_write_array *ary =
134 (struct rpcrdma_write_array *)va; 139 (struct rpcrdma_write_array *)va;
@@ -143,9 +148,12 @@ static u32 *decode_reply_array(u32 *va, u32 *vaend)
143 return NULL; 148 return NULL;
144 } 149 }
145 nchunks = ntohl(ary->wc_nchunks); 150 nchunks = ntohl(ary->wc_nchunks);
146 if (((unsigned long)&ary->wc_array[0] + 151
147 (sizeof(struct rpcrdma_write_chunk) * nchunks)) > 152 start = (unsigned long)&ary->wc_array[0];
148 (unsigned long)vaend) { 153 end = (unsigned long)vaend;
154 if (nchunks < 0 ||
155 nchunks > (SIZE_MAX - start) / sizeof(struct rpcrdma_write_chunk) ||
156 (start + (sizeof(struct rpcrdma_write_chunk) * nchunks)) > end) {
149 dprintk("svcrdma: ary=%p, wc_nchunks=%d, vaend=%p\n", 157 dprintk("svcrdma: ary=%p, wc_nchunks=%d, vaend=%p\n",
150 ary, nchunks, vaend); 158 ary, nchunks, vaend);
151 return NULL; 159 return NULL;