summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--fs/nfsd/nfs4proc.c24
1 files changed, 19 insertions, 5 deletions
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
index 72edf4add536..d476d108f6e1 100644
--- a/fs/nfsd/nfs4proc.c
+++ b/fs/nfsd/nfs4proc.c
@@ -1214,6 +1214,8 @@ nfsd4_setattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
struct nfsd_attrs attrs = {
.na_iattr = &setattr->sa_iattr,
.na_seclabel = &setattr->sa_label,
+ .na_pacl = setattr->sa_pacl,
+ .na_dpacl = setattr->sa_dpacl,
};
bool save_no_wcc, deleg_attrs;
struct nfs4_stid *st = NULL;
@@ -1221,6 +1223,10 @@ nfsd4_setattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
__be32 status = nfs_ok;
int err;
+ /* Transfer ownership to attrs for cleanup via nfsd_attrs_free() */
+ setattr->sa_pacl = NULL;
+ setattr->sa_dpacl = NULL;
+
deleg_attrs = setattr->sa_bmval[2] & (FATTR4_WORD2_TIME_DELEG_ACCESS |
FATTR4_WORD2_TIME_DELEG_MODIFY);
@@ -1234,7 +1240,7 @@ nfsd4_setattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
&cstate->current_fh, &setattr->sa_stateid,
flags, NULL, &st);
if (status)
- return status;
+ goto out_err;
}
if (deleg_attrs) {
@@ -1252,17 +1258,24 @@ nfsd4_setattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
if (st)
nfs4_put_stid(st);
if (status)
- return status;
+ goto out_err;
err = fh_want_write(&cstate->current_fh);
- if (err)
- return nfserrno(err);
+ if (err) {
+ status = nfserrno(err);
+ goto out_err;
+ }
status = nfs_ok;
status = check_attr_support(cstate, setattr->sa_bmval, nfsd_attrmask);
if (status)
goto out;
+ if (setattr->sa_acl && (attrs.na_dpacl || attrs.na_pacl)) {
+ status = nfserr_inval;
+ goto out;
+ }
+
inode = cstate->current_fh.fh_dentry->d_inode;
status = nfsd4_acl_to_attr(S_ISDIR(inode->i_mode) ? NF4DIR : NF4REG,
setattr->sa_acl, &attrs);
@@ -1280,8 +1293,9 @@ nfsd4_setattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
if (!status)
status = nfserrno(attrs.na_paclerr);
out:
- nfsd_attrs_free(&attrs);
fh_drop_write(&cstate->current_fh);
+out_err:
+ nfsd_attrs_free(&attrs);
return status;
}