Received: by 2002:a25:7ec1:0:0:0:0:0 with SMTP id z184csp5479036ybc; Wed, 27 Nov 2019 04:46:27 -0800 (PST) X-Google-Smtp-Source: APXvYqxsEqWmw02IGT4lS0NfWOJZNpPmHi0si5XLlyWYpVybtjJT57mJCUvpUlcFsg2UaLoWUpsq X-Received: by 2002:a50:ec83:: with SMTP id e3mr31690910edr.292.1574858787853; Wed, 27 Nov 2019 04:46:27 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1574858787; cv=none; d=google.com; s=arc-20160816; b=YA3GPOzuqZRTCn/0REtAC5LqiyUW8Ne7G39MZFyHvHT9pr/rqYiQvc8cmYXTVrBJvT JieTJCQjYj26N49d6TyUApWT0VvsHZtwODewxcUP+Lvd7LQ+0c/zzu0fgTvcc86GeonE HRyh/oJb38r0G5jTyNlhk14ARH69JJfPIzw4aZg3BcYc1vKQGFqnF/ImlmUpUMik6z08 M1JzAllDuwvjOnDqoWcmWKppg47UC0DWiyCubmMibrM5OaHugdr4LUAfcj5eUJoKxBgp cZL/2SoHJGmRfF9J2yjBJd+d6/MqNTBhSJnIj70qqa+Ul+O2tbeXF6XOpBIfx2nByEiW SnZA== 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=A5ocDmXUQYb7tegUkT641MWOGTClLw1OUd2peoH7pXc=; b=Qk39f4CAtwt8Etrz5MrKTDq2RrLK2CIysMHWZXaIAR5eZFQCNU63ydQaln9eEPMP3X 9wy2BBkqeq0nUlPQj52/FuZGcJl64QX04ket6OCM4Bi9v8Uoh3AEVeJR2bmYP4l4OHZm aSOTgYgGHgQ0mwczIvhhnI9vE/ZhOlpBr6+s/h8dHYwRu2+WgpCBq3rGEVu8C8EqHOZk IFL30FzOucUUYX65wVnHwnX7uuqUuIkz7szzMV5CcaFBKAzXjEbvzQ3R0B0HP1jlzEpr yrg63jMtwnSfY4WKf0KgugsOxSJ1G5NmITpsrreZnDKO9RJTjXF4kirqVEOoD8EI+EKF v5LQ== 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 dd11si3118035ejb.177.2019.11.27.04.46.03; Wed, 27 Nov 2019 04:46:27 -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 S1726587AbfK0Mmw convert rfc822-to-8bit (ORCPT + 99 others); Wed, 27 Nov 2019 07:42:52 -0500 Received: from Galois.linutronix.de ([193.142.43.55]:44615 "EHLO Galois.linutronix.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726478AbfK0Mmw (ORCPT ); Wed, 27 Nov 2019 07:42:52 -0500 Received: from bigeasy by Galois.linutronix.de with local (Exim 4.80) (envelope-from ) id 1iZweZ-0006Ro-Qo; Wed, 27 Nov 2019 13:42:43 +0100 Date: Wed, 27 Nov 2019 13:42:43 +0100 From: Sebastian Andrzej Siewior To: Barret Rhoden , Josh Bleecher Snyder Cc: "Rik van Riel\"" , x86@kernel.org, linux-kernel@vger.kernel.org, Thomas Gleixner , Ingo Molnar , Borislav Petkov Subject: [PATCH] x86/fpu: Don't cache access to fpu_fpregs_owner_ctx Message-ID: <20191127124243.u74osvlkhcmsskng@linutronix.de> References: <20191126202026.csrmjre6vn2nxq7c@linutronix.de> 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 we 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. Fixes: 5f409e20b7945 ("x86/fpu: Defer FPU state load until return to userspace") --- There is no Sign-off by here. Could this please be verified by the reporter? Also I would like to add Debugged-by: Ian Lance Taylor but I lack the complete address also I'm not sure if he wants to. Also please send a Reported-by line since I'm not sure who started this. 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