aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfsd/nfs3xdr.c')
-rw-r--r--fs/nfsd/nfs3xdr.c12
1 files changed, 8 insertions, 4 deletions
diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c
index 00575d776d91..7162ab7bc093 100644
--- a/fs/nfsd/nfs3xdr.c
+++ b/fs/nfsd/nfs3xdr.c
@@ -358,6 +358,7 @@ nfs3svc_decode_writeargs(struct svc_rqst *rqstp, __be32 *p,
358{ 358{
359 unsigned int len, v, hdr, dlen; 359 unsigned int len, v, hdr, dlen;
360 u32 max_blocksize = svc_max_payload(rqstp); 360 u32 max_blocksize = svc_max_payload(rqstp);
361 struct kvec *head = rqstp->rq_arg.head;
361 362
362 p = decode_fh(p, &args->fh); 363 p = decode_fh(p, &args->fh);
363 if (!p) 364 if (!p)
@@ -367,6 +368,8 @@ nfs3svc_decode_writeargs(struct svc_rqst *rqstp, __be32 *p,
367 args->count = ntohl(*p++); 368 args->count = ntohl(*p++);
368 args->stable = ntohl(*p++); 369 args->stable = ntohl(*p++);
369 len = args->len = ntohl(*p++); 370 len = args->len = ntohl(*p++);
371 if ((void *)p > head->iov_base + head->iov_len)
372 return 0;
370 /* 373 /*
371 * The count must equal the amount of data passed. 374 * The count must equal the amount of data passed.
372 */ 375 */
@@ -377,9 +380,8 @@ nfs3svc_decode_writeargs(struct svc_rqst *rqstp, __be32 *p,
377 * Check to make sure that we got the right number of 380 * Check to make sure that we got the right number of
378 * bytes. 381 * bytes.
379 */ 382 */
380 hdr = (void*)p - rqstp->rq_arg.head[0].iov_base; 383 hdr = (void*)p - head->iov_base;
381 dlen = rqstp->rq_arg.head[0].iov_len + rqstp->rq_arg.page_len 384 dlen = head->iov_len + rqstp->rq_arg.page_len - hdr;
382 - hdr;
383 /* 385 /*
384 * Round the length of the data which was specified up to 386 * Round the length of the data which was specified up to
385 * the next multiple of XDR units and then compare that 387 * the next multiple of XDR units and then compare that
@@ -396,7 +398,7 @@ nfs3svc_decode_writeargs(struct svc_rqst *rqstp, __be32 *p,
396 len = args->len = max_blocksize; 398 len = args->len = max_blocksize;
397 } 399 }
398 rqstp->rq_vec[0].iov_base = (void*)p; 400 rqstp->rq_vec[0].iov_base = (void*)p;
399 rqstp->rq_vec[0].iov_len = rqstp->rq_arg.head[0].iov_len - hdr; 401 rqstp->rq_vec[0].iov_len = head->iov_len - hdr;
400 v = 0; 402 v = 0;
401 while (len > rqstp->rq_vec[v].iov_len) { 403 while (len > rqstp->rq_vec[v].iov_len) {
402 len -= rqstp->rq_vec[v].iov_len; 404 len -= rqstp->rq_vec[v].iov_len;
@@ -471,6 +473,8 @@ nfs3svc_decode_symlinkargs(struct svc_rqst *rqstp, __be32 *p,
471 /* first copy and check from the first page */ 473 /* first copy and check from the first page */
472 old = (char*)p; 474 old = (char*)p;
473 vec = &rqstp->rq_arg.head[0]; 475 vec = &rqstp->rq_arg.head[0];
476 if ((void *)old > vec->iov_base + vec->iov_len)
477 return 0;
474 avail = vec->iov_len - (old - (char*)vec->iov_base); 478 avail = vec->iov_len - (old - (char*)vec->iov_base);
475 while (len && avail && *old) { 479 while (len && avail && *old) {
476 *new++ = *old++; 480 *new++ = *old++;