]> git.baikalelectronics.ru Git - kernel.git/commitdiff
x86/entry: Unbreak __irqentry_text_start/end magic
authorThomas Gleixner <tglx@linutronix.de>
Wed, 10 Jun 2020 06:37:01 +0000 (08:37 +0200)
committerThomas Gleixner <tglx@linutronix.de>
Thu, 11 Jun 2020 13:15:29 +0000 (15:15 +0200)
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>
arch/x86/entry/entry_32.S
arch/x86/entry/entry_64.S
arch/x86/include/asm/irq.h
arch/x86/kernel/kprobes/core.c
arch/x86/kernel/kprobes/opt.c
arch/x86/kernel/unwind_frame.c
arch/x86/kernel/vmlinux.lds.S
arch/x86/mm/pti.c
include/linux/interrupt.h

index 2d29f77a360122633ea153da21be9e20ba31df56..024d7d276cd40bac51d405357209c9dd4634f0f1 100644 (file)
@@ -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
index 8ecaeee53653837abe7f7881ed9beb0d41b2c540..d2a00c97e53f608ad67a4e24db1f5c64f1b9e880 100644 (file)
@@ -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
index f73dd3f8b043f4a17ccdac2a76b1ac0d776afd51..528c8a71fe7f72a34719256f7192322fca94a56e 100644 (file)
 #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);
index 85de8fa69b241c9ceaab6fa5311aa8a113902f11..3bafe1bd4dc702fbdab1167a3dd2ccc42cb3977d 100644 (file)
@@ -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);
 }
index 234f58e0fe8cc639de65533e6e155bb8a152dc19..321c1995028504399ed88a50ea042b8683b20e3d 100644 (file)
@@ -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. */
index 54226110bc7fd707c56c8d5715b3e776a8586c21..722a85f3b2dd09de180bb9f8d3340469f4165b84 100644 (file)
@@ -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)
index 1bf7e312361f4f90d65f57228e6a7e5c1127ddc1..b4c6b6f35548affacfe2d1ab8caa2529a84097ca 100644 (file)
@@ -134,7 +134,6 @@ SECTIONS
                KPROBES_TEXT
                ALIGN_ENTRY_TEXT_BEGIN
                ENTRY_TEXT
-               IRQENTRY_TEXT
                ALIGN_ENTRY_TEXT_END
                SOFTIRQENTRY_TEXT
                *(.fixup)
index a3c6757a65c75fd79fe77649ae41998fc6d3219c..a8a924b3c3358986cd2c97d9b9efec87ffc77a23 100644 (file)
@@ -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);
 }
 
index 80f637c3a6f38d0c04e60019a20a6666d924c571..5db970b6615afdd1e0c5313714dd68fa924aca7f 100644 (file)
@@ -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