From: Ilya Leoshkevich <i...@linux.ibm.com> Node.js crashes in qemu-system-s390x with random SIGSEGVs / SIGILLs.
The v8 JIT used by Node.js can garbage collect and overwrite unused code. Overwriting is performed by WritableJitAllocation::CopyCode(), which ultimately calls memcpy(). For certain sizes, memcpy() uses the MVC instruction. QEMU implements MVC and other similar instructions using helpers. While TCG store ops invalidate affected translation blocks automatically, helpers must do this manually by calling probe_access_flags(). The MVC helper does this using the access_prepare() -> access_prepare_nf() -> s390_probe_access() -> probe_access_flags() call chain. At the last step of this chain, the store size is replaced with 0. This causes the probe_access_flags() -> notdirty_write() -> tb_invalidate_phys_range_fast() chain to miss some translation blocks. When this happens, QEMU executes a mix of old and new code. This quickly leads to either a SIGSEGV or a SIGILL in case the old code ends in the middle of a new instruction. Fix by passing the true size. Reported-by: Berthold Gunreben <azo...@opensuse.org> Cc: Sarah Kriesch <ada.lovel...@gmx.de> Cc: qemu-sta...@nongnu.org Closes: https://bugzilla.opensuse.org/show_bug.cgi?id=1235709 Signed-off-by: Ilya Leoshkevich <i...@linux.ibm.com> Reviewed-by: Richard Henderson <richard.hender...@linaro.org> Reviewed-by: David Hildenbrand <da...@redhat.com> Fixes: e2faabee78ff ("accel/tcg: Forward probe size on to notdirty_write") Message-ID: <20250128001338.11474-1-...@linux.ibm.com> Signed-off-by: Thomas Huth <th...@redhat.com> (cherry picked from commit e43ced8be18dda77c229ab09f85136a4d600d40d) Signed-off-by: Michael Tokarev <m...@tls.msk.ru> diff --git a/target/s390x/tcg/mem_helper.c b/target/s390x/tcg/mem_helper.c index 0e12dae2aa..29ee5a8a07 100644 --- a/target/s390x/tcg/mem_helper.c +++ b/target/s390x/tcg/mem_helper.c @@ -146,7 +146,7 @@ static inline int s390_probe_access(CPUArchState *env, target_ulong addr, int mmu_idx, bool nonfault, void **phost, uintptr_t ra) { - int flags = probe_access_flags(env, addr, 0, access_type, mmu_idx, + int flags = probe_access_flags(env, addr, size, access_type, mmu_idx, nonfault, phost, ra); if (unlikely(flags & TLB_INVALID_MASK)) { -- 2.39.5