Received: by 2002:ac0:a594:0:0:0:0:0 with SMTP id m20-v6csp1954262imm; Thu, 24 May 2018 03:32:36 -0700 (PDT) X-Google-Smtp-Source: AB8JxZr0iKxaCOEx+ApzCEK87wP6xbMmhEbe5jvQB7L6puLtFmJm68lhU7Kf8SEOccPOaG0x4eAg X-Received: by 2002:a65:640d:: with SMTP id a13-v6mr4564747pgv.154.1527157956535; Thu, 24 May 2018 03:32:36 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1527157956; cv=none; d=google.com; s=arc-20160816; b=fdsV93k6KoM6bRNcFNakUAspZrfMlikTGMi469dvwzXWeDwzynU9NuCD9jAyudahgd vmEDeRLuEWvxUU4wjq+5W8NFtBV43Xf9hpLJiUtg8fuyHuKKPcFJuEFPDnIRpxAhjOuo 5KbcnNyDGtAwOxbWvpl0CHoACJ9NSFQwmoMO95DYRkPNEYq4rxWV7FDPDAGhAhtiukSS tIbk+zjABpzH3TmO2iOjLkC/Xe0ECiBZvSwiKnAEcDqt0JWrP+OkUQOYb+IUvTayRVgh fii2HjSCmfTvfdo5ardGHEhBuzZySUFxIHlKUUIRMbQqc1TtzNts7v0COJiZRqEQuyCL FeWg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:mime-version:user-agent:references :in-reply-to:message-id:date:subject:cc:to:from:dkim-signature :arc-authentication-results; bh=z3sA9cngb499wUZFbY04Q7+rWHMv0Y43VEoDq8/TvYQ=; b=BrY1v/85vTtyi3lt5SI12w3L2StP9inOOa2htWy2M2Ab3FSqckNv2DUr4EG5jUsnMC OpCduExASzPrTebhu7iH5oXwQzhv7FncYd3wXoOKLK2jz3cePV9FgLmk5hOR44BkysGD y0KbxxNRPFcK0D2xiW+MM0z1525hDIrRO3O+zgd0xuDjSpZ09HNg8mHyJIKrt9Jrn4Lc lyWgwRWwYsXVYHB3zXS8sFm4RdqiLqsuhlzahEehiN9v4JvN05+DGYJ08Og5OEOfuoTx dEwP2Z4JxffW0zi4gHzjhQWAmpy7CAsfIsEYfqiICUSpo/qQ3hNEfp9tsSwX50rYnY/7 eX0w== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=OvwV2alP; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id i125-v6si11573409pgc.88.2018.05.24.03.32.21; Thu, 24 May 2018 03:32:36 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=OvwV2alP; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1032123AbeEXKbe (ORCPT + 99 others); Thu, 24 May 2018 06:31:34 -0400 Received: from mail.kernel.org ([198.145.29.99]:45444 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1030867AbeEXKBE (ORCPT ); Thu, 24 May 2018 06:01:04 -0400 Received: from localhost (LFbn-1-12247-202.w90-92.abo.wanadoo.fr [90.92.61.202]) (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 3BAAB2088E; Thu, 24 May 2018 10:01:03 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1527156063; bh=tPik+/+YI8RAeFXucPPU5jKTxapLR2W6CNyhyuSdgvM=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=OvwV2alPJU7BE3RmS7Z5vkJN5X4JVo/MmwHW97LGGoz+up+YX4j1QAoWDIPgk8Y2Z jfIxdP1p9IR1tMdnNMnnelv6Dmrpa4w/2yt19ipvY9zIAqMzLvAl6Gu/YDpMJ9xpxp 4izRvnm9J6tiEKJQKX8QxyLXIun7aUVGHvJNrSv8= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org, stable@vger.kernel.org Cc: Greg Kroah-Hartman , Martin Schwidefsky Subject: [PATCH 4.16 050/161] s390: add automatic detection of the spectre defense Date: Thu, 24 May 2018 11:37:55 +0200 Message-Id: <20180524093024.452281026@linuxfoundation.org> X-Mailer: git-send-email 2.17.0 In-Reply-To: <20180524093018.331893860@linuxfoundation.org> References: <20180524093018.331893860@linuxfoundation.org> User-Agent: quilt/0.65 X-stable: review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 4.16-stable review patch. If anyone has any objections, please let me know. ------------------ From: Martin Schwidefsky [ Upstream commit 6e179d64126b909f0b288fa63cdbf07c531e9b1d ] Automatically decide between nobp vs. expolines if the spectre_v2=auto kernel parameter is specified or CONFIG_EXPOLINE_AUTO=y is set. The decision made at boot time due to CONFIG_EXPOLINE_AUTO=y being set can be overruled with the nobp, nospec and spectre_v2 kernel parameters. Signed-off-by: Martin Schwidefsky Signed-off-by: Greg Kroah-Hartman --- arch/s390/Kconfig | 2 - arch/s390/Makefile | 2 - arch/s390/include/asm/nospec-branch.h | 6 +-- arch/s390/kernel/alternative.c | 1 arch/s390/kernel/module.c | 11 ++--- arch/s390/kernel/nospec-branch.c | 68 +++++++++++++++++++++------------- 6 files changed, 52 insertions(+), 38 deletions(-) --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig @@ -576,7 +576,7 @@ choice config EXPOLINE_OFF bool "spectre_v2=off" -config EXPOLINE_MEDIUM +config EXPOLINE_AUTO bool "spectre_v2=auto" config EXPOLINE_FULL --- a/arch/s390/Makefile +++ b/arch/s390/Makefile @@ -84,7 +84,7 @@ ifdef CONFIG_EXPOLINE CC_FLAGS_EXPOLINE += -mfunction-return=thunk CC_FLAGS_EXPOLINE += -mindirect-branch-table export CC_FLAGS_EXPOLINE - cflags-y += $(CC_FLAGS_EXPOLINE) + cflags-y += $(CC_FLAGS_EXPOLINE) -DCC_USING_EXPOLINE endif endif --- a/arch/s390/include/asm/nospec-branch.h +++ b/arch/s390/include/asm/nospec-branch.h @@ -6,12 +6,10 @@ #include -extern int nospec_call_disable; -extern int nospec_return_disable; +extern int nospec_disable; void nospec_init_branches(void); -void nospec_call_revert(s32 *start, s32 *end); -void nospec_return_revert(s32 *start, s32 *end); +void nospec_revert(s32 *start, s32 *end); #endif /* __ASSEMBLY__ */ --- a/arch/s390/kernel/alternative.c +++ b/arch/s390/kernel/alternative.c @@ -2,6 +2,7 @@ #include #include #include +#include #define MAX_PATCH_LEN (255 - 1) --- a/arch/s390/kernel/module.c +++ b/arch/s390/kernel/module.c @@ -159,7 +159,7 @@ int module_frob_arch_sections(Elf_Ehdr * me->core_layout.size += me->arch.got_size; me->arch.plt_offset = me->core_layout.size; if (me->arch.plt_size) { - if (IS_ENABLED(CONFIG_EXPOLINE) && !nospec_call_disable) + if (IS_ENABLED(CONFIG_EXPOLINE) && !nospec_disable) me->arch.plt_size += PLT_ENTRY_SIZE; me->core_layout.size += me->arch.plt_size; } @@ -318,8 +318,7 @@ static int apply_rela(Elf_Rela *rela, El info->plt_offset; ip[0] = 0x0d10e310; /* basr 1,0 */ ip[1] = 0x100a0004; /* lg 1,10(1) */ - if (IS_ENABLED(CONFIG_EXPOLINE) && - !nospec_call_disable) { + if (IS_ENABLED(CONFIG_EXPOLINE) && !nospec_disable) { unsigned int *ij; ij = me->core_layout.base + me->arch.plt_offset + @@ -440,7 +439,7 @@ int module_finalize(const Elf_Ehdr *hdr, void *aseg; if (IS_ENABLED(CONFIG_EXPOLINE) && - !nospec_call_disable && me->arch.plt_size) { + !nospec_disable && me->arch.plt_size) { unsigned int *ij; ij = me->core_layout.base + me->arch.plt_offset + @@ -467,11 +466,11 @@ int module_finalize(const Elf_Ehdr *hdr, if (IS_ENABLED(CONFIG_EXPOLINE) && (!strcmp(".nospec_call_table", secname))) - nospec_call_revert(aseg, aseg + s->sh_size); + nospec_revert(aseg, aseg + s->sh_size); if (IS_ENABLED(CONFIG_EXPOLINE) && (!strcmp(".nospec_return_table", secname))) - nospec_return_revert(aseg, aseg + s->sh_size); + nospec_revert(aseg, aseg + s->sh_size); } jump_label_apply_nops(me); --- a/arch/s390/kernel/nospec-branch.c +++ b/arch/s390/kernel/nospec-branch.c @@ -10,10 +10,17 @@ static int __init nobp_setup_early(char rc = kstrtobool(str, &enabled); if (rc) return rc; - if (enabled && test_facility(82)) + if (enabled && test_facility(82)) { + /* + * The user explicitely requested nobp=1, enable it and + * disable the expoline support. + */ __set_facility(82, S390_lowcore.alt_stfle_fac_list); - else + if (IS_ENABLED(CONFIG_EXPOLINE)) + nospec_disable = 1; + } else { __clear_facility(82, S390_lowcore.alt_stfle_fac_list); + } return 0; } early_param("nobp", nobp_setup_early); @@ -27,31 +34,46 @@ early_param("nospec", nospec_setup_early #ifdef CONFIG_EXPOLINE -int nospec_call_disable = IS_ENABLED(CONFIG_EXPOLINE_OFF); -int nospec_return_disable = !IS_ENABLED(CONFIG_EXPOLINE_FULL); +int nospec_disable = IS_ENABLED(CONFIG_EXPOLINE_OFF); static int __init nospectre_v2_setup_early(char *str) { - nospec_call_disable = 1; - nospec_return_disable = 1; + nospec_disable = 1; return 0; } early_param("nospectre_v2", nospectre_v2_setup_early); +static int __init spectre_v2_auto_early(void) +{ + if (IS_ENABLED(CC_USING_EXPOLINE)) { + /* + * The kernel has been compiled with expolines. + * Keep expolines enabled and disable nobp. + */ + nospec_disable = 0; + __clear_facility(82, S390_lowcore.alt_stfle_fac_list); + } + /* + * If the kernel has not been compiled with expolines the + * nobp setting decides what is done, this depends on the + * CONFIG_KERNEL_NP option and the nobp/nospec parameters. + */ + return 0; +} +#ifdef CONFIG_EXPOLINE_AUTO +early_initcall(spectre_v2_auto_early); +#endif + static int __init spectre_v2_setup_early(char *str) { if (str && !strncmp(str, "on", 2)) { - nospec_call_disable = 0; - nospec_return_disable = 0; - } - if (str && !strncmp(str, "off", 3)) { - nospec_call_disable = 1; - nospec_return_disable = 1; - } - if (str && !strncmp(str, "auto", 4)) { - nospec_call_disable = 0; - nospec_return_disable = 1; + nospec_disable = 0; + __clear_facility(82, S390_lowcore.alt_stfle_fac_list); } + if (str && !strncmp(str, "off", 3)) + nospec_disable = 1; + if (str && !strncmp(str, "auto", 4)) + spectre_v2_auto_early(); return 0; } early_param("spectre_v2", spectre_v2_setup_early); @@ -104,15 +126,9 @@ static void __init_or_module __nospec_re } } -void __init_or_module nospec_call_revert(s32 *start, s32 *end) -{ - if (nospec_call_disable) - __nospec_revert(start, end); -} - -void __init_or_module nospec_return_revert(s32 *start, s32 *end) +void __init_or_module nospec_revert(s32 *start, s32 *end) { - if (nospec_return_disable) + if (nospec_disable) __nospec_revert(start, end); } @@ -120,8 +136,8 @@ extern s32 __nospec_call_start[], __nosp extern s32 __nospec_return_start[], __nospec_return_end[]; void __init nospec_init_branches(void) { - nospec_call_revert(__nospec_call_start, __nospec_call_end); - nospec_return_revert(__nospec_return_start, __nospec_return_end); + nospec_revert(__nospec_call_start, __nospec_call_end); + nospec_revert(__nospec_return_start, __nospec_return_end); } #endif /* CONFIG_EXPOLINE */