From 5b85d6da6a2943f4dd08ee6e140ef1238b0ae124 Mon Sep 17 00:00:00 2001 From: Andy Ross Date: Thu, 23 Jan 2020 12:54:52 -0800 Subject: [PATCH] arch/x86_64: Poison instruction pointer of running threads There was a bug where double-dispatch of a single thread on multiple SMP CPUs was possible. This can be mind-bending to diagnose, so when CONFIG_ASSERT is enabled add an extra instruction to __resume (the shared code path for both interupt return and context switch) that poisons the shared RIP of the now-running thread with a recognizable invalid value. Now attempts to run the thread again will crash instantly with a discoverable cookie in their instruction pointer, and this will remain true until it gets a new RIP at the next interrupt or switch. This is under CONFIG_ASSERT because it meets the same design goals of "a cheap test for impossible situations", not because it's part of the assertion framework. Signed-off-by: Andy Ross --- arch/x86/core/intel64/locore.S | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/arch/x86/core/intel64/locore.S b/arch/x86/core/intel64/locore.S index 9674491ee17..0a689417b59 100644 --- a/arch/x86/core/intel64/locore.S +++ b/arch/x86/core/intel64/locore.S @@ -263,6 +263,16 @@ __resume: #endif pushq _thread_offset_to_rip(%rdi) /* RIP */ +#ifdef CONFIG_ASSERT + /* Poison the old thread's saved RIP pointer with a + * recognizable value near NULL, to easily catch reuse of the + * thread object across CPUs in SMP. Strictly speaking this + * is not an assertion, but it's very cheap and worth having + * on during routine testing. + */ + movq $0xB9, _thread_offset_to_rip(%rdi) +#endif + movq _thread_offset_to_rbx(%rdi), %rbx movq _thread_offset_to_rbp(%rdi), %rbp movq _thread_offset_to_r12(%rdi), %r12