aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfsd/nfs3xdr.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfsd/nfs3xdr.c')
-rw-r--r--fs/nfsd/nfs3xdr.c71
1 files changed, 42 insertions, 29 deletions
diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c
index 7e4bb0af24d7..10f6e7dcf633 100644
--- a/fs/nfsd/nfs3xdr.c
+++ b/fs/nfsd/nfs3xdr.c
@@ -239,7 +239,7 @@ static __be32 *
239encode_post_op_attr(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp) 239encode_post_op_attr(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp)
240{ 240{
241 struct dentry *dentry = fhp->fh_dentry; 241 struct dentry *dentry = fhp->fh_dentry;
242 if (dentry && dentry->d_inode != NULL) { 242 if (dentry && dentry->d_inode) {
243 int err; 243 int err;
244 struct kstat stat; 244 struct kstat stat;
245 245
@@ -300,9 +300,9 @@ int
300nfs3svc_decode_sattrargs(struct svc_rqst *rqstp, __be32 *p, 300nfs3svc_decode_sattrargs(struct svc_rqst *rqstp, __be32 *p,
301 struct nfsd3_sattrargs *args) 301 struct nfsd3_sattrargs *args)
302{ 302{
303 if (!(p = decode_fh(p, &args->fh)) 303 if (!(p = decode_fh(p, &args->fh)))
304 || !(p = decode_sattr3(p, &args->attrs)))
305 return 0; 304 return 0;
305 p = decode_sattr3(p, &args->attrs);
306 306
307 if ((args->check_guard = ntohl(*p++)) != 0) { 307 if ((args->check_guard = ntohl(*p++)) != 0) {
308 struct timespec time; 308 struct timespec time;
@@ -343,9 +343,9 @@ nfs3svc_decode_readargs(struct svc_rqst *rqstp, __be32 *p,
343 int v,pn; 343 int v,pn;
344 u32 max_blocksize = svc_max_payload(rqstp); 344 u32 max_blocksize = svc_max_payload(rqstp);
345 345
346 if (!(p = decode_fh(p, &args->fh)) 346 if (!(p = decode_fh(p, &args->fh)))
347 || !(p = xdr_decode_hyper(p, &args->offset)))
348 return 0; 347 return 0;
348 p = xdr_decode_hyper(p, &args->offset);
349 349
350 len = args->count = ntohl(*p++); 350 len = args->count = ntohl(*p++);
351 351
@@ -369,28 +369,44 @@ int
369nfs3svc_decode_writeargs(struct svc_rqst *rqstp, __be32 *p, 369nfs3svc_decode_writeargs(struct svc_rqst *rqstp, __be32 *p,
370 struct nfsd3_writeargs *args) 370 struct nfsd3_writeargs *args)
371{ 371{
372 unsigned int len, v, hdr; 372 unsigned int len, v, hdr, dlen;
373 u32 max_blocksize = svc_max_payload(rqstp); 373 u32 max_blocksize = svc_max_payload(rqstp);
374 374
375 if (!(p = decode_fh(p, &args->fh)) 375 if (!(p = decode_fh(p, &args->fh)))
376 || !(p = xdr_decode_hyper(p, &args->offset)))
377 return 0; 376 return 0;
377 p = xdr_decode_hyper(p, &args->offset);
378 378
379 args->count = ntohl(*p++); 379 args->count = ntohl(*p++);
380 args->stable = ntohl(*p++); 380 args->stable = ntohl(*p++);
381 len = args->len = ntohl(*p++); 381 len = args->len = ntohl(*p++);
382 /*
383 * The count must equal the amount of data passed.
384 */
385 if (args->count != args->len)
386 return 0;
382 387
388 /*
389 * Check to make sure that we got the right number of
390 * bytes.
391 */
383 hdr = (void*)p - rqstp->rq_arg.head[0].iov_base; 392 hdr = (void*)p - rqstp->rq_arg.head[0].iov_base;
384 if (rqstp->rq_arg.len < hdr || 393 dlen = rqstp->rq_arg.head[0].iov_len + rqstp->rq_arg.page_len
385 rqstp->rq_arg.len - hdr < len) 394 - hdr;
395 /*
396 * Round the length of the data which was specified up to
397 * the next multiple of XDR units and then compare that
398 * against the length which was actually received.
399 */
400 if (dlen != XDR_QUADLEN(len)*4)
386 return 0; 401 return 0;
387 402
403 if (args->count > max_blocksize) {
404 args->count = max_blocksize;
405 len = args->len = max_blocksize;
406 }
388 rqstp->rq_vec[0].iov_base = (void*)p; 407 rqstp->rq_vec[0].iov_base = (void*)p;
389 rqstp->rq_vec[0].iov_len = rqstp->rq_arg.head[0].iov_len - hdr; 408 rqstp->rq_vec[0].iov_len = rqstp->rq_arg.head[0].iov_len - hdr;
390 409 v = 0;
391 if (len > max_blocksize)
392 len = max_blocksize;
393 v= 0;
394 while (len > rqstp->rq_vec[v].iov_len) { 410 while (len > rqstp->rq_vec[v].iov_len) {
395 len -= rqstp->rq_vec[v].iov_len; 411 len -= rqstp->rq_vec[v].iov_len;
396 v++; 412 v++;
@@ -398,9 +414,8 @@ nfs3svc_decode_writeargs(struct svc_rqst *rqstp, __be32 *p,
398 rqstp->rq_vec[v].iov_len = PAGE_SIZE; 414 rqstp->rq_vec[v].iov_len = PAGE_SIZE;
399 } 415 }
400 rqstp->rq_vec[v].iov_len = len; 416 rqstp->rq_vec[v].iov_len = len;
401 args->vlen = v+1; 417 args->vlen = v + 1;
402 418 return 1;
403 return args->count == args->len && rqstp->rq_vec[0].iov_len > 0;
404} 419}
405 420
406int 421int
@@ -414,8 +429,7 @@ nfs3svc_decode_createargs(struct svc_rqst *rqstp, __be32 *p,
414 switch (args->createmode = ntohl(*p++)) { 429 switch (args->createmode = ntohl(*p++)) {
415 case NFS3_CREATE_UNCHECKED: 430 case NFS3_CREATE_UNCHECKED:
416 case NFS3_CREATE_GUARDED: 431 case NFS3_CREATE_GUARDED:
417 if (!(p = decode_sattr3(p, &args->attrs))) 432 p = decode_sattr3(p, &args->attrs);
418 return 0;
419 break; 433 break;
420 case NFS3_CREATE_EXCLUSIVE: 434 case NFS3_CREATE_EXCLUSIVE:
421 args->verf = p; 435 args->verf = p;
@@ -431,10 +445,10 @@ int
431nfs3svc_decode_mkdirargs(struct svc_rqst *rqstp, __be32 *p, 445nfs3svc_decode_mkdirargs(struct svc_rqst *rqstp, __be32 *p,
432 struct nfsd3_createargs *args) 446 struct nfsd3_createargs *args)
433{ 447{
434 if (!(p = decode_fh(p, &args->fh)) 448 if (!(p = decode_fh(p, &args->fh)) ||
435 || !(p = decode_filename(p, &args->name, &args->len)) 449 !(p = decode_filename(p, &args->name, &args->len)))
436 || !(p = decode_sattr3(p, &args->attrs)))
437 return 0; 450 return 0;
451 p = decode_sattr3(p, &args->attrs);
438 452
439 return xdr_argsize_check(rqstp, p); 453 return xdr_argsize_check(rqstp, p);
440} 454}
@@ -448,11 +462,12 @@ nfs3svc_decode_symlinkargs(struct svc_rqst *rqstp, __be32 *p,
448 char *old, *new; 462 char *old, *new;
449 struct kvec *vec; 463 struct kvec *vec;
450 464
451 if (!(p = decode_fh(p, &args->ffh)) 465 if (!(p = decode_fh(p, &args->ffh)) ||
452 || !(p = decode_filename(p, &args->fname, &args->flen)) 466 !(p = decode_filename(p, &args->fname, &args->flen))
453 || !(p = decode_sattr3(p, &args->attrs))
454 ) 467 )
455 return 0; 468 return 0;
469 p = decode_sattr3(p, &args->attrs);
470
456 /* now decode the pathname, which might be larger than the first page. 471 /* now decode the pathname, which might be larger than the first page.
457 * As we have to check for nul's anyway, we copy it into a new page 472 * As we have to check for nul's anyway, we copy it into a new page
458 * This page appears in the rq_res.pages list, but as pages_len is always 473 * This page appears in the rq_res.pages list, but as pages_len is always
@@ -502,10 +517,8 @@ nfs3svc_decode_mknodargs(struct svc_rqst *rqstp, __be32 *p,
502 args->ftype = ntohl(*p++); 517 args->ftype = ntohl(*p++);
503 518
504 if (args->ftype == NF3BLK || args->ftype == NF3CHR 519 if (args->ftype == NF3BLK || args->ftype == NF3CHR
505 || args->ftype == NF3SOCK || args->ftype == NF3FIFO) { 520 || args->ftype == NF3SOCK || args->ftype == NF3FIFO)
506 if (!(p = decode_sattr3(p, &args->attrs))) 521 p = decode_sattr3(p, &args->attrs);
507 return 0;
508 }
509 522
510 if (args->ftype == NF3BLK || args->ftype == NF3CHR) { 523 if (args->ftype == NF3BLK || args->ftype == NF3CHR) {
511 args->major = ntohl(*p++); 524 args->major = ntohl(*p++);