aspeed OTP device can write off the end of its memory
The aspeed OTP device and the SBC device that talks to it are confused about how they pass the guest-specified address across, with the result that an out-of-range address can result in a write off the end of the memory used for storage. Specifically, in aspeed_sbc.c the read path (aspeed_sbc_otp_read()) converts the guest address in R_ADDR from a word offset to a byte offset before using it as the argument to address_space_read(). This means the OTP MemoryRegion read function gets a guaranteed in-range byte offset (because the MemoryRegion itself is the right size for that). However in the write path (aspeed_sbc_otp_prog()) the word offset from the guest is passed without bounds checking or modification to address_space_write(). Although the OTP code does do the conversion to a byte offset, it doesn't bounds check it either, so word offsets of 0x1000 or above write off the end of the allocated memory. Reproducer with clang ASAN: ``` $ $ cat aspeed-otp.txt # set SBC R_ADDR writel 0x1E6F2010 0x1000 # set SBC R_CMD to CMD_READ writel 0x1E6F2004 0x23b1e364 $ ASAN_OPTIONS="fast_unwind_on_malloc=0" ./build/arm-san/qemu-system-arm -M ast2600-evb -accel qtest -qtest chardev:repro -chardev file,id=repro,path=/dev/null,input-path=aspeed-otp.txt -display none ==3565349==WARNING: ASan doesn't fully support makecontext/swapcontext functions and may produce false positives in some cases! [I 0.000000] OPENED [R +0.384294] # set SBC R_ADDR [R +0.384326] writel 0x1E6F2010 0x1000 [S +0.384333] OK [R +0.384358] # set SBC R_CMD to CMD_READ [R +0.384378] writel 0x1E6F2004 0x23b1e364 ================================================================= ==3565349==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x52a000011000 at pc 0x5bb03302fac0 bp 0x7ffc45622ff0 sp 0x7ffc45622fe8 READ of size 4 at 0x52a000011000 thread T0 #0 0x5bb03302fabf in memcpy /usr/include/x86_64-linux-gnu/bits/string_fortified.h:29:10 #1 0x5bb03302fabf in program_otpmem_data /home/pm215/qemu/build/arm-san/../../hw/nvram/aspeed_otp.c:67:5 #2 0x5bb03302fabf in aspeed_otp_write /home/pm215/qemu/build/arm-san/../../hw/nvram/aspeed_otp.c:88:10 #3 0x5bb0336a8372 in memory_region_write_accessor /home/pm215/qemu/build/arm-san/../../system/memory.c:491:5 #4 0x5bb0336a784b in access_with_adjusted_size /home/pm215/qemu/build/arm-san/../../system/memory.c:567:18 #5 0x5bb0336a6f2a in memory_region_dispatch_write /home/pm215/qemu/build/arm-san/../../system/memory.c #6 0x5bb0336fb4ab in flatview_write_continue_step /home/pm215/qemu/build/arm-san/../../system/physmem.c:3269:18 #7 0x5bb0336edd46 in flatview_write_continue /home/pm215/qemu/build/arm-san/../../system/physmem.c:3299:19 #8 0x5bb0336edd46 in flatview_write /home/pm215/qemu/build/arm-san/../../system/physmem.c:3330:12 #9 0x5bb0336edacc in address_space_write /home/pm215/qemu/build/arm-san/../../system/physmem.c:3450:18 #10 0x5bb032d9baaf in aspeed_sbc_otp_prog /home/pm215/qemu/build/arm-san/../../hw/misc/aspeed_sbc.c:163:11 #11 0x5bb032d9baaf in aspeed_sbc_handle_command /home/pm215/qemu/build/arm-san/../../hw/misc/aspeed_sbc.c:202:15 #12 0x5bb032d9baaf in aspeed_sbc_write /home/pm215/qemu/build/arm-san/../../hw/misc/aspeed_sbc.c:237:9 #13 0x5bb0336a8372 in memory_region_write_accessor /home/pm215/qemu/build/arm-san/../../system/memory.c:491:5 #14 0x5bb0336a784b in access_with_adjusted_size /home/pm215/qemu/build/arm-san/../../system/memory.c:567:18 #15 0x5bb0336a6f2a in memory_region_dispatch_write /home/pm215/qemu/build/arm-san/../../system/memory.c #16 0x5bb0336fb4ab in flatview_write_continue_step /home/pm215/qemu/build/arm-san/../../system/physmem.c:3269:18 #17 0x5bb0336edd46 in flatview_write_continue /home/pm215/qemu/build/arm-san/../../system/physmem.c:3299:19 #18 0x5bb0336edd46 in flatview_write /home/pm215/qemu/build/arm-san/../../system/physmem.c:3330:12 #19 0x5bb0336edacc in address_space_write /home/pm215/qemu/build/arm-san/../../system/physmem.c:3450:18 #20 0x5bb0337051dc in qtest_process_command /home/pm215/qemu/build/arm-san/../../system/qtest.c:533:13 #21 0x5bb033703648 in qtest_process_inbuf /home/pm215/qemu/build/arm-san/../../system/qtest.c:778:9 #22 0x5bb0344ae526 in fd_chr_read /home/pm215/qemu/build/arm-san/../../chardev/char-fd.c:72:9 #23 0x7f6a2a7f045d (/lib/x86_64-linux-gnu/libglib-2.0.so.0+0x5d45d) (BuildId: 116e142b9b52c8a4dfd403e759e71ab8f95d8bb3) #24 0x7f6a2a7f06cf in g_main_context_dispatch (/lib/x86_64-linux-gnu/libglib-2.0.so.0+0x5d6cf) (BuildId: 116e142b9b52c8a4dfd403e759e71ab8f95d8bb3) #25 0x5bb034795422 in glib_pollfds_poll /home/pm215/qemu/build/arm-san/../../util/main-loop.c:290:9 #26 0x5bb034795422 in os_host_main_loop_wait /home/pm215/qemu/build/arm-san/../../util/main-loop.c:313:5 #27 0x5bb034795422 in main_loop_wait /home/pm215/qemu/build/arm-san/../../util/main-loop.c:592:11 #28 0x5bb033710926 in qemu_main_loop /home/pm215/qemu/build/arm-san/../../system/runstate.c:948:9 #29 0x5bb03455022b in qemu_default_main /home/pm215/qemu/build/arm-san/../../system/main.c:50:14 #30 0x5bb034550201 in main /home/pm215/qemu/build/arm-san/../../system/main.c:93:9 #31 0x7f6a2842a1c9 in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16 #32 0x7f6a2842a28a in __libc_start_main csu/../csu/libc-start.c:360:3 #33 0x5bb03245ddf4 in _start (/home/pm215/qemu/build/arm-san/qemu-system-arm+0x1c30df4) (BuildId: 1d5f5be6c63e4d36a76643ec4862af9446cc2b20) 0x52a000011000 is located 0 bytes after 16384-byte region [0x52a00000d000,0x52a000011000) allocated by thread T0 here: #0 0x5bb0324f972b in posix_memalign (/home/pm215/qemu/build/arm-san/qemu-system-arm+0x1ccc72b) (BuildId: 1d5f5be6c63e4d36a76643ec4862af9446cc2b20) #1 0x5bb034783f34 in qemu_try_memalign /home/pm215/qemu/build/arm-san/../../util/memalign.c:53:11 #2 0x5bb034784162 in qemu_memalign /home/pm215/qemu/build/arm-san/../../util/memalign.c:73:15 #3 0x5bb03302eb14 in aspeed_otp_realize /home/pm215/qemu/build/arm-san/../../hw/nvram/aspeed_otp.c:155:18 #4 0x5bb034046eaa in device_set_realized /home/pm215/qemu/build/arm-san/../../hw/core/qdev.c:523:13 #5 0x5bb034060eb9 in property_set_bool /home/pm215/qemu/build/arm-san/../../qom/object.c:2376:5 #6 0x5bb03405bf3e in object_property_set /home/pm215/qemu/build/arm-san/../../qom/object.c:1450:5 #7 0x5bb0340685dc in object_property_set_qobject /home/pm215/qemu/build/arm-san/../../qom/qom-qobject.c:28:10 #8 0x5bb03405c86f in object_property_set_bool /home/pm215/qemu/build/arm-san/../../qom/object.c:1520:15 #9 0x5bb032d9ae05 in aspeed_sbc_realize /home/pm215/qemu/build/arm-san/../../hw/misc/aspeed_sbc.c:296:14 #10 0x5bb034046eaa in device_set_realized /home/pm215/qemu/build/arm-san/../../hw/core/qdev.c:523:13 #11 0x5bb034060eb9 in property_set_bool /home/pm215/qemu/build/arm-san/../../qom/object.c:2376:5 #12 0x5bb03405bf3e in object_property_set /home/pm215/qemu/build/arm-san/../../qom/object.c:1450:5 #13 0x5bb0340685dc in object_property_set_qobject /home/pm215/qemu/build/arm-san/../../qom/qom-qobject.c:28:10 #14 0x5bb03405c86f in object_property_set_bool /home/pm215/qemu/build/arm-san/../../qom/object.c:1520:15 #15 0x5bb033e0b9e3 in aspeed_soc_ast2600_realize /home/pm215/qemu/build/arm-san/../../hw/arm/aspeed_ast2600.c:727:10 #16 0x5bb034046eaa in device_set_realized /home/pm215/qemu/build/arm-san/../../hw/core/qdev.c:523:13 #17 0x5bb034060eb9 in property_set_bool /home/pm215/qemu/build/arm-san/../../qom/object.c:2376:5 #18 0x5bb03405bf3e in object_property_set /home/pm215/qemu/build/arm-san/../../qom/object.c:1450:5 #19 0x5bb0340685dc in object_property_set_qobject /home/pm215/qemu/build/arm-san/../../qom/qom-qobject.c:28:10 #20 0x5bb03405c86f in object_property_set_bool /home/pm215/qemu/build/arm-san/../../qom/object.c:1520:15 #21 0x5bb033df5190 in aspeed_machine_init /home/pm215/qemu/build/arm-san/../../hw/arm/aspeed.c:188:5 #22 0x5bb0328f2b5d in machine_run_board_init /home/pm215/qemu/build/arm-san/../../hw/core/machine.c:1679:5 #23 0x5bb03366c2d5 in qemu_init_board /home/pm215/qemu/build/arm-san/../../system/vl.c:2713:5 #24 0x5bb03366c2d5 in qmp_x_exit_preconfig /home/pm215/qemu/build/arm-san/../../system/vl.c:2807:5 #25 0x5bb033672d8c in qemu_init /home/pm215/qemu/build/arm-san/../../system/vl.c:3845:9 #26 0x5bb034550151 in main /home/pm215/qemu/build/arm-san/../../system/main.c:71:5 #27 0x7f6a2842a1c9 in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16 #28 0x7f6a2842a28a in __libc_start_main csu/../csu/libc-start.c:360:3 SUMMARY: AddressSanitizer: heap-buffer-overflow /usr/include/x86_64-linux-gnu/bits/string_fortified.h:29:10 in memcpy Shadow bytes around the buggy address: 0x52a000010d80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x52a000010e00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x52a000010e80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x52a000010f00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x52a000010f80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 =>0x52a000011000:[fa]fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x52a000011080: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x52a000011100: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x52a000011180: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x52a000011200: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x52a000011280: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa Shadow byte legend (one shadow byte represents 8 application bytes): Addressable: 00 Partially addressable: 01 02 03 04 05 06 07 Heap left redzone: fa Freed heap region: fd Stack left redzone: f1 Stack mid redzone: f2 Stack right redzone: f3 Stack after return: f5 Stack use after scope: f8 Global redzone: f9 Global init order: f6 Poisoned by user: f7 Container overflow: fc Array cookie: ac Intra object redzone: bb ASan internal: fe Left alloca redzone: ca Right alloca redzone: cb ==3565349==ABORTING ```
issue