diff options
Diffstat (limited to 'fs')
| -rw-r--r-- | fs/nfsd/nfs4proc.c | 43 | ||||
| -rw-r--r-- | fs/nfsd/nfs4xdr.c | 38 | ||||
| -rw-r--r-- | fs/nfsd/nfsd.h | 21 |
3 files changed, 42 insertions, 60 deletions
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c index abb09b580389..e901cf124e9f 100644 --- a/fs/nfsd/nfs4proc.c +++ b/fs/nfsd/nfs4proc.c | |||
| @@ -96,33 +96,12 @@ check_attr_support(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
| 96 | { | 96 | { |
| 97 | struct dentry *dentry = cstate->current_fh.fh_dentry; | 97 | struct dentry *dentry = cstate->current_fh.fh_dentry; |
| 98 | 98 | ||
| 99 | /* | 99 | if (!nfsd_attrs_supported(cstate->minorversion, bmval)) |
| 100 | * Check about attributes are supported by the NFSv4 server or not. | ||
| 101 | * According to spec, unsupported attributes return ERR_ATTRNOTSUPP. | ||
| 102 | */ | ||
| 103 | if ((bmval[0] & ~nfsd_suppattrs0(cstate->minorversion)) || | ||
| 104 | (bmval[1] & ~nfsd_suppattrs1(cstate->minorversion)) || | ||
| 105 | (bmval[2] & ~nfsd_suppattrs2(cstate->minorversion))) | ||
| 106 | return nfserr_attrnotsupp; | 100 | return nfserr_attrnotsupp; |
| 107 | 101 | if ((bmval[0] & FATTR4_WORD0_ACL) && !IS_POSIXACL(d_inode(dentry))) | |
| 108 | /* | 102 | return nfserr_attrnotsupp; |
| 109 | * Check FATTR4_WORD0_ACL can be supported | 103 | if (writable && !bmval_is_subset(bmval, writable)) |
| 110 | * in current environment or not. | 104 | return nfserr_inval; |
| 111 | */ | ||
| 112 | if (bmval[0] & FATTR4_WORD0_ACL) { | ||
| 113 | if (!IS_POSIXACL(d_inode(dentry))) | ||
| 114 | return nfserr_attrnotsupp; | ||
| 115 | } | ||
| 116 | |||
| 117 | /* | ||
| 118 | * According to spec, read-only attributes return ERR_INVAL. | ||
| 119 | */ | ||
| 120 | if (writable) { | ||
| 121 | if ((bmval[0] & ~writable[0]) || (bmval[1] & ~writable[1]) || | ||
| 122 | (bmval[2] & ~writable[2])) | ||
| 123 | return nfserr_inval; | ||
| 124 | } | ||
| 125 | |||
| 126 | return nfs_ok; | 105 | return nfs_ok; |
| 127 | } | 106 | } |
| 128 | 107 | ||
| @@ -695,9 +674,9 @@ nfsd4_getattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
| 695 | if (getattr->ga_bmval[1] & NFSD_WRITEONLY_ATTRS_WORD1) | 674 | if (getattr->ga_bmval[1] & NFSD_WRITEONLY_ATTRS_WORD1) |
| 696 | return nfserr_inval; | 675 | return nfserr_inval; |
| 697 | 676 | ||
| 698 | getattr->ga_bmval[0] &= nfsd_suppattrs0(cstate->minorversion); | 677 | getattr->ga_bmval[0] &= nfsd_suppattrs[cstate->minorversion][0]; |
| 699 | getattr->ga_bmval[1] &= nfsd_suppattrs1(cstate->minorversion); | 678 | getattr->ga_bmval[1] &= nfsd_suppattrs[cstate->minorversion][1]; |
| 700 | getattr->ga_bmval[2] &= nfsd_suppattrs2(cstate->minorversion); | 679 | getattr->ga_bmval[2] &= nfsd_suppattrs[cstate->minorversion][2]; |
| 701 | 680 | ||
| 702 | getattr->ga_fhp = &cstate->current_fh; | 681 | getattr->ga_fhp = &cstate->current_fh; |
| 703 | return nfs_ok; | 682 | return nfs_ok; |
| @@ -799,9 +778,9 @@ nfsd4_readdir(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
| 799 | if (readdir->rd_bmval[1] & NFSD_WRITEONLY_ATTRS_WORD1) | 778 | if (readdir->rd_bmval[1] & NFSD_WRITEONLY_ATTRS_WORD1) |
| 800 | return nfserr_inval; | 779 | return nfserr_inval; |
| 801 | 780 | ||
| 802 | readdir->rd_bmval[0] &= nfsd_suppattrs0(cstate->minorversion); | 781 | readdir->rd_bmval[0] &= nfsd_suppattrs[cstate->minorversion][0]; |
| 803 | readdir->rd_bmval[1] &= nfsd_suppattrs1(cstate->minorversion); | 782 | readdir->rd_bmval[1] &= nfsd_suppattrs[cstate->minorversion][1]; |
| 804 | readdir->rd_bmval[2] &= nfsd_suppattrs2(cstate->minorversion); | 783 | readdir->rd_bmval[2] &= nfsd_suppattrs[cstate->minorversion][2]; |
| 805 | 784 | ||
| 806 | if ((cookie == 1) || (cookie == 2) || | 785 | if ((cookie == 1) || (cookie == 2) || |
| 807 | (cookie == 0 && memcmp(readdir->rd_verf.data, zeroverf.data, NFS4_VERIFIER_SIZE))) | 786 | (cookie == 0 && memcmp(readdir->rd_verf.data, zeroverf.data, NFS4_VERIFIER_SIZE))) |
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index c2d2895a1ec1..a99bbb88c6e1 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c | |||
| @@ -57,6 +57,20 @@ | |||
| 57 | 57 | ||
| 58 | #define NFSDDBG_FACILITY NFSDDBG_XDR | 58 | #define NFSDDBG_FACILITY NFSDDBG_XDR |
| 59 | 59 | ||
| 60 | u32 nfsd_suppattrs[3][3] = { | ||
| 61 | {NFSD4_SUPPORTED_ATTRS_WORD0, | ||
| 62 | NFSD4_SUPPORTED_ATTRS_WORD1, | ||
| 63 | NFSD4_SUPPORTED_ATTRS_WORD2}, | ||
| 64 | |||
| 65 | {NFSD4_1_SUPPORTED_ATTRS_WORD0, | ||
| 66 | NFSD4_1_SUPPORTED_ATTRS_WORD1, | ||
| 67 | NFSD4_1_SUPPORTED_ATTRS_WORD2}, | ||
| 68 | |||
| 69 | {NFSD4_1_SUPPORTED_ATTRS_WORD0, | ||
| 70 | NFSD4_1_SUPPORTED_ATTRS_WORD1, | ||
| 71 | NFSD4_2_SUPPORTED_ATTRS_WORD2}, | ||
| 72 | }; | ||
| 73 | |||
| 60 | /* | 74 | /* |
| 61 | * As per referral draft, the fsid for a referral MUST be different from the fsid of the containing | 75 | * As per referral draft, the fsid for a referral MUST be different from the fsid of the containing |
| 62 | * directory in order to indicate to the client that a filesystem boundary is present | 76 | * directory in order to indicate to the client that a filesystem boundary is present |
| @@ -2340,9 +2354,7 @@ nfsd4_encode_fattr(struct xdr_stream *xdr, struct svc_fh *fhp, | |||
| 2340 | struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id); | 2354 | struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id); |
| 2341 | 2355 | ||
| 2342 | BUG_ON(bmval1 & NFSD_WRITEONLY_ATTRS_WORD1); | 2356 | BUG_ON(bmval1 & NFSD_WRITEONLY_ATTRS_WORD1); |
| 2343 | BUG_ON(bmval0 & ~nfsd_suppattrs0(minorversion)); | 2357 | BUG_ON(!nfsd_attrs_supported(minorversion, bmval)); |
| 2344 | BUG_ON(bmval1 & ~nfsd_suppattrs1(minorversion)); | ||
| 2345 | BUG_ON(bmval2 & ~nfsd_suppattrs2(minorversion)); | ||
| 2346 | 2358 | ||
| 2347 | if (exp->ex_fslocs.migrated) { | 2359 | if (exp->ex_fslocs.migrated) { |
| 2348 | status = fattr_handle_absent_fs(&bmval0, &bmval1, &bmval2, &rdattr_err); | 2360 | status = fattr_handle_absent_fs(&bmval0, &bmval1, &bmval2, &rdattr_err); |
| @@ -2409,29 +2421,27 @@ nfsd4_encode_fattr(struct xdr_stream *xdr, struct svc_fh *fhp, | |||
| 2409 | p++; /* to be backfilled later */ | 2421 | p++; /* to be backfilled later */ |
| 2410 | 2422 | ||
| 2411 | if (bmval0 & FATTR4_WORD0_SUPPORTED_ATTRS) { | 2423 | if (bmval0 & FATTR4_WORD0_SUPPORTED_ATTRS) { |
| 2412 | u32 word0 = nfsd_suppattrs0(minorversion); | 2424 | u32 *supp = nfsd_suppattrs[minorversion]; |
| 2413 | u32 word1 = nfsd_suppattrs1(minorversion); | ||
| 2414 | u32 word2 = nfsd_suppattrs2(minorversion); | ||
| 2415 | 2425 | ||
| 2416 | if (!IS_POSIXACL(dentry->d_inode)) | 2426 | if (!IS_POSIXACL(dentry->d_inode)) |
| 2417 | word0 &= ~FATTR4_WORD0_ACL; | 2427 | supp[0] &= ~FATTR4_WORD0_ACL; |
| 2418 | if (!contextsupport) | 2428 | if (!contextsupport) |
| 2419 | word2 &= ~FATTR4_WORD2_SECURITY_LABEL; | 2429 | supp[2] &= ~FATTR4_WORD2_SECURITY_LABEL; |
| 2420 | if (!word2) { | 2430 | if (!supp[2]) { |
| 2421 | p = xdr_reserve_space(xdr, 12); | 2431 | p = xdr_reserve_space(xdr, 12); |
| 2422 | if (!p) | 2432 | if (!p) |
| 2423 | goto out_resource; | 2433 | goto out_resource; |
| 2424 | *p++ = cpu_to_be32(2); | 2434 | *p++ = cpu_to_be32(2); |
| 2425 | *p++ = cpu_to_be32(word0); | 2435 | *p++ = cpu_to_be32(supp[0]); |
| 2426 | *p++ = cpu_to_be32(word1); | 2436 | *p++ = cpu_to_be32(supp[1]); |
| 2427 | } else { | 2437 | } else { |
| 2428 | p = xdr_reserve_space(xdr, 16); | 2438 | p = xdr_reserve_space(xdr, 16); |
| 2429 | if (!p) | 2439 | if (!p) |
| 2430 | goto out_resource; | 2440 | goto out_resource; |
| 2431 | *p++ = cpu_to_be32(3); | 2441 | *p++ = cpu_to_be32(3); |
| 2432 | *p++ = cpu_to_be32(word0); | 2442 | *p++ = cpu_to_be32(supp[0]); |
| 2433 | *p++ = cpu_to_be32(word1); | 2443 | *p++ = cpu_to_be32(supp[1]); |
| 2434 | *p++ = cpu_to_be32(word2); | 2444 | *p++ = cpu_to_be32(supp[2]); |
| 2435 | } | 2445 | } |
| 2436 | } | 2446 | } |
| 2437 | if (bmval0 & FATTR4_WORD0_TYPE) { | 2447 | if (bmval0 & FATTR4_WORD0_TYPE) { |
diff --git a/fs/nfsd/nfsd.h b/fs/nfsd/nfsd.h index 9446849888d5..a72d4163273a 100644 --- a/fs/nfsd/nfsd.h +++ b/fs/nfsd/nfsd.h | |||
| @@ -361,25 +361,18 @@ void nfsd_lockd_shutdown(void); | |||
| 361 | (NFSD4_1_SUPPORTED_ATTRS_WORD2 | \ | 361 | (NFSD4_1_SUPPORTED_ATTRS_WORD2 | \ |
| 362 | NFSD4_2_SECURITY_ATTRS) | 362 | NFSD4_2_SECURITY_ATTRS) |
| 363 | 363 | ||
| 364 | static inline u32 nfsd_suppattrs0(u32 minorversion) | 364 | extern u32 nfsd_suppattrs[3][3]; |
| 365 | { | ||
| 366 | return minorversion ? NFSD4_1_SUPPORTED_ATTRS_WORD0 | ||
| 367 | : NFSD4_SUPPORTED_ATTRS_WORD0; | ||
| 368 | } | ||
| 369 | 365 | ||
| 370 | static inline u32 nfsd_suppattrs1(u32 minorversion) | 366 | static inline bool bmval_is_subset(u32 *bm1, u32 *bm2) |
| 371 | { | 367 | { |
| 372 | return minorversion ? NFSD4_1_SUPPORTED_ATTRS_WORD1 | 368 | return !((bm1[0] & ~bm2[0]) || |
| 373 | : NFSD4_SUPPORTED_ATTRS_WORD1; | 369 | (bm1[1] & ~bm2[1]) || |
| 370 | (bm1[2] & ~bm2[2])); | ||
| 374 | } | 371 | } |
| 375 | 372 | ||
| 376 | static inline u32 nfsd_suppattrs2(u32 minorversion) | 373 | static inline bool nfsd_attrs_supported(u32 minorversion, u32 *bmval) |
| 377 | { | 374 | { |
| 378 | switch (minorversion) { | 375 | return bmval_is_subset(bmval, nfsd_suppattrs[minorversion]); |
| 379 | default: return NFSD4_2_SUPPORTED_ATTRS_WORD2; | ||
| 380 | case 1: return NFSD4_1_SUPPORTED_ATTRS_WORD2; | ||
| 381 | case 0: return NFSD4_SUPPORTED_ATTRS_WORD2; | ||
| 382 | } | ||
| 383 | } | 376 | } |
| 384 | 377 | ||
| 385 | /* These will return ERR_INVAL if specified in GETATTR or READDIR. */ | 378 | /* These will return ERR_INVAL if specified in GETATTR or READDIR. */ |
