mtd: lpddr_cmds: fix signed shifts in lpddr_cmds

There are several places where a value of type 'int' is shifted by
lpddr->chipshift. lpddr->chipshift is derived from QINFO geometry and
might reach 31 when QINFO reports a 2 GiB size - the maximum supported by
LPDDR(1) compliant chips. This may cause unexpected sign-extensions when
casting the integer value to the type of 'unsigned long'.

Use '1UL << lpddr->chipshift' and cast 'j' to unsigned long before
shifting so the computation is performed at the destination width.

Found by Linux Verification Center (linuxtesting.org) with SVACE.

Fixes: c68264711c ("[MTD] LPDDR Command set driver")
Signed-off-by: Ivan Stepchenko <sid@itb.spb.ru>
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
This commit is contained in:
Ivan Stepchenko 2025-11-21 14:54:46 +03:00 committed by Miquel Raynal
parent 1cce5a5eca
commit c909fec69f
1 changed files with 4 additions and 4 deletions

View File

@ -79,7 +79,7 @@ struct mtd_info *lpddr_cmdset(struct map_info *map)
mutex_init(&shared[i].lock); mutex_init(&shared[i].lock);
for (j = 0; j < lpddr->qinfo->HWPartsNum; j++) { for (j = 0; j < lpddr->qinfo->HWPartsNum; j++) {
*chip = lpddr->chips[i]; *chip = lpddr->chips[i];
chip->start += j << lpddr->chipshift; chip->start += (unsigned long)j << lpddr->chipshift;
chip->oldstate = chip->state = FL_READY; chip->oldstate = chip->state = FL_READY;
chip->priv = &shared[i]; chip->priv = &shared[i];
/* those should be reset too since /* those should be reset too since
@ -559,7 +559,7 @@ static int lpddr_point(struct mtd_info *mtd, loff_t adr, size_t len,
break; break;
if ((len + ofs - 1) >> lpddr->chipshift) if ((len + ofs - 1) >> lpddr->chipshift)
thislen = (1<<lpddr->chipshift) - ofs; thislen = (1UL << lpddr->chipshift) - ofs;
else else
thislen = len; thislen = len;
/* get the chip */ /* get the chip */
@ -575,7 +575,7 @@ static int lpddr_point(struct mtd_info *mtd, loff_t adr, size_t len,
len -= thislen; len -= thislen;
ofs = 0; ofs = 0;
last_end += 1 << lpddr->chipshift; last_end += 1UL << lpddr->chipshift;
chipnum++; chipnum++;
chip = &lpddr->chips[chipnum]; chip = &lpddr->chips[chipnum];
} }
@ -601,7 +601,7 @@ static int lpddr_unpoint (struct mtd_info *mtd, loff_t adr, size_t len)
break; break;
if ((len + ofs - 1) >> lpddr->chipshift) if ((len + ofs - 1) >> lpddr->chipshift)
thislen = (1<<lpddr->chipshift) - ofs; thislen = (1UL << lpddr->chipshift) - ofs;
else else
thislen = len; thislen = len;