Message ID | 20230119212317.8324-7-rick.p.edgecombe@intel.com |
---|---|
State | New |
Headers |
Return-Path: <linux-kernel-owner@vger.kernel.org> Delivered-To: ouuuleilei@gmail.com Received: by 2002:adf:eb09:0:0:0:0:0 with SMTP id s9csp555371wrn; Thu, 19 Jan 2023 13:34:00 -0800 (PST) X-Google-Smtp-Source: AMrXdXtRU2F+MUiGTtYMODOjrrl9sNFeUtOdZcMUA+yh5+usGhUtWlnwHAjuxTFBGjl0vWdIVG/G X-Received: by 2002:a17:902:6ac3:b0:194:c25a:d824 with SMTP id i3-20020a1709026ac300b00194c25ad824mr5496596plt.26.1674164040153; Thu, 19 Jan 2023 13:34:00 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1674164040; cv=none; d=google.com; s=arc-20160816; b=QVCPmOV30CNdTvjrQvBd1m3h5bNdGeS3+FeAO/t1UAOrzc0PUr7yM1gFHb8OyaCpV8 C/nM4pop8cV0AT0/iPa5ZoaWGEFGKPbqnahWBpl4anuiFz9kAKwx7HLoarCbUATZZug5 xXACR0c6wRBbg5I4f5yLDrzYnu+YsREY4u9O3q8SBGaWGEj5eNZGK0ywtTHmyJQ9Z+ql s1fiQNsV4teYv1jEsU3Rc8eL5/Rd/lXG/l5YxbbuLd9dGXJaszfrPRJF/SZllUJXvEjw H5AVyzAoIjG0PX6e0KauRCQvH4UI0XChdGWkOUcrRr3wb7bbIowJBFp4FNSOlsVPf3PZ j0mw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:references:in-reply-to:message-id:date:subject :cc:to:from:dkim-signature; bh=/I2rA7g9gaeqAh7utVe0HX92Ho3+6Ko6l1A1i1JyDLw=; b=F3YVe2PufUZoCOPpO9qNRcsKEQF3au5k/FFyBi6Anf5rZlEe10kLrJhVR+G0IEXw2i Jwdbsn7OiTlWYlN4G8eh/lLZ+wDrj6y9Nfx8UxbrhzC+ZM2gpNURYWJ8SVMRhusPuvtS Gf2MwnBt95y/ZuwvggF/T+NKTQF6G88X/Y+jfUiLcg0FPEnPt3VFO5zTm+E1Z+v78j3y zrcE2b6w0/m3nl3jhnfyfyyPWWPW5v4k0Iyf59WsQh8e57Nl4TiM3+FsEi3HU3VxI4gS KD+PmEaZfR4o7+HwDlm/Rkn+2/9XppQ/36D8kOWw34vs/WtTLUUKdwbikk4C79uX2khm 1pmQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@intel.com header.s=Intel header.b=CU4D+mLB; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=intel.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id t23-20020a170902b21700b001946e6c4fb9si9972308plr.96.2023.01.19.13.33.47; Thu, 19 Jan 2023 13:34:00 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@intel.com header.s=Intel header.b=CU4D+mLB; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=intel.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230376AbjASVby (ORCPT <rfc822;pavtiger@gmail.com> + 99 others); Thu, 19 Jan 2023 16:31:54 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:45328 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230506AbjASVar (ORCPT <rfc822;linux-kernel@vger.kernel.org>); Thu, 19 Jan 2023 16:30:47 -0500 Received: from mga11.intel.com (mga11.intel.com [192.55.52.93]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 39881A7914; Thu, 19 Jan 2023 13:25:08 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1674163509; x=1705699509; h=from:to:cc:subject:date:message-id:in-reply-to: references; bh=AD5tXA8hUee5SZ1Pd+Ll3tDzu/Wr8phq95vUnNoKkT8=; b=CU4D+mLB7mIoLlEv8ME3Sg6ThixyUMvysX59m+nItF2n7lFvLiCdsEES dHYLyQaCni72Uwvflj2ees3kSSvdzO7xRg3whl8etMdJU5qN8hPVObSrG KC+H+r+UM13KCbgDdEugVWA6Epr8VUfcZbTllZt3bRrvarsykPrl/r7gO 3VyIi2tajAM9Uti60NkBpVq2HJAWX24ur8B/JZ5EPmq21b+jFq+HDbfTy 5LzLBXz98v24PPQLltyjDzinS8+zUT51ku/KWSqpA/yUqYbulpu2i71M6 gZKRMfbqmXK12RrXZvPTxjFblkNcQ3vRhgDOiCPTD6v267AVG5M5n8m0q A==; X-IronPort-AV: E=McAfee;i="6500,9779,10595"; a="323119291" X-IronPort-AV: E=Sophos;i="5.97,230,1669104000"; d="scan'208";a="323119291" Received: from fmsmga005.fm.intel.com ([10.253.24.32]) by fmsmga102.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 19 Jan 2023 13:23:34 -0800 X-IronPort-AV: E=McAfee;i="6500,9779,10595"; a="989139011" X-IronPort-AV: E=Sophos;i="5.97,230,1669104000"; d="scan'208";a="989139011" Received: from hossain3-mobl.amr.corp.intel.com (HELO rpedgeco-desk.amr.corp.intel.com) ([10.252.128.187]) by fmsmga005-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 19 Jan 2023 13:23:32 -0800 From: Rick Edgecombe <rick.p.edgecombe@intel.com> To: x86@kernel.org, "H . Peter Anvin" <hpa@zytor.com>, Thomas Gleixner <tglx@linutronix.de>, Ingo Molnar <mingo@redhat.com>, linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org, linux-mm@kvack.org, linux-arch@vger.kernel.org, linux-api@vger.kernel.org, Arnd Bergmann <arnd@arndb.de>, Andy Lutomirski <luto@kernel.org>, Balbir Singh <bsingharora@gmail.com>, Borislav Petkov <bp@alien8.de>, Cyrill Gorcunov <gorcunov@gmail.com>, Dave Hansen <dave.hansen@linux.intel.com>, Eugene Syromiatnikov <esyr@redhat.com>, Florian Weimer <fweimer@redhat.com>, "H . J . Lu" <hjl.tools@gmail.com>, Jann Horn <jannh@google.com>, Jonathan Corbet <corbet@lwn.net>, Kees Cook <keescook@chromium.org>, Mike Kravetz <mike.kravetz@oracle.com>, Nadav Amit <nadav.amit@gmail.com>, Oleg Nesterov <oleg@redhat.com>, Pavel Machek <pavel@ucw.cz>, Peter Zijlstra <peterz@infradead.org>, Randy Dunlap <rdunlap@infradead.org>, Weijiang Yang <weijiang.yang@intel.com>, "Kirill A . Shutemov" <kirill.shutemov@linux.intel.com>, John Allen <john.allen@amd.com>, kcc@google.com, eranian@google.com, rppt@kernel.org, jamorris@linux.microsoft.com, dethoma@microsoft.com, akpm@linux-foundation.org, Andrew.Cooper3@citrix.com, christina.schimpe@intel.com Cc: rick.p.edgecombe@intel.com Subject: [PATCH v5 06/39] x86/fpu: Add helper for modifying xstate Date: Thu, 19 Jan 2023 13:22:44 -0800 Message-Id: <20230119212317.8324-7-rick.p.edgecombe@intel.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20230119212317.8324-1-rick.p.edgecombe@intel.com> References: <20230119212317.8324-1-rick.p.edgecombe@intel.com> X-Spam-Status: No, score=-4.4 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_MED, SPF_HELO_NONE,SPF_NONE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: <linux-kernel.vger.kernel.org> X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1755488232201099275?= X-GMAIL-MSGID: =?utf-8?q?1755488232201099275?= |
Series |
Shadow stacks for userspace
|
|
Commit Message
Edgecombe, Rick P
Jan. 19, 2023, 9:22 p.m. UTC
Just like user xfeatures, supervisor xfeatures can be active in the registers or present in the task FPU buffer. If the registers are active, the registers can be modified directly. If the registers are not active, the modification must be performed on the task FPU buffer. When the state is not active, the kernel could perform modifications directly to the buffer. But in order for it to do that, it needs to know where in the buffer the specific state it wants to modify is located. Doing this is not robust against optimizations that compact the FPU buffer, as each access would require computing where in the buffer it is. The easiest way to modify supervisor xfeature data is to force restore the registers and write directly to the MSRs. Often times this is just fine anyway as the registers need to be restored before returning to userspace. Do this for now, leaving buffer writing optimizations for the future. Add a new function fpregs_lock_and_load() that can simultaneously call fpregs_lock() and do this restore. Also perform some extra sanity checks in this function since this will be used in non-fpu focused code. Tested-by: Pengfei Xu <pengfei.xu@intel.com> Tested-by: John Allen <john.allen@amd.com> Suggested-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Rick Edgecombe <rick.p.edgecombe@intel.com> --- v5: - Fix spelling error (Boris) - Don't export fpregs_lock_and_load() (Boris) v3: - Rename to fpregs_lock_and_load() to match the unlocking fpregs_unlock(). (Kees) - Elaborate in comment about helper. (Dave) v2: - Drop optimization of writing directly the buffer, and change API accordingly. - fpregs_lock_and_load() suggested by tglx - Some commit log verbiage from dhansen v1: - New patch. arch/x86/include/asm/fpu/api.h | 9 +++++++++ arch/x86/kernel/fpu/core.c | 18 ++++++++++++++++++ 2 files changed, 27 insertions(+)
Comments
On Thu, Jan 19, 2023 at 01:22:44PM -0800, Rick Edgecombe wrote: > Just like user xfeatures, supervisor xfeatures can be active in the > registers or present in the task FPU buffer. If the registers are > active, the registers can be modified directly. If the registers are > not active, the modification must be performed on the task FPU buffer. > > When the state is not active, the kernel could perform modifications > directly to the buffer. But in order for it to do that, it needs > to know where in the buffer the specific state it wants to modify is > located. Doing this is not robust against optimizations that compact > the FPU buffer, as each access would require computing where in the > buffer it is. > > The easiest way to modify supervisor xfeature data is to force restore > the registers and write directly to the MSRs. Often times this is just fine > anyway as the registers need to be restored before returning to userspace. > Do this for now, leaving buffer writing optimizations for the future. > > Add a new function fpregs_lock_and_load() that can simultaneously call > fpregs_lock() and do this restore. Also perform some extra sanity > checks in this function since this will be used in non-fpu focused code. > > Tested-by: Pengfei Xu <pengfei.xu@intel.com> > Tested-by: John Allen <john.allen@amd.com> > Suggested-by: Thomas Gleixner <tglx@linutronix.de> > Signed-off-by: Rick Edgecombe <rick.p.edgecombe@intel.com> Reviewed-by: Kees Cook <keescook@chromium.org>
On Thu, Jan 19, 2023 at 01:22:44PM -0800, Rick Edgecombe wrote: > +void fpregs_lock_and_load(void) > +{ > + /* > + * fpregs_lock() only disables preemption (mostly). So modifying state > + * in an interrupt could screw up some in progress fpregs operation, > + * but appear to work. Warn about it. I don't like comments where it sounds like we don't know what we're doing. "Appear to work"?
On Wed, 2023-02-01 at 12:01 +0100, Borislav Petkov wrote: > On Thu, Jan 19, 2023 at 01:22:44PM -0800, Rick Edgecombe wrote: > > +void fpregs_lock_and_load(void) > > +{ > > + /* > > + * fpregs_lock() only disables preemption (mostly). So > > modifying state > > + * in an interrupt could screw up some in progress fpregs > > operation, > > + * but appear to work. Warn about it. > > I don't like comments where it sounds like we don't know what we're > doing. "Appear to work"? I can change it. This patch started with the observation that modifying xstate from the kernel had been gotten wrong a couple times in the past, so that is what this is referencing. Since then, the fancy automatic solution got boiled down to this helper and a couple warnings.
On Wed, Feb 01, 2023 at 05:31:50PM +0000, Edgecombe, Rick P wrote: > On Wed, 2023-02-01 at 12:01 +0100, Borislav Petkov wrote: > > On Thu, Jan 19, 2023 at 01:22:44PM -0800, Rick Edgecombe wrote: > > > +void fpregs_lock_and_load(void) > > > +{ > > > + /* > > > + * fpregs_lock() only disables preemption (mostly). So > > > modifying state > > > + * in an interrupt could screw up some in progress fpregs > > > operation, > > > + * but appear to work. Warn about it. > > > > I don't like comments where it sounds like we don't know what we're > > doing. "Appear to work"? > > I can change it. This patch started with the observation that modifying > xstate from the kernel had been gotten wrong a couple times in the > past, so that is what this is referencing. Since then, the fancy > automatic solution got boiled down to this helper and a couple > warnings. Yeah, but that comment right now reads like: modifying in interrupt context can corrupt fpregs and you should not do it but it kinda works, by chance. Thus encouraging people to keep doing that. I guess "but appear to work" can go and then it is fine. Thx.
diff --git a/arch/x86/include/asm/fpu/api.h b/arch/x86/include/asm/fpu/api.h index 503a577814b2..aadc6893dcaa 100644 --- a/arch/x86/include/asm/fpu/api.h +++ b/arch/x86/include/asm/fpu/api.h @@ -82,6 +82,15 @@ static inline void fpregs_unlock(void) preempt_enable(); } +/* + * FPU state gets lazily restored before returning to userspace. So when in the + * kernel, the valid FPU state may be kept in the buffer. This function will force + * restore all the fpu state to the registers early if needed, and lock them from + * being automatically saved/restored. Then FPU state can be modified safely in the + * registers, before unlocking with fpregs_unlock(). + */ +void fpregs_lock_and_load(void); + #ifdef CONFIG_X86_DEBUG_FPU extern void fpregs_assert_state_consistent(void); #else diff --git a/arch/x86/kernel/fpu/core.c b/arch/x86/kernel/fpu/core.c index dccce58201b7..7317bfd5ea36 100644 --- a/arch/x86/kernel/fpu/core.c +++ b/arch/x86/kernel/fpu/core.c @@ -753,6 +753,24 @@ void switch_fpu_return(void) } EXPORT_SYMBOL_GPL(switch_fpu_return); +void fpregs_lock_and_load(void) +{ + /* + * fpregs_lock() only disables preemption (mostly). So modifying state + * in an interrupt could screw up some in progress fpregs operation, + * but appear to work. Warn about it. + */ + WARN_ON_ONCE(!irq_fpu_usable()); + WARN_ON_ONCE(current->flags & PF_KTHREAD); + + fpregs_lock(); + + fpregs_assert_state_consistent(); + + if (test_thread_flag(TIF_NEED_FPU_LOAD)) + fpregs_restore_userregs(); +} + #ifdef CONFIG_X86_DEBUG_FPU /* * If current FPU state according to its tracking (loaded FPU context on this