diff options
Diffstat (limited to 'fs/nfsd')
-rw-r--r-- | fs/nfsd/Makefile | 1 | ||||
-rw-r--r-- | fs/nfsd/export.c | 14 | ||||
-rw-r--r-- | fs/nfsd/nfs3proc.c | 2 | ||||
-rw-r--r-- | fs/nfsd/nfs3xdr.c | 71 | ||||
-rw-r--r-- | fs/nfsd/nfs4acl.c | 17 | ||||
-rw-r--r-- | fs/nfsd/nfs4state.c | 2 | ||||
-rw-r--r-- | fs/nfsd/nfsfh.c | 56 | ||||
-rw-r--r-- | fs/nfsd/nfsproc.c | 2 | ||||
-rw-r--r-- | fs/nfsd/nfsxdr.c | 53 |
9 files changed, 138 insertions, 80 deletions
diff --git a/fs/nfsd/Makefile b/fs/nfsd/Makefile index ce341dc76d5e..9b118ee20193 100644 --- a/fs/nfsd/Makefile +++ b/fs/nfsd/Makefile | |||
@@ -11,4 +11,3 @@ nfsd-$(CONFIG_NFSD_V3) += nfs3proc.o nfs3xdr.o | |||
11 | nfsd-$(CONFIG_NFSD_V3_ACL) += nfs3acl.o | 11 | nfsd-$(CONFIG_NFSD_V3_ACL) += nfs3acl.o |
12 | nfsd-$(CONFIG_NFSD_V4) += nfs4proc.o nfs4xdr.o nfs4state.o nfs4idmap.o \ | 12 | nfsd-$(CONFIG_NFSD_V4) += nfs4proc.o nfs4xdr.o nfs4state.o nfs4idmap.o \ |
13 | nfs4acl.o nfs4callback.o nfs4recover.o | 13 | nfs4acl.o nfs4callback.o nfs4recover.o |
14 | nfsd-objs := $(nfsd-y) | ||
diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c index 6f24768272a1..79bd03b8bbf8 100644 --- a/fs/nfsd/export.c +++ b/fs/nfsd/export.c | |||
@@ -469,6 +469,13 @@ static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen) | |||
469 | nd.dentry = NULL; | 469 | nd.dentry = NULL; |
470 | exp.ex_path = NULL; | 470 | exp.ex_path = NULL; |
471 | 471 | ||
472 | /* fs locations */ | ||
473 | exp.ex_fslocs.locations = NULL; | ||
474 | exp.ex_fslocs.locations_count = 0; | ||
475 | exp.ex_fslocs.migrated = 0; | ||
476 | |||
477 | exp.ex_uuid = NULL; | ||
478 | |||
472 | if (mesg[mlen-1] != '\n') | 479 | if (mesg[mlen-1] != '\n') |
473 | return -EINVAL; | 480 | return -EINVAL; |
474 | mesg[mlen-1] = 0; | 481 | mesg[mlen-1] = 0; |
@@ -509,13 +516,6 @@ static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen) | |||
509 | if (exp.h.expiry_time == 0) | 516 | if (exp.h.expiry_time == 0) |
510 | goto out; | 517 | goto out; |
511 | 518 | ||
512 | /* fs locations */ | ||
513 | exp.ex_fslocs.locations = NULL; | ||
514 | exp.ex_fslocs.locations_count = 0; | ||
515 | exp.ex_fslocs.migrated = 0; | ||
516 | |||
517 | exp.ex_uuid = NULL; | ||
518 | |||
519 | /* flags */ | 519 | /* flags */ |
520 | err = get_int(&mesg, &an_int); | 520 | err = get_int(&mesg, &an_int); |
521 | if (err == -ENOENT) | 521 | if (err == -ENOENT) |
diff --git a/fs/nfsd/nfs3proc.c b/fs/nfsd/nfs3proc.c index 7f5bad0393b1..eac82830bfd7 100644 --- a/fs/nfsd/nfs3proc.c +++ b/fs/nfsd/nfs3proc.c | |||
@@ -177,7 +177,7 @@ nfsd3_proc_read(struct svc_rqst *rqstp, struct nfsd3_readargs *argp, | |||
177 | if (max_blocksize < resp->count) | 177 | if (max_blocksize < resp->count) |
178 | resp->count = max_blocksize; | 178 | resp->count = max_blocksize; |
179 | 179 | ||
180 | svc_reserve(rqstp, ((1 + NFS3_POST_OP_ATTR_WORDS + 3)<<2) + resp->count +4); | 180 | svc_reserve_auth(rqstp, ((1 + NFS3_POST_OP_ATTR_WORDS + 3)<<2) + resp->count +4); |
181 | 181 | ||
182 | fh_copy(&resp->fh, &argp->fh); | 182 | fh_copy(&resp->fh, &argp->fh); |
183 | nfserr = nfsd_read(rqstp, &resp->fh, NULL, | 183 | nfserr = nfsd_read(rqstp, &resp->fh, NULL, |
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 * | |||
239 | encode_post_op_attr(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp) | 239 | encode_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 | |||
300 | nfs3svc_decode_sattrargs(struct svc_rqst *rqstp, __be32 *p, | 300 | nfs3svc_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 | |||
369 | nfs3svc_decode_writeargs(struct svc_rqst *rqstp, __be32 *p, | 369 | nfs3svc_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 | ||
406 | int | 421 | int |
@@ -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 | |||
431 | nfs3svc_decode_mkdirargs(struct svc_rqst *rqstp, __be32 *p, | 445 | nfs3svc_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++); |
diff --git a/fs/nfsd/nfs4acl.c b/fs/nfsd/nfs4acl.c index 673a53c014a3..cc3b7badd486 100644 --- a/fs/nfsd/nfs4acl.c +++ b/fs/nfsd/nfs4acl.c | |||
@@ -137,7 +137,6 @@ struct ace_container { | |||
137 | static short ace2type(struct nfs4_ace *); | 137 | static short ace2type(struct nfs4_ace *); |
138 | static void _posix_to_nfsv4_one(struct posix_acl *, struct nfs4_acl *, | 138 | static void _posix_to_nfsv4_one(struct posix_acl *, struct nfs4_acl *, |
139 | unsigned int); | 139 | unsigned int); |
140 | void nfs4_acl_add_ace(struct nfs4_acl *, u32, u32, u32, int, uid_t); | ||
141 | 140 | ||
142 | struct nfs4_acl * | 141 | struct nfs4_acl * |
143 | nfs4_acl_posix_to_nfsv4(struct posix_acl *pacl, struct posix_acl *dpacl, | 142 | nfs4_acl_posix_to_nfsv4(struct posix_acl *pacl, struct posix_acl *dpacl, |
@@ -785,21 +784,6 @@ nfs4_acl_new(int n) | |||
785 | return acl; | 784 | return acl; |
786 | } | 785 | } |
787 | 786 | ||
788 | void | ||
789 | nfs4_acl_add_ace(struct nfs4_acl *acl, u32 type, u32 flag, u32 access_mask, | ||
790 | int whotype, uid_t who) | ||
791 | { | ||
792 | struct nfs4_ace *ace = acl->aces + acl->naces; | ||
793 | |||
794 | ace->type = type; | ||
795 | ace->flag = flag; | ||
796 | ace->access_mask = access_mask; | ||
797 | ace->whotype = whotype; | ||
798 | ace->who = who; | ||
799 | |||
800 | acl->naces++; | ||
801 | } | ||
802 | |||
803 | static struct { | 787 | static struct { |
804 | char *string; | 788 | char *string; |
805 | int stringlen; | 789 | int stringlen; |
@@ -851,6 +835,5 @@ nfs4_acl_write_who(int who, char *p) | |||
851 | } | 835 | } |
852 | 836 | ||
853 | EXPORT_SYMBOL(nfs4_acl_new); | 837 | EXPORT_SYMBOL(nfs4_acl_new); |
854 | EXPORT_SYMBOL(nfs4_acl_add_ace); | ||
855 | EXPORT_SYMBOL(nfs4_acl_get_whotype); | 838 | EXPORT_SYMBOL(nfs4_acl_get_whotype); |
856 | EXPORT_SYMBOL(nfs4_acl_write_who); | 839 | EXPORT_SYMBOL(nfs4_acl_write_who); |
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 678f3be88ac0..3cc8ce422ab1 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c | |||
@@ -1326,8 +1326,6 @@ do_recall(void *__dp) | |||
1326 | { | 1326 | { |
1327 | struct nfs4_delegation *dp = __dp; | 1327 | struct nfs4_delegation *dp = __dp; |
1328 | 1328 | ||
1329 | daemonize("nfsv4-recall"); | ||
1330 | |||
1331 | nfsd4_cb_recall(dp); | 1329 | nfsd4_cb_recall(dp); |
1332 | return 0; | 1330 | return 0; |
1333 | } | 1331 | } |
diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c index 739dd3c5c3b2..6ca2d24fc216 100644 --- a/fs/nfsd/nfsfh.c +++ b/fs/nfsd/nfsfh.c | |||
@@ -323,7 +323,7 @@ fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry, | |||
323 | * | 323 | * |
324 | */ | 324 | */ |
325 | 325 | ||
326 | u8 version = 1; | 326 | u8 version; |
327 | u8 fsid_type = 0; | 327 | u8 fsid_type = 0; |
328 | struct inode * inode = dentry->d_inode; | 328 | struct inode * inode = dentry->d_inode; |
329 | struct dentry *parent = dentry->d_parent; | 329 | struct dentry *parent = dentry->d_parent; |
@@ -341,15 +341,59 @@ fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry, | |||
341 | * the reference filehandle (if it is in the same export) | 341 | * the reference filehandle (if it is in the same export) |
342 | * or the export options. | 342 | * or the export options. |
343 | */ | 343 | */ |
344 | retry: | ||
345 | version = 1; | ||
344 | if (ref_fh && ref_fh->fh_export == exp) { | 346 | if (ref_fh && ref_fh->fh_export == exp) { |
345 | version = ref_fh->fh_handle.fh_version; | 347 | version = ref_fh->fh_handle.fh_version; |
346 | if (version == 0xca) | 348 | fsid_type = ref_fh->fh_handle.fh_fsid_type; |
349 | |||
350 | if (ref_fh == fhp) | ||
351 | fh_put(ref_fh); | ||
352 | ref_fh = NULL; | ||
353 | |||
354 | switch (version) { | ||
355 | case 0xca: | ||
347 | fsid_type = FSID_DEV; | 356 | fsid_type = FSID_DEV; |
348 | else | 357 | break; |
349 | fsid_type = ref_fh->fh_handle.fh_fsid_type; | 358 | case 1: |
350 | /* We know this version/type works for this export | 359 | break; |
351 | * so there is no need for further checks. | 360 | default: |
361 | goto retry; | ||
362 | } | ||
363 | |||
364 | /* Need to check that this type works for this | ||
365 | * export point. As the fsid -> filesystem mapping | ||
366 | * was guided by user-space, there is no guarantee | ||
367 | * that the filesystem actually supports that fsid | ||
368 | * type. If it doesn't we loop around again without | ||
369 | * ref_fh set. | ||
352 | */ | 370 | */ |
371 | switch(fsid_type) { | ||
372 | case FSID_DEV: | ||
373 | if (!old_valid_dev(ex_dev)) | ||
374 | goto retry; | ||
375 | /* FALL THROUGH */ | ||
376 | case FSID_MAJOR_MINOR: | ||
377 | case FSID_ENCODE_DEV: | ||
378 | if (!(exp->ex_dentry->d_inode->i_sb->s_type->fs_flags | ||
379 | & FS_REQUIRES_DEV)) | ||
380 | goto retry; | ||
381 | break; | ||
382 | case FSID_NUM: | ||
383 | if (! (exp->ex_flags & NFSEXP_FSID)) | ||
384 | goto retry; | ||
385 | break; | ||
386 | case FSID_UUID8: | ||
387 | case FSID_UUID16: | ||
388 | if (!root_export) | ||
389 | goto retry; | ||
390 | /* fall through */ | ||
391 | case FSID_UUID4_INUM: | ||
392 | case FSID_UUID16_INUM: | ||
393 | if (exp->ex_uuid == NULL) | ||
394 | goto retry; | ||
395 | break; | ||
396 | } | ||
353 | } else if (exp->ex_uuid) { | 397 | } else if (exp->ex_uuid) { |
354 | if (fhp->fh_maxsize >= 64) { | 398 | if (fhp->fh_maxsize >= 64) { |
355 | if (root_export) | 399 | if (root_export) |
diff --git a/fs/nfsd/nfsproc.c b/fs/nfsd/nfsproc.c index 5cc2eec981b8..b2c7147aa921 100644 --- a/fs/nfsd/nfsproc.c +++ b/fs/nfsd/nfsproc.c | |||
@@ -155,7 +155,7 @@ nfsd_proc_read(struct svc_rqst *rqstp, struct nfsd_readargs *argp, | |||
155 | argp->count); | 155 | argp->count); |
156 | argp->count = NFSSVC_MAXBLKSIZE_V2; | 156 | argp->count = NFSSVC_MAXBLKSIZE_V2; |
157 | } | 157 | } |
158 | svc_reserve(rqstp, (19<<2) + argp->count + 4); | 158 | svc_reserve_auth(rqstp, (19<<2) + argp->count + 4); |
159 | 159 | ||
160 | resp->count = argp->count; | 160 | resp->count = argp->count; |
161 | nfserr = nfsd_read(rqstp, fh_copy(&resp->fh, &argp->fh), NULL, | 161 | nfserr = nfsd_read(rqstp, fh_copy(&resp->fh, &argp->fh), NULL, |
diff --git a/fs/nfsd/nfsxdr.c b/fs/nfsd/nfsxdr.c index 0c24b9e24fe8..cb3e7fadb772 100644 --- a/fs/nfsd/nfsxdr.c +++ b/fs/nfsd/nfsxdr.c | |||
@@ -231,9 +231,10 @@ int | |||
231 | nfssvc_decode_sattrargs(struct svc_rqst *rqstp, __be32 *p, | 231 | nfssvc_decode_sattrargs(struct svc_rqst *rqstp, __be32 *p, |
232 | struct nfsd_sattrargs *args) | 232 | struct nfsd_sattrargs *args) |
233 | { | 233 | { |
234 | if (!(p = decode_fh(p, &args->fh)) | 234 | p = decode_fh(p, &args->fh); |
235 | || !(p = decode_sattr(p, &args->attrs))) | 235 | if (!p) |
236 | return 0; | 236 | return 0; |
237 | p = decode_sattr(p, &args->attrs); | ||
237 | 238 | ||
238 | return xdr_argsize_check(rqstp, p); | 239 | return xdr_argsize_check(rqstp, p); |
239 | } | 240 | } |
@@ -284,8 +285,9 @@ int | |||
284 | nfssvc_decode_writeargs(struct svc_rqst *rqstp, __be32 *p, | 285 | nfssvc_decode_writeargs(struct svc_rqst *rqstp, __be32 *p, |
285 | struct nfsd_writeargs *args) | 286 | struct nfsd_writeargs *args) |
286 | { | 287 | { |
287 | unsigned int len; | 288 | unsigned int len, hdr, dlen; |
288 | int v; | 289 | int v; |
290 | |||
289 | if (!(p = decode_fh(p, &args->fh))) | 291 | if (!(p = decode_fh(p, &args->fh))) |
290 | return 0; | 292 | return 0; |
291 | 293 | ||
@@ -293,11 +295,30 @@ nfssvc_decode_writeargs(struct svc_rqst *rqstp, __be32 *p, | |||
293 | args->offset = ntohl(*p++); /* offset */ | 295 | args->offset = ntohl(*p++); /* offset */ |
294 | p++; /* totalcount */ | 296 | p++; /* totalcount */ |
295 | len = args->len = ntohl(*p++); | 297 | len = args->len = ntohl(*p++); |
296 | rqstp->rq_vec[0].iov_base = (void*)p; | 298 | /* |
297 | rqstp->rq_vec[0].iov_len = rqstp->rq_arg.head[0].iov_len - | 299 | * The protocol specifies a maximum of 8192 bytes. |
298 | (((void*)p) - rqstp->rq_arg.head[0].iov_base); | 300 | */ |
299 | if (len > NFSSVC_MAXBLKSIZE_V2) | 301 | if (len > NFSSVC_MAXBLKSIZE_V2) |
300 | len = NFSSVC_MAXBLKSIZE_V2; | 302 | return 0; |
303 | |||
304 | /* | ||
305 | * Check to make sure that we got the right number of | ||
306 | * bytes. | ||
307 | */ | ||
308 | hdr = (void*)p - rqstp->rq_arg.head[0].iov_base; | ||
309 | dlen = rqstp->rq_arg.head[0].iov_len + rqstp->rq_arg.page_len | ||
310 | - hdr; | ||
311 | |||
312 | /* | ||
313 | * Round the length of the data which was specified up to | ||
314 | * the next multiple of XDR units and then compare that | ||
315 | * against the length which was actually received. | ||
316 | */ | ||
317 | if (dlen != XDR_QUADLEN(len)*4) | ||
318 | return 0; | ||
319 | |||
320 | rqstp->rq_vec[0].iov_base = (void*)p; | ||
321 | rqstp->rq_vec[0].iov_len = rqstp->rq_arg.head[0].iov_len - hdr; | ||
301 | v = 0; | 322 | v = 0; |
302 | while (len > rqstp->rq_vec[v].iov_len) { | 323 | while (len > rqstp->rq_vec[v].iov_len) { |
303 | len -= rqstp->rq_vec[v].iov_len; | 324 | len -= rqstp->rq_vec[v].iov_len; |
@@ -306,18 +327,18 @@ nfssvc_decode_writeargs(struct svc_rqst *rqstp, __be32 *p, | |||
306 | rqstp->rq_vec[v].iov_len = PAGE_SIZE; | 327 | rqstp->rq_vec[v].iov_len = PAGE_SIZE; |
307 | } | 328 | } |
308 | rqstp->rq_vec[v].iov_len = len; | 329 | rqstp->rq_vec[v].iov_len = len; |
309 | args->vlen = v+1; | 330 | args->vlen = v + 1; |
310 | return rqstp->rq_vec[0].iov_len > 0; | 331 | return 1; |
311 | } | 332 | } |
312 | 333 | ||
313 | int | 334 | int |
314 | nfssvc_decode_createargs(struct svc_rqst *rqstp, __be32 *p, | 335 | nfssvc_decode_createargs(struct svc_rqst *rqstp, __be32 *p, |
315 | struct nfsd_createargs *args) | 336 | struct nfsd_createargs *args) |
316 | { | 337 | { |
317 | if (!(p = decode_fh(p, &args->fh)) | 338 | if ( !(p = decode_fh(p, &args->fh)) |
318 | || !(p = decode_filename(p, &args->name, &args->len)) | 339 | || !(p = decode_filename(p, &args->name, &args->len))) |
319 | || !(p = decode_sattr(p, &args->attrs))) | ||
320 | return 0; | 340 | return 0; |
341 | p = decode_sattr(p, &args->attrs); | ||
321 | 342 | ||
322 | return xdr_argsize_check(rqstp, p); | 343 | return xdr_argsize_check(rqstp, p); |
323 | } | 344 | } |
@@ -361,11 +382,11 @@ int | |||
361 | nfssvc_decode_symlinkargs(struct svc_rqst *rqstp, __be32 *p, | 382 | nfssvc_decode_symlinkargs(struct svc_rqst *rqstp, __be32 *p, |
362 | struct nfsd_symlinkargs *args) | 383 | struct nfsd_symlinkargs *args) |
363 | { | 384 | { |
364 | if (!(p = decode_fh(p, &args->ffh)) | 385 | if ( !(p = decode_fh(p, &args->ffh)) |
365 | || !(p = decode_filename(p, &args->fname, &args->flen)) | 386 | || !(p = decode_filename(p, &args->fname, &args->flen)) |
366 | || !(p = decode_pathname(p, &args->tname, &args->tlen)) | 387 | || !(p = decode_pathname(p, &args->tname, &args->tlen))) |
367 | || !(p = decode_sattr(p, &args->attrs))) | ||
368 | return 0; | 388 | return 0; |
389 | p = decode_sattr(p, &args->attrs); | ||
369 | 390 | ||
370 | return xdr_argsize_check(rqstp, p); | 391 | return xdr_argsize_check(rqstp, p); |
371 | } | 392 | } |