From: Chuck Lever <cel@kernel.org>
To: NeilBrown <neilb@ownmail.net>, Jeff Layton <jlayton@kernel.org>,
Olga Kornievskaia <okorniev@redhat.com>,
Dai Ngo <dai.ngo@oracle.com>, Tom Talpey <tom@talpey.com>
Cc: <linux-nfs@vger.kernel.org>, Rick Macklem <rmacklem@uoguelph.ca>
Subject: [PATCH v3 11/13] NFSD: Add support for POSIX draft ACLs for file creation
Date: Fri, 9 Jan 2026 11:21:40 -0500 [thread overview]
Message-ID: <20260109162143.4186112-12-cel@kernel.org> (raw)
In-Reply-To: <20260109162143.4186112-1-cel@kernel.org>
From: Rick Macklem <rmacklem@uoguelph.ca>
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 <rmacklem@uoguelph.ca>
Reviewed-by: Jeff Layton <jlayton@kernel.org>
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
fs/nfsd/nfs4proc.c | 62 +++++++++++++++++++++++++++++++++++++++-------
1 file changed, 53 insertions(+), 9 deletions(-)
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
index 2da092f9ac40..72edf4add536 100644
--- a/fs/nfsd/nfs4proc.c
+++ b/fs/nfsd/nfs4proc.c
@@ -91,6 +91,10 @@ check_attr_support(struct nfsd4_compound_state *cstate, u32 *bmval,
return nfserr_attrnotsupp;
if ((bmval[0] & FATTR4_WORD0_ACL) && !IS_POSIXACL(d_inode(dentry)))
return nfserr_attrnotsupp;
+ if ((bmval[2] & (FATTR4_WORD2_POSIX_DEFAULT_ACL |
+ FATTR4_WORD2_POSIX_ACCESS_ACL)) &&
+ !IS_POSIXACL(d_inode(dentry)))
+ return nfserr_attrnotsupp;
if ((bmval[2] & FATTR4_WORD2_SECURITY_LABEL) &&
!(exp->ex_flags & NFSEXP_SECURITY_LABEL))
return nfserr_attrnotsupp;
@@ -265,8 +269,20 @@ nfsd4_create_file(struct svc_rqst *rqstp, struct svc_fh *fhp,
if (host_err)
return nfserrno(host_err);
- if (is_create_with_attrs(open))
- nfsd4_acl_to_attr(NF4REG, open->op_acl, &attrs);
+ if (open->op_acl) {
+ if (open->op_dpacl || open->op_pacl) {
+ status = nfserr_inval;
+ goto out_write;
+ }
+ if (is_create_with_attrs(open))
+ nfsd4_acl_to_attr(NF4REG, open->op_acl, &attrs);
+ } else if (is_create_with_attrs(open)) {
+ /* The dpacl and pacl will get released by nfsd_attrs_free(). */
+ attrs.na_dpacl = open->op_dpacl;
+ attrs.na_pacl = open->op_pacl;
+ open->op_dpacl = NULL;
+ open->op_pacl = NULL;
+ }
child = start_creating(&nop_mnt_idmap, parent,
&QSTR_LEN(open->op_fname, open->op_fnamelen));
@@ -379,6 +395,10 @@ nfsd4_create_file(struct svc_rqst *rqstp, struct svc_fh *fhp,
open->op_bmval[2] &= ~FATTR4_WORD2_SECURITY_LABEL;
if (attrs.na_paclerr || attrs.na_dpaclerr)
open->op_bmval[0] &= ~FATTR4_WORD0_ACL;
+ if (attrs.na_dpaclerr)
+ open->op_bmval[2] &= ~FATTR4_WORD2_POSIX_DEFAULT_ACL;
+ if (attrs.na_paclerr)
+ open->op_bmval[2] &= ~FATTR4_WORD2_POSIX_ACCESS_ACL;
out:
end_creating(child);
nfsd_attrs_free(&attrs);
@@ -546,8 +566,10 @@ nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
open->op_rqstp = rqstp;
/* This check required by spec. */
- if (open->op_create && open->op_claim_type != NFS4_OPEN_CLAIM_NULL)
- return nfserr_inval;
+ if (open->op_create && open->op_claim_type != NFS4_OPEN_CLAIM_NULL) {
+ status = nfserr_inval;
+ goto out_err;
+ }
open->op_created = false;
/*
@@ -556,8 +578,10 @@ nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
*/
if (nfsd4_has_session(cstate) &&
!test_bit(NFSD4_CLIENT_RECLAIM_COMPLETE, &cstate->clp->cl_flags) &&
- open->op_claim_type != NFS4_OPEN_CLAIM_PREVIOUS)
- return nfserr_grace;
+ open->op_claim_type != NFS4_OPEN_CLAIM_PREVIOUS) {
+ status = nfserr_grace;
+ goto out_err;
+ }
if (nfsd4_has_session(cstate))
copy_clientid(&open->op_clientid, cstate->session);
@@ -644,6 +668,9 @@ nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
}
nfsd4_cleanup_open_state(cstate, open);
nfsd4_bump_seqid(cstate, status);
+out_err:
+ posix_acl_release(open->op_dpacl);
+ posix_acl_release(open->op_pacl);
return status;
}
@@ -784,22 +811,34 @@ nfsd4_create(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
struct nfsd_attrs attrs = {
.na_iattr = &create->cr_iattr,
.na_seclabel = &create->cr_label,
+ .na_dpacl = create->cr_dpacl,
+ .na_pacl = create->cr_pacl,
};
struct svc_fh resfh;
__be32 status;
dev_t rdev;
+ create->cr_dpacl = NULL;
+ create->cr_pacl = NULL;
+
fh_init(&resfh, NFS4_FHSIZE);
status = fh_verify(rqstp, &cstate->current_fh, S_IFDIR, NFSD_MAY_NOP);
if (status)
- return status;
+ goto out_aftermask;
status = check_attr_support(cstate, create->cr_bmval, nfsd_attrmask);
if (status)
- return status;
+ goto out_aftermask;
- status = nfsd4_acl_to_attr(create->cr_type, create->cr_acl, &attrs);
+ if (create->cr_acl) {
+ if (create->cr_dpacl || create->cr_pacl) {
+ status = nfserr_inval;
+ goto out_aftermask;
+ }
+ status = nfsd4_acl_to_attr(create->cr_type, create->cr_acl,
+ &attrs);
+ }
current->fs->umask = create->cr_umask;
switch (create->cr_type) {
case NF4LNK:
@@ -860,12 +899,17 @@ nfsd4_create(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
create->cr_bmval[2] &= ~FATTR4_WORD2_SECURITY_LABEL;
if (attrs.na_paclerr || attrs.na_dpaclerr)
create->cr_bmval[0] &= ~FATTR4_WORD0_ACL;
+ if (attrs.na_dpaclerr)
+ create->cr_bmval[2] &= ~FATTR4_WORD2_POSIX_DEFAULT_ACL;
+ if (attrs.na_paclerr)
+ create->cr_bmval[2] &= ~FATTR4_WORD2_POSIX_ACCESS_ACL;
set_change_info(&create->cr_cinfo, &cstate->current_fh);
fh_dup2(&cstate->current_fh, &resfh);
out:
fh_put(&resfh);
out_umask:
current->fs->umask = 0;
+out_aftermask:
nfsd_attrs_free(&attrs);
return status;
}
--
2.52.0
next prev parent reply other threads:[~2026-01-09 16:21 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-01-09 16:21 [PATCH v3 00/13] Add NFSv4.2 POSIX ACL support Chuck Lever
2026-01-09 16:21 ` [PATCH v3 01/13] xdrgen: Implement pass-through lines in specifications Chuck Lever
2026-01-09 16:21 ` [PATCH v3 02/13] NFSD: Add a Kconfig setting to enable support for NFSv4 POSIX ACLs Chuck Lever
2026-01-09 16:21 ` [PATCH v3 03/13] Add RPC language definition of NFSv4 POSIX ACL extension Chuck Lever
2026-01-09 16:21 ` [PATCH v3 04/13] NFSD: Add nfsd4_encode_fattr4_acl_trueform Chuck Lever
2026-01-09 16:21 ` [PATCH v3 05/13] NFSD: Add nfsd4_encode_fattr4_acl_trueform_scope Chuck Lever
2026-01-09 16:21 ` [PATCH v3 06/13] NFSD: Add nfsd4_encode_fattr4_posix_default_acl Chuck Lever
2026-01-09 16:21 ` [PATCH v3 07/13] NFSD: Add nfsd4_encode_fattr4_posix_access_acl Chuck Lever
2026-01-09 16:21 ` [PATCH v3 08/13] NFSD: Do not allow NFSv4 (N)VERIFY to check POSIX ACL attributes Chuck Lever
2026-01-09 16:21 ` [PATCH v3 09/13] NFSD: Refactor nfsd_setattr()'s ACL error reporting Chuck Lever
2026-01-09 16:21 ` [PATCH v3 10/13] NFSD: Add support for XDR decoding POSIX draft ACLs Chuck Lever
2026-01-09 16:21 ` Chuck Lever [this message]
2026-01-09 16:21 ` [PATCH v3 12/13] NFSD: Add POSIX draft ACL support to the NFSv4 SETATTR operation Chuck Lever
2026-01-09 16:21 ` [PATCH v3 13/13] NFSD: Add POSIX ACL file attributes to SUPPATTR bitmasks Chuck Lever
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260109162143.4186112-12-cel@kernel.org \
--to=cel@kernel.org \
--cc=dai.ngo@oracle.com \
--cc=jlayton@kernel.org \
--cc=linux-nfs@vger.kernel.org \
--cc=neilb@ownmail.net \
--cc=okorniev@redhat.com \
--cc=rmacklem@uoguelph.ca \
--cc=tom@talpey.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox