* [PATCH] nvdimm/btt: reject an arena whose nfree is below the lane count
@ 2026-06-20 21:41 Bryam Vargas via B4 Relay
2026-06-24 3:50 ` Alison Schofield
2026-07-15 0:03 ` Alison Schofield
0 siblings, 2 replies; 3+ messages in thread
From: Bryam Vargas via B4 Relay @ 2026-06-20 21:41 UTC (permalink / raw)
To: Dave Jiang, Ira Weiny, Vishal Verma, Dan Williams; +Cc: linux-kernel, nvdimm
From: Bryam Vargas <hexlabsecurity@proton.me>
The BTT info block's nfree field, the number of reserve free blocks, is
read from the medium without validation. btt_freelist_init() and
btt_rtt_init() size the per-lane freelist[] and rtt[] arrays by nfree,
but the I/O path indexes them by the lane from nd_region_acquire_lane(),
which is bounded by nd_region->num_lanes (ND_MAX_LANES), not by nfree.
A crafted or foreign arena whose nfree is below the lane count makes
freelist[lane]/rtt[lane] run past the allocation: an out-of-bounds write.
btt.rst documents the nlanes = min(nfree, num_cpus) invariant, which the
code does not currently honor: num_lanes is ND_MAX_LANES regardless of
nfree. Reject an arena whose nfree is below num_lanes at discovery,
before the per-lane arrays are allocated, enforcing that invariant.
Fixes: 5212e11fde4d ("nd_btt: atomic sector updates")
Cc: stable@vger.kernel.org
Signed-off-by: Bryam Vargas <hexlabsecurity@proton.me>
---
nd_btt_arena_is_valid() checks the signature, parent_uuid and a fletcher
checksum, none of which constrain nfree; the checksum is keyless, so a
crafted arena recomputes it. map_locks[] is indexed modulo nfree and is
unaffected; only the lane-indexed freelist[] and rtt[] are out of bounds.
Reproduced with an out-of-tree module that mirrors btt_rtt_init() ->
btt_read_pg() (kcalloc(nfree) then rtt[lane] across the lane range), since
the defect is the unchecked nfree vs the lane bound:
Build A (without this patch), nfree=2, num_lanes=8:
rtt[lane] for lane >= nfree writes past the kcalloc'd array ->
right of the 8-byte region (kmalloc-8) -> panic.
Build B (with this patch): the arena is rejected, no array is used -> clean.
Control (nfree >= num_lanes): every lane is in bounds -> clean.
BUG: KASAN: slab-out-of-bounds, Write of size 4, 0 bytes to the
---
drivers/nvdimm/btt.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/drivers/nvdimm/btt.c b/drivers/nvdimm/btt.c
index fdcb080a4314..25c609251f99 100644
--- a/drivers/nvdimm/btt.c
+++ b/drivers/nvdimm/btt.c
@@ -883,6 +883,14 @@ static int discover_arenas(struct btt *btt)
arena->external_lba_start = cur_nlba;
parse_arena_meta(arena, super, cur_off);
+ if (arena->nfree < btt->nd_region->num_lanes) {
+ dev_err(to_dev(arena),
+ "nfree %u smaller than lane count %d\n",
+ arena->nfree, btt->nd_region->num_lanes);
+ ret = -ENODEV;
+ goto out;
+ }
+
ret = log_set_indices(arena);
if (ret) {
dev_err(to_dev(arena),
---
base-commit: 8e65320d91cdc3b241d4b94855c88459b91abf66
change-id: 20260620-b4-disp-88b2514b-c71e8a0ba790
Best regards,
--
Bryam Vargas <hexlabsecurity@proton.me>
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH] nvdimm/btt: reject an arena whose nfree is below the lane count
2026-06-20 21:41 [PATCH] nvdimm/btt: reject an arena whose nfree is below the lane count Bryam Vargas via B4 Relay
@ 2026-06-24 3:50 ` Alison Schofield
2026-07-15 0:03 ` Alison Schofield
1 sibling, 0 replies; 3+ messages in thread
From: Alison Schofield @ 2026-06-24 3:50 UTC (permalink / raw)
To: hexlabsecurity
Cc: Dave Jiang, Ira Weiny, Vishal Verma, Dan Williams, linux-kernel, nvdimm
On Sat, Jun 20, 2026 at 04:41:31PM -0500, Bryam Vargas via B4 Relay wrote:
> From: Bryam Vargas <hexlabsecurity@proton.me>
>
> The BTT info block's nfree field, the number of reserve free blocks, is
> read from the medium without validation. btt_freelist_init() and
> btt_rtt_init() size the per-lane freelist[] and rtt[] arrays by nfree,
> but the I/O path indexes them by the lane from nd_region_acquire_lane(),
> which is bounded by nd_region->num_lanes (ND_MAX_LANES), not by nfree.
> A crafted or foreign arena whose nfree is below the lane count makes
> freelist[lane]/rtt[lane] run past the allocation: an out-of-bounds write.
>
> btt.rst documents the nlanes = min(nfree, num_cpus) invariant, which the
> code does not currently honor: num_lanes is ND_MAX_LANES regardless of
> nfree. Reject an arena whose nfree is below num_lanes at discovery,
> before the per-lane arrays are allocated, enforcing that invariant.
>
> Fixes: 5212e11fde4d ("nd_btt: atomic sector updates")
> Cc: stable@vger.kernel.org
> Signed-off-by: Bryam Vargas <hexlabsecurity@proton.me>
Hi Bryam,
Thanks for the patch. I reviewed and tested this against this branch,
which has a few other BTT fixups that'll land before this patch:
https://git.kernel.org/pub/scm/linux/kernel/git/nvdimm/nvdimm.git/log/?h=libnvdimm-for-next
All merged fine. It did lead me to create a testcase so I won't
ask you for that. I'll copy you when I post the test patch for review.
Reviewed-by: Alison Schofield <alison.schofield@intel.com>
Tested-by: Alison Schofield <alison.schofield@intel.com>
--Alison
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH] nvdimm/btt: reject an arena whose nfree is below the lane count
2026-06-20 21:41 [PATCH] nvdimm/btt: reject an arena whose nfree is below the lane count Bryam Vargas via B4 Relay
2026-06-24 3:50 ` Alison Schofield
@ 2026-07-15 0:03 ` Alison Schofield
1 sibling, 0 replies; 3+ messages in thread
From: Alison Schofield @ 2026-07-15 0:03 UTC (permalink / raw)
To: hexlabsecurity
Cc: Dave Jiang, Ira Weiny, Vishal Verma, Dan Williams, linux-kernel, nvdimm
On Sat, Jun 20, 2026 at 04:41:31PM -0500, Bryam Vargas via B4 Relay wrote:
> From: Bryam Vargas <hexlabsecurity@proton.me>
>
> The BTT info block's nfree field, the number of reserve free blocks, is
> read from the medium without validation. btt_freelist_init() and
> btt_rtt_init() size the per-lane freelist[] and rtt[] arrays by nfree,
> but the I/O path indexes them by the lane from nd_region_acquire_lane(),
> which is bounded by nd_region->num_lanes (ND_MAX_LANES), not by nfree.
> A crafted or foreign arena whose nfree is below the lane count makes
> freelist[lane]/rtt[lane] run past the allocation: an out-of-bounds write.
>
> btt.rst documents the nlanes = min(nfree, num_cpus) invariant, which the
> code does not currently honor: num_lanes is ND_MAX_LANES regardless of
> nfree. Reject an arena whose nfree is below num_lanes at discovery,
> before the per-lane arrays are allocated, enforcing that invariant.
>
> Fixes: 5212e11fde4d ("nd_btt: atomic sector updates")
> Cc: stable@vger.kernel.org
> Signed-off-by: Bryam Vargas <hexlabsecurity@proton.me>
Applied to libnvdimm-for-next:
https://git.kernel.org/pub/scm/linux/kernel/git/nvdimm/nvdimm.git/
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2026-07-15 0:03 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-06-20 21:41 [PATCH] nvdimm/btt: reject an arena whose nfree is below the lane count Bryam Vargas via B4 Relay
2026-06-24 3:50 ` Alison Schofield
2026-07-15 0:03 ` Alison Schofield
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®