From: Richard Henderson <[email protected]>

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: [email protected]
Reported-by: 李威威 <[email protected]>
Signed-off-by: Richard Henderson <[email protected]>
Reviewed-by: Anton Johansson <[email protected]>
Tested-by: Anton Johansson <[email protected]>
(cherry picked from commit 03fe6659803f83690b8587d01f8ee56bb4be4b90)
Signed-off-by: Michael Tokarev <[email protected]>

diff --git a/accel/tcg/tb-maint.c b/accel/tcg/tb-maint.c
index 9d9f651c78..077265172e 100644
--- a/accel/tcg/tb-maint.c
+++ b/accel/tcg/tb-maint.c
@@ -186,6 +186,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.47.3


Reply via email to