linux/include
Borislav Petkov 15b4f26b75 x86: Fix early boot crash on gcc-10, third try
commit a9a3ed1eff upstream.

... or the odyssey of trying to disable the stack protector for the
function which generates the stack canary value.

The whole story started with Sergei reporting a boot crash with a kernel
built with gcc-10:

  Kernel panic — not syncing: stack-protector: Kernel stack is corrupted in: start_secondary
  CPU: 1 PID: 0 Comm: swapper/1 Not tainted 5.6.0-rc5—00235—gfffb08b37df9 #139
  Hardware name: Gigabyte Technology Co., Ltd. To be filled by O.E.M./H77M—D3H, BIOS F12 11/14/2013
  Call Trace:
    dump_stack
    panic
    ? start_secondary
    __stack_chk_fail
    start_secondary
    secondary_startup_64
  -—-[ end Kernel panic — not syncing: stack—protector: Kernel stack is corrupted in: start_secondary

This happens because gcc-10 tail-call optimizes the last function call
in start_secondary() - cpu_startup_entry() - and thus emits a stack
canary check which fails because the canary value changes after the
boot_init_stack_canary() call.

To fix that, the initial attempt was to mark the one function which
generates the stack canary with:

  __attribute__((optimize("-fno-stack-protector"))) ... start_secondary(void *unused)

however, using the optimize attribute doesn't work cumulatively
as the attribute does not add to but rather replaces previously
supplied optimization options - roughly all -fxxx options.

The key one among them being -fno-omit-frame-pointer and thus leading to
not present frame pointer - frame pointer which the kernel needs.

The next attempt to prevent compilers from tail-call optimizing
the last function call cpu_startup_entry(), shy of carving out
start_secondary() into a separate compilation unit and building it with
-fno-stack-protector, was to add an empty asm("").

This current solution was short and sweet, and reportedly, is supported
by both compilers but we didn't get very far this time: future (LTO?)
optimization passes could potentially eliminate this, which leads us
to the third attempt: having an actual memory barrier there which the
compiler cannot ignore or move around etc.

That should hold for a long time, but hey we said that about the other
two solutions too so...

Reported-by: Sergei Trofimovich <slyfox@gentoo.org>
Signed-off-by: Borislav Petkov <bp@suse.de>
Tested-by: Kalle Valo <kvalo@codeaurora.org>
Cc: <stable@vger.kernel.org>
Link: https://lkml.kernel.org/r/20200314164451.346497-1-slyfox@gentoo.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2020-05-20 08:18:49 +02:00
..
acpi x86: ACPI: fix CPU hotplug deadlock 2020-04-23 10:30:20 +02:00
asm-generic
clocksource
crypto
drm
dt-bindings
keys KEYS: Don't write out to userspace while holding key semaphore 2020-04-23 10:30:24 +02:00
kvm
linux x86: Fix early boot crash on gcc-10, third try 2020-05-20 08:18:49 +02:00
math-emu
media
memory
misc
net netfilter: conntrack: avoid gcc-10 zero-length-bounds warning 2020-05-20 08:18:43 +02:00
pcmcia
ras
rdma
scsi scsi: Revert "target: iscsi: Wait for all commands to finish before freeing a session" 2020-02-28 16:38:58 +01:00
soc
sound ALSA: rawmidi: Fix racy buffer resize under concurrent accesses 2020-05-20 08:18:47 +02:00
target scsi: target: fix hang when multiple threads try to destroy the same iscsi session 2020-04-21 09:03:11 +02:00
trace svcrdma: Fix trace point use-after-free race 2020-05-02 17:25:51 +02:00
uapi include/uapi/linux/swab.h: fix userspace breakage, use __BITS_PER_LONG for swap 2020-05-02 17:25:48 +02:00
video
xen