[PATCH 5/5] NFSv4/flexfiles: bound stripe_unit to 32 bits

Junrui Luo via B4 Relay <[email protected]>
Newsgroups org.kernel.vger.linux-nfs,org.kernel.feeds.b4-sent,org.kernel.vger.linux-kernel,org.kernel.vger.stable
Message-ID <[email protected]>
From: Junrui Luo <[email protected]>

ff_layout_alloc_lseg() decodes stripe_unit from the flexfiles LAYOUTGET
body as a 64-bit value and validates it as one:

	if (dss_count > 1 && stripe_unit == 0)
		goto out_err_free;

but every consumer divides by only its low 32 bits.  ff_layout_pg_test()
narrows it explicitly:

	u32 stripe_unit = FF_LAYOUT_LSEG(pgio->pg_lseg)->stripe_unit;
	...
	do_div(p_stripe, stripe_unit);

and nfs4_ff_layout_calc_dss_id() passes the u64 straight to do_div(),
which narrows the divisor itself.

A server-supplied non-zero multiple of 2^32 such as 0x100000000
therefore passes the check and reaches both dividers as a zero divisor,
so the first read or write through the layout takes a divide error and
panics the client.  The same narrowing silently turns any other value
above U32_MAX into an unrelated stripe size.

Values that do not fit in 32 bits are not representable by the
arithmetic this driver performs on stripe_unit, so reject them at decode
time rather than truncating them.

Fixes: 20b1d75fb840 ("NFSv4/flexfiles: Add support for striped layouts")
Reported-by: Yuhao Jiang <[email protected]>
Assisted-by: Claude:claude-opus-5
Cc: [email protected]
Signed-off-by: Junrui Luo <[email protected]>
---
 fs/nfs/flexfilelayout/flexfilelayout.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/fs/nfs/flexfilelayout/flexfilelayout.c b/fs/nfs/flexfilelayout/flexfilelayout.c
index bdc4b960eeb7..63391f48c5d9 100644
--- a/fs/nfs/flexfilelayout/flexfilelayout.c
+++ b/fs/nfs/flexfilelayout/flexfilelayout.c
@@ -515,7 +515,8 @@ ff_layout_alloc_lseg(struct pnfs_layout_hdr *lh,
 		    dss_count == 0)
 			goto out_err_free;
 
-		if (dss_count > 1 && stripe_unit == 0)
+		if (dss_count > 1 &&
+		    (stripe_unit == 0 || stripe_unit > U32_MAX))
 			goto out_err_free;
 
 		fls->mirror_array[i] = ff_layout_alloc_mirror(dss_count, gfp_flags);

-- 
2.51.2
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.