diff options
author | Dan Carpenter <dan.carpenter@oracle.com> | 2013-07-12 02:39:03 -0400 |
---|---|---|
committer | J. Bruce Fields <bfields@redhat.com> | 2013-07-15 11:46:23 -0400 |
commit | b2781e1021525649c0b33fffd005ef219da33926 (patch) | |
tree | 8169f00611f6e56b1201d56fbbcd9e4020859231 /net/sunrpc | |
parent | 35f7a14fc1180164d6358a5885031fc187ef1bfa (diff) |
svcrdma: underflow issue in decode_write_list()
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.
Cc: stable@vger.kernel.org
Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
Diffstat (limited to 'net/sunrpc')
-rw-r--r-- | net/sunrpc/xprtrdma/svc_rdma_marshal.c | 20 |
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 | */ |
99 | static u32 *decode_write_list(u32 *va, u32 *vaend) | 99 | static 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 | ||
130 | static u32 *decode_reply_array(u32 *va, u32 *vaend) | 134 | static 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; |