nfsd: release OPEN-decoded posix ACLs via op_release
Subsystems (2)
Jeff Layton
maintainerPATCH v3 1/1 nfsd: release OPEN-decoded posix ACLs via op_release
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.
Move the op_release() call out of nfsd4_encode_operation() and the replay branch, placing it after the if-else in nfsd4_proc_compound(). This gives a single call site in a fairly obviously-correct place, covering both the normal encoding and replay paths.
---
Changes in v3:
- Move op_release to a single callsite that accomodates all cases
- Link to v2: https://lore.kernel.org/r/[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 | 13 +++++++++++-- fs/nfsd/nfs4xdr.c | 3 --- 2 files changed, 11 insertions(+), 5 deletions(-)
fs/nfsd/nfs4proc.c +11 -2
@@ -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_statreturn 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. */
@@ -3219,6 +3224,9 @@ nfsd4_proc_compound(struct svc_rqst *rqstp) status = op->status; } +if (op->opdesc && op->opdesc->op_release) + op->opdesc->op_release (&op->u); +trace_nfsd_compound_status (args->client_opcnt, resp->opcnt, status,nfsd4_op_name (op->opnum));
@@ -3718,6 +3726,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,
fs/nfsd/nfs4xdr.c +0 -3
@@ -6654,9 +6654,6 @@ nfsd4_encode_operation(struct nfsd4_compoundres *resp, struct nfsd4_op *op)write_bytes_to_xdr_buf (xdr->buf, op_status_offset, &op->status,XDR_UNIT ); release: -if (opdesc && opdesc->op_release) - opdesc->op_release (&op->u); -/* * Account for pages consumed while encoding this operation. * The xdr_stream primitives don't manage rq_next_page.
---
base-commit: 6c0004650ba248a12937ada16f9ba961b35ce2b5
change-id: 20260531-nfsd-testing-9122bf51ce95
Best regards,
Signature · 1 line
Jeff Layton <[email protected]>
Chuck Lever
maintainerFrom: Chuck Lever <[email protected]>
Quoted 9 lines · Jeff Layton
nfsd4_decode_createhow4()callsnfsd4_decode_fattr4(), which allocates refcounted structposix_aclobjects viaposix_acl_alloc()and stores them inopen->op_paclandopen->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 beforeop_funcruns:[...]
Applied to nfsd-testing, thanks!
[1/1] nfsd: release OPEN-decoded posix ACLs via op_release
commit: 844f63869b2038377b82cdb90f8872acbdc8fde3
--
Chuck Lever <[email protected]>