Received: by 2002:a25:7ec1:0:0:0:0:0 with SMTP id z184csp6542052ybc; Thu, 28 Nov 2019 01:01:22 -0800 (PST) X-Google-Smtp-Source: APXvYqwjRAK3MzLGdzeyfVB2ZOnHvgt6yYbsy1xV33Z1H3mt5MJYaXrdqrBIKeNbtQCS8rNl4va7 X-Received: by 2002:a7b:c411:: with SMTP id k17mr8213099wmi.119.1574931681972; Thu, 28 Nov 2019 01:01:21 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1574931681; cv=none; d=google.com; s=arc-20160816; b=cePoCUxM1YIUDwMN2owsxlQwHkBHzP0oh9SmbYOGcYWIUDKIQBHpWhuuCJlXdkMhGx /kIsSJ1ti0b/G7zpnhgjtQCJE9mgEklWk3qlU2xI5c6QEJkzaDQgQ5ty0sXuHX9s2swb udKHxOtGbYCU27QxisQJAGLPQenWVbZPB0M3ckmDk47/PU1/XfFIv8bRbR0xXvPo4E5d y+Y63ecN3hc5qTw5KICIua2ECmOQLIkHsAuVkvUFUm8pExZ2/lXNpwIKRRw7A2cQt82p RYsiCU49IPGfbflJD46Yagt3fBD9vM6HjEvdycLaK/DfdOqKzVYdloVT91ORSZsLw11h aHZA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:in-reply-to:content-transfer-encoding :content-disposition:mime-version:references:message-id:subject:cc :to:from:date; bh=63q6oXysWISvqqLIhAgcteSXOQBzJESBlob4AWxTr+s=; b=IaCLSr013JYyOZoTupjgyWvJqcvRufsRxPRk6wLcU5bflsbi5z+42L1TAc5Q14wa8/ TyH1U3En1LG/CfZH1Jz6aKBsRroi3JRk8Dl56QI8fUPKC8GOsb8z8f+rsH/3gnIIXiVy i82ElBGx4Tqn0v9ZnLCmK+95vuaoUM4yy9+7QGlRzNbepPMx+m4yGyaPhrunysZTL2XH nhGtETa6AyimTJ/P3j9yccoF8RRDhW40LfjBf174VZBaxupdy5QZnKIanef0RY9Mwq65 UIKqTb+L0Q4t7ai9CPyDwwQeDe8EcABcI9QbOwG6u3L84OqHWXVQYlw5K1p/A1d0zidn sQoA== 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 f23si13683070edj.380.2019.11.28.01.00.57; Thu, 28 Nov 2019 01:01:21 -0800 (PST) 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 S1727608AbfK1IxP convert rfc822-to-8bit (ORCPT + 99 others); Thu, 28 Nov 2019 03:53:15 -0500 Received: from Galois.linutronix.de ([193.142.43.55]:46358 "EHLO Galois.linutronix.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726749AbfK1IxP (ORCPT ); Thu, 28 Nov 2019 03:53:15 -0500 Received: from bigeasy by Galois.linutronix.de with local (Exim 4.80) (envelope-from ) id 1iaFXu-0003iG-Ny; Thu, 28 Nov 2019 09:53:06 +0100 Date: Thu, 28 Nov 2019 09:53:06 +0100 From: Sebastian Andrzej Siewior To: Barret Rhoden Cc: Borislav Petkov , Josh Bleecher Snyder , Rik van Riel , x86@kernel.org, linux-kernel@vger.kernel.org, Thomas Gleixner , Ingo Molnar , ian@airs.com, Austin Clements , David Chase Subject: [PATCH v2] x86/fpu: Don't cache access to fpu_fpregs_owner_ctx Message-ID: <20191128085306.hxfa2o3knqtu4wfn@linutronix.de> References: <20191126202026.csrmjre6vn2nxq7c@linutronix.de> <20191127124243.u74osvlkhcmsskng@linutronix.de> <20191127140754.GB3812@zn.tnic> MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Disposition: inline Content-Transfer-Encoding: 8BIT In-Reply-To: Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org The state/owner of FPU is saved fpu_fpregs_owner_ctx by pointing to the context that is currently loaded. It never changed during the life time of a task and remained stable/constant. Since deferred loading the FPU registers on return to userland, the content of fpu_fpregs_owner_ctx may change during preemption and must not be cached. This went unnoticed for some time and was now noticed, in particular gcc-9 is able to cache that load in copy_fpstate_to_sigframe() and reuse it in the retry loop: copy_fpstate_to_sigframe() load fpu_fpregs_owner_ctx and save on stack fpregs_lock() copy_fpregs_to_sigframe() /* failed */ fpregs_unlock() *** PREEMPTION, another uses FPU, changes fpu_fpregs_owner_ctx *** fault_in_pages_writeable() /* succeed, retry */ fpregs_lock() __fpregs_load_activate() fpregs_state_valid() /* uses fpu_fpregs_owner_ctx from stack */ copy_fpregs_to_sigframe() /* succeeds, random FPU content */ This is a comparison of the assembly of gcc-9, without vs with this patch: | # arch/x86/kernel/fpu/signal.c:173: if (!access_ok(buf, size)) | cmpq %rdx, %rax # tmp183, _4 | jb .L190 #, |-# arch/x86/include/asm/fpu/internal.h:512: return fpu == this_cpu_read_stable(fpu_fpregs_owner_ctx) && cpu == fpu->last_cpu; |-#APP |-# 512 "arch/x86/include/asm/fpu/internal.h" 1 |- movq %gs:fpu_fpregs_owner_ctx,%rax #, pfo_ret__ |-# 0 "" 2 |-#NO_APP |- movq %rax, -88(%rbp) # pfo_ret__, %sfp … |-# arch/x86/include/asm/fpu/internal.h:512: return fpu == this_cpu_read_stable(fpu_fpregs_owner_ctx) && cpu == fpu->last_cpu; |- movq -88(%rbp), %rcx # %sfp, pfo_ret__ |- cmpq %rcx, -64(%rbp) # pfo_ret__, %sfp |+# arch/x86/include/asm/fpu/internal.h:512: return fpu == this_cpu_read(fpu_fpregs_owner_ctx) && cpu == fpu->last_cpu; |+#APP |+# 512 "arch/x86/include/asm/fpu/internal.h" 1 |+ movq %gs:fpu_fpregs_owner_ctx(%rip),%rax # fpu_fpregs_owner_ctx, pfo_ret__ |+# 0 "" 2 |+# arch/x86/include/asm/fpu/internal.h:512: return fpu == this_cpu_read(fpu_fpregs_owner_ctx) && cpu == fpu->last_cpu; |+#NO_APP |+ cmpq %rax, -64(%rbp) # pfo_ret__, %sfp Use this_cpu_read() instead this_cpu_read_stable() to avoid caching of fpu_fpregs_owner_ctx during preemption points. The fixes tag points to the commit where defered FPU loading was added. Since this commit the compiler is no longer allowed move the load of fpu_fpregs_owner_ctx somewhere else / outside of the locked section. A task preemption will change its value and stale content will be observed. Link: https://bugzilla.kernel.org/show_bug.cgi?id=205663 Fixes: 5f409e20b7945 ("x86/fpu: Defer FPU state load until return to userspace") Debugged-by: Austin Clements Debugged-by: David Chase Debugged-by: Ian Lance Taylor Tested-by: Borislav Petkov Reviewed-by: Rik van Riel Signed-off-by: Sebastian Andrzej Siewior --- v1…v2: - Adding tags - Explaining why Fixes: does not point to the bisected commit. arch/x86/include/asm/fpu/internal.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/include/asm/fpu/internal.h b/arch/x86/include/asm/fpu/internal.h index 4c95c365058aa..44c48e34d7994 100644 --- a/arch/x86/include/asm/fpu/internal.h +++ b/arch/x86/include/asm/fpu/internal.h @@ -509,7 +509,7 @@ static inline void __fpu_invalidate_fpregs_state(struct fpu *fpu) static inline int fpregs_state_valid(struct fpu *fpu, unsigned int cpu) { - return fpu == this_cpu_read_stable(fpu_fpregs_owner_ctx) && cpu == fpu->last_cpu; + return fpu == this_cpu_read(fpu_fpregs_owner_ctx) && cpu == fpu->last_cpu; } /* -- 2.24.0