[PATCH 5/5] NFSv4/flexfiles: bound stripe_unit to 32 bits
Junrui Luo via B4 Relay <[email protected]> Tue, 04 Aug 2026 18:55:05 +0800
| Newsgroups | gmane.linux.kernel,gmane.linux.nfs,gmane.linux.kernel.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