When the bit offset is BITS_PER_BYTE or larger the read position is advanced by `bytes_offset`. This is not taken into account in the per-byte read loop which still reads `cell->bytes` resulting in an out of bounds read of `bytes_offset` bytes. The information read OOB does not leak directly as the erroneously read bits are cleared. Detected by KASAN while looking for a use-after-free in simplefb.c. Cc: stable@vger.kernel.org Fixes: 7a06ef751077 ("nvmem: core: fix bit offsets of more than one byte") Tested-by: Dmitry Sinyavin Signed-off-by: Janne Grunau --- Changes in v2: - added "Cc: stable@..." - added Dmitry Sinyavin's Tested-by: - use 12 char SHA1 in Fixes: tag - Link to v1: https://lore.kernel.org/r/20250901-nvmem-read-oob-bit-offset-v1-1-b610e18cdd3c@jannau.net To: Srinivas Kandagatla To: Greg Kroah-Hartman To: Dmitry Baryshkov Cc: linux-kernel@vger.kernel.org --- drivers/nvmem/core.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c index 0556d140170a..b4e5069d9e38 100644 --- a/drivers/nvmem/core.c +++ b/drivers/nvmem/core.c @@ -1598,12 +1598,14 @@ static void nvmem_shift_read_buffer_in_place(struct nvmem_cell_entry *cell, void *p = *b++ >> bit_offset; /* setup rest of the bytes if any */ - for (i = 1; i < cell->bytes; i++) { + for (i = 1; i < (cell->bytes - bytes_offset); i++) { /* Get bits from next byte and shift them towards msb */ *p++ |= *b << (BITS_PER_BYTE - bit_offset); *p = *b++ >> bit_offset; } + /* point to end of the buffer unused bits will be cleared */ + p = buf + cell->bytes - 1; } else if (p != b) { memmove(p, b, cell->bytes - bytes_offset); p += cell->bytes - 1; --- base-commit: cee9395acd8043be0644b25c34bfa86623f2b935 change-id: 20250901-nvmem-read-oob-bit-offset-dc1c2f39af6c Best regards, -- Janne Grunau