-
Notifications
You must be signed in to change notification settings - Fork 8
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Is the "on_block_transition/executed" in cpp plugin executing after a block is executed? #12
Comments
Hello aar0nge, you saw the right comment. QEMU plugin API offers a way to put hooks when a block is translated/executed. CPP Plugin is offering an interface to put hooks when a block is executed only (translation could be added if needed). Since it gives you information about how the block was reached, easy access to its instructions and statistics during its execution (memory accesses mainly), we report block execution AFTER it was executed (and before new one is executed). Code generated can't be modified (we offer a "read-only" view of the execution). If you want to use CPP Plugin, you do not have to deal with QEMU interface like "pre_tb_helper_code". Just inherit Interface and put your code here (see this plugin for example https://github.com/atos-tools/qemu/blob/next/master/tcg/plugins/cpp/count_instructions.cpp). If you want QEMU "pure" plugins, then see documentation for plugins (https://github.com/atos-tools/qemu/blob/next/master/tcg/plugins/dyncount.c for example). If you want to implement hook for malloc with any method, I would go with detecting first execution of a block inside malloc function, then put your stuff there. If you want to modify behavior of malloc, you'll have to go with QEMU plugins (CPP plugin does not modify generated code). If you only want to monitor number of calls to malloc, then CPP Plugin should be able to get you there. CPP Plugin: Hope it helps! |
To go further, on_block_transition/on_block_executed could have been implemented in the same function (they are called one after the other in plugin_api.cpp). The point is that a lot of plugin only need to have access to block executed, without needing to know what happens between blocks (like counting instructions). Thus, on_block_transition was added for the need to analyze this. It was just a design choice (I wanted the simpliest API possible for a simple plugin like counting instructions). For your need, you could as well implement your malloc hook by keeping track of current function executed (with a pointer) and check if it changed between two blocks (using on_block_executed). |
Thanks for your reply ! I understand that CPP plugin is an abstract API, and I am just trying to understand your implementation of it. |
Ok! better for you to go with QEMU plugins in this case. To explain, as you saw, interesting code for you is there (https://github.com/second-reality/qemu/blob/next/master/tcg/plugins/cpp.c). I'll detail code.
This function generates a call at the beginning of a block executed (on_block_exec), thus CPP interface is notified each time a block is started. (1) At this time of generation, some information are not known (like size of block, ...), thus second function after generation:
It will patch parameter of generated call before (see 1 above), so that correct block is obtained. The point is that "get_translation_block" will create view of block (disassemble it, record it, ...), so we need block to be fully emitted before doing all this. Thus the mechanics between before and after gen. That is the kind of things that made me develop a CPP API for my needs. I'm pretty sure you know about it, but probably you are a bit confused between translation and execution time. What we do in QEMU plugins is patching at Translation time. CPP API offers a view at execution time (that will have a fixed parameter representing current block called at beginning of any of them that is obtained... at translation time). |
Oh, now I know. Thanks for your detailed explaination! It really helps. |
Include the qtest reproducer provided by Alexander Bulekov in https://gitlab.com/qemu-project/qemu/-/issues/542. Without the previous commit, we get: $ make check-qtest-i386 ... Running test tests/qtest/intel-hda-test AddressSanitizer:DEADLYSIGNAL ================================================================= ==1580408==ERROR: AddressSanitizer: stack-overflow on address 0x7ffc3d566fe0 #0 0x63d297cf in address_space_translate_internal softmmu/physmem.c:356 atos-tools#1 0x63d27260 in flatview_do_translate softmmu/physmem.c:499:15 atos-tools#2 0x63d27af5 in flatview_translate softmmu/physmem.c:565:15 atos-tools#3 0x63d4ce84 in flatview_write softmmu/physmem.c:2850:10 atos-tools#4 0x63d4cb18 in address_space_write softmmu/physmem.c:2950:18 atos-tools#5 0x63d4d387 in address_space_rw softmmu/physmem.c:2960:16 atos-tools#6 0x62ae12f2 in dma_memory_rw_relaxed include/sysemu/dma.h:89:12 atos-tools#7 0x62ae104a in dma_memory_rw include/sysemu/dma.h:132:12 atos-tools#8 0x62ae6157 in dma_memory_write include/sysemu/dma.h:173:12 atos-tools#9 0x62ae5ec0 in stl_le_dma include/sysemu/dma.h:275:1 atos-tools#10 0x62ae5ba2 in stl_le_pci_dma include/hw/pci/pci.h:871:1 atos-tools#11 0x62ad59a6 in intel_hda_response hw/audio/intel-hda.c:372:12 atos-tools#12 0x62ad2afb in hda_codec_response hw/audio/intel-hda.c:107:5 atos-tools#13 0x62aec4e1 in hda_audio_command hw/audio/hda-codec.c:655:5 atos-tools#14 0x62ae05d9 in intel_hda_send_command hw/audio/intel-hda.c:307:5 atos-tools#15 0x62adff54 in intel_hda_corb_run hw/audio/intel-hda.c:342:9 atos-tools#16 0x62adc13b in intel_hda_set_corb_wp hw/audio/intel-hda.c:548:5 atos-tools#17 0x62ae5942 in intel_hda_reg_write hw/audio/intel-hda.c:977:9 atos-tools#18 0x62ada10a in intel_hda_mmio_write hw/audio/intel-hda.c:1054:5 atos-tools#19 0x63d8f383 in memory_region_write_accessor softmmu/memory.c:492:5 atos-tools#20 0x63d8ecc1 in access_with_adjusted_size softmmu/memory.c:554:18 atos-tools#21 0x63d8d5d6 in memory_region_dispatch_write softmmu/memory.c:1504:16 atos-tools#22 0x63d5e85e in flatview_write_continue softmmu/physmem.c:2812:23 qemu#23 0x63d4d05b in flatview_write softmmu/physmem.c:2854:12 qemu#24 0x63d4cb18 in address_space_write softmmu/physmem.c:2950:18 qemu#25 0x63d4d387 in address_space_rw softmmu/physmem.c:2960:16 qemu#26 0x62ae12f2 in dma_memory_rw_relaxed include/sysemu/dma.h:89:12 qemu#27 0x62ae104a in dma_memory_rw include/sysemu/dma.h:132:12 qemu#28 0x62ae6157 in dma_memory_write include/sysemu/dma.h:173:12 qemu#29 0x62ae5ec0 in stl_le_dma include/sysemu/dma.h:275:1 qemu#30 0x62ae5ba2 in stl_le_pci_dma include/hw/pci/pci.h:871:1 qemu#31 0x62ad59a6 in intel_hda_response hw/audio/intel-hda.c:372:12 qemu#32 0x62ad2afb in hda_codec_response hw/audio/intel-hda.c:107:5 qemu#33 0x62aec4e1 in hda_audio_command hw/audio/hda-codec.c:655:5 qemu#34 0x62ae05d9 in intel_hda_send_command hw/audio/intel-hda.c:307:5 qemu#35 0x62adff54 in intel_hda_corb_run hw/audio/intel-hda.c:342:9 qemu#36 0x62adc13b in intel_hda_set_corb_wp hw/audio/intel-hda.c:548:5 qemu#37 0x62ae5942 in intel_hda_reg_write hw/audio/intel-hda.c:977:9 qemu#38 0x62ada10a in intel_hda_mmio_write hw/audio/intel-hda.c:1054:5 qemu#39 0x63d8f383 in memory_region_write_accessor softmmu/memory.c:492:5 qemu#40 0x63d8ecc1 in access_with_adjusted_size softmmu/memory.c:554:18 qemu#41 0x63d8d5d6 in memory_region_dispatch_write softmmu/memory.c:1504:16 qemu#42 0x63d5e85e in flatview_write_continue softmmu/physmem.c:2812:23 qemu#43 0x63d4d05b in flatview_write softmmu/physmem.c:2854:12 qemu#44 0x63d4cb18 in address_space_write softmmu/physmem.c:2950:18 qemu#45 0x63d4d387 in address_space_rw softmmu/physmem.c:2960:16 qemu#46 0x62ae12f2 in dma_memory_rw_relaxed include/sysemu/dma.h:89:12 qemu#47 0x62ae104a in dma_memory_rw include/sysemu/dma.h:132:12 qemu#48 0x62ae6157 in dma_memory_write include/sysemu/dma.h:173:12 ... SUMMARY: AddressSanitizer: stack-overflow softmmu/physmem.c:356 in address_space_translate_internal ==1580408==ABORTING Broken pipe Aborted (core dumped) Signed-off-by: Philippe Mathieu-Daudé <[email protected]> Acked-by: Thomas Huth <[email protected]> Message-Id: <[email protected]> Signed-off-by: Thomas Huth <[email protected]>
The issue reported by OSS-Fuzz produces the following backtrace: ==447470==ERROR: AddressSanitizer: heap-buffer-overflow READ of size 1 at 0x61500002a080 thread T0 #0 0x71766d47 in sdhci_read_dataport hw/sd/sdhci.c:474:18 atos-tools#1 0x7175f139 in sdhci_read hw/sd/sdhci.c:1022:19 atos-tools#2 0x721b937b in memory_region_read_accessor softmmu/memory.c:440:11 atos-tools#3 0x72171e51 in access_with_adjusted_size softmmu/memory.c:554:18 atos-tools#4 0x7216f47c in memory_region_dispatch_read1 softmmu/memory.c:1424:16 atos-tools#5 0x7216ebb9 in memory_region_dispatch_read softmmu/memory.c:1452:9 atos-tools#6 0x7212db5d in flatview_read_continue softmmu/physmem.c:2879:23 atos-tools#7 0x7212f958 in flatview_read softmmu/physmem.c:2921:12 atos-tools#8 0x7212f418 in address_space_read_full softmmu/physmem.c:2934:18 atos-tools#9 0x721305a9 in address_space_rw softmmu/physmem.c:2962:16 atos-tools#10 0x7175a392 in dma_memory_rw_relaxed include/sysemu/dma.h:89:12 atos-tools#11 0x7175a0ea in dma_memory_rw include/sysemu/dma.h:132:12 atos-tools#12 0x71759684 in dma_memory_read include/sysemu/dma.h:152:12 atos-tools#13 0x7175518c in sdhci_do_adma hw/sd/sdhci.c:823:27 atos-tools#14 0x7174bf69 in sdhci_data_transfer hw/sd/sdhci.c:935:13 atos-tools#15 0x7176aaa7 in sdhci_send_command hw/sd/sdhci.c:376:9 atos-tools#16 0x717629ee in sdhci_write hw/sd/sdhci.c:1212:9 atos-tools#17 0x72172513 in memory_region_write_accessor softmmu/memory.c:492:5 atos-tools#18 0x72171e51 in access_with_adjusted_size softmmu/memory.c:554:18 atos-tools#19 0x72170766 in memory_region_dispatch_write softmmu/memory.c:1504:16 atos-tools#20 0x721419ee in flatview_write_continue softmmu/physmem.c:2812:23 atos-tools#21 0x721301eb in flatview_write softmmu/physmem.c:2854:12 atos-tools#22 0x7212fca8 in address_space_write softmmu/physmem.c:2950:18 qemu#23 0x721d9a53 in qtest_process_command softmmu/qtest.c:727:9 A DMA descriptor is previously filled in RAM. An I/O access to the device (frames atos-tools#22 to atos-tools#16) start the DMA engine (frame atos-tools#13). The engine fetch the descriptor and execute the request, which itself accesses the SDHCI I/O registers (frame atos-tools#1 and #0), triggering a re-entrancy issue. Fix by prohibit transactions from the DMA to devices. The DMA engine is thus restricted to memories. Reported-by: OSS-Fuzz (Issue 36391) Signed-off-by: Philippe Mathieu-Daudé <[email protected]> Reviewed-by: Thomas Huth <[email protected]> Resolves: https://gitlab.com/qemu-project/qemu/-/issues/451 Message-Id: <[email protected]> Signed-off-by: Thomas Huth <[email protected]>
Include the qtest reproducer provided by Alexander Bulekov in https://gitlab.com/qemu-project/qemu/-/issues/451. Without the previous commit, we get: $ make check-qtest-i386 ... Running test qtest-i386/fuzz-sdcard-test ==447470==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x61500002a080 at pc 0x564c71766d48 bp 0x7ffc126c62b0 sp 0x7ffc126c62a8 READ of size 1 at 0x61500002a080 thread T0 #0 0x564c71766d47 in sdhci_read_dataport hw/sd/sdhci.c:474:18 atos-tools#1 0x564c7175f139 in sdhci_read hw/sd/sdhci.c:1022:19 atos-tools#2 0x564c721b937b in memory_region_read_accessor softmmu/memory.c:440:11 atos-tools#3 0x564c72171e51 in access_with_adjusted_size softmmu/memory.c:554:18 atos-tools#4 0x564c7216f47c in memory_region_dispatch_read1 softmmu/memory.c:1424:16 atos-tools#5 0x564c7216ebb9 in memory_region_dispatch_read softmmu/memory.c:1452:9 atos-tools#6 0x564c7212db5d in flatview_read_continue softmmu/physmem.c:2879:23 atos-tools#7 0x564c7212f958 in flatview_read softmmu/physmem.c:2921:12 atos-tools#8 0x564c7212f418 in address_space_read_full softmmu/physmem.c:2934:18 atos-tools#9 0x564c721305a9 in address_space_rw softmmu/physmem.c:2962:16 atos-tools#10 0x564c7175a392 in dma_memory_rw_relaxed include/sysemu/dma.h:89:12 atos-tools#11 0x564c7175a0ea in dma_memory_rw include/sysemu/dma.h:132:12 atos-tools#12 0x564c71759684 in dma_memory_read include/sysemu/dma.h:152:12 atos-tools#13 0x564c7175518c in sdhci_do_adma hw/sd/sdhci.c:823:27 atos-tools#14 0x564c7174bf69 in sdhci_data_transfer hw/sd/sdhci.c:935:13 atos-tools#15 0x564c7176aaa7 in sdhci_send_command hw/sd/sdhci.c:376:9 atos-tools#16 0x564c717629ee in sdhci_write hw/sd/sdhci.c:1212:9 atos-tools#17 0x564c72172513 in memory_region_write_accessor softmmu/memory.c:492:5 atos-tools#18 0x564c72171e51 in access_with_adjusted_size softmmu/memory.c:554:18 atos-tools#19 0x564c72170766 in memory_region_dispatch_write softmmu/memory.c:1504:16 atos-tools#20 0x564c721419ee in flatview_write_continue softmmu/physmem.c:2812:23 atos-tools#21 0x564c721301eb in flatview_write softmmu/physmem.c:2854:12 atos-tools#22 0x564c7212fca8 in address_space_write softmmu/physmem.c:2950:18 qemu#23 0x564c721d9a53 in qtest_process_command softmmu/qtest.c:727:9 0x61500002a080 is located 0 bytes to the right of 512-byte region [0x615000029e80,0x61500002a080) allocated by thread T0 here: #0 0x564c708e1737 in __interceptor_calloc (qemu-system-i386+0x1e6a737) atos-tools#1 0x7ff05567b5e0 in g_malloc0 (/lib64/libglib-2.0.so.0+0x5a5e0) atos-tools#2 0x564c71774adb in sdhci_pci_realize hw/sd/sdhci-pci.c:36:5 SUMMARY: AddressSanitizer: heap-buffer-overflow hw/sd/sdhci.c:474:18 in sdhci_read_dataport Shadow bytes around the buggy address: 0x0c2a7fffd3c0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c2a7fffd3d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x0c2a7fffd3e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x0c2a7fffd3f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x0c2a7fffd400: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 =>0x0c2a7fffd410:[fa]fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c2a7fffd420: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd 0x0c2a7fffd430: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd 0x0c2a7fffd440: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd 0x0c2a7fffd450: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd 0x0c2a7fffd460: 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 Heap left redzone: fa Freed heap region: fd ==447470==ABORTING Broken pipe ERROR qtest-i386/fuzz-sdcard-test - too few tests run (expected 3, got 2) Signed-off-by: Philippe Mathieu-Daudé <[email protected]> Acked-by: Thomas Huth <[email protected]> Message-Id: <[email protected]> [thuth: Replaced "-m 4G" with "-m 512M"] Signed-off-by: Thomas Huth <[email protected]>
I see that the comments said it is "called after block was executed" and not quite understand. It seems is called in "before_gen_tb", which is executed before a block? Is it because it uses "tcg_gen_callN" to generate code in on_block_executed so it waits until a block is executed?
I also don't understand the differences between on_block_transition and on_block_executed. Can someone help me please ?
I'm trying to implement a hook on functions like malloc using this plugin, so I think I should use "pre_tb_helper_code", right? Thanks for your help !
The text was updated successfully, but these errors were encountered: