From: Pierrick Bouvier <[email protected]> Syscall arguments are abi_long in user code, and plugin syscall interface works with uint64_t only.
According to C integer promotion rules, the value is sign extended before becoming unsigned, thus setting high bits when only 32-bit lower ones should have a significant value. As a result, we need to clamp values we receive from user-code accordingly. Signed-off-by: Pierrick Bouvier <[email protected]> --- plugins/core.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/plugins/core.c b/plugins/core.c index 42fd986593..d6173422e9 100644 --- a/plugins/core.c +++ b/plugins/core.c @@ -513,6 +513,23 @@ void qemu_plugin_tb_trans_cb(CPUState *cpu, struct qemu_plugin_tb *tb) } } +static void clamp_syscall_arguments(uint64_t *a1, uint64_t *a2, uint64_t *a3, + uint64_t *a4, uint64_t *a5, uint64_t *a6, + uint64_t *a7, uint64_t *a8) +{ + if (target_long_bits() == 32) { + const uint64_t mask = UINT32_MAX; + *a1 &= mask; + *a2 &= mask; + *a3 &= mask; + *a4 &= mask; + *a5 &= mask; + *a6 &= mask; + *a7 &= mask; + *a8 &= mask; + } +} + /* * Disable CFI checks. * The callback function has been loaded from an external library so we do not @@ -531,6 +548,8 @@ qemu_plugin_vcpu_syscall(CPUState *cpu, int64_t num, uint64_t a1, uint64_t a2, return; } + clamp_syscall_arguments(&a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8); + QLIST_FOREACH_SAFE_RCU(cb, &plugin.cb_lists[ev], entry, next) { qemu_plugin_vcpu_syscall_cb_t func = cb->f.vcpu_syscall; @@ -584,6 +603,8 @@ qemu_plugin_vcpu_syscall_filter(CPUState *cpu, int64_t num, uint64_t a1, return false; } + clamp_syscall_arguments(&a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8); + qemu_plugin_set_cb_flags(cpu, QEMU_PLUGIN_CB_RW_REGS); QLIST_FOREACH_SAFE_RCU(cb, &plugin.cb_lists[ev], entry, next) { -- 2.53.0
