[PATCH] mtd: nand: bbt: clamp GENMASK high bit to word boundary

Daniel Golle daniel at makrotopia.org
Sat Apr 11 17:05:23 PDT 2026


When a BBT entry straddles an unsigned long boundary, the GENMASK in
nanddev_bbt_set_block_status() can potentially overflow because
offs + bits_per_block - 1 can theoretically exceed BITS_PER_LONG - 1.
Clamp the high bit so only bits within the current word are masked.
The cross-word portion is already handled by the pos[1] block below.

Discovered by UBSAN: shift-out-of-bounds in
drivers/mtd/nand/bbt.c:116:13
shift exponent 18446744073709551614 is too large for 64-bit type
'long unsigned int'

Fixes: 9c3736a3de21 ("mtd: nand: Add core infrastructure to deal with NAND devices")
Signed-off-by: Daniel Golle <daniel at makrotopia.org>
---
 drivers/mtd/nand/bbt.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/mtd/nand/bbt.c b/drivers/mtd/nand/bbt.c
index db4f93a903e48..dfe4a6a991c15 100644
--- a/drivers/mtd/nand/bbt.c
+++ b/drivers/mtd/nand/bbt.c
@@ -113,7 +113,8 @@ int nanddev_bbt_set_block_status(struct nand_device *nand, unsigned int entry,
 	if (entry >= nanddev_neraseblocks(nand))
 		return -ERANGE;
 
-	pos[0] &= ~GENMASK(offs + bits_per_block - 1, offs);
+	pos[0] &= ~GENMASK(min(offs + bits_per_block - 1,
+			       BITS_PER_LONG - 1), offs);
 	pos[0] |= val << offs;
 
 	if (bits_per_block + offs > BITS_PER_LONG) {
-- 
2.53.0



More information about the linux-mtd mailing list