Skip to content

Commit 345b415

Browse files
chuckleverJ. Bruce Fields
authored andcommitted
lockd: Update the NLMv4 TEST arguments decoder to use struct xdr_stream
Signed-off-by: Chuck Lever <[email protected]> Signed-off-by: J. Bruce Fields <[email protected]>
1 parent 7956521 commit 345b415

File tree

1 file changed

+66
-6
lines changed

1 file changed

+66
-6
lines changed

fs/lockd/xdr4.c

Lines changed: 66 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,32 @@ nlm4_decode_fh(__be32 *p, struct nfs_fh *f)
9696
return p + XDR_QUADLEN(f->size);
9797
}
9898

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+
99125
/*
100126
* Encode and decode owner handle
101127
*/
@@ -135,6 +161,39 @@ nlm4_decode_lock(__be32 *p, struct nlm_lock *lock)
135161
return p;
136162
}
137163

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+
138197
/*
139198
* Encode result of a TEST/TEST_MSG call
140199
*/
@@ -189,19 +248,20 @@ nlm4svc_decode_void(struct svc_rqst *rqstp, __be32 *p)
189248
int
190249
nlm4svc_decode_testargs(struct svc_rqst *rqstp, __be32 *p)
191250
{
251+
struct xdr_stream *xdr = &rqstp->rq_arg_stream;
192252
struct nlm_args *argp = rqstp->rq_argp;
193-
u32 exclusive;
253+
u32 exclusive;
194254

195-
if (!(p = nlm4_decode_cookie(p, &argp->cookie)))
255+
if (!svcxdr_decode_cookie(xdr, &argp->cookie))
196256
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))
200260
return 0;
201261
if (exclusive)
202262
argp->lock.fl.fl_type = F_WRLCK;
203263

204-
return xdr_argsize_check(rqstp, p);
264+
return 1;
205265
}
206266

207267
int

0 commit comments

Comments
 (0)