@@ -96,6 +96,32 @@ nlm4_decode_fh(__be32 *p, struct nfs_fh *f)
96
96
return p + XDR_QUADLEN (f -> size );
97
97
}
98
98
99
+ /*
100
+ * NLM file handles are defined by specification to be a variable-length
101
+ * XDR opaque no longer than 1024 bytes. However, this implementation
102
+ * limits their length to the size of an NFSv3 file handle.
103
+ */
104
+ static bool
105
+ svcxdr_decode_fhandle (struct xdr_stream * xdr , struct nfs_fh * fh )
106
+ {
107
+ __be32 * p ;
108
+ u32 len ;
109
+
110
+ if (xdr_stream_decode_u32 (xdr , & len ) < 0 )
111
+ return false;
112
+ if (len > NFS_MAXFHSIZE )
113
+ return false;
114
+
115
+ p = xdr_inline_decode (xdr , len );
116
+ if (!p )
117
+ return false;
118
+ fh -> size = len ;
119
+ memcpy (fh -> data , p , len );
120
+ memset (fh -> data + len , 0 , sizeof (fh -> data ) - len );
121
+
122
+ return true;
123
+ }
124
+
99
125
/*
100
126
* Encode and decode owner handle
101
127
*/
@@ -135,6 +161,39 @@ nlm4_decode_lock(__be32 *p, struct nlm_lock *lock)
135
161
return p ;
136
162
}
137
163
164
+ static bool
165
+ svcxdr_decode_lock (struct xdr_stream * xdr , struct nlm_lock * lock )
166
+ {
167
+ struct file_lock * fl = & lock -> fl ;
168
+ u64 len , start ;
169
+ s64 end ;
170
+
171
+ if (!svcxdr_decode_string (xdr , & lock -> caller , & lock -> len ))
172
+ return false;
173
+ if (!svcxdr_decode_fhandle (xdr , & lock -> fh ))
174
+ return false;
175
+ if (!svcxdr_decode_owner (xdr , & lock -> oh ))
176
+ return false;
177
+ if (xdr_stream_decode_u32 (xdr , & lock -> svid ) < 0 )
178
+ return false;
179
+ if (xdr_stream_decode_u64 (xdr , & start ) < 0 )
180
+ return false;
181
+ if (xdr_stream_decode_u64 (xdr , & len ) < 0 )
182
+ return false;
183
+
184
+ locks_init_lock (fl );
185
+ fl -> fl_flags = FL_POSIX ;
186
+ fl -> fl_type = F_RDLCK ;
187
+ end = start + len - 1 ;
188
+ fl -> fl_start = s64_to_loff_t (start );
189
+ if (len == 0 || end < 0 )
190
+ fl -> fl_end = OFFSET_MAX ;
191
+ else
192
+ fl -> fl_end = s64_to_loff_t (end );
193
+
194
+ return true;
195
+ }
196
+
138
197
/*
139
198
* Encode result of a TEST/TEST_MSG call
140
199
*/
@@ -189,19 +248,20 @@ nlm4svc_decode_void(struct svc_rqst *rqstp, __be32 *p)
189
248
int
190
249
nlm4svc_decode_testargs (struct svc_rqst * rqstp , __be32 * p )
191
250
{
251
+ struct xdr_stream * xdr = & rqstp -> rq_arg_stream ;
192
252
struct nlm_args * argp = rqstp -> rq_argp ;
193
- u32 exclusive ;
253
+ u32 exclusive ;
194
254
195
- if (!( p = nlm4_decode_cookie ( p , & argp -> cookie ) ))
255
+ if (!svcxdr_decode_cookie ( xdr , & argp -> cookie ))
196
256
return 0 ;
197
-
198
- exclusive = ntohl ( * p ++ ) ;
199
- if (!( p = nlm4_decode_lock ( p , & argp -> lock ) ))
257
+ if ( xdr_stream_decode_bool ( xdr , & exclusive ) < 0 )
258
+ return 0 ;
259
+ if (!svcxdr_decode_lock ( xdr , & argp -> lock ))
200
260
return 0 ;
201
261
if (exclusive )
202
262
argp -> lock .fl .fl_type = F_WRLCK ;
203
263
204
- return xdr_argsize_check ( rqstp , p ) ;
264
+ return 1 ;
205
265
}
206
266
207
267
int
0 commit comments