Skip to content

Commit 345c4b7

Browse files
rmacklemchucklever
authored andcommitted
NFSD: Refactor nfsd_setattr()'s ACL error reporting
Support for FATTR4_POSIX_ACCESS_ACL and FATTR4_POSIX_DEFAULT_ACL attributes in subsequent patches allows clients to set both ACL types simultaneously during SETATTR and file creation. Each ACL type can succeed or fail independently, requiring the server to clear individual attribute bits in the reply bitmap when one fails while the other succeeds. The existing na_aclerr field cannot distinguish which ACL type encountered an error. Separate error fields (na_paclerr for access ACLs, na_dpaclerr for default ACLs) enable the server to report per-ACL-type failures accurately. This refactoring also adds validation previously absent: default ACL processing rejects non-directory targets with EINVAL and passes NULL to set_posix_acl() when a_count is zero to delete the ACL. Access ACL processing rejects zero a_count with EINVAL for ACL_SCOPE_FILE_SYSTEM semantics (the only scope currently supported). The changes preserve compatibility with existing NFSv4 ACL code. NFSv4 ACL conversion (nfs4_acl_nfsv4_to_posix()) never produces POSIX ACLs with a_count == 0, so the new validation logic only affects future POSIX ACL attribute handling. Signed-off-by: Rick Macklem <[email protected]> Reviewed-by: Jeff Layton <[email protected]> Signed-off-by: Chuck Lever <[email protected]>
1 parent 9ac6fc0 commit 345c4b7

3 files changed

Lines changed: 34 additions & 11 deletions

File tree

fs/nfsd/nfs4proc.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -377,7 +377,7 @@ nfsd4_create_file(struct svc_rqst *rqstp, struct svc_fh *fhp,
377377

378378
if (attrs.na_labelerr)
379379
open->op_bmval[2] &= ~FATTR4_WORD2_SECURITY_LABEL;
380-
if (attrs.na_aclerr)
380+
if (attrs.na_paclerr || attrs.na_dpaclerr)
381381
open->op_bmval[0] &= ~FATTR4_WORD0_ACL;
382382
out:
383383
end_creating(child);
@@ -858,7 +858,7 @@ nfsd4_create(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
858858

859859
if (attrs.na_labelerr)
860860
create->cr_bmval[2] &= ~FATTR4_WORD2_SECURITY_LABEL;
861-
if (attrs.na_aclerr)
861+
if (attrs.na_paclerr || attrs.na_dpaclerr)
862862
create->cr_bmval[0] &= ~FATTR4_WORD0_ACL;
863863
set_change_info(&create->cr_cinfo, &cstate->current_fh);
864864
fh_dup2(&cstate->current_fh, &resfh);
@@ -1232,7 +1232,9 @@ nfsd4_setattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
12321232
if (!status)
12331233
status = nfserrno(attrs.na_labelerr);
12341234
if (!status)
1235-
status = nfserrno(attrs.na_aclerr);
1235+
status = nfserrno(attrs.na_dpaclerr);
1236+
if (!status)
1237+
status = nfserrno(attrs.na_paclerr);
12361238
out:
12371239
nfsd_attrs_free(&attrs);
12381240
fh_drop_write(&cstate->current_fh);

fs/nfsd/vfs.c

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -596,15 +596,35 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp,
596596
if (attr->na_seclabel && attr->na_seclabel->len)
597597
attr->na_labelerr = security_inode_setsecctx(dentry,
598598
attr->na_seclabel->data, attr->na_seclabel->len);
599-
if (IS_ENABLED(CONFIG_FS_POSIX_ACL) && attr->na_pacl)
600-
attr->na_aclerr = set_posix_acl(&nop_mnt_idmap,
601-
dentry, ACL_TYPE_ACCESS,
602-
attr->na_pacl);
603-
if (IS_ENABLED(CONFIG_FS_POSIX_ACL) &&
604-
!attr->na_aclerr && attr->na_dpacl && S_ISDIR(inode->i_mode))
605-
attr->na_aclerr = set_posix_acl(&nop_mnt_idmap,
599+
if (IS_ENABLED(CONFIG_FS_POSIX_ACL) && attr->na_dpacl) {
600+
if (!S_ISDIR(inode->i_mode))
601+
attr->na_dpaclerr = -EINVAL;
602+
else if (attr->na_dpacl->a_count > 0)
603+
/* a_count == 0 means delete the ACL. */
604+
attr->na_dpaclerr = set_posix_acl(&nop_mnt_idmap,
606605
dentry, ACL_TYPE_DEFAULT,
607606
attr->na_dpacl);
607+
else
608+
attr->na_dpaclerr = set_posix_acl(&nop_mnt_idmap,
609+
dentry, ACL_TYPE_DEFAULT,
610+
NULL);
611+
}
612+
if (IS_ENABLED(CONFIG_FS_POSIX_ACL) && attr->na_pacl) {
613+
/*
614+
* For any file system that is not ACL_SCOPE_FILE_OBJECT,
615+
* a_count == 0 MUST reply nfserr_inval.
616+
* For a file system that is ACL_SCOPE_FILE_OBJECT,
617+
* a_count == 0 deletes the ACL.
618+
* XXX File systems that are ACL_SCOPE_FILE_OBJECT
619+
* are not yet supported.
620+
*/
621+
if (attr->na_pacl->a_count > 0)
622+
attr->na_paclerr = set_posix_acl(&nop_mnt_idmap,
623+
dentry, ACL_TYPE_ACCESS,
624+
attr->na_pacl);
625+
else
626+
attr->na_paclerr = -EINVAL;
627+
}
608628
out_fill_attrs:
609629
/*
610630
* RFC 1813 Section 3.3.2 does not mandate that an NFS server

fs/nfsd/vfs.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,8 @@ struct nfsd_attrs {
5353
struct posix_acl *na_dpacl; /* input */
5454

5555
int na_labelerr; /* output */
56-
int na_aclerr; /* output */
56+
int na_dpaclerr; /* output */
57+
int na_paclerr; /* output */
5758
};
5859

5960
static inline void nfsd_attrs_free(struct nfsd_attrs *attrs)

0 commit comments

Comments
 (0)