Received: by 2002:a25:7ec1:0:0:0:0:0 with SMTP id z184csp6563276ybc; Thu, 28 Nov 2019 01:24:51 -0800 (PST) X-Google-Smtp-Source: APXvYqztonlbZ76D0eHH6AibBIF8pGkDiL7qKXO5Eu76W0PoQq2Jn9UWP0WmdJIXZ7lXW6OL4Qa+ X-Received: by 2002:a17:906:80c:: with SMTP id e12mr54496608ejd.59.1574933090926; Thu, 28 Nov 2019 01:24:50 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1574933090; cv=none; d=google.com; s=arc-20160816; b=lNnPX98FrOLQ2IKPTXmcRfvLKukRONXOZG9h02zq5Vx5wSIikTyWlOFXBU/dB/jBmJ RfEccSfXPPpI+SaLhukGHh+xr0PgUcSgfiSr12a9FDoC5xNKsvKyyLLUuFarETmYqmF9 +92Hs4fvhW+qy4XCATR7jBf4SbIOHdbBNrZlWp9X4Yfvomj7DbzYL/0d80rY/MSZJsRH FoJ8U1flEUsYf92Z17mjeHBBrk3asfSjnrWkk6Cxtg8RTa68u7Uz6cF6RWYs0LsyX4aI UxqJokoEFjnNzyXzr/V1vvg151sbtdWVANJmPwDXxrNDfdlWYVtMnehSX74rpj2kpD8Y aI+A== 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 :robot-unsubscribe:robot-id:message-id:mime-version:references :in-reply-to:cc:subject:to:reply-to:from:date; bh=AH4YqdKBzNirrSsgQLyKDC7sMso1qzMdst5zgPITwuw=; b=xGzfp+B/3GcBRLeqi5fosnYWv+Y9C0jnczzEhbNzpq9bw0+ujZi6dUH6XO0kTW6Frk 3VIy7KK990706w1e+x1/G2hnsL0EcpkVR7U/DbBtVgtPJh9U2FyVF6AK8VWgedyW4GPy 5pJ8JvefJePKzfTXeCvTBY5Uhc6asR8vRRNX/W1SnuXmW8lSaAE4PEhGz75aKYqFqoaD 2jUvUn7DaWi5Aj9Ogm0ilr6cGYHM5BedNR7B5LJmQDOJRV7LlEe4hBwTRz7diEwu0QJB wemYJ8wW0Iiyw4GzFTBgJtk8ZSW38Od1eScBn9/uEeXhVtuGjfNRfTOLZ4btK3lH1NTV w0Aw== 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 q18si12541639edg.23.2019.11.28.01.24.26; Thu, 28 Nov 2019 01:24:50 -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 S1726920AbfK1JWg convert rfc822-to-8bit (ORCPT + 99 others); Thu, 28 Nov 2019 04:22:36 -0500 Received: from Galois.linutronix.de ([193.142.43.55]:46415 "EHLO Galois.linutronix.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726092AbfK1JWf (ORCPT ); Thu, 28 Nov 2019 04:22:35 -0500 Received: from [5.158.153.53] (helo=tip-bot2.lab.linutronix.de) by Galois.linutronix.de with esmtpsa (TLS1.2:DHE_RSA_AES_256_CBC_SHA256:256) (Exim 4.80) (envelope-from ) id 1iaG04-000467-9b; Thu, 28 Nov 2019 10:22:12 +0100 Received: from [127.0.1.1] (localhost [IPv6:::1]) by tip-bot2.lab.linutronix.de (Postfix) with ESMTP id B5F9A1C1AEF; Thu, 28 Nov 2019 10:22:11 +0100 (CET) Date: Thu, 28 Nov 2019 09:22:11 -0000 From: "tip-bot2 for Sebastian Andrzej Siewior" Reply-to: linux-kernel@vger.kernel.org To: linux-tip-commits@vger.kernel.org Subject: [tip: x86/urgent] x86/fpu: Don't cache access to fpu_fpregs_owner_ctx Cc: Sebastian Andrzej Siewior , Borislav Petkov , Rik van Riel , Aubrey Li , Austin Clements , Barret Rhoden , Dave Hansen , David Chase , "H. Peter Anvin" , ian@airs.com, Ingo Molnar , Josh Bleecher Snyder , Thomas Gleixner , "x86-ml" , LKML In-Reply-To: <20191128085306.hxfa2o3knqtu4wfn@linutronix.de> References: <20191128085306.hxfa2o3knqtu4wfn@linutronix.de> MIME-Version: 1.0 Message-ID: <157493293150.21853.7731511969770345792.tip-bot2@tip-bot2> X-Mailer: tip-git-log-daemon Robot-ID: Robot-Unsubscribe: Contact to get blacklisted from these emails Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 8BIT 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 The following commit has been merged into the x86/urgent branch of tip: Commit-ID: 59c4bd853abcea95eccc167a7d7fd5f1a5f47b98 Gitweb: https://git.kernel.org/tip/59c4bd853abcea95eccc167a7d7fd5f1a5f47b98 Author: Sebastian Andrzej Siewior AuthorDate: Thu, 28 Nov 2019 09:53:06 +01:00 Committer: Borislav Petkov CommitterDate: Thu, 28 Nov 2019 10:16:46 +01:00 x86/fpu: Don't cache access to fpu_fpregs_owner_ctx The state/owner of the FPU is saved to fpu_fpregs_owner_ctx by pointing to the context that is currently loaded. It never changed during the lifetime of a task - it remained stable/constant. After deferred FPU registers loading until return to userland was implemented, 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 since gcc 9 is caching that load in copy_fpstate_to_sigframe() and reusing 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 produced by 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 deferred FPU loading was added. Since this commit, the compiler is no longer allowed to 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. [ bp: Massage. ] Debugged-by: Austin Clements Debugged-by: David Chase Debugged-by: Ian Lance Taylor Fixes: 5f409e20b7945 ("x86/fpu: Defer FPU state load until return to userspace") Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Borislav Petkov Reviewed-by: Rik van Riel Tested-by: Borislav Petkov Cc: Aubrey Li Cc: Austin Clements Cc: Barret Rhoden Cc: Dave Hansen Cc: David Chase Cc: "H. Peter Anvin" Cc: ian@airs.com Cc: Ingo Molnar Cc: Josh Bleecher Snyder Cc: Thomas Gleixner Cc: x86-ml Link: https://lkml.kernel.org/r/20191128085306.hxfa2o3knqtu4wfn@linutronix.de Link: https://bugzilla.kernel.org/show_bug.cgi?id=205663 --- 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 4c95c36..44c48e3 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; } /*