diff options
-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. */ |