Commit f0178fc0 authored by Thomas Gleixner's avatar Thomas Gleixner
Browse files

x86/entry: Unbreak __irqentry_text_start/end magic



The entry rework moved interrupt entry code from the irqentry to the
noinstr section which made the irqentry section empty.

This breaks boundary checks which rely on the __irqentry_text_start/end
markers to find out whether a function in a stack trace is
interrupt/exception entry code. This affects the function graph tracer and
filter_irq_stacks().

As the IDT entry points are all sequentialy emitted this is rather simple
to unbreak by injecting __irqentry_text_start/end as global labels.

To make this work correctly:

  - Remove the IRQENTRY_TEXT section from the x86 linker script
  - Define __irqentry so it breaks the build if it's used
  - Adjust the entry mirroring in PTI
  - Remove the redundant kprobes and unwinder bound checks

Reported-by: default avatarQian Cai <cai@lca.pw>
Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
parent 2823e83a
Loading
Loading
Loading
Loading
+10 −1
Original line number Diff line number Diff line
@@ -743,10 +743,19 @@ SYM_CODE_END(asm_\cfunc)

/*
 * Include the defines which emit the idt entries which are shared
 * shared between 32 and 64 bit.
 * shared between 32 and 64 bit and emit the __irqentry_text_* markers
 * so the stacktrace boundary checks work.
 */
	.align 16
	.globl __irqentry_text_start
__irqentry_text_start:

#include <asm/idtentry.h>

	.align 16
	.globl __irqentry_text_end
__irqentry_text_end:

/*
 * %eax: prev task
 * %edx: next task
+10 −1
Original line number Diff line number Diff line
@@ -478,10 +478,19 @@ SYM_CODE_END(\asmsym)

/*
 * Include the defines which emit the idt entries which are shared
 * shared between 32 and 64 bit.
 * shared between 32 and 64 bit and emit the __irqentry_text_* markers
 * so the stacktrace boundary checks work.
 */
	.align 16
	.globl __irqentry_text_start
__irqentry_text_start:

#include <asm/idtentry.h>

	.align 16
	.globl __irqentry_text_end
__irqentry_text_end:

SYM_CODE_START_LOCAL(common_interrupt_return)
SYM_INNER_LABEL(swapgs_restore_regs_and_return_to_usermode, SYM_L_GLOBAL)
#ifdef CONFIG_DEBUG_ENTRY
+7 −0
Original line number Diff line number Diff line
@@ -11,6 +11,13 @@
#include <asm/apicdef.h>
#include <asm/irq_vectors.h>

/*
 * The irq entry code is in the noinstr section and the start/end of
 * __irqentry_text is emitted via labels. Make the build fail if
 * something moves a C function into the __irq_entry section.
 */
#define __irq_entry __invalid_section

static inline int irq_canonicalize(int irq)
{
	return ((irq == 2) ? 9 : irq);
+0 −7
Original line number Diff line number Diff line
@@ -1073,13 +1073,6 @@ NOKPROBE_SYMBOL(kprobe_fault_handler);

int __init arch_populate_kprobe_blacklist(void)
{
	int ret;

	ret = kprobe_add_area_blacklist((unsigned long)__irqentry_text_start,
					 (unsigned long)__irqentry_text_end);
	if (ret)
		return ret;

	return kprobe_add_area_blacklist((unsigned long)__entry_text_start,
					 (unsigned long)__entry_text_end);
}
+1 −3
Original line number Diff line number Diff line
@@ -286,9 +286,7 @@ static int can_optimize(unsigned long paddr)
	 * stack handling and registers setup.
	 */
	if (((paddr >= (unsigned long)__entry_text_start) &&
	     (paddr <  (unsigned long)__entry_text_end)) ||
	    ((paddr >= (unsigned long)__irqentry_text_start) &&
	     (paddr <  (unsigned long)__irqentry_text_end)))
	     (paddr <  (unsigned long)__entry_text_end)))
		return 0;

	/* Check there is enough space for a relative jump. */
Loading