Re: [PATCH v2] nfsd: release OPEN-decoded posix ACLs via op_release

Jeff Layton <[email protected]>
Newsgroups gmane.linux.kernel,gmane.linux.nfs
Message-ID <[email protected]>
On Mon, 2026-06-01 at 11:06 +1000, NeilBrown wrote:
> On Mon, 01 Jun 2026, Jeff Layton wrote:
> > nfsd4_decode_createhow4() calls nfsd4_decode_fattr4(), which allocates
> > refcounted struct posix_acl objects via posix_acl_alloc() and stores
> > them in open->op_pacl and open->op_dpacl. These pointers must be
> > released once the OPEN compound finishes.
> > 
> > When nfsd4_decode_open_claim4() returns a non-seqid-mutating error,
> > the dispatcher short-circuits before op_func runs:
> > 
> >     nfsd4_proc_compound()
> >       opdesc->op_func == nfsd4_open_omfg
> >         if (!seqid_mutating_err(ntohl(op->status)))
> >             return op->status;   /* nfsd4_open() never runs */
> >       opdesc->op_release(&op->u)  /* must still release op_pacl/op_dpacl */
> > 
> > Before this change OP_OPEN had no .op_release in nfsd4_ops[], and the
> > release pair lived inside nfsd4_open() at its out_err: label. On the
> > short-circuit path nfsd4_open() is never invoked, so both posix_acl
> > refs leak on every malformed OPEN compound that carries valid POSIX
> > ACL createhow4 attributes.
> > 
> > Add nfsd4_open_release() and wire it as .op_release for OP_OPEN.
> > posix_acl_release() is NULL-safe, so the single release site covers
> > both the normal path and the nfsd4_open_omfg short-circuit. Remove
> > the matching posix_acl_release() pair from nfsd4_open()'s out_err:
> > label to avoid double-releasing.
> > 
> > The compound loop has two encoding branches: nfsd4_encode_operation()
> > for normal ops, and nfsd4_encode_replay() for v4.0 replayed ops.
> > op_release was only called from nfsd4_encode_operation(), so resources
> > attached to op->u leak on the replay path. Add an op_release call to
> > the replay branch as well to ensure cleanup on every path.
> > 
> > Fixes: 5fc51dfc2eb1 ("NFSD: Add support for XDR decoding POSIX draft ACLs")
> > Signed-off-by: Chris Mason <[email protected]>
> > Reviewed-by: Chuck Lever <[email protected]>
> > Signed-off-by: Jeff Layton <[email protected]>
> > ---
> > Changes in v2:
> > - Ensure that op_release is called in the v4.0 replay case as well
> > - Link to v1: https://lore.kernel.org/r/[email protected]
> > ---
> >  fs/nfsd/nfs4proc.c | 12 ++++++++++--
> >  1 file changed, 10 insertions(+), 2 deletions(-)
> > 
> > diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
> > index 017474cd63b5..51998d7885ae 100644
> > --- a/fs/nfsd/nfs4proc.c
> > +++ b/fs/nfsd/nfs4proc.c
> > @@ -681,8 +681,6 @@ 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;
> >  }
> >  
> > @@ -704,6 +702,13 @@ static __be32 nfsd4_open_omfg(struct svc_rqst *rqstp, struct nfsd4_compound_stat
> >  	return nfsd4_open(rqstp, cstate, &op->u);
> >  }
> >  
> > +static void
> > +nfsd4_open_release(union nfsd4_op_u *u)
> > +{
> > +	posix_acl_release(u->open.op_dpacl);
> > +	posix_acl_release(u->open.op_pacl);
> > +}
> > +
> >  /*
> >   * filehandle-manipulating ops.
> >   */
> > @@ -3214,6 +3219,8 @@ nfsd4_proc_compound(struct svc_rqst *rqstp)
> >  			op->replay = &cstate->replay_owner->so_replay;
> >  			nfsd4_encode_replay(resp->xdr, op);
> >  			status = op->status = op->replay->rp_status;
> > +			if (op->opdesc->op_release)
> > +				op->opdesc->op_release(&op->u);
> >  		} else {
> >  			nfsd4_encode_operation(resp, op);
> >  			status = op->status;
> 
> I think this patch is good, but I think it would be even better if the
> ->op_release() call were moved out of nfsd4_encode_operation() and
> places after this if-else.  Then there would be only one call-site in a
> fairly obviously-correct place.
> But:
>   Reviewed-by: NeilBrown <[email protected]>
> for if you just want to stick with this version.
> 
> Thanks,
> NeilBrown
> 

I like that idea.

I'll be testing a pile of other patches today anyway, so I'll make this
change and test it alongside the rest.

Chuck, you can either take this one and I'll do a cleanup patch along
the lines of what Neil suggests, or I can send a v3.

> 
> > @@ -3718,6 +3725,7 @@ static const struct nfsd4_operation nfsd4_ops[] = {
> >  	},
> >  	[OP_OPEN] = {
> >  		.op_func = nfsd4_open,
> > +		.op_release = nfsd4_open_release,
> >  		.op_flags = OP_HANDLES_WRONGSEC | OP_MODIFIES_SOMETHING,
> >  		.op_name = "OP_OPEN",
> >  		.op_rsize_bop = nfsd4_open_rsize,
> > 
> > ---
> > base-commit: 6c0004650ba248a12937ada16f9ba961b35ce2b5
> > change-id: 20260531-nfsd-testing-9122bf51ce95
> > 
> > Best regards,
> > -- 
> > Jeff Layton <[email protected]>
> > 
> > 

-- 
Jeff Layton <[email protected]>
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.