* [PATCH v2 0/2] linux-user: add a syscall-filter plugin API @ 2025-12-12 14:15 Ziyang Zhang 2025-12-12 14:15 ` [PATCH v2 1/2] linux-user: add a plugin API to filter syscalls Ziyang Zhang 2025-12-12 14:15 ` [PATCH v2 2/2] tcg tests: add a test to verify the syscall filter plugin API Ziyang Zhang 0 siblings, 2 replies; 5+ messages in thread From: Ziyang Zhang @ 2025-12-12 14:15 UTC (permalink / raw) To: qemu-devel Cc: Riku Voipio, Laurent Vivier, Alex Bennee, Alexandre Iooss, Mahmoud Mandour, Pierrick Bouvier, Richard Henderson, Zhengwei Qi, Yun Wang, Mingyuan Xia, Kailiang Xu, Ziyang Zhang We have resolved the merge conflict of the PATCH v1 [1], rebased on the latest (9c23f2a7b0b45277693a14074b1aaa827eecdb92). PATCH v2: 1. Rebased on newest version of master PATCH v1: 1. Format the code RFC v2: 1. Simplify the syscall filter mechanism and remove fork-cpu 2. Add QEMU_PLUGIN_EV_VCPU_SYSCALL_FILTER enum RFC v1: 1. Add syscall filter registry 2. Add fork-cpu interface to re-enter cpu_loop when handling syscalls [1] https://lore.kernel.org/qemu-devel/20251110133442.579086-1-functioner@sjtu.edu.cn/ Ziyang Zhang (2): linux-user: add a plugin API to filter syscalls tcg tests: add a test to verify the syscall filter plugin API include/qemu/plugin-event.h | 1 + include/qemu/plugin.h | 31 +++++++++++----- include/qemu/qemu-plugin.h | 24 +++++++++++++ include/user/syscall-trace.h | 17 +++++++++ linux-user/syscall.c | 7 ++-- plugins/api.c | 7 ++++ plugins/core.c | 36 +++++++++++++++++++ tests/tcg/multiarch/Makefile.target | 4 ++- .../multiarch/test-plugin-syscall-filter.c | 20 +++++++++++ tests/tcg/plugins/syscall.c | 15 ++++++++ 10 files changed, 150 insertions(+), 12 deletions(-) create mode 100644 tests/tcg/multiarch/test-plugin-syscall-filter.c -- 2.34.1 ^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH v2 1/2] linux-user: add a plugin API to filter syscalls 2025-12-12 14:15 [PATCH v2 0/2] linux-user: add a syscall-filter plugin API Ziyang Zhang @ 2025-12-12 14:15 ` Ziyang Zhang 2025-12-12 14:15 ` [PATCH v2 2/2] tcg tests: add a test to verify the syscall filter plugin API Ziyang Zhang 1 sibling, 0 replies; 5+ messages in thread From: Ziyang Zhang @ 2025-12-12 14:15 UTC (permalink / raw) To: qemu-devel Cc: Riku Voipio, Laurent Vivier, Alex Bennee, Alexandre Iooss, Mahmoud Mandour, Pierrick Bouvier, Richard Henderson, Zhengwei Qi, Yun Wang, Mingyuan Xia, Kailiang Xu, Ziyang Zhang This commit adds a syscall filter API to the TCG plugin API set. Plugins can register a filter callback to QEMU to decide whether to intercept a syscall, process it and bypass the QEMU syscall handler. Signed-off-by: Ziyang Zhang <functioner@sjtu.edu.cn> Co-authored-by: Mingyuan Xia <xiamy@ultrarisc.com> --- include/qemu/plugin-event.h | 1 + include/qemu/plugin.h | 31 ++++++++++++++++++++++--------- include/qemu/qemu-plugin.h | 24 ++++++++++++++++++++++++ include/user/syscall-trace.h | 17 +++++++++++++++++ linux-user/syscall.c | 7 +++++-- plugins/api.c | 7 +++++++ plugins/core.c | 36 ++++++++++++++++++++++++++++++++++++ 7 files changed, 112 insertions(+), 11 deletions(-) diff --git a/include/qemu/plugin-event.h b/include/qemu/plugin-event.h index 1100dae212..7f3c5927f1 100644 --- a/include/qemu/plugin-event.h +++ b/include/qemu/plugin-event.h @@ -23,6 +23,7 @@ enum qemu_plugin_event { QEMU_PLUGIN_EV_VCPU_INTERRUPT, QEMU_PLUGIN_EV_VCPU_EXCEPTION, QEMU_PLUGIN_EV_VCPU_HOSTCALL, + QEMU_PLUGIN_EV_VCPU_SYSCALL_FILTER, QEMU_PLUGIN_EV_MAX, /* total number of plugin events we support */ }; diff --git a/include/qemu/plugin.h b/include/qemu/plugin.h index cea0a68858..4eb8612cb9 100644 --- a/include/qemu/plugin.h +++ b/include/qemu/plugin.h @@ -55,15 +55,16 @@ void qemu_plugin_opt_parse(const char *optstr, QemuPluginList *head); int qemu_plugin_load_list(QemuPluginList *head, Error **errp); union qemu_plugin_cb_sig { - qemu_plugin_simple_cb_t simple; - qemu_plugin_udata_cb_t udata; - qemu_plugin_vcpu_simple_cb_t vcpu_simple; - qemu_plugin_vcpu_udata_cb_t vcpu_udata; - qemu_plugin_vcpu_discon_cb_t vcpu_discon; - qemu_plugin_vcpu_tb_trans_cb_t vcpu_tb_trans; - qemu_plugin_vcpu_mem_cb_t vcpu_mem; - qemu_plugin_vcpu_syscall_cb_t vcpu_syscall; - qemu_plugin_vcpu_syscall_ret_cb_t vcpu_syscall_ret; + qemu_plugin_simple_cb_t simple; + qemu_plugin_udata_cb_t udata; + qemu_plugin_vcpu_simple_cb_t vcpu_simple; + qemu_plugin_vcpu_udata_cb_t vcpu_udata; + qemu_plugin_vcpu_discon_cb_t vcpu_discon; + qemu_plugin_vcpu_tb_trans_cb_t vcpu_tb_trans; + qemu_plugin_vcpu_mem_cb_t vcpu_mem; + qemu_plugin_vcpu_syscall_cb_t vcpu_syscall; + qemu_plugin_vcpu_syscall_ret_cb_t vcpu_syscall_ret; + qemu_plugin_vcpu_syscall_filter_cb_t vcpu_syscall_filter; void *generic; }; @@ -169,6 +170,11 @@ qemu_plugin_vcpu_syscall(CPUState *cpu, int64_t num, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5, uint64_t a6, uint64_t a7, uint64_t a8); void qemu_plugin_vcpu_syscall_ret(CPUState *cpu, int64_t num, int64_t ret); +bool +qemu_plugin_vcpu_syscall_filter(CPUState *cpu, int64_t num, uint64_t a1, + uint64_t a2, uint64_t a3, uint64_t a4, + uint64_t a5, uint64_t a6, uint64_t a7, + uint64_t a8, uint64_t *ret); void qemu_plugin_vcpu_mem_cb(CPUState *cpu, uint64_t vaddr, uint64_t value_low, @@ -280,6 +286,13 @@ static inline void qemu_plugin_vcpu_syscall_ret(CPUState *cpu, int64_t num, int64_t ret) { } +static inline bool +qemu_plugin_vcpu_syscall_filter(CPUState *cpu, int64_t num, uint64_t a1, + uint64_t a2, uint64_t a3, uint64_t a4, + uint64_t a5, uint64_t a6, uint64_t a7, + uint64_t a8, uint64_t *ret) +{ } + static inline void qemu_plugin_vcpu_mem_cb(CPUState *cpu, uint64_t vaddr, uint64_t value_low, uint64_t value_high, diff --git a/include/qemu/qemu-plugin.h b/include/qemu/qemu-plugin.h index 60de4fdd3f..b70049c80c 100644 --- a/include/qemu/qemu-plugin.h +++ b/include/qemu/qemu-plugin.h @@ -798,6 +798,25 @@ typedef void uint64_t a3, uint64_t a4, uint64_t a5, uint64_t a6, uint64_t a7, uint64_t a8); +/* + * typedef qemu_plugin_vcpu_syscall_filter_cb_t - vCPU syscall filter callback + * function type + * @vcpu_index: the executing vCPU + * @num: the syscall number + * @a1-a8: the syscall arguments + * @ret: the address of the syscall return value, set this if filtered + * + * Returns: true if you want to filter this syscall (i.e. stop it being + * handled further), otherwise return false. + */ +typedef bool +(*qemu_plugin_vcpu_syscall_filter_cb_t)(qemu_plugin_id_t id, + unsigned int vcpu_index, + int64_t num, uint64_t a1, uint64_t a2, + uint64_t a3, uint64_t a4, uint64_t a5, + uint64_t a6, uint64_t a7, uint64_t a8, + uint64_t *ret); + QEMU_PLUGIN_API void qemu_plugin_register_vcpu_syscall_cb(qemu_plugin_id_t id, qemu_plugin_vcpu_syscall_cb_t cb); @@ -811,6 +830,11 @@ void qemu_plugin_register_vcpu_syscall_ret_cb(qemu_plugin_id_t id, qemu_plugin_vcpu_syscall_ret_cb_t cb); +QEMU_PLUGIN_API +void +qemu_plugin_register_vcpu_syscall_filter_cb(qemu_plugin_id_t id, + qemu_plugin_vcpu_syscall_filter_cb_t cb); + /** * qemu_plugin_insn_disas() - return disassembly string for instruction diff --git a/include/user/syscall-trace.h b/include/user/syscall-trace.h index 9bd7ca19c8..61cdbd7583 100644 --- a/include/user/syscall-trace.h +++ b/include/user/syscall-trace.h @@ -39,5 +39,22 @@ static inline void record_syscall_return(CPUState *cpu, int num, abi_long ret) gdb_syscall_return(cpu, num); } +static bool send_through_syscall_filters(CPUState *cpu, int num, + abi_long arg1, abi_long arg2, + abi_long arg3, abi_long arg4, + abi_long arg5, abi_long arg6, + abi_long arg7, abi_long arg8, + abi_long *ret) +{ + uint64_t sysret64 = 0; + bool filtered = qemu_plugin_vcpu_syscall_filter(cpu, num, arg1, arg2, + arg3, arg4, arg5, arg6, + arg7, arg8, &sysret64); + if (filtered) { + *ret = sysret64; + } + return filtered; +} + #endif /* SYSCALL_TRACE_H */ diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 2060e561a2..9ae3c5bfbd 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -14201,8 +14201,11 @@ abi_long do_syscall(CPUArchState *cpu_env, int num, abi_long arg1, print_syscall(cpu_env, num, arg1, arg2, arg3, arg4, arg5, arg6); } - ret = do_syscall1(cpu_env, num, arg1, arg2, arg3, arg4, - arg5, arg6, arg7, arg8); + if (!send_through_syscall_filters(cpu, num, arg1, arg2, arg3, arg4, arg5, + arg6, arg7, arg8, &ret)) { + ret = do_syscall1(cpu_env, num, arg1, arg2, arg3, arg4, + arg5, arg6, arg7, arg8); + } if (unlikely(qemu_loglevel_mask(LOG_STRACE))) { print_syscall_ret(cpu_env, num, ret, arg1, arg2, diff --git a/plugins/api.c b/plugins/api.c index eac04cc1f6..478d0c8889 100644 --- a/plugins/api.c +++ b/plugins/api.c @@ -208,6 +208,13 @@ qemu_plugin_register_vcpu_syscall_ret_cb(qemu_plugin_id_t id, plugin_register_cb(id, QEMU_PLUGIN_EV_VCPU_SYSCALL_RET, cb); } +void +qemu_plugin_register_vcpu_syscall_filter_cb(qemu_plugin_id_t id, + qemu_plugin_vcpu_syscall_filter_cb_t cb) +{ + plugin_register_cb(id, QEMU_PLUGIN_EV_VCPU_SYSCALL_FILTER, cb); +} + /* * Plugin Queries * diff --git a/plugins/core.c b/plugins/core.c index b4b783008f..de82d0f5d6 100644 --- a/plugins/core.c +++ b/plugins/core.c @@ -564,6 +564,42 @@ void qemu_plugin_vcpu_syscall_ret(CPUState *cpu, int64_t num, int64_t ret) } } +/* + * Disable CFI checks. + * The callback function has been loaded from an external library so we do not + * have type information + */ +QEMU_DISABLE_CFI +bool +qemu_plugin_vcpu_syscall_filter(CPUState *cpu, int64_t num, uint64_t a1, + uint64_t a2, uint64_t a3, uint64_t a4, + uint64_t a5, uint64_t a6, uint64_t a7, + uint64_t a8, uint64_t *ret) +{ + struct qemu_plugin_cb *cb, *next; + enum qemu_plugin_event ev = QEMU_PLUGIN_EV_VCPU_SYSCALL_FILTER; + + if (!test_bit(ev, cpu->plugin_state->event_mask)) { + return false; + } + + bool filtered = false; + QLIST_FOREACH_SAFE_RCU(cb, &plugin.cb_lists[ev], entry, next) { + qemu_plugin_vcpu_syscall_filter_cb_t func = cb->f.vcpu_syscall_filter; + + qemu_plugin_set_cb_flags(cpu, QEMU_PLUGIN_CB_RW_REGS); + if (func(cb->ctx->id, cpu->cpu_index, num, a1, a2, a3, a4, + a5, a6, a7, a8, ret)) { + filtered = true; + } + qemu_plugin_set_cb_flags(cpu, QEMU_PLUGIN_CB_NO_REGS); + + if (filtered) + break; + } + return filtered; +} + void qemu_plugin_vcpu_idle_cb(CPUState *cpu) { /* idle and resume cb may be called before init, ignore in this case */ -- 2.34.1 ^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH v2 2/2] tcg tests: add a test to verify the syscall filter plugin API 2025-12-12 14:15 [PATCH v2 0/2] linux-user: add a syscall-filter plugin API Ziyang Zhang 2025-12-12 14:15 ` [PATCH v2 1/2] linux-user: add a plugin API to filter syscalls Ziyang Zhang @ 2025-12-12 14:15 ` Ziyang Zhang 2025-12-12 16:00 ` Alex Bennée 1 sibling, 1 reply; 5+ messages in thread From: Ziyang Zhang @ 2025-12-12 14:15 UTC (permalink / raw) To: qemu-devel Cc: Riku Voipio, Laurent Vivier, Alex Bennee, Alexandre Iooss, Mahmoud Mandour, Pierrick Bouvier, Richard Henderson, Zhengwei Qi, Yun Wang, Mingyuan Xia, Kailiang Xu, Ziyang Zhang Register a syscall filter callback in tests/tcg/plugins/sycall.c, returns a specific value for a magic system call number, and check it in tests/tcg/multiarch/test-plugin-syscall-filter.c. Signed-off-by: Ziyang Zhang <functioner@sjtu.edu.cn> Co-authored-by: Mingyuan Xia <xiamy@ultrarisc.com> --- tests/tcg/multiarch/Makefile.target | 4 +++- .../multiarch/test-plugin-syscall-filter.c | 20 +++++++++++++++++++ tests/tcg/plugins/syscall.c | 15 ++++++++++++++ 3 files changed, 38 insertions(+), 1 deletion(-) create mode 100644 tests/tcg/multiarch/test-plugin-syscall-filter.c diff --git a/tests/tcg/multiarch/Makefile.target b/tests/tcg/multiarch/Makefile.target index f5b4d2b813..4005e3a8a9 100644 --- a/tests/tcg/multiarch/Makefile.target +++ b/tests/tcg/multiarch/Makefile.target @@ -202,8 +202,10 @@ run-plugin-test-plugin-mem-access-with-libmem.so: \ CHECK_PLUGIN_OUTPUT_COMMAND= \ $(SRC_PATH)/tests/tcg/multiarch/check-plugin-output.sh \ $(QEMU) $< +run-plugin-test-plugin-syscall-filter-with-libsyscall.so: -EXTRA_RUNS_WITH_PLUGIN += run-plugin-test-plugin-mem-access-with-libmem.so +EXTRA_RUNS_WITH_PLUGIN += run-plugin-test-plugin-mem-access-with-libmem.so \ + run-plugin-test-plugin-syscall-filter-with-libsyscall.so endif # Update TESTS diff --git a/tests/tcg/multiarch/test-plugin-syscall-filter.c b/tests/tcg/multiarch/test-plugin-syscall-filter.c new file mode 100644 index 0000000000..cc694e0a71 --- /dev/null +++ b/tests/tcg/multiarch/test-plugin-syscall-filter.c @@ -0,0 +1,20 @@ +/* + * SPDX-License-Identifier: GPL-2.0-or-later + * + * This test attempts to execute a magic syscall. The syscall test plugin + * should intercept this and returns an expected value. + */ + +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + +int main(int argc, char *argv[]) { + long ret = syscall(0x66CCFF); + if (ret != 0xFFCC66) { + perror("ERROR: syscall returned unexpected value!!!"); + return EXIT_FAILURE; + } + return EXIT_SUCCESS; +} \ No newline at end of file diff --git a/tests/tcg/plugins/syscall.c b/tests/tcg/plugins/syscall.c index 42801f5c86..1323e18bc0 100644 --- a/tests/tcg/plugins/syscall.c +++ b/tests/tcg/plugins/syscall.c @@ -170,6 +170,20 @@ static void vcpu_syscall_ret(qemu_plugin_id_t id, unsigned int vcpu_idx, } } +static bool vcpu_syscall_filter(qemu_plugin_id_t id, unsigned int vcpu_index, + int64_t num, uint64_t a1, uint64_t a2, + uint64_t a3, uint64_t a4, uint64_t a5, + uint64_t a6, uint64_t a7, uint64_t a8, + uint64_t *ret) +{ + if (num == 0x66CCFF) { + *ret = 0xFFCC66; + qemu_plugin_outs("syscall 0x66CCFF filtered, ret=0xFFCC66\n"); + return true; + } + return false; +} + static void print_entry(gpointer val, gpointer user_data) { SyscallStats *entry = (SyscallStats *) val; @@ -255,6 +269,7 @@ QEMU_PLUGIN_EXPORT int qemu_plugin_install(qemu_plugin_id_t id, qemu_plugin_register_vcpu_syscall_cb(id, vcpu_syscall); qemu_plugin_register_vcpu_syscall_ret_cb(id, vcpu_syscall_ret); + qemu_plugin_register_vcpu_syscall_filter_cb(id, vcpu_syscall_filter); qemu_plugin_register_atexit_cb(id, plugin_exit, NULL); return 0; } -- 2.34.1 ^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH v2 2/2] tcg tests: add a test to verify the syscall filter plugin API 2025-12-12 14:15 ` [PATCH v2 2/2] tcg tests: add a test to verify the syscall filter plugin API Ziyang Zhang @ 2025-12-12 16:00 ` Alex Bennée 2025-12-12 17:32 ` Pierrick Bouvier 0 siblings, 1 reply; 5+ messages in thread From: Alex Bennée @ 2025-12-12 16:00 UTC (permalink / raw) To: Ziyang Zhang Cc: qemu-devel, Riku Voipio, Laurent Vivier, Alexandre Iooss, Mahmoud Mandour, Pierrick Bouvier, Richard Henderson, Zhengwei Qi, Yun Wang, Mingyuan Xia, Kailiang Xu Ziyang Zhang <functioner@sjtu.edu.cn> writes: > Register a syscall filter callback in tests/tcg/plugins/sycall.c, > returns a specific value for a magic system call number, and check > it in tests/tcg/multiarch/test-plugin-syscall-filter.c. > > Signed-off-by: Ziyang Zhang <functioner@sjtu.edu.cn> > Co-authored-by: Mingyuan Xia <xiamy@ultrarisc.com> > --- > tests/tcg/multiarch/Makefile.target | 4 +++- > .../multiarch/test-plugin-syscall-filter.c | 20 +++++++++++++++++++ > tests/tcg/plugins/syscall.c | 15 ++++++++++++++ > 3 files changed, 38 insertions(+), 1 deletion(-) > create mode 100644 tests/tcg/multiarch/test-plugin-syscall-filter.c > > diff --git a/tests/tcg/multiarch/Makefile.target b/tests/tcg/multiarch/Makefile.target > index f5b4d2b813..4005e3a8a9 100644 > --- a/tests/tcg/multiarch/Makefile.target > +++ b/tests/tcg/multiarch/Makefile.target > @@ -202,8 +202,10 @@ run-plugin-test-plugin-mem-access-with-libmem.so: \ > CHECK_PLUGIN_OUTPUT_COMMAND= \ > $(SRC_PATH)/tests/tcg/multiarch/check-plugin-output.sh \ > $(QEMU) $< > +run-plugin-test-plugin-syscall-filter-with-libsyscall.so: > > -EXTRA_RUNS_WITH_PLUGIN += run-plugin-test-plugin-mem-access-with-libmem.so > +EXTRA_RUNS_WITH_PLUGIN += run-plugin-test-plugin-mem-access-with-libmem.so \ > + run-plugin-test-plugin-syscall-filter-with-libsyscall.so > endif > > # Update TESTS > diff --git a/tests/tcg/multiarch/test-plugin-syscall-filter.c b/tests/tcg/multiarch/test-plugin-syscall-filter.c > new file mode 100644 > index 0000000000..cc694e0a71 > --- /dev/null > +++ b/tests/tcg/multiarch/test-plugin-syscall-filter.c > @@ -0,0 +1,20 @@ > +/* > + * SPDX-License-Identifier: GPL-2.0-or-later > + * > + * This test attempts to execute a magic syscall. The syscall test plugin > + * should intercept this and returns an expected value. > + */ > + > +#include <stdint.h> > +#include <stdio.h> > +#include <stdlib.h> > +#include <unistd.h> > + > +int main(int argc, char *argv[]) { > + long ret = syscall(0x66CCFF); > + if (ret != 0xFFCC66) { > + perror("ERROR: syscall returned unexpected value!!!"); > + return EXIT_FAILURE; > + } > + return EXIT_SUCCESS; > +} This breaks some arches: (gdb) r Starting program: /home/alex/lsrc/qemu.git/builds/sanitisers/qemu-arm -plugin tests/tcg/plugins/libsyscall.so -d plugin ./tests/tcg/arm-linux-user/test-plugin-syscall-filter [New Thread 0x7ffff37ff6c0 (LWP 63692)] qemu: uncaught target signal 4 (Illegal instruction) - core dumped syscall no. calls errors 45 5 0 338 1 1 256 1 0 191 1 0 398 1 1 125 1 0 384 1 0 332 1 0 Thread 1 "qemu-arm" received signal SIGILL, Illegal instruction. Download failed: Invalid argument. Continuing without source file ./nptl/../sysdeps/unix/sysv/linux/x86_64/syscall_cancel.S. __syscall_cancel_arch () at ../sysdeps/unix/sysv/linux/x86_64/syscall_cancel.S:56 warning: 56 ../sysdeps/unix/sysv/linux/x86_64/syscall_cancel.S: No such file or directory (gdb) bt #0 __syscall_cancel_arch () at ../sysdeps/unix/sysv/linux/x86_64/syscall_cancel.S:56 #1 0x00007ffff6a51668 in __internal_syscall_cancel (a1=<optimized out>, a2=a2@entry=8, a3=a3@entry=0, a4=a4@entry=0, a5=a5@entry=0, a6=a6@entry=0, nr=130) at ./nptl/cancellation.c:49 #2 0x00007ffff6a516ad in __syscall_cancel (a1=<optimized out>, a2=a2@entry=8, a3=a3@entry=0, a4=a4@entry=0, a5=a5@entry=0, a6=a6@entry=0, nr=130) at ./nptl/cancellation.c:75 #3 0x00007ffff6a0207d in __GI___sigsuspend (set=<optimized out>) at ../sysdeps/unix/sysv/linux/sigsuspend.c:26 #4 0x0000555555a49b80 in die_with_signal (host_sig=4) at ../../linux-user/signal.c:807 #5 0x0000555555a49ed0 in dump_core_and_abort (env=0x532000004300, target_sig=4) at ../../linux-user/signal.c:847 #6 0x0000555555a4c969 in handle_pending_signal (cpu_env=0x532000004300, sig=4, k=0x5250000029d0) at ../../linux-user/signal.c:1306 #7 0x0000555555a4d0e5 in process_pending_signals (cpu_env=0x532000004300) at ../../linux-user/signal.c:1386 #8 0x0000555555873930 in cpu_loop (env=0x532000004300) at ../../linux-user/arm/cpu_loop.c:479 #9 0x0000555555a3eca7 in main (argc=6, argv=0x7fffffffe588, envp=0x7fffffffe5c0) at ../../linux-user/main.c:1035 (gdb) > \ No newline at end of file > diff --git a/tests/tcg/plugins/syscall.c b/tests/tcg/plugins/syscall.c > index 42801f5c86..1323e18bc0 100644 > --- a/tests/tcg/plugins/syscall.c > +++ b/tests/tcg/plugins/syscall.c > @@ -170,6 +170,20 @@ static void vcpu_syscall_ret(qemu_plugin_id_t id, unsigned int vcpu_idx, > } > } > > +static bool vcpu_syscall_filter(qemu_plugin_id_t id, unsigned int vcpu_index, > + int64_t num, uint64_t a1, uint64_t a2, > + uint64_t a3, uint64_t a4, uint64_t a5, > + uint64_t a6, uint64_t a7, uint64_t a8, > + uint64_t *ret) > +{ > + if (num == 0x66CCFF) { > + *ret = 0xFFCC66; > + qemu_plugin_outs("syscall 0x66CCFF filtered, ret=0xFFCC66\n"); > + return true; > + } > + return false; > +} > + > static void print_entry(gpointer val, gpointer user_data) > { > SyscallStats *entry = (SyscallStats *) val; > @@ -255,6 +269,7 @@ QEMU_PLUGIN_EXPORT int qemu_plugin_install(qemu_plugin_id_t id, > > qemu_plugin_register_vcpu_syscall_cb(id, vcpu_syscall); > qemu_plugin_register_vcpu_syscall_ret_cb(id, vcpu_syscall_ret); > + qemu_plugin_register_vcpu_syscall_filter_cb(id, vcpu_syscall_filter); > qemu_plugin_register_atexit_cb(id, plugin_exit, NULL); > return 0; > } -- Alex Bennée Virtualisation Tech Lead @ Linaro ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH v2 2/2] tcg tests: add a test to verify the syscall filter plugin API 2025-12-12 16:00 ` Alex Bennée @ 2025-12-12 17:32 ` Pierrick Bouvier 0 siblings, 0 replies; 5+ messages in thread From: Pierrick Bouvier @ 2025-12-12 17:32 UTC (permalink / raw) To: Alex Bennée, Ziyang Zhang Cc: qemu-devel, Riku Voipio, Laurent Vivier, Alexandre Iooss, Mahmoud Mandour, Richard Henderson, Zhengwei Qi, Yun Wang, Mingyuan Xia, Kailiang Xu On 12/12/25 8:00 AM, Alex Bennée wrote: > Ziyang Zhang <functioner@sjtu.edu.cn> writes: > >> Register a syscall filter callback in tests/tcg/plugins/sycall.c, >> returns a specific value for a magic system call number, and check >> it in tests/tcg/multiarch/test-plugin-syscall-filter.c. >> >> Signed-off-by: Ziyang Zhang <functioner@sjtu.edu.cn> >> Co-authored-by: Mingyuan Xia <xiamy@ultrarisc.com> >> --- >> tests/tcg/multiarch/Makefile.target | 4 +++- >> .../multiarch/test-plugin-syscall-filter.c | 20 +++++++++++++++++++ >> tests/tcg/plugins/syscall.c | 15 ++++++++++++++ >> 3 files changed, 38 insertions(+), 1 deletion(-) >> create mode 100644 tests/tcg/multiarch/test-plugin-syscall-filter.c >> >> diff --git a/tests/tcg/multiarch/Makefile.target b/tests/tcg/multiarch/Makefile.target >> index f5b4d2b813..4005e3a8a9 100644 >> --- a/tests/tcg/multiarch/Makefile.target >> +++ b/tests/tcg/multiarch/Makefile.target >> @@ -202,8 +202,10 @@ run-plugin-test-plugin-mem-access-with-libmem.so: \ >> CHECK_PLUGIN_OUTPUT_COMMAND= \ >> $(SRC_PATH)/tests/tcg/multiarch/check-plugin-output.sh \ >> $(QEMU) $< >> +run-plugin-test-plugin-syscall-filter-with-libsyscall.so: >> >> -EXTRA_RUNS_WITH_PLUGIN += run-plugin-test-plugin-mem-access-with-libmem.so >> +EXTRA_RUNS_WITH_PLUGIN += run-plugin-test-plugin-mem-access-with-libmem.so \ >> + run-plugin-test-plugin-syscall-filter-with-libsyscall.so >> endif >> >> # Update TESTS >> diff --git a/tests/tcg/multiarch/test-plugin-syscall-filter.c b/tests/tcg/multiarch/test-plugin-syscall-filter.c >> new file mode 100644 >> index 0000000000..cc694e0a71 >> --- /dev/null >> +++ b/tests/tcg/multiarch/test-plugin-syscall-filter.c >> @@ -0,0 +1,20 @@ >> +/* >> + * SPDX-License-Identifier: GPL-2.0-or-later >> + * >> + * This test attempts to execute a magic syscall. The syscall test plugin >> + * should intercept this and returns an expected value. >> + */ >> + >> +#include <stdint.h> >> +#include <stdio.h> >> +#include <stdlib.h> >> +#include <unistd.h> >> + >> +int main(int argc, char *argv[]) { >> + long ret = syscall(0x66CCFF); >> + if (ret != 0xFFCC66) { >> + perror("ERROR: syscall returned unexpected value!!!"); >> + return EXIT_FAILURE; >> + } >> + return EXIT_SUCCESS; >> +} > > This breaks some arches: > > (gdb) r > Starting program: /home/alex/lsrc/qemu.git/builds/sanitisers/qemu-arm -plugin tests/tcg/plugins/libsyscall.so -d plugin ./tests/tcg/arm-linux-user/test-plugin-syscall-filter > [New Thread 0x7ffff37ff6c0 (LWP 63692)] > qemu: uncaught target signal 4 (Illegal instruction) - core dumped > syscall no. calls errors > 45 5 0 > 338 1 1 > 256 1 0 > 191 1 0 > 398 1 1 > 125 1 0 > 384 1 0 > 332 1 0 > > Thread 1 "qemu-arm" received signal SIGILL, Illegal instruction. > Download failed: Invalid argument. Continuing without source file ./nptl/../sysdeps/unix/sysv/linux/x86_64/syscall_cancel.S. > __syscall_cancel_arch () at ../sysdeps/unix/sysv/linux/x86_64/syscall_cancel.S:56 > warning: 56 ../sysdeps/unix/sysv/linux/x86_64/syscall_cancel.S: No such file or directory > (gdb) bt > #0 __syscall_cancel_arch () at ../sysdeps/unix/sysv/linux/x86_64/syscall_cancel.S:56 > #1 0x00007ffff6a51668 in __internal_syscall_cancel (a1=<optimized out>, a2=a2@entry=8, a3=a3@entry=0, a4=a4@entry=0, a5=a5@entry=0, a6=a6@entry=0, nr=130) > at ./nptl/cancellation.c:49 > #2 0x00007ffff6a516ad in __syscall_cancel (a1=<optimized out>, a2=a2@entry=8, a3=a3@entry=0, a4=a4@entry=0, a5=a5@entry=0, a6=a6@entry=0, nr=130) > at ./nptl/cancellation.c:75 > #3 0x00007ffff6a0207d in __GI___sigsuspend (set=<optimized out>) at ../sysdeps/unix/sysv/linux/sigsuspend.c:26 > #4 0x0000555555a49b80 in die_with_signal (host_sig=4) at ../../linux-user/signal.c:807 > #5 0x0000555555a49ed0 in dump_core_and_abort (env=0x532000004300, target_sig=4) at ../../linux-user/signal.c:847 > #6 0x0000555555a4c969 in handle_pending_signal (cpu_env=0x532000004300, sig=4, k=0x5250000029d0) at ../../linux-user/signal.c:1306 > #7 0x0000555555a4d0e5 in process_pending_signals (cpu_env=0x532000004300) at ../../linux-user/signal.c:1386 > #8 0x0000555555873930 in cpu_loop (env=0x532000004300) at ../../linux-user/arm/cpu_loop.c:479 > #9 0x0000555555a3eca7 in main (argc=6, argv=0x7fffffffe588, envp=0x7fffffffe5c0) at ../../linux-user/main.c:1035 > (gdb) > >> \ No newline at end of file >> diff --git a/tests/tcg/plugins/syscall.c b/tests/tcg/plugins/syscall.c >> index 42801f5c86..1323e18bc0 100644 >> --- a/tests/tcg/plugins/syscall.c >> +++ b/tests/tcg/plugins/syscall.c >> @@ -170,6 +170,20 @@ static void vcpu_syscall_ret(qemu_plugin_id_t id, unsigned int vcpu_idx, >> } >> } >> >> +static bool vcpu_syscall_filter(qemu_plugin_id_t id, unsigned int vcpu_index, >> + int64_t num, uint64_t a1, uint64_t a2, >> + uint64_t a3, uint64_t a4, uint64_t a5, >> + uint64_t a6, uint64_t a7, uint64_t a8, >> + uint64_t *ret) >> +{ >> + if (num == 0x66CCFF) { >> + *ret = 0xFFCC66; >> + qemu_plugin_outs("syscall 0x66CCFF filtered, ret=0xFFCC66\n"); >> + return true; >> + } >> + return false; >> +} >> + >> static void print_entry(gpointer val, gpointer user_data) >> { >> SyscallStats *entry = (SyscallStats *) val; >> @@ -255,6 +269,7 @@ QEMU_PLUGIN_EXPORT int qemu_plugin_install(qemu_plugin_id_t id, >> >> qemu_plugin_register_vcpu_syscall_cb(id, vcpu_syscall); >> qemu_plugin_register_vcpu_syscall_ret_cb(id, vcpu_syscall_ret); >> + qemu_plugin_register_vcpu_syscall_filter_cb(id, vcpu_syscall_filter); >> qemu_plugin_register_atexit_cb(id, plugin_exit, NULL); >> return 0; >> } > Looks like a simple issue with 32 bits target. ^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2025-12-12 17:32 UTC | newest] Thread overview: 5+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2025-12-12 14:15 [PATCH v2 0/2] linux-user: add a syscall-filter plugin API Ziyang Zhang 2025-12-12 14:15 ` [PATCH v2 1/2] linux-user: add a plugin API to filter syscalls Ziyang Zhang 2025-12-12 14:15 ` [PATCH v2 2/2] tcg tests: add a test to verify the syscall filter plugin API Ziyang Zhang 2025-12-12 16:00 ` Alex Bennée 2025-12-12 17:32 ` Pierrick Bouvier
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).