All of lore.kernel.org
 help / color / mirror / Atom feed
From: Thomas Gleixner <tglx@linutronix.de>
To: LKML <linux-kernel@vger.kernel.org>
Cc: x86@kernel.org, Andy Lutomirski <luto@kernel.org>,
	Josh Poimboeuf <jpoimboe@redhat.com>,
	Sean Christopherson <sean.j.christopherson@intel.com>
Subject: [patch V3 30/32] x86/irq/64: Split the IRQ stack into its own pages
Date: Sun, 14 Apr 2019 18:00:06 +0200	[thread overview]
Message-ID: <20190414160146.267376656@linutronix.de> (raw)
In-Reply-To: 20190414155936.679808307@linutronix.de

From: Andy Lutomirski <luto@kernel.org>

Currently the IRQ stack is hardcoded as the first page of the percpu area,
and the stack canary lives on the IRQ stack.  The former gets in the way of
adding an IRQ stack guard page, and the latter is a potential weakness in
the stack canary mechanism.

Split the IRQ stack into its own private percpu pages.

[ tglx: Make 64 and 32 bit share struct irq_stack ]

Signed-off-by: Andy Lutomirski <luto@kernel.org>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 arch/x86/entry/entry_64.S             |    4 ++--
 arch/x86/include/asm/processor.h      |   32 ++++++++++++++------------------
 arch/x86/include/asm/stackprotector.h |    6 +++---
 arch/x86/kernel/asm-offsets_64.c      |    2 +-
 arch/x86/kernel/cpu/common.c          |    8 ++++----
 arch/x86/kernel/head_64.S             |    2 +-
 arch/x86/kernel/irq_64.c              |    5 ++++-
 arch/x86/kernel/setup_percpu.c        |    5 -----
 arch/x86/kernel/vmlinux.lds.S         |    7 ++++---
 arch/x86/tools/relocs.c               |    2 +-
 arch/x86/xen/xen-head.S               |   10 +++++-----
 11 files changed, 39 insertions(+), 44 deletions(-)

--- a/arch/x86/entry/entry_64.S
+++ b/arch/x86/entry/entry_64.S
@@ -298,7 +298,7 @@ ENTRY(__switch_to_asm)
 
 #ifdef CONFIG_STACKPROTECTOR
 	movq	TASK_stack_canary(%rsi), %rbx
-	movq	%rbx, PER_CPU_VAR(irq_stack_union)+stack_canary_offset
+	movq	%rbx, PER_CPU_VAR(fixed_percpu_data) + stack_canary_offset
 #endif
 
 #ifdef CONFIG_RETPOLINE
@@ -430,7 +430,7 @@ END(irq_entries_start)
 	 * it before we actually move ourselves to the IRQ stack.
 	 */
 
-	movq	\old_rsp, PER_CPU_VAR(irq_stack_union + IRQ_STACK_SIZE - 8)
+	movq	\old_rsp, PER_CPU_VAR(irq_stack_backing_store + IRQ_STACK_SIZE - 8)
 	movq	PER_CPU_VAR(hardirq_stack_ptr), %rsp
 
 #ifdef CONFIG_DEBUG_ENTRY
--- a/arch/x86/include/asm/processor.h
+++ b/arch/x86/include/asm/processor.h
@@ -367,6 +367,13 @@ DECLARE_PER_CPU_PAGE_ALIGNED(struct tss_
 #define __KERNEL_TSS_LIMIT	\
 	(IO_BITMAP_OFFSET + IO_BITMAP_BYTES + sizeof(unsigned long) - 1)
 
+/* Per CPU interrupt stacks */
+struct irq_stack {
+	char		stack[IRQ_STACK_SIZE];
+} __aligned(IRQ_STACK_SIZE);
+
+DECLARE_PER_CPU(struct irq_stack *, hardirq_stack_ptr);
+
 #ifdef CONFIG_X86_32
 DECLARE_PER_CPU(unsigned long, cpu_current_top_of_stack);
 #else
@@ -375,28 +382,24 @@ DECLARE_PER_CPU(unsigned long, cpu_curre
 #endif
 
 #ifdef CONFIG_X86_64
-union irq_stack_union {
-	char irq_stack[IRQ_STACK_SIZE];
+struct fixed_percpu_data {
 	/*
 	 * GCC hardcodes the stack canary as %gs:40.  Since the
 	 * irq_stack is the object at %gs:0, we reserve the bottom
 	 * 48 bytes of the irq stack for the canary.
 	 */
-	struct {
-		char gs_base[40];
-		unsigned long stack_canary;
-	};
+	char		gs_base[40];
+	unsigned long	stack_canary;
 };
 
-DECLARE_PER_CPU_FIRST(union irq_stack_union, irq_stack_union) __visible;
-DECLARE_INIT_PER_CPU(irq_stack_union);
+DECLARE_PER_CPU_FIRST(struct fixed_percpu_data, fixed_percpu_data) __visible;
+DECLARE_INIT_PER_CPU(fixed_percpu_data);
 
 static inline unsigned long cpu_kernelmode_gs_base(int cpu)
 {
-	return (unsigned long)per_cpu(irq_stack_union.gs_base, cpu);
+	return (unsigned long)per_cpu(fixed_percpu_data.gs_base, cpu);
 }
 
-DECLARE_PER_CPU(char *, hardirq_stack_ptr);
 DECLARE_PER_CPU(unsigned int, irq_count);
 extern asmlinkage void ignore_sysret(void);
 
@@ -418,14 +421,7 @@ struct stack_canary {
 };
 DECLARE_PER_CPU_ALIGNED(struct stack_canary, stack_canary);
 #endif
-/*
- * per-CPU IRQ handling stacks
- */
-struct irq_stack {
-	char			stack[IRQ_STACK_SIZE];
-} __aligned(IRQ_STACK_SIZE);
-
-DECLARE_PER_CPU(struct irq_stack *, hardirq_stack_ptr);
+/* Per CPU softirq stack pointer */
 DECLARE_PER_CPU(struct irq_stack *, softirq_stack_ptr);
 #endif	/* X86_64 */
 
--- a/arch/x86/include/asm/stackprotector.h
+++ b/arch/x86/include/asm/stackprotector.h
@@ -13,7 +13,7 @@
  * On x86_64, %gs is shared by percpu area and stack canary.  All
  * percpu symbols are zero based and %gs points to the base of percpu
  * area.  The first occupant of the percpu area is always
- * irq_stack_union which contains stack_canary at offset 40.  Userland
+ * fixed_percpu_data which contains stack_canary at offset 40.  Userland
  * %gs is always saved and restored on kernel entry and exit using
  * swapgs, so stack protector doesn't add any complexity there.
  *
@@ -64,7 +64,7 @@ static __always_inline void boot_init_st
 	u64 tsc;
 
 #ifdef CONFIG_X86_64
-	BUILD_BUG_ON(offsetof(union irq_stack_union, stack_canary) != 40);
+	BUILD_BUG_ON(offsetof(struct fixed_percpu_data, stack_canary) != 40);
 #endif
 	/*
 	 * We both use the random pool and the current TSC as a source
@@ -79,7 +79,7 @@ static __always_inline void boot_init_st
 
 	current->stack_canary = canary;
 #ifdef CONFIG_X86_64
-	this_cpu_write(irq_stack_union.stack_canary, canary);
+	this_cpu_write(fixed_percpu_data.stack_canary, canary);
 #else
 	this_cpu_write(stack_canary.canary, canary);
 #endif
--- a/arch/x86/kernel/asm-offsets_64.c
+++ b/arch/x86/kernel/asm-offsets_64.c
@@ -73,7 +73,7 @@ int main(void)
 	BLANK();
 
 #ifdef CONFIG_STACKPROTECTOR
-	DEFINE(stack_canary_offset, offsetof(union irq_stack_union, stack_canary));
+	DEFINE(stack_canary_offset, offsetof(struct fixed_percpu_data, stack_canary));
 	BLANK();
 #endif
 
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -1498,9 +1498,9 @@ static __init int setup_clearcpuid(char
 __setup("clearcpuid=", setup_clearcpuid);
 
 #ifdef CONFIG_X86_64
-DEFINE_PER_CPU_FIRST(union irq_stack_union,
-		     irq_stack_union) __aligned(PAGE_SIZE) __visible;
-EXPORT_PER_CPU_SYMBOL_GPL(irq_stack_union);
+DEFINE_PER_CPU_FIRST(struct fixed_percpu_data,
+		     fixed_percpu_data) __aligned(PAGE_SIZE) __visible;
+EXPORT_PER_CPU_SYMBOL_GPL(fixed_percpu_data);
 
 /*
  * The following percpu variables are hot.  Align current_task to
@@ -1510,7 +1510,7 @@ DEFINE_PER_CPU(struct task_struct *, cur
 	&init_task;
 EXPORT_PER_CPU_SYMBOL(current_task);
 
-DEFINE_PER_CPU(char *, hardirq_stack_ptr);
+DEFINE_PER_CPU(struct irq_stack *, hardirq_stack_ptr);
 DEFINE_PER_CPU(unsigned int, irq_count) __visible = -1;
 
 DEFINE_PER_CPU(int, __preempt_count) = INIT_PREEMPT_COUNT;
--- a/arch/x86/kernel/head_64.S
+++ b/arch/x86/kernel/head_64.S
@@ -265,7 +265,7 @@ ENDPROC(start_cpu0)
 	GLOBAL(initial_code)
 	.quad	x86_64_start_kernel
 	GLOBAL(initial_gs)
-	.quad	INIT_PER_CPU_VAR(irq_stack_union)
+	.quad	INIT_PER_CPU_VAR(fixed_percpu_data)
 	GLOBAL(initial_stack)
 	/*
 	 * The SIZEOF_PTREGS gap is a convention which helps the in-kernel
--- a/arch/x86/kernel/irq_64.c
+++ b/arch/x86/kernel/irq_64.c
@@ -23,6 +23,9 @@
 #include <asm/io_apic.h>
 #include <asm/apic.h>
 
+DEFINE_PER_CPU_PAGE_ALIGNED(struct irq_stack, irq_stack_backing_store) __visible;
+DECLARE_INIT_PER_CPU(irq_stack_backing_store);
+
 int sysctl_panic_on_stackoverflow;
 
 /*
@@ -90,7 +93,7 @@ bool handle_irq(struct irq_desc *desc, s
 
 static int map_irq_stack(unsigned int cpu)
 {
-	void *va = per_cpu_ptr(irq_stack_union.irq_stack, cpu);
+	void *va = per_cpu_ptr(&irq_stack_backing_store, cpu);
 
 	per_cpu(hardirq_stack_ptr, cpu) = va + IRQ_STACK_SIZE;
 	return 0;
--- a/arch/x86/kernel/setup_percpu.c
+++ b/arch/x86/kernel/setup_percpu.c
@@ -244,11 +244,6 @@ void __init setup_per_cpu_areas(void)
 		per_cpu(x86_cpu_to_logical_apicid, cpu) =
 			early_per_cpu_map(x86_cpu_to_logical_apicid, cpu);
 #endif
-#ifdef CONFIG_X86_64
-		per_cpu(hardirq_stack_ptr, cpu) =
-			per_cpu(irq_stack_union.irq_stack, cpu) +
-			IRQ_STACK_SIZE;
-#endif
 #ifdef CONFIG_NUMA
 		per_cpu(x86_cpu_to_node_map, cpu) =
 			early_per_cpu_map(x86_cpu_to_node_map, cpu);
--- a/arch/x86/kernel/vmlinux.lds.S
+++ b/arch/x86/kernel/vmlinux.lds.S
@@ -403,7 +403,8 @@ SECTIONS
  */
 #define INIT_PER_CPU(x) init_per_cpu__##x = ABSOLUTE(x) + __per_cpu_load
 INIT_PER_CPU(gdt_page);
-INIT_PER_CPU(irq_stack_union);
+INIT_PER_CPU(fixed_percpu_data);
+INIT_PER_CPU(irq_stack_backing_store);
 
 /*
  * Build-time check on the image size:
@@ -412,8 +413,8 @@ INIT_PER_CPU(irq_stack_union);
 	   "kernel image bigger than KERNEL_IMAGE_SIZE");
 
 #ifdef CONFIG_SMP
-. = ASSERT((irq_stack_union == 0),
-           "irq_stack_union is not at start of per-cpu area");
+. = ASSERT((fixed_percpu_data == 0),
+           "fixed_percpu_data is not at start of per-cpu area");
 #endif
 
 #endif /* CONFIG_X86_32 */
--- a/arch/x86/tools/relocs.c
+++ b/arch/x86/tools/relocs.c
@@ -738,7 +738,7 @@ static void percpu_init(void)
  *	__per_cpu_load
  *
  * The "gold" linker incorrectly associates:
- *	init_per_cpu__irq_stack_union
+ *	init_per_cpu__fixed_percpu_data
  *	init_per_cpu__gdt_page
  */
 static int is_percpu_sym(ElfW(Sym) *sym, const char *symname)
--- a/arch/x86/xen/xen-head.S
+++ b/arch/x86/xen/xen-head.S
@@ -40,13 +40,13 @@ ENTRY(startup_xen)
 #ifdef CONFIG_X86_64
 	/* Set up %gs.
 	 *
-	 * The base of %gs always points to the bottom of the irqstack
-	 * union.  If the stack protector canary is enabled, it is
-	 * located at %gs:40.  Note that, on SMP, the boot cpu uses
-	 * init data section till per cpu areas are set up.
+	 * The base of %gs always points to fixed_percpu_data.  If the
+	 * stack protector canary is enabled, it is located at %gs:40.
+	 * Note that, on SMP, the boot cpu uses init data section until
+	 * the per cpu areas are set up.
 	 */
 	movl	$MSR_GS_BASE,%ecx
-	movq	$INIT_PER_CPU_VAR(irq_stack_union),%rax
+	movq	$INIT_PER_CPU_VAR(fixed_percpu_data),%rax
 	cdq
 	wrmsr
 #endif



  parent reply	other threads:[~2019-04-14 16:03 UTC|newest]

Thread overview: 89+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-04-14 15:59 [patch V3 00/32] x86: Add guard pages to exception and interrupt stacks Thomas Gleixner
2019-04-14 15:59 ` [patch V3 01/32] mm/slab: Fix broken stack trace storage Thomas Gleixner
2019-04-14 16:16   ` Andy Lutomirski
2019-04-14 16:16     ` Andy Lutomirski
2019-04-14 16:34     ` Thomas Gleixner
2019-04-14 16:34       ` Thomas Gleixner
2019-04-15  9:02       ` [patch V4 " Thomas Gleixner
2019-04-15  9:02         ` Thomas Gleixner
2019-04-15 13:23         ` Josh Poimboeuf
2019-04-15 16:07           ` Thomas Gleixner
2019-04-15 16:07             ` Thomas Gleixner
2019-04-15 16:16             ` Josh Poimboeuf
2019-04-15 17:05               ` Andy Lutomirski
2019-04-15 17:05                 ` Andy Lutomirski
2019-04-15 21:22                 ` Thomas Gleixner
2019-04-15 21:22                   ` Thomas Gleixner
2019-04-16 11:37                   ` Vlastimil Babka
2019-04-16 14:10                     ` [patch V5 01/32] mm/slab: Remove " Thomas Gleixner
2019-04-16 14:10                       ` Thomas Gleixner
2019-04-16 15:16                       ` Vlastimil Babka
2019-04-15 21:20               ` [patch V4 01/32] mm/slab: Fix " Thomas Gleixner
2019-04-15 21:20                 ` Thomas Gleixner
2019-04-15 16:21             ` Peter Zijlstra
2019-04-15 16:58       ` [patch V3 " Andy Lutomirski
2019-04-15 16:58         ` Andy Lutomirski
2019-04-14 15:59 ` [patch V3 02/32] x86/irq/64: Limit IST stack overflow check to #DB stack Thomas Gleixner
2019-04-17 14:02   ` [tip:x86/irq] " tip-bot for Thomas Gleixner
2019-04-14 15:59 ` [patch V3 03/32] x86/dumpstack: Fix off-by-one errors in stack identification Thomas Gleixner
2019-04-17 14:03   ` [tip:x86/irq] " tip-bot for Andy Lutomirski
2019-04-14 15:59 ` [patch V3 04/32] x86/irq/64: Remove a hardcoded irq_stack_union access Thomas Gleixner
2019-04-17 14:03   ` [tip:x86/irq] " tip-bot for Andy Lutomirski
2019-04-14 15:59 ` [patch V3 05/32] x86/irq/64: Sanitize the top/bottom confusion Thomas Gleixner
2019-04-17 14:04   ` [tip:x86/irq] " tip-bot for Thomas Gleixner
2019-04-14 15:59 ` [patch V3 06/32] x86/idt: Remove unused macro SISTG Thomas Gleixner
2019-04-17 14:05   ` [tip:x86/irq] " tip-bot for Thomas Gleixner
2019-04-14 15:59 ` [patch V3 07/32] x86/64: Remove stale CURRENT_MASK Thomas Gleixner
2019-04-17 14:06   ` [tip:x86/irq] " tip-bot for Thomas Gleixner
2019-04-14 15:59 ` [patch V3 08/32] x86/exceptions: Remove unused stack defines on 32bit Thomas Gleixner
2019-04-17 14:06   ` [tip:x86/irq] " tip-bot for Thomas Gleixner
2019-04-14 15:59 ` [patch V3 09/32] x86/exceptions: Make IST index zero based Thomas Gleixner
2019-04-17 14:07   ` [tip:x86/irq] " tip-bot for Thomas Gleixner
2019-04-14 15:59 ` [patch V3 10/32] x86/cpu_entry_area: Cleanup setup functions Thomas Gleixner
2019-04-17 14:08   ` [tip:x86/irq] " tip-bot for Thomas Gleixner
2019-04-14 15:59 ` [patch V3 11/32] x86/exceptions: Add structs for exception stacks Thomas Gleixner
2019-04-16 18:20   ` Sean Christopherson
2019-04-17 14:08   ` [tip:x86/irq] " tip-bot for Thomas Gleixner
2019-04-14 15:59 ` [patch V3 12/32] x86/cpu_entry_area: Prepare for IST guard pages Thomas Gleixner
2019-04-17 14:09   ` [tip:x86/irq] " tip-bot for Thomas Gleixner
2019-04-14 15:59 ` [patch V3 13/32] x86/cpu_entry_area: Provide exception stack accessor Thomas Gleixner
2019-04-17 14:10   ` [tip:x86/irq] " tip-bot for Thomas Gleixner
2019-04-14 15:59 ` [patch V3 14/32] x86/traps: Use cpu_entry_area instead of orig_ist Thomas Gleixner
2019-04-17 14:10   ` [tip:x86/irq] " tip-bot for Thomas Gleixner
2019-04-14 15:59 ` [patch V3 15/32] x86/irq/64: Use cpu entry area " Thomas Gleixner
2019-04-17 14:11   ` [tip:x86/irq] " tip-bot for Thomas Gleixner
2019-04-14 15:59 ` [patch V3 16/32] x86/dumpstack/64: Use cpu_entry_area " Thomas Gleixner
2019-04-17 14:12   ` [tip:x86/irq] " tip-bot for Thomas Gleixner
2019-04-14 15:59 ` [patch V3 17/32] x86/cpu: Prepare TSS.IST setup for guard pages Thomas Gleixner
2019-04-17 14:13   ` [tip:x86/irq] " tip-bot for Thomas Gleixner
2019-04-14 15:59 ` [patch V3 18/32] x86/cpu: Remove orig_ist array Thomas Gleixner
2019-04-17 14:13   ` [tip:x86/irq] " tip-bot for Thomas Gleixner
2019-04-14 15:59 ` [patch V3 19/32] x86/exceptions: Disconnect IST index and stack order Thomas Gleixner
2019-04-17 14:14   ` [tip:x86/irq] " tip-bot for Thomas Gleixner
2019-04-14 15:59 ` [patch V3 20/32] x86/exceptions: Enable IST guard pages Thomas Gleixner
2019-04-17 14:15   ` [tip:x86/irq] " tip-bot for Thomas Gleixner
2019-04-14 15:59 ` [patch V3 21/32] x86/exceptions: Split debug IST stack Thomas Gleixner
2019-04-16 22:07   ` Sean Christopherson
2019-04-17 14:15   ` [tip:x86/irq] " tip-bot for Thomas Gleixner
2019-04-14 15:59 ` [patch V3 22/32] x86/dumpstack/64: Speedup in_exception_stack() Thomas Gleixner
2019-04-17 14:16   ` [tip:x86/irq] " tip-bot for Thomas Gleixner
2019-04-14 15:59 ` [patch V3 23/32] x86/irq/32: Define IRQ_STACK_SIZE Thomas Gleixner
2019-04-17 14:17   ` [tip:x86/irq] " tip-bot for Thomas Gleixner
2019-04-14 16:00 ` [patch V3 24/32] x86/irq/32: Make irq stack a character array Thomas Gleixner
2019-04-17 14:18   ` [tip:x86/irq] " tip-bot for Thomas Gleixner
2019-04-14 16:00 ` [patch V3 25/32] x86/irq/32: Rename hard/softirq_stack to hard/softirq_stack_ptr Thomas Gleixner
2019-04-17 14:18   ` [tip:x86/irq] " tip-bot for Thomas Gleixner
2019-04-14 16:00 ` [patch V3 26/32] x86/irq/64: Rename irq_stack_ptr to hardirq_stack_ptr Thomas Gleixner
2019-04-17 14:19   ` [tip:x86/irq] " tip-bot for Thomas Gleixner
2019-04-14 16:00 ` [patch V3 27/32] x86/irq/32: Invoke irq_ctx_init() from init_IRQ() Thomas Gleixner
2019-04-17 14:20   ` [tip:x86/irq] " tip-bot for Thomas Gleixner
2019-04-14 16:00 ` [patch V3 28/32] x86/irq/32: Handle irq stack allocation failure proper Thomas Gleixner
2019-04-17 14:20   ` [tip:x86/irq] " tip-bot for Thomas Gleixner
2019-04-14 16:00 ` [patch V3 29/32] x86/irq/64: Init hardirq_stack_ptr during CPU hotplug Thomas Gleixner
2019-04-17 14:21   ` [tip:x86/irq] " tip-bot for Thomas Gleixner
2019-04-14 16:00 ` Thomas Gleixner [this message]
2019-04-17 14:22   ` [tip:x86/irq] x86/irq/64: Split the IRQ stack into its own pages tip-bot for Andy Lutomirski
2019-04-14 16:00 ` [patch V3 31/32] x86/irq/64: Remap the IRQ stack with guard pages Thomas Gleixner
2019-04-17 14:22   ` [tip:x86/irq] " tip-bot for Andy Lutomirski
2019-04-14 16:00 ` [patch V3 32/32] x86/irq/64: Remove stack overflow debug code Thomas Gleixner
2019-04-17 14:23   ` [tip:x86/irq] " tip-bot for Thomas Gleixner

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20190414160146.267376656@linutronix.de \
    --to=tglx@linutronix.de \
    --cc=jpoimboe@redhat.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=luto@kernel.org \
    --cc=sean.j.christopherson@intel.com \
    --cc=x86@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.