Skip to content

Commit d2ca506

Browse files
rmacklemchucklever
authored andcommitted
NFSD: Add support for POSIX draft ACLs for file creation
NFSv4.2 clients can specify POSIX draft ACLs when creating file objects via OPEN(CREATE) and CREATE operations. The previous patch added POSIX ACL support to the NFSv4 SETATTR operation for modifying existing objects, but file creation follows different code paths that also require POSIX ACL handling. This patch integrates POSIX ACL support into nfsd4_create() and nfsd4_create_file(). Ownership of the decoded ACL pointers (op_dpacl, op_pacl, cr_dpacl, cr_pacl) transfers to the nfsd_attrs structure immediately, with the original fields cleared to NULL. This transfer ensures nfsd_attrs_free() releases the ACLs upon completion while preventing double-free on error paths. Mutual exclusion between NFSv4 ACLs and POSIX ACLs is enforced: setting both op_acl and op_dpacl/op_pacl simultaneously returns nfserr_inval. Errors during ACL application clear the corresponding bits in the result bitmask (fattr->bmval), signaling partial completion to the client. Signed-off-by: Rick Macklem <[email protected]> Reviewed-by: Jeff Layton <[email protected]> Signed-off-by: Chuck Lever <[email protected]>
1 parent 5fc51df commit d2ca506

1 file changed

Lines changed: 53 additions & 9 deletions

File tree

fs/nfsd/nfs4proc.c

Lines changed: 53 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,10 @@ check_attr_support(struct nfsd4_compound_state *cstate, u32 *bmval,
9191
return nfserr_attrnotsupp;
9292
if ((bmval[0] & FATTR4_WORD0_ACL) && !IS_POSIXACL(d_inode(dentry)))
9393
return nfserr_attrnotsupp;
94+
if ((bmval[2] & (FATTR4_WORD2_POSIX_DEFAULT_ACL |
95+
FATTR4_WORD2_POSIX_ACCESS_ACL)) &&
96+
!IS_POSIXACL(d_inode(dentry)))
97+
return nfserr_attrnotsupp;
9498
if ((bmval[2] & FATTR4_WORD2_SECURITY_LABEL) &&
9599
!(exp->ex_flags & NFSEXP_SECURITY_LABEL))
96100
return nfserr_attrnotsupp;
@@ -265,8 +269,20 @@ nfsd4_create_file(struct svc_rqst *rqstp, struct svc_fh *fhp,
265269
if (host_err)
266270
return nfserrno(host_err);
267271

268-
if (is_create_with_attrs(open))
269-
nfsd4_acl_to_attr(NF4REG, open->op_acl, &attrs);
272+
if (open->op_acl) {
273+
if (open->op_dpacl || open->op_pacl) {
274+
status = nfserr_inval;
275+
goto out_write;
276+
}
277+
if (is_create_with_attrs(open))
278+
nfsd4_acl_to_attr(NF4REG, open->op_acl, &attrs);
279+
} else if (is_create_with_attrs(open)) {
280+
/* The dpacl and pacl will get released by nfsd_attrs_free(). */
281+
attrs.na_dpacl = open->op_dpacl;
282+
attrs.na_pacl = open->op_pacl;
283+
open->op_dpacl = NULL;
284+
open->op_pacl = NULL;
285+
}
270286

271287
child = start_creating(&nop_mnt_idmap, parent,
272288
&QSTR_LEN(open->op_fname, open->op_fnamelen));
@@ -379,6 +395,10 @@ nfsd4_create_file(struct svc_rqst *rqstp, struct svc_fh *fhp,
379395
open->op_bmval[2] &= ~FATTR4_WORD2_SECURITY_LABEL;
380396
if (attrs.na_paclerr || attrs.na_dpaclerr)
381397
open->op_bmval[0] &= ~FATTR4_WORD0_ACL;
398+
if (attrs.na_dpaclerr)
399+
open->op_bmval[2] &= ~FATTR4_WORD2_POSIX_DEFAULT_ACL;
400+
if (attrs.na_paclerr)
401+
open->op_bmval[2] &= ~FATTR4_WORD2_POSIX_ACCESS_ACL;
382402
out:
383403
end_creating(child);
384404
nfsd_attrs_free(&attrs);
@@ -546,8 +566,10 @@ nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
546566
open->op_rqstp = rqstp;
547567

548568
/* This check required by spec. */
549-
if (open->op_create && open->op_claim_type != NFS4_OPEN_CLAIM_NULL)
550-
return nfserr_inval;
569+
if (open->op_create && open->op_claim_type != NFS4_OPEN_CLAIM_NULL) {
570+
status = nfserr_inval;
571+
goto out_err;
572+
}
551573

552574
open->op_created = false;
553575
/*
@@ -556,8 +578,10 @@ nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
556578
*/
557579
if (nfsd4_has_session(cstate) &&
558580
!test_bit(NFSD4_CLIENT_RECLAIM_COMPLETE, &cstate->clp->cl_flags) &&
559-
open->op_claim_type != NFS4_OPEN_CLAIM_PREVIOUS)
560-
return nfserr_grace;
581+
open->op_claim_type != NFS4_OPEN_CLAIM_PREVIOUS) {
582+
status = nfserr_grace;
583+
goto out_err;
584+
}
561585

562586
if (nfsd4_has_session(cstate))
563587
copy_clientid(&open->op_clientid, cstate->session);
@@ -644,6 +668,9 @@ nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
644668
}
645669
nfsd4_cleanup_open_state(cstate, open);
646670
nfsd4_bump_seqid(cstate, status);
671+
out_err:
672+
posix_acl_release(open->op_dpacl);
673+
posix_acl_release(open->op_pacl);
647674
return status;
648675
}
649676

@@ -784,22 +811,34 @@ nfsd4_create(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
784811
struct nfsd_attrs attrs = {
785812
.na_iattr = &create->cr_iattr,
786813
.na_seclabel = &create->cr_label,
814+
.na_dpacl = create->cr_dpacl,
815+
.na_pacl = create->cr_pacl,
787816
};
788817
struct svc_fh resfh;
789818
__be32 status;
790819
dev_t rdev;
791820

821+
create->cr_dpacl = NULL;
822+
create->cr_pacl = NULL;
823+
792824
fh_init(&resfh, NFS4_FHSIZE);
793825

794826
status = fh_verify(rqstp, &cstate->current_fh, S_IFDIR, NFSD_MAY_NOP);
795827
if (status)
796-
return status;
828+
goto out_aftermask;
797829

798830
status = check_attr_support(cstate, create->cr_bmval, nfsd_attrmask);
799831
if (status)
800-
return status;
832+
goto out_aftermask;
801833

802-
status = nfsd4_acl_to_attr(create->cr_type, create->cr_acl, &attrs);
834+
if (create->cr_acl) {
835+
if (create->cr_dpacl || create->cr_pacl) {
836+
status = nfserr_inval;
837+
goto out_aftermask;
838+
}
839+
status = nfsd4_acl_to_attr(create->cr_type, create->cr_acl,
840+
&attrs);
841+
}
803842
current->fs->umask = create->cr_umask;
804843
switch (create->cr_type) {
805844
case NF4LNK:
@@ -860,12 +899,17 @@ nfsd4_create(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
860899
create->cr_bmval[2] &= ~FATTR4_WORD2_SECURITY_LABEL;
861900
if (attrs.na_paclerr || attrs.na_dpaclerr)
862901
create->cr_bmval[0] &= ~FATTR4_WORD0_ACL;
902+
if (attrs.na_dpaclerr)
903+
create->cr_bmval[2] &= ~FATTR4_WORD2_POSIX_DEFAULT_ACL;
904+
if (attrs.na_paclerr)
905+
create->cr_bmval[2] &= ~FATTR4_WORD2_POSIX_ACCESS_ACL;
863906
set_change_info(&create->cr_cinfo, &cstate->current_fh);
864907
fh_dup2(&cstate->current_fh, &resfh);
865908
out:
866909
fh_put(&resfh);
867910
out_umask:
868911
current->fs->umask = 0;
912+
out_aftermask:
869913
nfsd_attrs_free(&attrs);
870914
return status;
871915
}

0 commit comments

Comments
 (0)