Commit 2b14660c authored by Chenxi Hou's avatar Chenxi Hou Committed by Miquel Raynal
Browse files

mtd: jedec_probe: fix shift-out-of-bounds UB in JEDEC ID masking



UBSAN reports shift-out-of-bounds in jedec_read_mfr() and jedec_read_id():

  UBSAN: shift-out-of-bounds in drivers/mtd/chips/jedec_probe.c:1924:13
  shift exponent 32 is too large for 32-bit type 'int'
  UBSAN: shift-out-of-bounds in drivers/mtd/chips/jedec_probe.c:1940:12
  shift exponent 32 is too large for 32-bit type 'int'

The JEDEC manufacturer/device ID masking uses:

  (1 << (cfi->device_type * 8)) - 1

When cfi->device_type is 4, this evaluates to 1 << 32. Since the
literal '1' has type int, this is a 32-bit shift and is undefined behavior.

Fix it by using a 64-bit literal (1ULL) so the shift is performed in a 64-bit type.

Co-developed-by: default avatarHui Peng <benquike@gmail.com>
Signed-off-by: default avatarHui Peng <benquike@gmail.com>
Co-developed-by: default avatarZhihao Yao (Zephyr) <zhihao.yao@njit.edu>
Signed-off-by: default avatarZhihao Yao (Zephyr) <zhihao.yao@njit.edu>
Signed-off-by: default avatarChenxi Hou <ch395@njit.edu>
Signed-off-by: default avatarMiquel Raynal <miquel.raynal@bootlin.com>
parent 779c5927
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -1921,7 +1921,7 @@ static inline u32 jedec_read_mfr(struct map_info *map, uint32_t base,
	 */
	do {
		uint32_t ofs = cfi_build_cmd_addr(0 + (bank << 8), map, cfi);
		mask = (1 << (cfi->device_type * 8)) - 1;
		mask = (1ULL << (cfi->device_type * 8)) - 1;
		if (ofs >= map->size)
			return 0;
		result = map_read(map, base + ofs);
@@ -1937,7 +1937,7 @@ static inline u32 jedec_read_id(struct map_info *map, uint32_t base,
	map_word result;
	unsigned long mask;
	u32 ofs = cfi_build_cmd_addr(1, map, cfi);
	mask = (1 << (cfi->device_type * 8)) -1;
	mask = (1ULL << (cfi->device_type * 8)) - 1;
	result = map_read(map, base + ofs);
	return result.x[0] & mask;
}