Commit 3c8e03166ae234d16e7871f8009638e0946d303c

Authored by Yu Zhiguo
Committed by J. Bruce Fields
1 parent 1dbd0d53f3

NFSv4: do exact check about attribute specified

Server should return NFS4ERR_ATTRNOTSUPP if an attribute specified is
not supported in current environment.
Operations CREATE, NVERIFY, OPEN, SETATTR and VERIFY should do this check.

This bug is found when do newpynfs tests. The names of the tests that failed
are following:
  CR12 NVF7a NVF7b NVF7c NVF7d NVF7f NVF7r NVF7s
  OPEN15 VF7a VF7b VF7c VF7d VF7f VF7r VF7s

Add function do_check_fattr() to do exact check:
1, Check attribute specified is supported by the NFSv4 server or not.
2, Check FATTR4_WORD0_ACL & FATTR4_WORD0_FS_LOCATIONS are supported
   in current environment or not.
3, Check attribute specified is writable or not.

step 1 and 3 are done in function nfsd4_decode_fattr() but removed
to this function now.

Signed-off-by: Yu Zhiguo <yuzg@cn.fujitsu.com>
Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>

Showing 2 changed files with 103 additions and 38 deletions Side-by-side Diff

... ... @@ -51,6 +51,78 @@
51 51  
52 52 #define NFSDDBG_FACILITY NFSDDBG_PROC
53 53  
  54 +static u32 nfsd_attrmask[] = {
  55 + NFSD_WRITEABLE_ATTRS_WORD0,
  56 + NFSD_WRITEABLE_ATTRS_WORD1,
  57 + NFSD_WRITEABLE_ATTRS_WORD2
  58 +};
  59 +
  60 +static u32 nfsd41_ex_attrmask[] = {
  61 + NFSD_SUPPATTR_EXCLCREAT_WORD0,
  62 + NFSD_SUPPATTR_EXCLCREAT_WORD1,
  63 + NFSD_SUPPATTR_EXCLCREAT_WORD2
  64 +};
  65 +
  66 +static __be32
  67 +check_attr_support(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
  68 + u32 *bmval, u32 *writable)
  69 +{
  70 + struct dentry *dentry = cstate->current_fh.fh_dentry;
  71 + struct svc_export *exp = cstate->current_fh.fh_export;
  72 +
  73 + /*
  74 + * Check about attributes are supported by the NFSv4 server or not.
  75 + * According to spec, unsupported attributes return ERR_ATTRNOTSUPP.
  76 + */
  77 + if ((bmval[0] & ~nfsd_suppattrs0(cstate->minorversion)) ||
  78 + (bmval[1] & ~nfsd_suppattrs1(cstate->minorversion)) ||
  79 + (bmval[2] & ~nfsd_suppattrs2(cstate->minorversion)))
  80 + return nfserr_attrnotsupp;
  81 +
  82 + /*
  83 + * Check FATTR4_WORD0_ACL & FATTR4_WORD0_FS_LOCATIONS can be supported
  84 + * in current environment or not.
  85 + */
  86 + if (bmval[0] & FATTR4_WORD0_ACL) {
  87 + if (!IS_POSIXACL(dentry->d_inode))
  88 + return nfserr_attrnotsupp;
  89 + }
  90 + if (bmval[0] & FATTR4_WORD0_FS_LOCATIONS) {
  91 + if (exp->ex_fslocs.locations == NULL)
  92 + return nfserr_attrnotsupp;
  93 + }
  94 +
  95 + /*
  96 + * According to spec, read-only attributes return ERR_INVAL.
  97 + */
  98 + if (writable) {
  99 + if ((bmval[0] & ~writable[0]) || (bmval[1] & ~writable[1]) ||
  100 + (bmval[2] & ~writable[2]))
  101 + return nfserr_inval;
  102 + }
  103 +
  104 + return nfs_ok;
  105 +}
  106 +
  107 +static __be32
  108 +nfsd4_check_open_attributes(struct svc_rqst *rqstp,
  109 + struct nfsd4_compound_state *cstate, struct nfsd4_open *open)
  110 +{
  111 + __be32 status = nfs_ok;
  112 +
  113 + if (open->op_create == NFS4_OPEN_CREATE) {
  114 + if (open->op_createmode == NFS4_CREATE_UNCHECKED
  115 + || open->op_createmode == NFS4_CREATE_GUARDED)
  116 + status = check_attr_support(rqstp, cstate,
  117 + open->op_bmval, nfsd_attrmask);
  118 + else if (open->op_createmode == NFS4_CREATE_EXCLUSIVE4_1)
  119 + status = check_attr_support(rqstp, cstate,
  120 + open->op_bmval, nfsd41_ex_attrmask);
  121 + }
  122 +
  123 + return status;
  124 +}
  125 +
54 126 static inline void
55 127 fh_dup2(struct svc_fh *dst, struct svc_fh *src)
56 128 {
... ... @@ -225,6 +297,10 @@
225 297 if (status)
226 298 goto out;
227 299  
  300 + status = nfsd4_check_open_attributes(rqstp, cstate, open);
  301 + if (status)
  302 + goto out;
  303 +
228 304 /* Openowner is now set, so sequence id will get bumped. Now we need
229 305 * these checks before we do any creates: */
230 306 status = nfserr_grace;
... ... @@ -395,6 +471,11 @@
395 471 if (status)
396 472 return status;
397 473  
  474 + status = check_attr_support(rqstp, cstate, create->cr_bmval,
  475 + nfsd_attrmask);
  476 + if (status)
  477 + return status;
  478 +
398 479 switch (create->cr_type) {
399 480 case NF4LNK:
400 481 /* ugh! we have to null-terminate the linktext, or
... ... @@ -689,6 +770,12 @@
689 770 if (status)
690 771 return status;
691 772 status = nfs_ok;
  773 +
  774 + status = check_attr_support(rqstp, cstate, setattr->sa_bmval,
  775 + nfsd_attrmask);
  776 + if (status)
  777 + goto out;
  778 +
692 779 if (setattr->sa_acl != NULL)
693 780 status = nfsd4_set_nfs4_acl(rqstp, &cstate->current_fh,
694 781 setattr->sa_acl);
... ... @@ -763,10 +850,10 @@
763 850 if (status)
764 851 return status;
765 852  
766   - if ((verify->ve_bmval[0] & ~nfsd_suppattrs0(cstate->minorversion))
767   - || (verify->ve_bmval[1] & ~nfsd_suppattrs1(cstate->minorversion))
768   - || (verify->ve_bmval[2] & ~nfsd_suppattrs2(cstate->minorversion)))
769   - return nfserr_attrnotsupp;
  853 + status = check_attr_support(rqstp, cstate, verify->ve_bmval, NULL);
  854 + if (status)
  855 + return status;
  856 +
770 857 if ((verify->ve_bmval[0] & FATTR4_WORD0_RDATTR_ERROR)
771 858 || (verify->ve_bmval[1] & NFSD_WRITEONLY_ATTRS_WORD1))
772 859 return nfserr_inval;
... ... @@ -244,20 +244,8 @@
244 244 DECODE_TAIL;
245 245 }
246 246  
247   -static u32 nfsd_attrmask[] = {
248   - NFSD_WRITEABLE_ATTRS_WORD0,
249   - NFSD_WRITEABLE_ATTRS_WORD1,
250   - NFSD_WRITEABLE_ATTRS_WORD2
251   -};
252   -
253   -static u32 nfsd41_ex_attrmask[] = {
254   - NFSD_SUPPATTR_EXCLCREAT_WORD0,
255   - NFSD_SUPPATTR_EXCLCREAT_WORD1,
256   - NFSD_SUPPATTR_EXCLCREAT_WORD2
257   -};
258   -
259 247 static __be32
260   -nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval, u32 *writable,
  248 +nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval,
261 249 struct iattr *iattr, struct nfs4_acl **acl)
262 250 {
263 251 int expected_len, len = 0;
... ... @@ -270,18 +258,6 @@
270 258 if ((status = nfsd4_decode_bitmap(argp, bmval)))
271 259 return status;
272 260  
273   - /*
274   - * According to spec, unsupported attributes return ERR_ATTRNOTSUPP;
275   - * read-only attributes return ERR_INVAL.
276   - */
277   - if ((bmval[0] & ~nfsd_suppattrs0(argp->minorversion)) ||
278   - (bmval[1] & ~nfsd_suppattrs1(argp->minorversion)) ||
279   - (bmval[2] & ~nfsd_suppattrs2(argp->minorversion)))
280   - return nfserr_attrnotsupp;
281   - if ((bmval[0] & ~writable[0]) || (bmval[1] & ~writable[1]) ||
282   - (bmval[2] & ~writable[2]))
283   - return nfserr_inval;
284   -
285 261 READ_BUF(4);
286 262 READ32(expected_len);
287 263  
... ... @@ -414,8 +390,11 @@
414 390 goto xdr_error;
415 391 }
416 392 }
417   - BUG_ON(bmval[2]); /* no such writeable attr supported yet */
418   - if (len != expected_len)
  393 + if (bmval[0] & ~NFSD_WRITEABLE_ATTRS_WORD0
  394 + || bmval[1] & ~NFSD_WRITEABLE_ATTRS_WORD1
  395 + || bmval[2] & ~NFSD_WRITEABLE_ATTRS_WORD2)
  396 + READ_BUF(expected_len - len);
  397 + else if (len != expected_len)
419 398 goto xdr_error;
420 399  
421 400 DECODE_TAIL;
... ... @@ -508,8 +487,8 @@
508 487 if ((status = check_filename(create->cr_name, create->cr_namelen, nfserr_inval)))
509 488 return status;
510 489  
511   - status = nfsd4_decode_fattr(argp, create->cr_bmval, nfsd_attrmask,
512   - &create->cr_iattr, &create->cr_acl);
  490 + status = nfsd4_decode_fattr(argp, create->cr_bmval, &create->cr_iattr,
  491 + &create->cr_acl);
513 492 if (status)
514 493 goto out;
515 494  
... ... @@ -672,7 +651,7 @@
672 651 case NFS4_CREATE_UNCHECKED:
673 652 case NFS4_CREATE_GUARDED:
674 653 status = nfsd4_decode_fattr(argp, open->op_bmval,
675   - nfsd_attrmask, &open->op_iattr, &open->op_acl);
  654 + &open->op_iattr, &open->op_acl);
676 655 if (status)
677 656 goto out;
678 657 break;
... ... @@ -686,8 +665,7 @@
686 665 READ_BUF(8);
687 666 COPYMEM(open->op_verf.data, 8);
688 667 status = nfsd4_decode_fattr(argp, open->op_bmval,
689   - nfsd41_ex_attrmask, &open->op_iattr,
690   - &open->op_acl);
  668 + &open->op_iattr, &open->op_acl);
691 669 if (status)
692 670 goto out;
693 671 break;
... ... @@ -883,8 +861,8 @@
883 861 status = nfsd4_decode_stateid(argp, &setattr->sa_stateid);
884 862 if (status)
885 863 return status;
886   - return nfsd4_decode_fattr(argp, setattr->sa_bmval, nfsd_attrmask,
887   - &setattr->sa_iattr, &setattr->sa_acl);
  864 + return nfsd4_decode_fattr(argp, setattr->sa_bmval, &setattr->sa_iattr,
  865 + &setattr->sa_acl);
888 866 }
889 867  
890 868 static __be32