mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-11-24 06:10:53 +07:00
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: Qian Cai <cai@lca.pw> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
This commit is contained in:
parent
2823e83a3d
commit
f0178fc01f
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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. */
|
||||
|
@ -74,13 +74,7 @@ static bool in_entry_code(unsigned long ip)
|
||||
{
|
||||
char *addr = (char *)ip;
|
||||
|
||||
if (addr >= __entry_text_start && addr < __entry_text_end)
|
||||
return true;
|
||||
|
||||
if (addr >= __irqentry_text_start && addr < __irqentry_text_end)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
return addr >= __entry_text_start && addr < __entry_text_end;
|
||||
}
|
||||
|
||||
static inline unsigned long *last_frame(struct unwind_state *state)
|
||||
|
@ -134,7 +134,6 @@ SECTIONS
|
||||
KPROBES_TEXT
|
||||
ALIGN_ENTRY_TEXT_BEGIN
|
||||
ENTRY_TEXT
|
||||
IRQENTRY_TEXT
|
||||
ALIGN_ENTRY_TEXT_END
|
||||
SOFTIRQENTRY_TEXT
|
||||
*(.fixup)
|
||||
|
@ -492,12 +492,12 @@ static void __init pti_setup_espfix64(void)
|
||||
}
|
||||
|
||||
/*
|
||||
* Clone the populated PMDs of the entry and irqentry text and force it RO.
|
||||
* Clone the populated PMDs of the entry text and force it RO.
|
||||
*/
|
||||
static void pti_clone_entry_text(void)
|
||||
{
|
||||
pti_clone_pgtable((unsigned long) __entry_text_start,
|
||||
(unsigned long) __irqentry_text_end,
|
||||
(unsigned long) __entry_text_end,
|
||||
PTI_CLONE_PMD);
|
||||
}
|
||||
|
||||
|
@ -760,8 +760,10 @@ extern int arch_early_irq_init(void);
|
||||
/*
|
||||
* We want to know which function is an entrypoint of a hardirq or a softirq.
|
||||
*/
|
||||
#define __irq_entry __attribute__((__section__(".irqentry.text")))
|
||||
#define __softirq_entry \
|
||||
__attribute__((__section__(".softirqentry.text")))
|
||||
#ifndef __irq_entry
|
||||
# define __irq_entry __attribute__((__section__(".irqentry.text")))
|
||||
#endif
|
||||
|
||||
#define __softirq_entry __attribute__((__section__(".softirqentry.text")))
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user