When we remove dest from orig's links, we lose the link that we rely on later to reset links. This can lead to failure to release from spinlock with self-modifying code.
Cc: qemu-sta...@nongnu.org Reported-by: 李威威 <liwei...@kubuds.cn> Signed-off-by: Richard Henderson <richard.hender...@linaro.org> Reviewed-by: Anton Johansson <a...@rev.ng> Tested-by: Anton Johansson <a...@rev.ng> --- accel/tcg/tb-maint.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/accel/tcg/tb-maint.c b/accel/tcg/tb-maint.c index 0048316f99..e6d45c9c12 100644 --- a/accel/tcg/tb-maint.c +++ b/accel/tcg/tb-maint.c @@ -836,6 +836,14 @@ static inline void tb_remove_from_jmp_list(TranslationBlock *orig, int n_orig) * We first acquired the lock, and since the destination pointer matches, * we know for sure that @orig is in the jmp list. */ + if (dest == orig) { + /* + * In the case of a TB that links to itself, removing the entry + * from the list means that it won't be present later during + * tb_jmp_unlink -- unlink now. + */ + tb_reset_jump(orig, n_orig); + } pprev = &dest->jmp_list_head; TB_FOR_EACH_JMP(dest, tb, n) { if (tb == orig && n == n_orig) { -- 2.43.0