Re: [PATCH 10/10] nfsd: validate symlink target length in NFSv4 CREATE
From: Chuck Lever
Date: Fri May 29 2026 - 15:07:22 EST
On Thu, May 28, 2026, at 5:55 PM, Jeff Layton wrote:
> nfsd4_decode_create() accepts an unbounded cr_datalen from the wire for
> NF4LNK symlink targets, allowing a client to force a kmalloc of up to
> the RPC-max size (~1 MiB) per COMPOUND op that persists until compound
> teardown. The VFS rejects oversized targets with ENAMETOOLONG, but the
> allocation has already occurred.
>
> Reject cr_datalen == 0 or cr_datalen >= PATH_MAX early with
> nfserr_nametoolong to bound the allocation.
>
> Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
> Assisted-by: kres:claude-opus-4-7
> Signed-off-by: Jeff Layton <jlayton@xxxxxxxxxx>
> ---
> fs/nfsd/nfs4xdr.c | 4 ++++
> 1 file changed, 4 insertions(+)
>
> diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
> index 5469c6c207ba..1f5e49f50f3a 100644
> --- a/fs/nfsd/nfs4xdr.c
> +++ b/fs/nfsd/nfs4xdr.c
> @@ -957,6 +957,10 @@ nfsd4_decode_create(struct nfsd4_compoundargs
> *argp, union nfsd4_op_u *u)
> case NF4LNK:
> if (xdr_stream_decode_u32(argp->xdr, &create->cr_datalen) < 0)
> return nfserr_bad_xdr;
> + if (create->cr_datalen == 0)
> + return nfserr_inval;
> + if (create->cr_datalen >= PATH_MAX)
> + return nfserr_nametoolong;
Nit: The protocol already has NFS4_MAXPATHLEN defined to PATH_MAX.
The v3 decoder uses its analog NFS3_MAXPATHLEN. Using
NFS4_MAXPATHLEN here expresses the protocol-layer intent and
matches the cross-version idiom.
The new boundary condition differs from v2/v3. v3 uses
"tlen > NFS3_MAXPATHLEN", accepting a target of exactly PATH_MAX
bytes; this uses ">= PATH_MAX", rejecting it. Switching to
"> NFS4_MAXPATHLEN" both adopts the named constant and realigns
the maximum accepted length with v2/v3.
> p = xdr_inline_decode(argp->xdr, create->cr_datalen);
> if (!p)
> return nfserr_bad_xdr;
>
> --
> 2.54.0
--
Chuck Lever