All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] x86/alternatives: check int3 breakpoint physical addresses
@ 2019-01-25 14:57 Alexandre Chartre
  2019-02-10 21:23 ` Thomas Gleixner
  0 siblings, 1 reply; 6+ messages in thread
From: Alexandre Chartre @ 2019-01-25 14:57 UTC (permalink / raw)
  To: linux-kernel
  Cc: Alexandre Chartre, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
	H. Peter Anvin, Josh Poimboeuf, x86

Modifying multi-byte instructions is achieved by temporarily replacing
the first instruction to patch with an int3 instruction. Then, if an
int3 interrupt is raised, the int3 handler will check if the interrupt
was caused by this temporary patch by comparing the address that raises
the interrupt (the interrupt address) and the address that was patched
(the patched address).

The int3 handler compares virtual addresses of the interrupt and
patched addresses. However, this doesn't work if the code to modify
is mapped to multiple virtual addresses because, in that case, the
patched virtual address can be different from the interrupt virtual
address.

A simple solution is then to also compare physical addresses when
virtual addresses do not match. Note that we still compare virtual
addresses because that's a faster comparison than having to fully
resolve and compare physical addresses.

Signed-off-by: Alexandre Chartre <alexandre.chartre@oracle.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: x86@kernel.org
---

This is a potential issue and I don't know if it can be triggered with the
current kernel: is there any code mapped to multiple virtual addresses
which can be updated with text_poke_bp()? However as the patch is small and
simple, it might be worth applying it anyway to prevent any such issue.

Note that this issue has been observed and reproduced with a custom kernel
with some code mapped to different virtual addresses and using jump labels
As jump labels use text_poke_bp(), crashes were sometimes observed when
updating jump labels.

 arch/x86/kernel/alternative.c |   13 ++++++++++++-
 1 files changed, 12 insertions(+), 1 deletions(-)

diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c
index ebeac48..e563573 100644
--- a/arch/x86/kernel/alternative.c
+++ b/arch/x86/kernel/alternative.c
@@ -757,7 +757,18 @@ int poke_int3_handler(struct pt_regs *regs)
 	if (likely(!bp_patching_in_progress))
 		return 0;
 
-	if (user_mode(regs) || regs->ip != (unsigned long)bp_int3_addr)
+	if (user_mode(regs))
+		return 0;
+
+	/*
+	 * If virtual addresses are different, check if physical addresses
+	 * are the same in case we have the same code mapped to different
+	 * virtual addresses. Note that we could just compare physical
+	 * addresses, however we first compare virtual addresses because
+	 * this is much faster and very likely to succeed.
+	 */
+	if (regs->ip != (unsigned long)bp_int3_addr &&
+	    slow_virt_to_phys((void *)regs->ip) != slow_virt_to_phys(bp_int3_addr))
 		return 0;
 
 	/* set up the specified breakpoint handler */
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH] x86/alternatives: check int3 breakpoint physical addresses
  2019-01-25 14:57 [PATCH] x86/alternatives: check int3 breakpoint physical addresses Alexandre Chartre
@ 2019-02-10 21:23 ` Thomas Gleixner
  2019-02-11  9:08   ` Alexandre Chartre
  0 siblings, 1 reply; 6+ messages in thread
From: Thomas Gleixner @ 2019-02-10 21:23 UTC (permalink / raw)
  To: Alexandre Chartre
  Cc: LKML, Ingo Molnar, Borislav Petkov, H. Peter Anvin,
	Josh Poimboeuf, x86, Peter Zijlstra

On Fri, 25 Jan 2019, Alexandre Chartre wrote:
> Note that this issue has been observed and reproduced with a custom kernel
> with some code mapped to different virtual addresses and using jump labels
> As jump labels use text_poke_bp(), crashes were sometimes observed when
> updating jump labels.

Rightfully so. text_poke_bp() pokes at the kernels text mapping which is
very well defined and unique. Why would you map the same text to different
virtual addresses and then use a randomly chosen one to poke at it?

Thanks,

	tglx

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH] x86/alternatives: check int3 breakpoint physical addresses
  2019-02-10 21:23 ` Thomas Gleixner
@ 2019-02-11  9:08   ` Alexandre Chartre
  2019-02-11  9:15     ` Thomas Gleixner
  0 siblings, 1 reply; 6+ messages in thread
From: Alexandre Chartre @ 2019-02-11  9:08 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: LKML, Ingo Molnar, Borislav Petkov, H. Peter Anvin,
	Josh Poimboeuf, x86, Peter Zijlstra, Alexandre Chartre


On 02/10/2019 10:23 PM, Thomas Gleixner wrote:
> On Fri, 25 Jan 2019, Alexandre Chartre wrote:
>> Note that this issue has been observed and reproduced with a custom kernel
>> with some code mapped to different virtual addresses and using jump labels
>> As jump labels use text_poke_bp(), crashes were sometimes observed when
>> updating jump labels.
>
> Rightfully so. text_poke_bp() pokes at the kernels text mapping which is
> very well defined and unique. Why would you map the same text to different
> virtual addresses and then use a randomly chosen one to poke at it?
>

As an example, we used to have per-CPU SYSCALL entry trampoline [1] where the
entry_SYSCALL_64_trampoline function was mapped to a different virtual address
for each CPU. So, a syscall would execute entry_SYSCALL_64_trampoline() from a
different virtual address depending on the CPU being used. With that code,
adding a jump label in entry_SYSCALL_64_trampoline() causes the described issue.

This mapping was eventually removed [2]. I don't know if any other code like this
is currently present in the kernel (I couldn't find any, but I might not have
covered everything). But, as this past commit have shown, this is definitively
something that can happen.

Thanks,

alex.

---
[1] 3386bc8aed82 ("x86/entry/64: Create a per-CPU SYSCALL entry trampoline")
     https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=3386bc8aed82

[2] bf904d2762ee ("x86/pti/64: Remove the SYSCALL64 entry trampoline")
     https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=bf904d2762ee

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH] x86/alternatives: check int3 breakpoint physical addresses
  2019-02-11  9:08   ` Alexandre Chartre
@ 2019-02-11  9:15     ` Thomas Gleixner
  2019-02-11  9:57       ` Alexandre Chartre
  0 siblings, 1 reply; 6+ messages in thread
From: Thomas Gleixner @ 2019-02-11  9:15 UTC (permalink / raw)
  To: Alexandre Chartre
  Cc: LKML, Ingo Molnar, Borislav Petkov, H. Peter Anvin,
	Josh Poimboeuf, x86, Peter Zijlstra

On Mon, 11 Feb 2019, Alexandre Chartre wrote:
> On 02/10/2019 10:23 PM, Thomas Gleixner wrote:
> > On Fri, 25 Jan 2019, Alexandre Chartre wrote:
> > > Note that this issue has been observed and reproduced with a custom kernel
> > > with some code mapped to different virtual addresses and using jump labels
> > > As jump labels use text_poke_bp(), crashes were sometimes observed when
> > > updating jump labels.
> > 
> > Rightfully so. text_poke_bp() pokes at the kernels text mapping which is
> > very well defined and unique. Why would you map the same text to different
> > virtual addresses and then use a randomly chosen one to poke at it?
> > 
> 
> As an example, we used to have per-CPU SYSCALL entry trampoline [1] where the
> entry_SYSCALL_64_trampoline function was mapped to a different virtual address
> for each CPU. So, a syscall would execute entry_SYSCALL_64_trampoline() from a
> different virtual address depending on the CPU being used. With that code,
> adding a jump label in entry_SYSCALL_64_trampoline() causes the described
> issue.

Right, but we knew that and there was no reason to put a jump label into
that. AFAICT we don't have anything like this in the kernel.

That said, I'm not opposed to apply the patch as is, I just wanted to get a
better understanding about the background.

Thanks,

	tglx

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH] x86/alternatives: check int3 breakpoint physical addresses
  2019-02-11  9:15     ` Thomas Gleixner
@ 2019-02-11  9:57       ` Alexandre Chartre
  2019-02-21 10:14         ` Alexandre Chartre
  0 siblings, 1 reply; 6+ messages in thread
From: Alexandre Chartre @ 2019-02-11  9:57 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: LKML, Ingo Molnar, Borislav Petkov, H. Peter Anvin,
	Josh Poimboeuf, x86, Peter Zijlstra, Alexandre Chartre


On 02/11/2019 10:15 AM, Thomas Gleixner wrote:
> On Mon, 11 Feb 2019, Alexandre Chartre wrote:
>> On 02/10/2019 10:23 PM, Thomas Gleixner wrote:
>>> On Fri, 25 Jan 2019, Alexandre Chartre wrote:
>>>> Note that this issue has been observed and reproduced with a custom kernel
>>>> with some code mapped to different virtual addresses and using jump labels
>>>> As jump labels use text_poke_bp(), crashes were sometimes observed when
>>>> updating jump labels.
>>>
>>> Rightfully so. text_poke_bp() pokes at the kernels text mapping which is
>>> very well defined and unique. Why would you map the same text to different
>>> virtual addresses and then use a randomly chosen one to poke at it?
>>>
>>
>> As an example, we used to have per-CPU SYSCALL entry trampoline [1] where the
>> entry_SYSCALL_64_trampoline function was mapped to a different virtual address
>> for each CPU. So, a syscall would execute entry_SYSCALL_64_trampoline() from a
>> different virtual address depending on the CPU being used. With that code,
>> adding a jump label in entry_SYSCALL_64_trampoline() causes the described
>> issue.
>
> Right, but we knew that and there was no reason to put a jump label into
> that. AFAICT we don't have anything like this in the kernel.

In our particular case, we have introduced a jump label in JMP_NOSPEC (which
is used by entry_SYSCALL_64_trampoline()) to have the option to dynamically
enable/disable retpoline at runtime. So that's when we faced this issue.

> That said, I'm not opposed to apply the patch as is, I just wanted to get a
> better understanding about the background.

Sure. I am aware this is a corner case, and I was precisely looking for feedback
to check if it is worth fixing that issue. So I appreciate your reply, and I would
understand if the patch is rejected because that's a case that we are just not
expecting to happen.

Thanks,

alex.

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH] x86/alternatives: check int3 breakpoint physical addresses
  2019-02-11  9:57       ` Alexandre Chartre
@ 2019-02-21 10:14         ` Alexandre Chartre
  0 siblings, 0 replies; 6+ messages in thread
From: Alexandre Chartre @ 2019-02-21 10:14 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: LKML, Ingo Molnar, Borislav Petkov, H. Peter Anvin,
	Josh Poimboeuf, x86, Peter Zijlstra


On 02/11/2019 10:57 AM, Alexandre Chartre wrote:
>
> On 02/11/2019 10:15 AM, Thomas Gleixner wrote:
>> On Mon, 11 Feb 2019, Alexandre Chartre wrote:
>>> On 02/10/2019 10:23 PM, Thomas Gleixner wrote:
>>>> On Fri, 25 Jan 2019, Alexandre Chartre wrote:
>>>>> Note that this issue has been observed and reproduced with a custom kernel
>>>>> with some code mapped to different virtual addresses and using jump labels
>>>>> As jump labels use text_poke_bp(), crashes were sometimes observed when
>>>>> updating jump labels.
>>>>
>>>> Rightfully so. text_poke_bp() pokes at the kernels text mapping which is
>>>> very well defined and unique. Why would you map the same text to different
>>>> virtual addresses and then use a randomly chosen one to poke at it?
>>>>
>>>
>>> As an example, we used to have per-CPU SYSCALL entry trampoline [1] where the
>>> entry_SYSCALL_64_trampoline function was mapped to a different virtual address
>>> for each CPU. So, a syscall would execute entry_SYSCALL_64_trampoline() from a
>>> different virtual address depending on the CPU being used. With that code,
>>> adding a jump label in entry_SYSCALL_64_trampoline() causes the described
>>> issue.
>>
>> Right, but we knew that and there was no reason to put a jump label into
>> that. AFAICT we don't have anything like this in the kernel.
>
> In our particular case, we have introduced a jump label in JMP_NOSPEC (which
> is used by entry_SYSCALL_64_trampoline()) to have the option to dynamically
> enable/disable retpoline at runtime. So that's when we faced this issue.
>
>> That said, I'm not opposed to apply the patch as is, I just wanted to get a
>> better understanding about the background.
>
> Sure. I am aware this is a corner case, and I was precisely looking for feedback
> to check if it is worth fixing that issue. So I appreciate your reply, and I would
> understand if the patch is rejected because that's a case that we are just not
> expecting to happen.
>

Hi Thomas,

Do you have any final thought about this patch? Should we drop it or apply it?
As the patch is small and simple, I think it's worth applying it to prevent
any such (future?) issue.

Thanks,

alex.

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2019-02-21 10:15 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-01-25 14:57 [PATCH] x86/alternatives: check int3 breakpoint physical addresses Alexandre Chartre
2019-02-10 21:23 ` Thomas Gleixner
2019-02-11  9:08   ` Alexandre Chartre
2019-02-11  9:15     ` Thomas Gleixner
2019-02-11  9:57       ` Alexandre Chartre
2019-02-21 10:14         ` Alexandre Chartre

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.