Received: by 2002:a25:868d:0:0:0:0:0 with SMTP id z13csp2934685ybk; Mon, 18 May 2020 11:29:07 -0700 (PDT) X-Google-Smtp-Source: ABdhPJwB+MVS+LF6UYMIjDQZIWMpA2ZPzsfFvXcvE1xa9TKli7nP1b9rs8jAQiqV9/3udvWnBgo/ X-Received: by 2002:a05:6402:2d4:: with SMTP id b20mr15382762edx.118.1589826547122; Mon, 18 May 2020 11:29:07 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1589826547; cv=none; d=google.com; s=arc-20160816; b=yijGChU453+HHvEkHFvbj0rPvz86M19Y6sOAVJfmfy699C1mJLqF6cRyPTYKFd+uBB sw7aX0UI3sGjRPCmufs0TfZV7lIhHi5o18ODohbvuOpaCeZSuVaF3jyVaS9olwA3u1wB I5Cc8WdSeBTwWf8AnDACLlk281drsPD4W3VTw2AwsHaXz3s94UnypeomVj4fISBiUg6L W4TNn3W1mL+345vIfJopIEnvxnqgs2X1p4cm7jsJu0ut6bj55sVQ8dwcA4WwThaQ/hSe mLxG9ldNGZc3e7BBPIJqy0E3FCZJH4AyvdS7bRncpfUw73GjdVhafeTYLSDm0tH6zTeA LT3A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=sCsjcoxzQkFwnFNkNnHb4429uGEHQ5O5yHpEimGVfPg=; b=H84eTK4LuTuDYjOkISy5WQajsJewUk/dTRWik/G4cWrCYEHF5hWhsYqIcn6hv4TVA3 mqSy3iNvgn6vsqQlKvlBB5EhJQDyM5HxR1fgwgkEm9/uTc+96R2DJNWQTGKGlN2tAA7j aVcZBalL1gKbjA9HhGYFfaN2Ro3ERfT3+ZY4FmD5YP2KQNYXAZFTQSnVP/qDb89yIQle fbDBSNymeJcKusbwiFkPfMfW9z4RuQPJ64VGH10H8zmzYK6LAm+/Aihi4tJUdhHtrxl8 ttRzFDyOoO531CU8LyT6f+dfP6+pBd3yqMLPupfJAqX9mAzTsmfRKEy433Z2p0JIlcJg decQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=OIQVwC0u; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id s24si6837761ejd.57.2020.05.18.11.28.40; Mon, 18 May 2020 11:29:07 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=OIQVwC0u; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729850AbgERRpD (ORCPT + 99 others); Mon, 18 May 2020 13:45:03 -0400 Received: from mail.kernel.org ([198.145.29.99]:43478 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729824AbgERRoz (ORCPT ); Mon, 18 May 2020 13:44:55 -0400 Received: from localhost (83-86-89-107.cable.dynamic.v4.ziggo.nl [83.86.89.107]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id 1490B20657; Mon, 18 May 2020 17:44:54 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1589823895; bh=bc9aIWpS1FEP4YyzZDKXtHerIJXQULWKw7gPJfzIuaU=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=OIQVwC0u1lFEhwWHVCVq2DL3t5R/kPoWvNokK+gfoQ2NWgipHvNhs5/7sZe30mGPS Y2CxXYVWrdBgmc8dQsbHY7MHLsinYWVO9gAHHEFJY8xmz1g0q8mCxRYJiiqhIG88Fm zjJz/OWBx9hwpgUTod8klGTcTfTWS0boaB7JnwqY= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Sergei Trofimovich , Borislav Petkov , Kalle Valo Subject: [PATCH 4.9 80/90] x86: Fix early boot crash on gcc-10, third try Date: Mon, 18 May 2020 19:36:58 +0200 Message-Id: <20200518173507.502191111@linuxfoundation.org> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20200518173450.930655662@linuxfoundation.org> References: <20200518173450.930655662@linuxfoundation.org> User-Agent: quilt/0.66 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Borislav Petkov commit a9a3ed1eff3601b63aea4fb462d8b3b92c7c1e7e 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 Signed-off-by: Borislav Petkov Tested-by: Kalle Valo Cc: Link: https://lkml.kernel.org/r/20200314164451.346497-1-slyfox@gentoo.org Signed-off-by: Greg Kroah-Hartman --- arch/x86/include/asm/stackprotector.h | 7 ++++++- arch/x86/kernel/smpboot.c | 8 ++++++++ arch/x86/xen/smp.c | 1 + include/linux/compiler.h | 7 +++++++ init/main.c | 2 ++ 5 files changed, 24 insertions(+), 1 deletion(-) --- a/arch/x86/include/asm/stackprotector.h +++ b/arch/x86/include/asm/stackprotector.h @@ -54,8 +54,13 @@ /* * Initialize the stackprotector canary value. * - * NOTE: this must only be called from functions that never return, + * NOTE: this must only be called from functions that never return * and it must always be inlined. + * + * In addition, it should be called from a compilation unit for which + * stack protector is disabled. Alternatively, the caller should not end + * with a function call which gets tail-call optimized as that would + * lead to checking a modified canary value. */ static __always_inline void boot_init_stack_canary(void) { --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c @@ -249,6 +249,14 @@ static void notrace start_secondary(void wmb(); cpu_startup_entry(CPUHP_AP_ONLINE_IDLE); + + /* + * Prevent tail call to cpu_startup_entry() because the stack protector + * guard has been changed a couple of function calls up, in + * boot_init_stack_canary() and must not be checked before tail calling + * another function. + */ + prevent_tail_call_optimization(); } /** --- a/arch/x86/xen/smp.c +++ b/arch/x86/xen/smp.c @@ -116,6 +116,7 @@ asmlinkage __visible void cpu_bringup_an #endif cpu_bringup(); cpu_startup_entry(CPUHP_AP_ONLINE_IDLE); + prevent_tail_call_optimization(); } void xen_smp_intr_free(unsigned int cpu) --- a/include/linux/compiler.h +++ b/include/linux/compiler.h @@ -605,4 +605,11 @@ unsigned long read_word_at_a_time(const # define __kprobes # define nokprobe_inline inline #endif + +/* + * This is needed in functions which generate the stack canary, see + * arch/x86/kernel/smpboot.c::start_secondary() for an example. + */ +#define prevent_tail_call_optimization() mb() + #endif /* __LINUX_COMPILER_H */ --- a/init/main.c +++ b/init/main.c @@ -662,6 +662,8 @@ asmlinkage __visible void __init start_k /* Do the rest non-__init'ed, we're now alive */ rest_init(); + + prevent_tail_call_optimization(); } /* Call all constructor functions linked into the kernel. */