Received: by 2002:a25:ad19:0:0:0:0:0 with SMTP id y25csp9395816ybi; Wed, 10 Jul 2019 09:32:41 -0700 (PDT) X-Google-Smtp-Source: APXvYqxQ8uK4L8+8LPgRe28Hbci6t1cZV4YVBJPr+f72gqrDKKQtv4WizT8U9lJrx5Ge8t5+n1qa X-Received: by 2002:a63:fe15:: with SMTP id p21mr17967095pgh.149.1562776361593; Wed, 10 Jul 2019 09:32:41 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1562776361; cv=none; d=google.com; s=arc-20160816; b=KyDS3cmsXZD0YFDUp00EqVYBKX2Jd41CvdUhNId7RVGSmM5RUc4KdOfTfCrHKMJRnb N94RY3qifmfn6T6I5FrhWB9XCYs+4jqk4Ddk7YcwLhm41wvo7iv/2ZICKQCrijFfR73V tk2OMHRtHoDhO0l2J7wH31Cp0qsCrWXeE6Zp3UIym0cNSkMGIv8a/iU72FmPPdcsGwQ4 qK0zhKAoCbfL1INIVpML8RgQcEvtxZv7bLTrQa7qkrlfClbt5W3DhD6FQGVF5q/U7Rn3 dH/MSFGyeNfZh823foWUUo0rJF28cSIEHji7MpPlVAcFpV/l41av7KGpYov/Zn9s45xe t4RQ== 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 :message-id:in-reply-to:subject:cc:to:from:date; bh=id0CeWSHlh++5pJsAV67X8bC2hSh3ViPru240NTtDyI=; b=0E7HQ3tyt12KwAafaqAWbUF1s7DaXh8RYqqOUpZTYz9m3G7t6GP3oa/2HsJeIZEauZ mLwKGvgAML3/vZq2LFtKCAq21eaIAATTpnDUjDfUKlGpKsBOsbWLYtWzzci8t5yAQ8VS rQO7Pfbg99v5BhzZhuenIkR3EaPbm2S/Gxbtk66wvqV/ptknFYYKY6pI0gH+CwX2zGsy vKAR+bcc+yxPFbAJFPsJOu0cLpeuSzoTLZNksYMWqsm8+Vw6qXCLALtgfQ43ncgHLO4z 7e7alZTqLG+fwuWdTBvV7V88TMf0NwWV//8j51rtNcrhS3sXTnl3DsfkgcKLBcVp+aZ9 De4g== ARC-Authentication-Results: i=1; mx.google.com; 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 d5si2377564pgv.584.2019.07.10.09.32.25; Wed, 10 Jul 2019 09:32:41 -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; 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 S1727427AbfGJPNi (ORCPT + 99 others); Wed, 10 Jul 2019 11:13:38 -0400 Received: from Galois.linutronix.de ([193.142.43.55]:47975 "EHLO Galois.linutronix.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727030AbfGJPNi (ORCPT ); Wed, 10 Jul 2019 11:13:38 -0400 Received: from pd9ef1cb8.dip0.t-ipconnect.de ([217.239.28.184] helo=nanos) by Galois.linutronix.de with esmtpsa (TLS1.2:DHE_RSA_AES_256_CBC_SHA256:256) (Exim 4.80) (envelope-from ) id 1hlEHd-0005JO-8B; Wed, 10 Jul 2019 17:13:25 +0200 Date: Wed, 10 Jul 2019 17:13:24 +0200 (CEST) From: Thomas Gleixner To: Peter Zijlstra cc: Jiri Kosina , Xi Ruoyao , Kees Cook , Linus Torvalds , Ingo Molnar , Linux List Kernel Mailing , Borislav Petkov , Len Brown , Andrew Morton , "Rafael J. Wysocki" , Tony Luck , Bob Moore , Erik Schmauss , Josh Poimboeuf , Daniel Bristot de Oliveira , Nadav Amit , Juergen Gross Subject: Re: [GIT PULL] x86/topology changes for v5.3 In-Reply-To: <20190710142653.GJ3419@hirez.programming.kicks-ass.net> Message-ID: References: <201907091727.91CC6C72D8@keescook> <1ad2de95e694a29909801d022fe2d556df9a4bd5.camel@mengyan1223.wang> <768463eb26a2feb0fcc374fd7f9cc28b96976917.camel@mengyan1223.wang> <20190710134433.GN3402@hirez.programming.kicks-ass.net> <20190710142653.GJ3419@hirez.programming.kicks-ass.net> User-Agent: Alpine 2.21 (DEB 202 2017-01-01) MIME-Version: 1.0 Content-Type: text/plain; charset=US-ASCII X-Linutronix-Spam-Score: -1.0 X-Linutronix-Spam-Level: - X-Linutronix-Spam-Status: No , -1.0 points, 5.0 required, ALL_TRUSTED=-1,SHORTCIRCUIT=-0.0001 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Wed, 10 Jul 2019, Peter Zijlstra wrote: > On Wed, Jul 10, 2019 at 04:22:51PM +0200, Jiri Kosina wrote: > > On Wed, 10 Jul 2019, Peter Zijlstra wrote: > > > > > If we mark the key as RO after init, and then try and modify the key to > > > link module usage sites, things might go bang as described. > > > > > > Thanks! > > > > > > > > > diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c > > > index 27d7864e7252..5bf7a8354da2 100644 > > > --- a/arch/x86/kernel/cpu/common.c > > > +++ b/arch/x86/kernel/cpu/common.c > > > @@ -366,7 +366,7 @@ static __always_inline void setup_umip(struct cpuinfo_x86 *c) > > > cr4_clear_bits(X86_CR4_UMIP); > > > } > > > > > > -DEFINE_STATIC_KEY_FALSE_RO(cr_pinning); > > > +DEFINE_STATIC_KEY_FALSE(cr_pinning); > > > > Good catch, I guess that is going to fix it. > > > > At the same time though, it sort of destroys the original intent of Kees' > > patch, right? The exploits will just have to call static_key_disable() > > prior to calling native_write_cr4() again, and the protection is gone. > > This is fixable by moving native_write_cr*() out-of-line, such that they > never end up in a module. Something like the below. Builds and boots, must be perfect. Thanks, tglx 8<---------------- arch/x86/include/asm/processor.h | 1 arch/x86/include/asm/special_insns.h | 41 ------------------- arch/x86/kernel/cpu/common.c | 72 +++++++++++++++++++++++++++-------- arch/x86/kernel/smpboot.c | 14 ------ arch/x86/xen/smp_pv.c | 1 5 files changed, 61 insertions(+), 68 deletions(-) --- a/arch/x86/include/asm/processor.h +++ b/arch/x86/include/asm/processor.h @@ -741,6 +741,7 @@ extern void load_direct_gdt(int); extern void load_fixmap_gdt(int); extern void load_percpu_segment(int); extern void cpu_init(void); +extern void cr4_init(void); static inline unsigned long get_debugctlmsr(void) { --- a/arch/x86/include/asm/special_insns.h +++ b/arch/x86/include/asm/special_insns.h @@ -18,9 +18,7 @@ */ extern unsigned long __force_order; -/* Starts false and gets enabled once CPU feature detection is done. */ -DECLARE_STATIC_KEY_FALSE(cr_pinning); -extern unsigned long cr4_pinned_bits; +void native_write_cr0(unsigned long val); static inline unsigned long native_read_cr0(void) { @@ -29,24 +27,6 @@ static inline unsigned long native_read_ return val; } -static inline void native_write_cr0(unsigned long val) -{ - unsigned long bits_missing = 0; - -set_register: - asm volatile("mov %0,%%cr0": "+r" (val), "+m" (__force_order)); - - if (static_branch_likely(&cr_pinning)) { - if (unlikely((val & X86_CR0_WP) != X86_CR0_WP)) { - bits_missing = X86_CR0_WP; - val |= bits_missing; - goto set_register; - } - /* Warn after we've set the missing bits. */ - WARN_ONCE(bits_missing, "CR0 WP bit went missing!?\n"); - } -} - static inline unsigned long native_read_cr2(void) { unsigned long val; @@ -91,24 +71,7 @@ static inline unsigned long native_read_ return val; } -static inline void native_write_cr4(unsigned long val) -{ - unsigned long bits_missing = 0; - -set_register: - asm volatile("mov %0,%%cr4": "+r" (val), "+m" (cr4_pinned_bits)); - - if (static_branch_likely(&cr_pinning)) { - if (unlikely((val & cr4_pinned_bits) != cr4_pinned_bits)) { - bits_missing = ~val & cr4_pinned_bits; - val |= bits_missing; - goto set_register; - } - /* Warn after we've set the missing bits. */ - WARN_ONCE(bits_missing, "CR4 bits went missing: %lx!?\n", - bits_missing); - } -} +void native_write_cr4(unsigned long val); #ifdef CONFIG_X86_64 static inline unsigned long native_read_cr8(void) --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -366,10 +366,62 @@ static __always_inline void setup_umip(s cr4_clear_bits(X86_CR4_UMIP); } -DEFINE_STATIC_KEY_FALSE_RO(cr_pinning); -EXPORT_SYMBOL(cr_pinning); -unsigned long cr4_pinned_bits __ro_after_init; -EXPORT_SYMBOL(cr4_pinned_bits); +static DEFINE_STATIC_KEY_FALSE_RO(cr_pinning); +static unsigned long cr4_pinned_bits __ro_after_init; + +void native_write_cr0(unsigned long val) +{ + unsigned long bits_missing = 0; + +set_register: + asm volatile("mov %0,%%cr0": "+r" (val), "+m" (__force_order)); + + if (static_branch_likely(&cr_pinning)) { + if (unlikely((val & X86_CR0_WP) != X86_CR0_WP)) { + bits_missing = X86_CR0_WP; + val |= bits_missing; + goto set_register; + } + /* Warn after we've set the missing bits. */ + WARN_ONCE(bits_missing, "CR0 WP bit went missing!?\n"); + } +} +EXPORT_SYMBOL(native_write_cr0); + +void native_write_cr4(unsigned long val) +{ + unsigned long bits_missing = 0; + +set_register: + asm volatile("mov %0,%%cr4": "+r" (val), "+m" (cr4_pinned_bits)); + + if (static_branch_likely(&cr_pinning)) { + if (unlikely((val & cr4_pinned_bits) != cr4_pinned_bits)) { + bits_missing = ~val & cr4_pinned_bits; + val |= bits_missing; + goto set_register; + } + /* Warn after we've set the missing bits. */ + WARN_ONCE(bits_missing, "CR4 bits went missing: %lx!?\n", + bits_missing); + } +} +EXPORT_SYMBOL(native_write_cr4); + +void cr4_init(void) +{ + unsigned long cr4 = __read_cr4(); + + if (boot_cpu_has(X86_FEATURE_PCID)) + cr4 |= X86_CR4_PCIDE; + if (static_branch_likely(&cr_pinning)) + cr4 |= cr4_pinned_bits; + + __write_cr4(cr4); + + /* Initialize cr4 shadow for this CPU. */ + this_cpu_write(cpu_tlbstate.cr4, cr4); +} /* * Once CPU feature detection is finished (and boot params have been @@ -1723,12 +1775,6 @@ void cpu_init(void) wait_for_master_cpu(cpu); - /* - * Initialize the CR4 shadow before doing anything that could - * try to read it. - */ - cr4_init_shadow(); - if (cpu) load_ucode_ap(); @@ -1823,12 +1869,6 @@ void cpu_init(void) wait_for_master_cpu(cpu); - /* - * Initialize the CR4 shadow before doing anything that could - * try to read it. - */ - cr4_init_shadow(); - show_ucode_info_early(); pr_info("Initializing CPU#%d\n", cpu); --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c @@ -210,28 +210,16 @@ static int enable_start_cpu0; */ static void notrace start_secondary(void *unused) { - unsigned long cr4 = __read_cr4(); - /* * Don't put *anything* except direct CPU state initialization * before cpu_init(), SMP booting is too fragile that we want to * limit the things done here to the most necessary things. */ - if (boot_cpu_has(X86_FEATURE_PCID)) - cr4 |= X86_CR4_PCIDE; - if (static_branch_likely(&cr_pinning)) - cr4 |= cr4_pinned_bits; - - __write_cr4(cr4); + cr4_init(); #ifdef CONFIG_X86_32 /* switch away from the initial page table */ load_cr3(swapper_pg_dir); - /* - * Initialize the CR4 shadow before doing anything that could - * try to read it. - */ - cr4_init_shadow(); __flush_tlb_all(); #endif load_current_idt(); --- a/arch/x86/xen/smp_pv.c +++ b/arch/x86/xen/smp_pv.c @@ -58,6 +58,7 @@ static void cpu_bringup(void) { int cpu; + cr4_init(); cpu_init(); touch_softlockup_watchdog(); preempt_disable();