* [PATCH-for-9.0 v2 0/3] hw/block/nand: Fix out-of-bound access in NAND block buffer
@ 2024-04-09 13:59 Philippe Mathieu-Daudé
2024-04-09 13:59 ` [PATCH-for-9.0 v2 1/3] hw/block/nand: Factor nand_load_iolen() method out Philippe Mathieu-Daudé
` (4 more replies)
0 siblings, 5 replies; 7+ messages in thread
From: Philippe Mathieu-Daudé @ 2024-04-09 13:59 UTC (permalink / raw)
To: qemu-devel, Kevin Wolf
Cc: Qiang Liu, qemu-block, Alexander Bulekov, Hanna Reitz,
Philippe Mathieu-Daudé
Fix for https://gitlab.com/qemu-project/qemu/-/issues/1446
Since v1:
- Addressed Kevin trivial suggestions (unsigned offset)
Philippe Mathieu-Daudé (3):
hw/block/nand: Factor nand_load_iolen() method out
hw/block/nand: Have blk_load() take unsigned offset and return boolean
hw/block/nand: Fix out-of-bound access in NAND block buffer
hw/block/nand.c | 55 ++++++++++++++++++++++++++++++++++---------------
1 file changed, 38 insertions(+), 17 deletions(-)
--
2.41.0
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH-for-9.0 v2 1/3] hw/block/nand: Factor nand_load_iolen() method out
2024-04-09 13:59 [PATCH-for-9.0 v2 0/3] hw/block/nand: Fix out-of-bound access in NAND block buffer Philippe Mathieu-Daudé
@ 2024-04-09 13:59 ` Philippe Mathieu-Daudé
2024-04-09 13:59 ` [PATCH-for-9.0 v2 2/3] hw/block/nand: Have blk_load() take unsigned offset and return boolean Philippe Mathieu-Daudé
` (3 subsequent siblings)
4 siblings, 0 replies; 7+ messages in thread
From: Philippe Mathieu-Daudé @ 2024-04-09 13:59 UTC (permalink / raw)
To: qemu-devel, Kevin Wolf
Cc: Qiang Liu, qemu-block, Alexander Bulekov, Hanna Reitz,
Philippe Mathieu-Daudé, Richard Henderson
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
---
hw/block/nand.c | 35 ++++++++++++++++++++++-------------
1 file changed, 22 insertions(+), 13 deletions(-)
diff --git a/hw/block/nand.c b/hw/block/nand.c
index d1435f2207..f33eb2d552 100644
--- a/hw/block/nand.c
+++ b/hw/block/nand.c
@@ -243,9 +243,28 @@ static inline void nand_pushio_byte(NANDFlashState *s, uint8_t value)
}
}
+/*
+ * nand_load_block: Load block containing (s->addr + @offset).
+ * Returns length of data available at @offset in this block.
+ */
+static unsigned nand_load_block(NANDFlashState *s, unsigned offset)
+{
+ unsigned iolen;
+
+ s->blk_load(s, s->addr, offset);
+
+ iolen = (1 << s->page_shift);
+ if (s->gnd) {
+ iolen += 1 << s->oob_shift;
+ }
+ assert(offset <= iolen);
+ iolen -= offset;
+
+ return iolen;
+}
+
static void nand_command(NANDFlashState *s)
{
- unsigned int offset;
switch (s->cmd) {
case NAND_CMD_READ0:
s->iolen = 0;
@@ -271,12 +290,7 @@ static void nand_command(NANDFlashState *s)
case NAND_CMD_NOSERIALREAD2:
if (!(nand_flash_ids[s->chip_id].options & NAND_SAMSUNG_LP))
break;
- offset = s->addr & ((1 << s->addr_shift) - 1);
- s->blk_load(s, s->addr, offset);
- if (s->gnd)
- s->iolen = (1 << s->page_shift) - offset;
- else
- s->iolen = (1 << s->page_shift) + (1 << s->oob_shift) - offset;
+ s->iolen = nand_load_block(s, s->addr & ((1 << s->addr_shift) - 1));
break;
case NAND_CMD_RESET:
@@ -597,12 +611,7 @@ uint32_t nand_getio(DeviceState *dev)
if (!s->iolen && s->cmd == NAND_CMD_READ0) {
offset = (int) (s->addr & ((1 << s->addr_shift) - 1)) + s->offset;
s->offset = 0;
-
- s->blk_load(s, s->addr, offset);
- if (s->gnd)
- s->iolen = (1 << s->page_shift) - offset;
- else
- s->iolen = (1 << s->page_shift) + (1 << s->oob_shift) - offset;
+ s->iolen = nand_load_block(s, offset);
}
if (s->ce || s->iolen <= 0) {
--
2.41.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH-for-9.0 v2 2/3] hw/block/nand: Have blk_load() take unsigned offset and return boolean
2024-04-09 13:59 [PATCH-for-9.0 v2 0/3] hw/block/nand: Fix out-of-bound access in NAND block buffer Philippe Mathieu-Daudé
2024-04-09 13:59 ` [PATCH-for-9.0 v2 1/3] hw/block/nand: Factor nand_load_iolen() method out Philippe Mathieu-Daudé
@ 2024-04-09 13:59 ` Philippe Mathieu-Daudé
2024-04-09 13:59 ` [PATCH-for-9.0 v2 3/3] hw/block/nand: Fix out-of-bound access in NAND block buffer Philippe Mathieu-Daudé
` (2 subsequent siblings)
4 siblings, 0 replies; 7+ messages in thread
From: Philippe Mathieu-Daudé @ 2024-04-09 13:59 UTC (permalink / raw)
To: qemu-devel, Kevin Wolf
Cc: Qiang Liu, qemu-block, Alexander Bulekov, Hanna Reitz,
Philippe Mathieu-Daudé, Richard Henderson
Negative offset is meaningless, use unsigned type.
Return a boolean value indicating success.
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
---
hw/block/nand.c | 14 ++++++++++----
1 file changed, 10 insertions(+), 4 deletions(-)
diff --git a/hw/block/nand.c b/hw/block/nand.c
index f33eb2d552..5a31d78b6b 100644
--- a/hw/block/nand.c
+++ b/hw/block/nand.c
@@ -84,7 +84,11 @@ struct NANDFlashState {
void (*blk_write)(NANDFlashState *s);
void (*blk_erase)(NANDFlashState *s);
- void (*blk_load)(NANDFlashState *s, uint64_t addr, int offset);
+ /*
+ * Returns %true when block containing (@addr + @offset) is
+ * successfully loaded, otherwise %false.
+ */
+ bool (*blk_load)(NANDFlashState *s, uint64_t addr, unsigned offset);
uint32_t ioaddr_vmstate;
};
@@ -772,11 +776,11 @@ static void glue(nand_blk_erase_, NAND_PAGE_SIZE)(NANDFlashState *s)
}
}
-static void glue(nand_blk_load_, NAND_PAGE_SIZE)(NANDFlashState *s,
- uint64_t addr, int offset)
+static bool glue(nand_blk_load_, NAND_PAGE_SIZE)(NANDFlashState *s,
+ uint64_t addr, unsigned offset)
{
if (PAGE(addr) >= s->pages) {
- return;
+ return false;
}
if (s->blk) {
@@ -804,6 +808,8 @@ static void glue(nand_blk_load_, NAND_PAGE_SIZE)(NANDFlashState *s,
offset, NAND_PAGE_SIZE + OOB_SIZE - offset);
s->ioaddr = s->io;
}
+
+ return true;
}
static void glue(nand_init_, NAND_PAGE_SIZE)(NANDFlashState *s)
--
2.41.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH-for-9.0 v2 3/3] hw/block/nand: Fix out-of-bound access in NAND block buffer
2024-04-09 13:59 [PATCH-for-9.0 v2 0/3] hw/block/nand: Fix out-of-bound access in NAND block buffer Philippe Mathieu-Daudé
2024-04-09 13:59 ` [PATCH-for-9.0 v2 1/3] hw/block/nand: Factor nand_load_iolen() method out Philippe Mathieu-Daudé
2024-04-09 13:59 ` [PATCH-for-9.0 v2 2/3] hw/block/nand: Have blk_load() take unsigned offset and return boolean Philippe Mathieu-Daudé
@ 2024-04-09 13:59 ` Philippe Mathieu-Daudé
2024-04-09 14:04 ` [PATCH-for-9.0 v2 0/3] " Philippe Mathieu-Daudé
2024-04-09 14:18 ` Kevin Wolf
4 siblings, 0 replies; 7+ messages in thread
From: Philippe Mathieu-Daudé @ 2024-04-09 13:59 UTC (permalink / raw)
To: qemu-devel, Kevin Wolf
Cc: Qiang Liu, qemu-block, Alexander Bulekov, Hanna Reitz,
Philippe Mathieu-Daudé, Richard Henderson
nand_command() and nand_getio() don't check @offset points
into the block, nor the available data length (s->iolen) is
not negative.
In order to fix:
- check the offset is in range in nand_blk_load_NAND_PAGE_SIZE(),
- do not set @iolen if blk_load() failed.
Reproducer:
$ cat << EOF | qemu-system-arm -machine tosa \
-monitor none -serial none \
-display none -qtest stdio
write 0x10000111 0x1 0xca
write 0x10000104 0x1 0x47
write 0x1000ca04 0x1 0xd7
write 0x1000ca01 0x1 0xe0
write 0x1000ca04 0x1 0x71
write 0x1000ca00 0x1 0x50
write 0x1000ca04 0x1 0xd7
read 0x1000ca02 0x1
write 0x1000ca01 0x1 0x10
EOF
=================================================================
==15750==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x61f000000de0
at pc 0x560e61557210 bp 0x7ffcfc4a59f0 sp 0x7ffcfc4a59e8
READ of size 1 at 0x61f000000de0 thread T0
#0 0x560e6155720f in mem_and hw/block/nand.c:101:20
#1 0x560e6155ac9c in nand_blk_write_512 hw/block/nand.c:663:9
#2 0x560e61544200 in nand_command hw/block/nand.c:293:13
#3 0x560e6153cc83 in nand_setio hw/block/nand.c:520:13
#4 0x560e61a0a69e in tc6393xb_nand_writeb hw/display/tc6393xb.c:380:13
#5 0x560e619f9bf7 in tc6393xb_writeb hw/display/tc6393xb.c:524:9
#6 0x560e647c7d03 in memory_region_write_accessor softmmu/memory.c:492:5
#7 0x560e647c7641 in access_with_adjusted_size softmmu/memory.c:554:18
#8 0x560e647c5f66 in memory_region_dispatch_write softmmu/memory.c:1514:16
#9 0x560e6485409e in flatview_write_continue softmmu/physmem.c:2825:23
#10 0x560e648421eb in flatview_write softmmu/physmem.c:2867:12
#11 0x560e64841ca8 in address_space_write softmmu/physmem.c:2963:18
#12 0x560e61170162 in qemu_writeb tests/qtest/videzzo/videzzo_qemu.c:1080:5
#13 0x560e6116eef7 in dispatch_mmio_write tests/qtest/videzzo/videzzo_qemu.c:1227:28
0x61f000000de0 is located 0 bytes to the right of 3424-byte region [0x61f000000080,0x61f000000de0)
allocated by thread T0 here:
#0 0x560e611276cf in malloc /root/llvm-project/compiler-rt/lib/asan/asan_malloc_linux.cpp:145:3
#1 0x7f7959a87e98 in g_malloc (/lib/x86_64-linux-gnu/libglib-2.0.so.0+0x57e98)
#2 0x560e64b98871 in object_new qom/object.c:749:12
#3 0x560e64b5d1a1 in qdev_new hw/core/qdev.c:153:19
#4 0x560e61547ea5 in nand_init hw/block/nand.c:639:11
#5 0x560e619f8772 in tc6393xb_init hw/display/tc6393xb.c:558:16
#6 0x560e6390bad2 in tosa_init hw/arm/tosa.c:250:12
SUMMARY: AddressSanitizer: heap-buffer-overflow hw/block/nand.c:101:20 in mem_and
==15750==ABORTING
Broken since introduction in commit 3e3d5815cb ("NAND Flash memory
emulation and ECC calculation helpers for use by NAND controllers").
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1445
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1446
Reported-by: Qiang Liu <cyruscyliu@gmail.com>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
---
hw/block/nand.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/hw/block/nand.c b/hw/block/nand.c
index 5a31d78b6b..e2433c25bd 100644
--- a/hw/block/nand.c
+++ b/hw/block/nand.c
@@ -255,7 +255,9 @@ static unsigned nand_load_block(NANDFlashState *s, unsigned offset)
{
unsigned iolen;
- s->blk_load(s, s->addr, offset);
+ if (!s->blk_load(s, s->addr, offset)) {
+ return 0;
+ }
iolen = (1 << s->page_shift);
if (s->gnd) {
@@ -783,6 +785,10 @@ static bool glue(nand_blk_load_, NAND_PAGE_SIZE)(NANDFlashState *s,
return false;
}
+ if (offset > NAND_PAGE_SIZE + OOB_SIZE) {
+ return false;
+ }
+
if (s->blk) {
if (s->mem_oob) {
if (blk_pread(s->blk, SECTOR(addr) << BDRV_SECTOR_BITS,
--
2.41.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH-for-9.0 v2 0/3] hw/block/nand: Fix out-of-bound access in NAND block buffer
2024-04-09 13:59 [PATCH-for-9.0 v2 0/3] hw/block/nand: Fix out-of-bound access in NAND block buffer Philippe Mathieu-Daudé
` (2 preceding siblings ...)
2024-04-09 13:59 ` [PATCH-for-9.0 v2 3/3] hw/block/nand: Fix out-of-bound access in NAND block buffer Philippe Mathieu-Daudé
@ 2024-04-09 14:04 ` Philippe Mathieu-Daudé
2024-04-09 14:18 ` Kevin Wolf
4 siblings, 0 replies; 7+ messages in thread
From: Philippe Mathieu-Daudé @ 2024-04-09 14:04 UTC (permalink / raw)
To: Kevin Wolf
Cc: qemu-devel, Qiang Liu, qemu-block, Alexander Bulekov, Hanna Reitz
On 9/4/24 15:59, Philippe Mathieu-Daudé wrote:
> Fix for https://gitlab.com/qemu-project/qemu/-/issues/1446
>
> Since v1:
> - Addressed Kevin trivial suggestions (unsigned offset)
$ git backport-diff
Key:
[----] : patches are identical
[####] : number of functional differences between upstream/downstream patch
[down] : patch is downstream-only
The flags [FC] indicate (F)unctional and (C)ontextual differences,
respectively
001/ 3:[0009] [FC] 'hw/block/nand: Factor nand_load_iolen() method
out'
002/ 3:[0004] [FC] 'hw/block/nand: Have blk_load() return boolean
indicating success'
003/ 3:[----] [-C] 'hw/block/nand: Fix out-of-bound access in NAND
block buffer'
$ git diff
diff --git a/hw/block/nand.c b/hw/block/nand.c
index d90dc965a1..e2433c25bd 100644
--- a/hw/block/nand.c
+++ b/hw/block/nand.c
@@ -88,7 +88,7 @@ struct NANDFlashState {
* Returns %true when block containing (@addr + @offset) is
* successfully loaded, otherwise %false.
*/
- bool (*blk_load)(NANDFlashState *s, uint64_t addr, int offset);
+ bool (*blk_load)(NANDFlashState *s, uint64_t addr, unsigned offset);
uint32_t ioaddr_vmstate;
};
@@ -251,18 +251,21 @@ static inline void nand_pushio_byte(NANDFlashState
*s, uint8_t value)
* nand_load_block: Load block containing (s->addr + @offset).
* Returns length of data available at @offset in this block.
*/
-static int nand_load_block(NANDFlashState *s, int offset)
+static unsigned nand_load_block(NANDFlashState *s, unsigned offset)
{
- int iolen;
+ unsigned iolen;
if (!s->blk_load(s, s->addr, offset)) {
return 0;
}
- iolen = (1 << s->page_shift) - offset;
+ iolen = (1 << s->page_shift);
if (s->gnd) {
iolen += 1 << s->oob_shift;
}
+ assert(offset <= iolen);
+ iolen -= offset;
+
return iolen;
}
@@ -776,7 +779,7 @@ static void glue(nand_blk_erase_,
NAND_PAGE_SIZE)(NANDFlashState *s)
}
static bool glue(nand_blk_load_, NAND_PAGE_SIZE)(NANDFlashState *s,
- uint64_t addr, int offset)
+ uint64_t addr, unsigned offset)
{
if (PAGE(addr) >= s->pages) {
return false;
---
>
> Philippe Mathieu-Daudé (3):
> hw/block/nand: Factor nand_load_iolen() method out
> hw/block/nand: Have blk_load() take unsigned offset and return boolean
> hw/block/nand: Fix out-of-bound access in NAND block buffer
>
> hw/block/nand.c | 55 ++++++++++++++++++++++++++++++++++---------------
> 1 file changed, 38 insertions(+), 17 deletions(-)
>
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH-for-9.0 v2 0/3] hw/block/nand: Fix out-of-bound access in NAND block buffer
2024-04-09 13:59 [PATCH-for-9.0 v2 0/3] hw/block/nand: Fix out-of-bound access in NAND block buffer Philippe Mathieu-Daudé
` (3 preceding siblings ...)
2024-04-09 14:04 ` [PATCH-for-9.0 v2 0/3] " Philippe Mathieu-Daudé
@ 2024-04-09 14:18 ` Kevin Wolf
2024-04-09 14:31 ` Philippe Mathieu-Daudé
4 siblings, 1 reply; 7+ messages in thread
From: Kevin Wolf @ 2024-04-09 14:18 UTC (permalink / raw)
To: Philippe Mathieu-Daudé
Cc: qemu-devel, Qiang Liu, qemu-block, Alexander Bulekov, Hanna Reitz
Am 09.04.2024 um 15:59 hat Philippe Mathieu-Daudé geschrieben:
> Fix for https://gitlab.com/qemu-project/qemu/-/issues/1446
>
> Since v1:
> - Addressed Kevin trivial suggestions (unsigned offset)
You already kept the Reviewed-by tags, but looks good to me.
Kevin
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH-for-9.0 v2 0/3] hw/block/nand: Fix out-of-bound access in NAND block buffer
2024-04-09 14:18 ` Kevin Wolf
@ 2024-04-09 14:31 ` Philippe Mathieu-Daudé
0 siblings, 0 replies; 7+ messages in thread
From: Philippe Mathieu-Daudé @ 2024-04-09 14:31 UTC (permalink / raw)
To: Kevin Wolf
Cc: qemu-devel, Qiang Liu, qemu-block, Alexander Bulekov, Hanna Reitz
On 9/4/24 16:18, Kevin Wolf wrote:
> Am 09.04.2024 um 15:59 hat Philippe Mathieu-Daudé geschrieben:
>> Fix for https://gitlab.com/qemu-project/qemu/-/issues/1446
>>
>> Since v1:
>> - Addressed Kevin trivial suggestions (unsigned offset)
>
> You already kept the Reviewed-by tags, but looks good to me.
Less work on your side ;)
The changes seemed trivial enough to keep them, but better
be safe than sorry.
Thanks!
Series queued.
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2024-04-09 14:32 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-04-09 13:59 [PATCH-for-9.0 v2 0/3] hw/block/nand: Fix out-of-bound access in NAND block buffer Philippe Mathieu-Daudé
2024-04-09 13:59 ` [PATCH-for-9.0 v2 1/3] hw/block/nand: Factor nand_load_iolen() method out Philippe Mathieu-Daudé
2024-04-09 13:59 ` [PATCH-for-9.0 v2 2/3] hw/block/nand: Have blk_load() take unsigned offset and return boolean Philippe Mathieu-Daudé
2024-04-09 13:59 ` [PATCH-for-9.0 v2 3/3] hw/block/nand: Fix out-of-bound access in NAND block buffer Philippe Mathieu-Daudé
2024-04-09 14:04 ` [PATCH-for-9.0 v2 0/3] " Philippe Mathieu-Daudé
2024-04-09 14:18 ` Kevin Wolf
2024-04-09 14:31 ` Philippe Mathieu-Daudé
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).