Skip to content

Commit c2e857b

Browse files
committed
hw/sd/sdcard: Avoid OOB in sd_read_byte() during unexpected CMD switch
For multi-bytes commands, our implementation uses the @data_start and @data_offset fields to track byte access. We initialize the command start/offset in buffer once. Malicious guest might abuse by switching command while staying in the 'transfer' state, switching command buffer size, and our implementation can access out of buffer boundary. For example, CMD17 (READ_SINGLE_BLOCK) allows to read up to 512 bytes, and CMD13 (SEND_STATUS) up to 64 bytes. By switching from CMD17 to CMD13 (see reproducer below), bytes [64-511] are out of the 'status' buffer. Our implementation return R0 status code for unexpected commands. Such in-transaction command switch is unexpected and returns R0. This is a good place to reset the start/offset fields to avoid malicious accesses. Can be reproduced running: $ export UBSAN_OPTIONS=print_stacktrace=1:halt_on_error=1 $ cat << EOF | qemu-system-i386 \ -display none -nographic \ -machine accel=qtest -m 512M \ -nodefaults \ -device sdhci-pci,sd-spec-version=3 \ -device sd-card,drive=mydrive \ -drive if=none,index=0,file=null-co://,format=raw,id=mydrive \ -qtest stdio -trace sd\* -trace -sdbus_read outl 0xcf8 0x80001010 outl 0xcfc 0xe0000000 outl 0xcf8 0x80001004 outw 0xcfc 0x02 write 0xe000002c 0x1 0x05 write 0xe000000f 0x1 0x37 write 0xe000000a 0x1 0x01 write 0xe000000f 0x1 0x29 write 0xe000000f 0x1 0x02 write 0xe000000f 0x1 0x03 write 0xe000000c 0x1 0x32 write 0xe000000f 0x1 0x06 write 0xe0000005 0x1 0x01 write 0xe0000007 0x1 0x01 write 0xe0000003 0x1 0x00 write 0xe000000f 0x1 0x11 write 0xe000002a 0x1 0x01 write 0xe000002a 0x1 0x02 write 0xe000000f 0x1 0x0d write 0xe000002a 0x1 0x01 write 0xe000002a 0x1 0x02 EOF hw/sd/sd.c:1984:15: runtime error: index 256 out of bounds for type 'uint8_t [64]' #0 sd_read_byte hw/sd/sd.c:1984:15 #1 sdbus_read_data hw/sd/core.c:157:23 qemu#2 sdhci_read_block_from_card hw/sd/sdhci.c:423:9 qemu#3 sdhci_blkgap_write hw/sd/sdhci.c:1074:13 qemu#4 sdhci_write hw/sd/sdhci.c:1195:13 qemu#5 memory_region_write_accessor softmmu/memory.c:492:5 qemu#6 access_with_adjusted_size softmmu/memory.c:554:18 qemu#7 memory_region_dispatch_write softmmu/memory.c qemu#8 flatview_write_continue softmmu/physmem.c:2778:23 qemu#9 flatview_write softmmu/physmem.c:2818:14 qemu#10 address_space_write softmmu/physmem.c:2910:18 SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior hw/sd/sd.c:1984:15 Reported-by: Alexander Bulekov <[email protected]> Resolves: https://gitlab.com/qemu-project/qemu/-/issues/487 Buglink: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=36240 Signed-off-by: Philippe Mathieu-Daudé <[email protected]> Message-Id: <[email protected]>
1 parent 4fbeddb commit c2e857b

File tree

1 file changed

+7
-0
lines changed

1 file changed

+7
-0
lines changed

hw/sd/sd.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1826,6 +1826,13 @@ int sd_do_command(SDState *sd, SDRequest *req,
18261826
break;
18271827

18281828
case sd_r0:
1829+
/*
1830+
* Invalid state transition, reset implementation
1831+
* fields to avoid OOB abuse.
1832+
*/
1833+
sd->data_start = 0;
1834+
sd->data_offset = 0;
1835+
/* fall-through */
18291836
case sd_illegal:
18301837
rsplen = 0;
18311838
break;

0 commit comments

Comments
 (0)