Skip to content

Instantly share code, notes, and snippets.

@hiroyuki-sato
Created April 5, 2026 04:10
Show Gist options
  • Select an option

  • Save hiroyuki-sato/8ab30dffbbd2499e8b4741d89fd383be to your computer and use it in GitHub Desktop.

Select an option

Save hiroyuki-sato/8ab30dffbbd2499e8b4741d89fd383be to your computer and use it in GitHub Desktop.
[Q] NFSD: COMPOUND reply tag padding not zeroed? (e.g. \xff\xff)
nfs

Hello,

1. Observed behavior

  • When sending a COMPOUND request with the tag "create_session" (14 bytes), the reply is expected to include XDR padding to a 4-byte boundary, i.e. "create_session" + "\x00\x00".
  • On 5.14.0-611.45.1.el9_7.x86_64, the padding bytes are sometimes observed to be non-zero (e.g. "\xff\xff").
  • From inspection of recent upstream code, nfs4svc_encode_compoundres() also appears not to explicitly zero-fill the padding.

2. Questions

  • Is this understanding correct?
  • If so, is this a known issue or something that should be fixed?

3. Analysis

  • In nfsd4_proc_compound(), space for taglen + tag + opcnt is reserved via: xdr_reserve_space(resp->xdr, XDR_UNIT * 2 + args->taglen);

  • In nfs4svc_encode_compoundres(), only the tag payload is copied: memcpy(p, resp->tag, resp->taglen);

  • The pointer is then advanced using: p += XDR_QUADLEN(resp->taglen);

  • but the padding bytes do not appear to be explicitly zeroed.

  • As a result, it seems possible that uninitialized data remains in the padding region, which may explain why non-zero values such as \xff\xff appear on the wire.

https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/fs/nfsd/nfs4proc.c#n3055

/*
 * COMPOUND call.
 */
static __be32
nfsd4_proc_compound(struct svc_rqst *rqstp)
{
    // snip
	/* reserve space for: taglen, tag, and opcnt */
	xdr_reserve_space(resp->xdr, XDR_UNIT * 2 + args->taglen);

https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/fs/nfsd/nfs4xdr.c#n6389

bool
nfs4svc_encode_compoundres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
{
    // snip
	memcpy(p, resp->tag, resp->taglen);
	p += XDR_QUADLEN(resp->taglen);

4. Additional observations

  • A packet capture excerpt (attached separately via gist) shows: above
  • The issue is not deterministic: when repeatedly sending CREATE_SESSION, it was observed roughly once every ~5 attempts.
  • This was discovered while implementing an NFSv4 client in Rust.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment