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>
This commit is contained in:
parent
1dbd0d53f3
commit
3c8e03166a
|
@ -51,6 +51,78 @@
|
||||||
|
|
||||||
#define NFSDDBG_FACILITY NFSDDBG_PROC
|
#define NFSDDBG_FACILITY NFSDDBG_PROC
|
||||||
|
|
||||||
|
static u32 nfsd_attrmask[] = {
|
||||||
|
NFSD_WRITEABLE_ATTRS_WORD0,
|
||||||
|
NFSD_WRITEABLE_ATTRS_WORD1,
|
||||||
|
NFSD_WRITEABLE_ATTRS_WORD2
|
||||||
|
};
|
||||||
|
|
||||||
|
static u32 nfsd41_ex_attrmask[] = {
|
||||||
|
NFSD_SUPPATTR_EXCLCREAT_WORD0,
|
||||||
|
NFSD_SUPPATTR_EXCLCREAT_WORD1,
|
||||||
|
NFSD_SUPPATTR_EXCLCREAT_WORD2
|
||||||
|
};
|
||||||
|
|
||||||
|
static __be32
|
||||||
|
check_attr_support(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
|
||||||
|
u32 *bmval, u32 *writable)
|
||||||
|
{
|
||||||
|
struct dentry *dentry = cstate->current_fh.fh_dentry;
|
||||||
|
struct svc_export *exp = cstate->current_fh.fh_export;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check about attributes are supported by the NFSv4 server or not.
|
||||||
|
* According to spec, unsupported attributes return ERR_ATTRNOTSUPP.
|
||||||
|
*/
|
||||||
|
if ((bmval[0] & ~nfsd_suppattrs0(cstate->minorversion)) ||
|
||||||
|
(bmval[1] & ~nfsd_suppattrs1(cstate->minorversion)) ||
|
||||||
|
(bmval[2] & ~nfsd_suppattrs2(cstate->minorversion)))
|
||||||
|
return nfserr_attrnotsupp;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check FATTR4_WORD0_ACL & FATTR4_WORD0_FS_LOCATIONS can be supported
|
||||||
|
* in current environment or not.
|
||||||
|
*/
|
||||||
|
if (bmval[0] & FATTR4_WORD0_ACL) {
|
||||||
|
if (!IS_POSIXACL(dentry->d_inode))
|
||||||
|
return nfserr_attrnotsupp;
|
||||||
|
}
|
||||||
|
if (bmval[0] & FATTR4_WORD0_FS_LOCATIONS) {
|
||||||
|
if (exp->ex_fslocs.locations == NULL)
|
||||||
|
return nfserr_attrnotsupp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* According to spec, read-only attributes return ERR_INVAL.
|
||||||
|
*/
|
||||||
|
if (writable) {
|
||||||
|
if ((bmval[0] & ~writable[0]) || (bmval[1] & ~writable[1]) ||
|
||||||
|
(bmval[2] & ~writable[2]))
|
||||||
|
return nfserr_inval;
|
||||||
|
}
|
||||||
|
|
||||||
|
return nfs_ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
static __be32
|
||||||
|
nfsd4_check_open_attributes(struct svc_rqst *rqstp,
|
||||||
|
struct nfsd4_compound_state *cstate, struct nfsd4_open *open)
|
||||||
|
{
|
||||||
|
__be32 status = nfs_ok;
|
||||||
|
|
||||||
|
if (open->op_create == NFS4_OPEN_CREATE) {
|
||||||
|
if (open->op_createmode == NFS4_CREATE_UNCHECKED
|
||||||
|
|| open->op_createmode == NFS4_CREATE_GUARDED)
|
||||||
|
status = check_attr_support(rqstp, cstate,
|
||||||
|
open->op_bmval, nfsd_attrmask);
|
||||||
|
else if (open->op_createmode == NFS4_CREATE_EXCLUSIVE4_1)
|
||||||
|
status = check_attr_support(rqstp, cstate,
|
||||||
|
open->op_bmval, nfsd41_ex_attrmask);
|
||||||
|
}
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
fh_dup2(struct svc_fh *dst, struct svc_fh *src)
|
fh_dup2(struct svc_fh *dst, struct svc_fh *src)
|
||||||
{
|
{
|
||||||
|
@ -225,6 +297,10 @@ nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
|
||||||
if (status)
|
if (status)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
status = nfsd4_check_open_attributes(rqstp, cstate, open);
|
||||||
|
if (status)
|
||||||
|
goto out;
|
||||||
|
|
||||||
/* Openowner is now set, so sequence id will get bumped. Now we need
|
/* Openowner is now set, so sequence id will get bumped. Now we need
|
||||||
* these checks before we do any creates: */
|
* these checks before we do any creates: */
|
||||||
status = nfserr_grace;
|
status = nfserr_grace;
|
||||||
|
@ -395,6 +471,11 @@ nfsd4_create(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
|
||||||
if (status)
|
if (status)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
|
status = check_attr_support(rqstp, cstate, create->cr_bmval,
|
||||||
|
nfsd_attrmask);
|
||||||
|
if (status)
|
||||||
|
return status;
|
||||||
|
|
||||||
switch (create->cr_type) {
|
switch (create->cr_type) {
|
||||||
case NF4LNK:
|
case NF4LNK:
|
||||||
/* ugh! we have to null-terminate the linktext, or
|
/* ugh! we have to null-terminate the linktext, or
|
||||||
|
@ -689,6 +770,12 @@ nfsd4_setattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
|
||||||
if (status)
|
if (status)
|
||||||
return status;
|
return status;
|
||||||
status = nfs_ok;
|
status = nfs_ok;
|
||||||
|
|
||||||
|
status = check_attr_support(rqstp, cstate, setattr->sa_bmval,
|
||||||
|
nfsd_attrmask);
|
||||||
|
if (status)
|
||||||
|
goto out;
|
||||||
|
|
||||||
if (setattr->sa_acl != NULL)
|
if (setattr->sa_acl != NULL)
|
||||||
status = nfsd4_set_nfs4_acl(rqstp, &cstate->current_fh,
|
status = nfsd4_set_nfs4_acl(rqstp, &cstate->current_fh,
|
||||||
setattr->sa_acl);
|
setattr->sa_acl);
|
||||||
|
@ -763,10 +850,10 @@ _nfsd4_verify(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
|
||||||
if (status)
|
if (status)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
if ((verify->ve_bmval[0] & ~nfsd_suppattrs0(cstate->minorversion))
|
status = check_attr_support(rqstp, cstate, verify->ve_bmval, NULL);
|
||||||
|| (verify->ve_bmval[1] & ~nfsd_suppattrs1(cstate->minorversion))
|
if (status)
|
||||||
|| (verify->ve_bmval[2] & ~nfsd_suppattrs2(cstate->minorversion)))
|
return status;
|
||||||
return nfserr_attrnotsupp;
|
|
||||||
if ((verify->ve_bmval[0] & FATTR4_WORD0_RDATTR_ERROR)
|
if ((verify->ve_bmval[0] & FATTR4_WORD0_RDATTR_ERROR)
|
||||||
|| (verify->ve_bmval[1] & NFSD_WRITEONLY_ATTRS_WORD1))
|
|| (verify->ve_bmval[1] & NFSD_WRITEONLY_ATTRS_WORD1))
|
||||||
return nfserr_inval;
|
return nfserr_inval;
|
||||||
|
|
|
@ -244,20 +244,8 @@ nfsd4_decode_bitmap(struct nfsd4_compoundargs *argp, u32 *bmval)
|
||||||
DECODE_TAIL;
|
DECODE_TAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static u32 nfsd_attrmask[] = {
|
|
||||||
NFSD_WRITEABLE_ATTRS_WORD0,
|
|
||||||
NFSD_WRITEABLE_ATTRS_WORD1,
|
|
||||||
NFSD_WRITEABLE_ATTRS_WORD2
|
|
||||||
};
|
|
||||||
|
|
||||||
static u32 nfsd41_ex_attrmask[] = {
|
|
||||||
NFSD_SUPPATTR_EXCLCREAT_WORD0,
|
|
||||||
NFSD_SUPPATTR_EXCLCREAT_WORD1,
|
|
||||||
NFSD_SUPPATTR_EXCLCREAT_WORD2
|
|
||||||
};
|
|
||||||
|
|
||||||
static __be32
|
static __be32
|
||||||
nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval, u32 *writable,
|
nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval,
|
||||||
struct iattr *iattr, struct nfs4_acl **acl)
|
struct iattr *iattr, struct nfs4_acl **acl)
|
||||||
{
|
{
|
||||||
int expected_len, len = 0;
|
int expected_len, len = 0;
|
||||||
|
@ -270,18 +258,6 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval, u32 *writable,
|
||||||
if ((status = nfsd4_decode_bitmap(argp, bmval)))
|
if ((status = nfsd4_decode_bitmap(argp, bmval)))
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
/*
|
|
||||||
* According to spec, unsupported attributes return ERR_ATTRNOTSUPP;
|
|
||||||
* read-only attributes return ERR_INVAL.
|
|
||||||
*/
|
|
||||||
if ((bmval[0] & ~nfsd_suppattrs0(argp->minorversion)) ||
|
|
||||||
(bmval[1] & ~nfsd_suppattrs1(argp->minorversion)) ||
|
|
||||||
(bmval[2] & ~nfsd_suppattrs2(argp->minorversion)))
|
|
||||||
return nfserr_attrnotsupp;
|
|
||||||
if ((bmval[0] & ~writable[0]) || (bmval[1] & ~writable[1]) ||
|
|
||||||
(bmval[2] & ~writable[2]))
|
|
||||||
return nfserr_inval;
|
|
||||||
|
|
||||||
READ_BUF(4);
|
READ_BUF(4);
|
||||||
READ32(expected_len);
|
READ32(expected_len);
|
||||||
|
|
||||||
|
@ -414,8 +390,11 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval, u32 *writable,
|
||||||
goto xdr_error;
|
goto xdr_error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
BUG_ON(bmval[2]); /* no such writeable attr supported yet */
|
if (bmval[0] & ~NFSD_WRITEABLE_ATTRS_WORD0
|
||||||
if (len != expected_len)
|
|| bmval[1] & ~NFSD_WRITEABLE_ATTRS_WORD1
|
||||||
|
|| bmval[2] & ~NFSD_WRITEABLE_ATTRS_WORD2)
|
||||||
|
READ_BUF(expected_len - len);
|
||||||
|
else if (len != expected_len)
|
||||||
goto xdr_error;
|
goto xdr_error;
|
||||||
|
|
||||||
DECODE_TAIL;
|
DECODE_TAIL;
|
||||||
|
@ -508,8 +487,8 @@ nfsd4_decode_create(struct nfsd4_compoundargs *argp, struct nfsd4_create *create
|
||||||
if ((status = check_filename(create->cr_name, create->cr_namelen, nfserr_inval)))
|
if ((status = check_filename(create->cr_name, create->cr_namelen, nfserr_inval)))
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
status = nfsd4_decode_fattr(argp, create->cr_bmval, nfsd_attrmask,
|
status = nfsd4_decode_fattr(argp, create->cr_bmval, &create->cr_iattr,
|
||||||
&create->cr_iattr, &create->cr_acl);
|
&create->cr_acl);
|
||||||
if (status)
|
if (status)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
@ -672,7 +651,7 @@ nfsd4_decode_open(struct nfsd4_compoundargs *argp, struct nfsd4_open *open)
|
||||||
case NFS4_CREATE_UNCHECKED:
|
case NFS4_CREATE_UNCHECKED:
|
||||||
case NFS4_CREATE_GUARDED:
|
case NFS4_CREATE_GUARDED:
|
||||||
status = nfsd4_decode_fattr(argp, open->op_bmval,
|
status = nfsd4_decode_fattr(argp, open->op_bmval,
|
||||||
nfsd_attrmask, &open->op_iattr, &open->op_acl);
|
&open->op_iattr, &open->op_acl);
|
||||||
if (status)
|
if (status)
|
||||||
goto out;
|
goto out;
|
||||||
break;
|
break;
|
||||||
|
@ -686,8 +665,7 @@ nfsd4_decode_open(struct nfsd4_compoundargs *argp, struct nfsd4_open *open)
|
||||||
READ_BUF(8);
|
READ_BUF(8);
|
||||||
COPYMEM(open->op_verf.data, 8);
|
COPYMEM(open->op_verf.data, 8);
|
||||||
status = nfsd4_decode_fattr(argp, open->op_bmval,
|
status = nfsd4_decode_fattr(argp, open->op_bmval,
|
||||||
nfsd41_ex_attrmask, &open->op_iattr,
|
&open->op_iattr, &open->op_acl);
|
||||||
&open->op_acl);
|
|
||||||
if (status)
|
if (status)
|
||||||
goto out;
|
goto out;
|
||||||
break;
|
break;
|
||||||
|
@ -883,8 +861,8 @@ nfsd4_decode_setattr(struct nfsd4_compoundargs *argp, struct nfsd4_setattr *seta
|
||||||
status = nfsd4_decode_stateid(argp, &setattr->sa_stateid);
|
status = nfsd4_decode_stateid(argp, &setattr->sa_stateid);
|
||||||
if (status)
|
if (status)
|
||||||
return status;
|
return status;
|
||||||
return nfsd4_decode_fattr(argp, setattr->sa_bmval, nfsd_attrmask,
|
return nfsd4_decode_fattr(argp, setattr->sa_bmval, &setattr->sa_iattr,
|
||||||
&setattr->sa_iattr, &setattr->sa_acl);
|
&setattr->sa_acl);
|
||||||
}
|
}
|
||||||
|
|
||||||
static __be32
|
static __be32
|
||||||
|
|
Loading…
Reference in New Issue