The test executes a non-existent syscall, which the syscall plugin intercepts and redirects to a clean exit. Due to architecture-specific quirks, the Makefile requires setting specific compiler and linker flags for some architectures.
Signed-off-by: Florian Hofhammer <[email protected]> --- tests/tcg/multiarch/Makefile.target | 42 +++++++++++++++++++ .../tcg/multiarch/test-plugin-skip-syscalls.c | 26 ++++++++++++ tests/tcg/plugins/syscall.c | 6 +++ 3 files changed, 74 insertions(+) create mode 100644 tests/tcg/multiarch/test-plugin-skip-syscalls.c diff --git a/tests/tcg/multiarch/Makefile.target b/tests/tcg/multiarch/Makefile.target index f5b4d2b813..7df3da2aba 100644 --- a/tests/tcg/multiarch/Makefile.target +++ b/tests/tcg/multiarch/Makefile.target @@ -204,6 +204,48 @@ run-plugin-test-plugin-mem-access-with-libmem.so: \ $(QEMU) $< EXTRA_RUNS_WITH_PLUGIN += run-plugin-test-plugin-mem-access-with-libmem.so + +# Test plugin control flow redirection by skipping system calls +ifeq ($(TARGET),arm-linux-user) +# Require emitting arm32 instructions, otherwise the vCPU might accidentally +# try to execute Thumb instructions in arm32 mode after qemu_plugin_set_pc() +test-plugin-skip-syscalls: CFLAGS+=-marm +endif +ifneq ($(filter mips64%-linux-user,$(TARGET)),) +# Require no ABI calls to avoid $t9-relative .got address calculation +test-plugin-skip-syscalls: CFLAGS+=-mno-abicalls -fno-pie +test-plugin-skip-syscalls: LDFLAGS+=-no-pie +endif +ifneq ($(filter mips%-linux-user,\ + $(filter-out mips64%-linux-user,\ + $(TARGET))),) +# qemu-mips(el) returns ENOSYS without triggering syscall plugin callbacks +run-plugin-test-plugin-skip-syscalls-with-libsyscall.so: + $(call skip-test, $<, "qemu-mips(el) does not execute invalid syscalls") +endif +ifeq ($(TARGET),sparc64-linux-user) +# The defined addresses for the binary are not aligned correctly for sparc64 +# but adjusting them breaks other architectures, so just skip it on sparc64. +run-plugin-test-plugin-skip-syscalls-with-libsyscall.so: + $(call skip-test, $<, "qemu-sparc64 does not allow mapping at our given fixed address") +endif +ifeq ($(TARGET),hexagon-linux-user) +# hexagon uses clang/lld which does not support -Ttext-segment but GNU ld does +# not generally support --image-base. +test-plugin-skip-syscalls: LDFLAGS+=-Wl,--image-base=0x40000 +else +test-plugin-skip-syscalls: LDFLAGS+=-Wl,-Ttext-segment=0x40000 +endif +test-plugin-skip-syscalls: LDFLAGS+=-Wl,--section-start,.redirect=0x20000 +run-plugin-test-plugin-skip-syscalls-with-libsyscall.so: + +EXTRA_RUNS_WITH_PLUGIN += run-plugin-test-plugin-skip-syscalls-with-libsyscall.so + +else # CONFIG_PLUGIN=n +# Do not build the syscall skipping test if it's not tested with a plugin +# because it will simply return an error and fail the test. +MULTIARCH_TESTS := $(filter-out "test-plugin-skip-syscalls", $(MULTIARCH_TESTS)) + endif # Update TESTS diff --git a/tests/tcg/multiarch/test-plugin-skip-syscalls.c b/tests/tcg/multiarch/test-plugin-skip-syscalls.c new file mode 100644 index 0000000000..1f5cbc3851 --- /dev/null +++ b/tests/tcg/multiarch/test-plugin-skip-syscalls.c @@ -0,0 +1,26 @@ +/* + * SPDX-License-Identifier: GPL-2.0-or-later + * + * This test attempts to execute an invalid syscall. The syscall test plugin + * should intercept this. + */ +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + +void exit_success(void) __attribute__((section(".redirect"), noinline, + noreturn, used)); + +void exit_success(void) { + _exit(EXIT_SUCCESS); +} + +int main(int argc, char *argv[]) { + long ret = syscall(0xc0deUL); + if (ret != 0L) { + perror(""); + } + /* We should never get here */ + return EXIT_FAILURE; +} diff --git a/tests/tcg/plugins/syscall.c b/tests/tcg/plugins/syscall.c index 42801f5c86..c5bac2d928 100644 --- a/tests/tcg/plugins/syscall.c +++ b/tests/tcg/plugins/syscall.c @@ -148,6 +148,12 @@ static void vcpu_syscall(qemu_plugin_id_t id, unsigned int vcpu_index, fprintf(stderr, "Error reading memory from vaddr %"PRIu64"\n", a2); } } + + if (num == 0xc0deUL) { + /* Special syscall to test the control flow redirection functionality. */ + qemu_plugin_outs("Marker syscall detected, jump to clean exit\n"); + qemu_plugin_set_pc(0x20000); + } } static void vcpu_syscall_ret(qemu_plugin_id_t id, unsigned int vcpu_idx, -- 2.51.0
