1
1
/*
2
+ * Copyright (c) 2016 Oracle. All rights reserved.
2
3
* Copyright (c) 2005-2006 Network Appliance, Inc. All rights reserved.
3
4
*
4
5
* This software is available to you under a choice of one of two
47
48
48
49
#define RPCDBG_FACILITY RPCDBG_SVCXPRT
49
50
50
- /*
51
- * Decodes a read chunk list. The expected format is as follows:
52
- * descrim : xdr_one
53
- * position : __be32 offset into XDR stream
54
- * handle : __be32 RKEY
55
- * . . .
56
- * end-of-list: xdr_zero
57
- */
58
- static __be32 * decode_read_list (__be32 * va , __be32 * vaend )
51
+ static __be32 * xdr_check_read_list (__be32 * p , __be32 * end )
59
52
{
60
- struct rpcrdma_read_chunk * ch = ( struct rpcrdma_read_chunk * ) va ;
53
+ __be32 * next ;
61
54
62
- while (ch -> rc_discrim != xdr_zero ) {
63
- if (((unsigned long )ch + sizeof (struct rpcrdma_read_chunk )) >
64
- (unsigned long )vaend ) {
65
- dprintk ("svcrdma: vaend=%p, ch=%p\n" , vaend , ch );
55
+ while (* p ++ != xdr_zero ) {
56
+ next = p + rpcrdma_readchunk_maxsz - 1 ;
57
+ if (next > end )
66
58
return NULL ;
67
- }
68
- ch ++ ;
59
+ p = next ;
69
60
}
70
- return & ch -> rc_position ;
61
+ return p ;
71
62
}
72
63
73
- /*
74
- * Decodes a write chunk list. The expected format is as follows:
75
- * descrim : xdr_one
76
- * nchunks : <count>
77
- * handle : __be32 RKEY ---+
78
- * length : __be32 <len of segment> |
79
- * offset : remove va + <count>
80
- * . . . |
81
- * ---+
82
- */
83
- static __be32 * decode_write_list (__be32 * va , __be32 * vaend )
64
+ static __be32 * xdr_check_write_list (__be32 * p , __be32 * end )
84
65
{
85
- unsigned long start , end ;
86
- int nchunks ;
87
-
88
- struct rpcrdma_write_array * ary =
89
- (struct rpcrdma_write_array * )va ;
90
-
91
- /* Check for not write-array */
92
- if (ary -> wc_discrim == xdr_zero )
93
- return & ary -> wc_nchunks ;
66
+ __be32 * next ;
94
67
95
- if ((unsigned long )ary + sizeof (struct rpcrdma_write_array ) >
96
- (unsigned long )vaend ) {
97
- dprintk ("svcrdma: ary=%p, vaend=%p\n" , ary , vaend );
98
- return NULL ;
99
- }
100
- nchunks = be32_to_cpu (ary -> wc_nchunks );
101
-
102
- start = (unsigned long )& ary -> wc_array [0 ];
103
- end = (unsigned long )vaend ;
104
- if (nchunks < 0 ||
105
- nchunks > (SIZE_MAX - start ) / sizeof (struct rpcrdma_write_chunk ) ||
106
- (start + (sizeof (struct rpcrdma_write_chunk ) * nchunks )) > end ) {
107
- dprintk ("svcrdma: ary=%p, wc_nchunks=%d, vaend=%p\n" ,
108
- ary , nchunks , vaend );
109
- return NULL ;
68
+ while (* p ++ != xdr_zero ) {
69
+ next = p + 1 + be32_to_cpup (p ) * rpcrdma_segment_maxsz ;
70
+ if (next > end )
71
+ return NULL ;
72
+ p = next ;
110
73
}
111
- /*
112
- * rs_length is the 2nd 4B field in wc_target and taking its
113
- * address skips the list terminator
114
- */
115
- return & ary -> wc_array [nchunks ].wc_target .rs_length ;
74
+ return p ;
116
75
}
117
76
118
- static __be32 * decode_reply_array (__be32 * va , __be32 * vaend )
77
+ static __be32 * xdr_check_reply_chunk (__be32 * p , __be32 * end )
119
78
{
120
- unsigned long start , end ;
121
- int nchunks ;
122
- struct rpcrdma_write_array * ary =
123
- (struct rpcrdma_write_array * )va ;
124
-
125
- /* Check for no reply-array */
126
- if (ary -> wc_discrim == xdr_zero )
127
- return & ary -> wc_nchunks ;
128
-
129
- if ((unsigned long )ary + sizeof (struct rpcrdma_write_array ) >
130
- (unsigned long )vaend ) {
131
- dprintk ("svcrdma: ary=%p, vaend=%p\n" , ary , vaend );
132
- return NULL ;
133
- }
134
- nchunks = be32_to_cpu (ary -> wc_nchunks );
135
-
136
- start = (unsigned long )& ary -> wc_array [0 ];
137
- end = (unsigned long )vaend ;
138
- if (nchunks < 0 ||
139
- nchunks > (SIZE_MAX - start ) / sizeof (struct rpcrdma_write_chunk ) ||
140
- (start + (sizeof (struct rpcrdma_write_chunk ) * nchunks )) > end ) {
141
- dprintk ("svcrdma: ary=%p, wc_nchunks=%d, vaend=%p\n" ,
142
- ary , nchunks , vaend );
143
- return NULL ;
79
+ __be32 * next ;
80
+
81
+ if (* p ++ != xdr_zero ) {
82
+ next = p + 1 + be32_to_cpup (p ) * rpcrdma_segment_maxsz ;
83
+ if (next > end )
84
+ return NULL ;
85
+ p = next ;
144
86
}
145
- return ( __be32 * ) & ary -> wc_array [ nchunks ] ;
87
+ return p ;
146
88
}
147
89
148
90
/**
@@ -158,87 +100,71 @@ static __be32 *decode_reply_array(__be32 *va, __be32 *vaend)
158
100
*/
159
101
int svc_rdma_xdr_decode_req (struct xdr_buf * rq_arg )
160
102
{
161
- struct rpcrdma_msg * rmsgp ;
162
- __be32 * va , * vaend ;
163
- unsigned int len ;
164
- u32 hdr_len ;
103
+ __be32 * p , * end , * rdma_argp ;
104
+ unsigned int hdr_len ;
165
105
166
106
/* Verify that there's enough bytes for header + something */
167
- if (rq_arg -> len <= RPCRDMA_HDRLEN_ERR ) {
168
- dprintk ("svcrdma: header too short = %d\n" ,
169
- rq_arg -> len );
170
- return - EINVAL ;
171
- }
107
+ if (rq_arg -> len <= RPCRDMA_HDRLEN_ERR )
108
+ goto out_short ;
172
109
173
- rmsgp = (struct rpcrdma_msg * )rq_arg -> head [0 ].iov_base ;
174
- if (rmsgp -> rm_vers != rpcrdma_version ) {
175
- dprintk ("%s: bad version %u\n" , __func__ ,
176
- be32_to_cpu (rmsgp -> rm_vers ));
177
- return - EPROTONOSUPPORT ;
178
- }
110
+ rdma_argp = rq_arg -> head [0 ].iov_base ;
111
+ if (* (rdma_argp + 1 ) != rpcrdma_version )
112
+ goto out_version ;
179
113
180
- switch (be32_to_cpu ( rmsgp -> rm_type )) {
181
- case RDMA_MSG :
182
- case RDMA_NOMSG :
114
+ switch (* ( rdma_argp + 3 )) {
115
+ case rdma_msg :
116
+ case rdma_nomsg :
183
117
break ;
184
118
185
- case RDMA_DONE :
186
- /* Just drop it */
187
- dprintk ("svcrdma: dropping RDMA_DONE message\n" );
188
- return 0 ;
189
-
190
- case RDMA_ERROR :
191
- /* Possible if this is a backchannel reply.
192
- * XXX: We should cancel this XID, though.
193
- */
194
- dprintk ("svcrdma: dropping RDMA_ERROR message\n" );
195
- return 0 ;
196
-
197
- case RDMA_MSGP :
198
- /* Pull in the extra for the padded case, bump our pointer */
199
- rmsgp -> rm_body .rm_padded .rm_align =
200
- be32_to_cpu (rmsgp -> rm_body .rm_padded .rm_align );
201
- rmsgp -> rm_body .rm_padded .rm_thresh =
202
- be32_to_cpu (rmsgp -> rm_body .rm_padded .rm_thresh );
203
-
204
- va = & rmsgp -> rm_body .rm_padded .rm_pempty [4 ];
205
- rq_arg -> head [0 ].iov_base = va ;
206
- len = (u32 )((unsigned long )va - (unsigned long )rmsgp );
207
- rq_arg -> head [0 ].iov_len -= len ;
208
- if (len > rq_arg -> len )
209
- return - EINVAL ;
210
- return len ;
211
- default :
212
- dprintk ("svcrdma: bad rdma procedure (%u)\n" ,
213
- be32_to_cpu (rmsgp -> rm_type ));
214
- return - EINVAL ;
215
- }
119
+ case rdma_done :
120
+ goto out_drop ;
216
121
217
- /* The chunk list may contain either a read chunk list or a write
218
- * chunk list and a reply chunk list.
219
- */
220
- va = & rmsgp -> rm_body .rm_chunks [0 ];
221
- vaend = (__be32 * )((unsigned long )rmsgp + rq_arg -> len );
222
- va = decode_read_list (va , vaend );
223
- if (!va ) {
224
- dprintk ("svcrdma: failed to decode read list\n" );
225
- return - EINVAL ;
226
- }
227
- va = decode_write_list (va , vaend );
228
- if (!va ) {
229
- dprintk ("svcrdma: failed to decode write list\n" );
230
- return - EINVAL ;
231
- }
232
- va = decode_reply_array (va , vaend );
233
- if (!va ) {
234
- dprintk ("svcrdma: failed to decode reply chunk\n" );
235
- return - EINVAL ;
122
+ case rdma_error :
123
+ goto out_drop ;
124
+
125
+ default :
126
+ goto out_proc ;
236
127
}
237
128
238
- rq_arg -> head [0 ].iov_base = va ;
239
- hdr_len = (unsigned long )va - (unsigned long )rmsgp ;
129
+ end = (__be32 * )((unsigned long )rdma_argp + rq_arg -> len );
130
+ p = xdr_check_read_list (rdma_argp + 4 , end );
131
+ if (!p )
132
+ goto out_inval ;
133
+ p = xdr_check_write_list (p , end );
134
+ if (!p )
135
+ goto out_inval ;
136
+ p = xdr_check_reply_chunk (p , end );
137
+ if (!p )
138
+ goto out_inval ;
139
+ if (p > end )
140
+ goto out_inval ;
141
+
142
+ rq_arg -> head [0 ].iov_base = p ;
143
+ hdr_len = (unsigned long )p - (unsigned long )rdma_argp ;
240
144
rq_arg -> head [0 ].iov_len -= hdr_len ;
241
145
return hdr_len ;
146
+
147
+ out_short :
148
+ dprintk ("svcrdma: header too short = %d\n" , rq_arg -> len );
149
+ return - EINVAL ;
150
+
151
+ out_version :
152
+ dprintk ("svcrdma: bad xprt version: %u\n" ,
153
+ be32_to_cpup (rdma_argp + 1 ));
154
+ return - EPROTONOSUPPORT ;
155
+
156
+ out_drop :
157
+ dprintk ("svcrdma: dropping RDMA_DONE/ERROR message\n" );
158
+ return 0 ;
159
+
160
+ out_proc :
161
+ dprintk ("svcrdma: bad rdma procedure (%u)\n" ,
162
+ be32_to_cpup (rdma_argp + 3 ));
163
+ return - EINVAL ;
164
+
165
+ out_inval :
166
+ dprintk ("svcrdma: failed to parse transport header\n" );
167
+ return - EINVAL ;
242
168
}
243
169
244
170
int svc_rdma_xdr_encode_error (struct svcxprt_rdma * xprt ,
0 commit comments