Message ID | 20230227222957.24501-35-rick.p.edgecombe@intel.com |
---|---|
State | New |
Headers |
Return-Path: <linux-kernel-owner@vger.kernel.org> Delivered-To: ouuuleilei@gmail.com Received: by 2002:a5d:5915:0:0:0:0:0 with SMTP id v21csp2683510wrd; Mon, 27 Feb 2023 14:36:47 -0800 (PST) X-Google-Smtp-Source: AK7set+23hfpTxhqBUlmHuRRW1sTH2e2aLWpDBRcGvbcU26jdtu5/dyIo00kLU6ERrCK+ypmMGOL X-Received: by 2002:a17:90b:1a8d:b0:236:84a:8da0 with SMTP id ng13-20020a17090b1a8d00b00236084a8da0mr859588pjb.13.1677537407540; Mon, 27 Feb 2023 14:36:47 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1677537407; cv=none; d=google.com; s=arc-20160816; b=yr3yEvgaPfWYyEXFnByzyt7RugxXep3bLKI+FMvAUUnRVwadKHRaFk5VFDG5vvpyee aLcuVTnrWTPdpRJ8HiKGyWAHuCCLe/DvJmQ0a1VMwPrFQdYCUFKbo04T9q8a69zOtJjC Tj18s0OiJ3K4kAx4HBj2HTLiy1sPS0t5LZK9hcnO9m10T8GnG0/OD7b0XcPBPTFC71I4 xQazY0U0qlASujOI2YJe9KoTJQGfZSfrBPpt3yk0GM7PtHvkSocN9F7wmKT3U6bZ4TZK JlkOukPqMYmLeY6wmxVW1VZjHZAU+8Vm5vo/kEsBWpSKDYjYnZSazCO+20HtFJ7NQHCZ c7Mw== 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=PfVyx2ZUIDwJeog9TcVEcCcnDkbyw8PVB33z8FVE0wQ=; b=lQWdwYMbntaU+0UB6EQr1qGlO1VXmVP77WCSNXX4i/kuNST4AfCwgYk0ARbXcyypyZ /9KO+vn4wPCxB0jfFfBobVEgMnZmhmTQC95IUKvkydBwK+O9SZRTCwbQCtRdU01ux9Hf 5UlcSDia+krX0WrQX9ssgR28UDBSpF0geeFfhdFiN+/PUVJyRn3EHRsH8A4ty8n36XDE 3Ii0eZZNP7BU/pwf3peTQ8fpIwcNBp7IIyk1SjPUDK0L07D6jBYpURDAcXfBeckB50Ts LLJGZHCVgJHIp0hfRkqWEAmygOM6eeh5Y667K8LcJp7bCfliIxttIiPXwAGFDFa4zH8T 5Mcw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@intel.com header.s=Intel header.b=dKeS0exe; 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 h1-20020a17090adb8100b00234a84d3ed4si11052482pjv.190.2023.02.27.14.36.34; Mon, 27 Feb 2023 14:36:47 -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=dKeS0exe; 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 S231130AbjB0Wfk (ORCPT <rfc822;wenzhi022@gmail.com> + 99 others); Mon, 27 Feb 2023 17:35:40 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40722 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230489AbjB0Wd5 (ORCPT <rfc822;linux-kernel@vger.kernel.org>); Mon, 27 Feb 2023 17:33:57 -0500 Received: from mga12.intel.com (mga12.intel.com [192.55.52.136]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 5E2182A987; Mon, 27 Feb 2023 14:32:10 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1677537130; x=1709073130; h=from:to:cc:subject:date:message-id:in-reply-to: references; bh=HyAWoaPlsuor4NZWrHVRIBqQGXmP1Us+CQiWWbdiIWE=; b=dKeS0exeUw/fCSLIBphDUePDD7wM2QZfX2yWGrD7+jKxwdQBZmkCIEjc LzNP318wYk3/Ndrty5105V9MRmFwleatEfsGO238WeWGs3SQfrX48Wb6x 5SFOfVym456KXRMpQZHdWWCtkA7qohLnRpbftSW9OpA+ZNIJhfHLbuYp4 Sk6Ns1PQz7EYCJJ6q3jE9BRBAIvXjaTVuC6go3+aycDH5wHu1fBfYswJz qwEbTWaoTPJhCUeofwvoaESQOuIx4M6jGKkkcg8AA4Mu+SXpNsz7vTbi6 +Ln0SVor4orIto94v+lHwW7xeQfk8UTVFJEC4qivsZgXpfOmeWW4oToCl Q==; X-IronPort-AV: E=McAfee;i="6500,9779,10634"; a="313657843" X-IronPort-AV: E=Sophos;i="5.98,220,1673942400"; d="scan'208";a="313657843" Received: from orsmga005.jf.intel.com ([10.7.209.41]) by fmsmga106.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 27 Feb 2023 14:31:33 -0800 X-IronPort-AV: E=McAfee;i="6500,9779,10634"; a="848024775" X-IronPort-AV: E=Sophos;i="5.98,220,1673942400"; d="scan'208";a="848024775" Received: from leonqu-mobl1.amr.corp.intel.com (HELO rpedgeco-desk.amr.corp.intel.com) ([10.209.72.19]) by orsmga005-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 27 Feb 2023 14:31: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, david@redhat.com, debug@rivosinc.com Cc: rick.p.edgecombe@intel.com Subject: [PATCH v7 34/41] x86/shstk: Support WRSS for userspace Date: Mon, 27 Feb 2023 14:29:50 -0800 Message-Id: <20230227222957.24501-35-rick.p.edgecombe@intel.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20230227222957.24501-1-rick.p.edgecombe@intel.com> References: <20230227222957.24501-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_PASS,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?1759025464699830480?= X-GMAIL-MSGID: =?utf-8?q?1759025464699830480?= |
Series |
Shadow stacks for userspace
|
|
Commit Message
Edgecombe, Rick P
Feb. 27, 2023, 10:29 p.m. UTC
For the current shadow stack implementation, shadow stacks contents can't easily be provisioned with arbitrary data. This property helps apps protect themselves better, but also restricts any potential apps that may want to do exotic things at the expense of a little security. The x86 shadow stack feature introduces a new instruction, WRSS, which can be enabled to write directly to shadow stack permissioned memory from userspace. Allow it to get enabled via the prctl interface. Only enable the userspace WRSS instruction, which allows writes to userspace shadow stacks from userspace. Do not allow it to be enabled independently of shadow stack, as HW does not support using WRSS when shadow stack is disabled. From a fault handler perspective, WRSS will behave very similar to WRUSS, which is treated like a user access from a #PF err code perspective. Tested-by: Pengfei Xu <pengfei.xu@intel.com> Tested-by: John Allen <john.allen@amd.com> Tested-by: Kees Cook <keescook@chromium.org> Acked-by: Mike Rapoport (IBM) <rppt@kernel.org> Reviewed-by: Kees Cook <keescook@chromium.org> Signed-off-by: Rick Edgecombe <rick.p.edgecombe@intel.com> --- v6: - Make set_clr_bits_msrl() avoid side affects in 'msr' v5: - Switch to EOPNOTSUPP - Move set_clr_bits_msrl() to patch where it is first used - Commit log formatting v3: - Make wrss_control() static - Fix verbiage in commit log (Kees) v2: - Add some commit log verbiage from (Dave Hansen) v1: - New patch. --- arch/x86/include/asm/msr.h | 11 +++++++++++ arch/x86/include/uapi/asm/prctl.h | 1 + arch/x86/kernel/shstk.c | 32 ++++++++++++++++++++++++++++++- 3 files changed, 43 insertions(+), 1 deletion(-)
Comments
On Mon, Feb 27, 2023 at 02:29:50PM -0800, Rick Edgecombe wrote: > For the current shadow stack implementation, shadow stacks contents can't > easily be provisioned with arbitrary data. This property helps apps > protect themselves better, but also restricts any potential apps that may > want to do exotic things at the expense of a little security. > > The x86 shadow stack feature introduces a new instruction, WRSS, which > can be enabled to write directly to shadow stack permissioned memory from s/permissioned // By now it is clear that shadow stack memory is a special thing anyway. > userspace. Allow it to get enabled via the prctl interface. > > Only enable the userspace WRSS instruction, which allows writes to > userspace shadow stacks from userspace. Do not allow it to be enabled > independently of shadow stack, as HW does not support using WRSS when > shadow stack is disabled. > > From a fault handler perspective, WRSS will behave very similar to WRUSS, > which is treated like a user access from a #PF err code perspective. ... > diff --git a/arch/x86/include/asm/msr.h b/arch/x86/include/asm/msr.h > index 65ec1965cd28..2d3b35c957ad 100644 > --- a/arch/x86/include/asm/msr.h > +++ b/arch/x86/include/asm/msr.h > @@ -310,6 +310,17 @@ void msrs_free(struct msr *msrs); > int msr_set_bit(u32 msr, u8 bit); > int msr_clear_bit(u32 msr, u8 bit); > > +/* Helper that can never get accidentally un-inlined. */ > +#define set_clr_bits_msrl(msr, set, clear) do { \ Uff, pls kill this thing. Our MSR interfaces universe is already insane and arch/x86/lib/msr.c already has similar attempts to what you're doing here in addition to all the other gunk in msr.h. I highly doubt this can't be done the usual way, lemme see... > + u64 __val, __new_val, __msr = msr; \ > + \ > + rdmsrl(__msr, __val); \ > + __new_val = (__val & ~(clear)) | (set); \ > + \ > + if (__new_val != __val) \ > + wrmsrl(__msr, __new_val); \ > +} while (0) > + > #ifdef CONFIG_SMP > int rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h); > int wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h); > diff --git a/arch/x86/include/uapi/asm/prctl.h b/arch/x86/include/uapi/asm/prctl.h > index 7dfd9dc00509..e31495668056 100644 > --- a/arch/x86/include/uapi/asm/prctl.h > +++ b/arch/x86/include/uapi/asm/prctl.h > @@ -28,5 +28,6 @@ > > /* ARCH_SHSTK_ features bits */ > #define ARCH_SHSTK_SHSTK (1ULL << 0) > +#define ARCH_SHSTK_WRSS (1ULL << 1) > > #endif /* _ASM_X86_PRCTL_H */ > diff --git a/arch/x86/kernel/shstk.c b/arch/x86/kernel/shstk.c > index 0a3decab70ee..009cb3fa0ae5 100644 > --- a/arch/x86/kernel/shstk.c > +++ b/arch/x86/kernel/shstk.c > @@ -363,6 +363,36 @@ void shstk_free(struct task_struct *tsk) > unmap_shadow_stack(shstk->base, shstk->size); > } > > +static int wrss_control(bool enable) > +{ > + if (!cpu_feature_enabled(X86_FEATURE_USER_SHSTK)) > + return -EOPNOTSUPP; > + > + /* > + * Only enable wrss if shadow stack is enabled. If shadow stack is not "WRSS". Insns in all caps pls. > + * enabled, wrss will already be disabled, so don't bother clearing it Ditto. > + * when disabling. > + */ > + if (!features_enabled(ARCH_SHSTK_SHSTK)) > + return -EPERM; > + > + /* Already enabled/disabled? */ > + if (features_enabled(ARCH_SHSTK_WRSS) == enable) > + return 0; > + > + fpregs_lock_and_load(); > + if (enable) { > + set_clr_bits_msrl(MSR_IA32_U_CET, CET_WRSS_EN, 0); > + features_set(ARCH_SHSTK_WRSS); > + } else { > + set_clr_bits_msrl(MSR_IA32_U_CET, 0, CET_WRSS_EN); > + features_clr(ARCH_SHSTK_WRSS); > + } > + fpregs_unlock(); Yes, doing it the "usual" way is more readable because it is a common code pattern which one encounters all around arch/x86/. Diff ontop: diff --git a/arch/x86/kernel/shstk.c b/arch/x86/kernel/shstk.c index 009cb3fa0ae5..914feff26b23 100644 --- a/arch/x86/kernel/shstk.c +++ b/arch/x86/kernel/shstk.c @@ -365,6 +365,8 @@ void shstk_free(struct task_struct *tsk) static int wrss_control(bool enable) { + u64 msrval; + if (!cpu_feature_enabled(X86_FEATURE_USER_SHSTK)) return -EOPNOTSUPP; @@ -381,13 +383,22 @@ static int wrss_control(bool enable) return 0; fpregs_lock_and_load(); + rdmsrl(MSR_IA32_U_CET, msrval); + if (enable) { - set_clr_bits_msrl(MSR_IA32_U_CET, CET_WRSS_EN, 0); features_set(ARCH_SHSTK_WRSS); + msrval |= CET_WRSS_EN; } else { - set_clr_bits_msrl(MSR_IA32_U_CET, 0, CET_WRSS_EN); features_clr(ARCH_SHSTK_WRSS); + if (!(msrval & CET_WRSS_EN)) + goto unlock; + + msrval &= ~CET_WRSS_EN; } + + wrmsrl(MSR_IA32_U_CET, msrval); + +unlock: fpregs_unlock(); return 0;
On Fri, 2023-03-10 at 17:44 +0100, Borislav Petkov wrote: Thanks on text edits. > > > > +/* Helper that can never get accidentally un-inlined. */ > > +#define set_clr_bits_msrl(msr, set, clear) do { \ > > Uff, pls kill this thing. > > Our MSR interfaces universe is already insane and arch/x86/lib/msr.c > already has similar attempts to what you're doing here in addition to > all the other gunk in msr.h. > > I highly doubt this can't be done the usual way, lemme see... Seems reasonable.
diff --git a/arch/x86/include/asm/msr.h b/arch/x86/include/asm/msr.h index 65ec1965cd28..2d3b35c957ad 100644 --- a/arch/x86/include/asm/msr.h +++ b/arch/x86/include/asm/msr.h @@ -310,6 +310,17 @@ void msrs_free(struct msr *msrs); int msr_set_bit(u32 msr, u8 bit); int msr_clear_bit(u32 msr, u8 bit); +/* Helper that can never get accidentally un-inlined. */ +#define set_clr_bits_msrl(msr, set, clear) do { \ + u64 __val, __new_val, __msr = msr; \ + \ + rdmsrl(__msr, __val); \ + __new_val = (__val & ~(clear)) | (set); \ + \ + if (__new_val != __val) \ + wrmsrl(__msr, __new_val); \ +} while (0) + #ifdef CONFIG_SMP int rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h); int wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h); diff --git a/arch/x86/include/uapi/asm/prctl.h b/arch/x86/include/uapi/asm/prctl.h index 7dfd9dc00509..e31495668056 100644 --- a/arch/x86/include/uapi/asm/prctl.h +++ b/arch/x86/include/uapi/asm/prctl.h @@ -28,5 +28,6 @@ /* ARCH_SHSTK_ features bits */ #define ARCH_SHSTK_SHSTK (1ULL << 0) +#define ARCH_SHSTK_WRSS (1ULL << 1) #endif /* _ASM_X86_PRCTL_H */ diff --git a/arch/x86/kernel/shstk.c b/arch/x86/kernel/shstk.c index 0a3decab70ee..009cb3fa0ae5 100644 --- a/arch/x86/kernel/shstk.c +++ b/arch/x86/kernel/shstk.c @@ -363,6 +363,36 @@ void shstk_free(struct task_struct *tsk) unmap_shadow_stack(shstk->base, shstk->size); } +static int wrss_control(bool enable) +{ + if (!cpu_feature_enabled(X86_FEATURE_USER_SHSTK)) + return -EOPNOTSUPP; + + /* + * Only enable wrss if shadow stack is enabled. If shadow stack is not + * enabled, wrss will already be disabled, so don't bother clearing it + * when disabling. + */ + if (!features_enabled(ARCH_SHSTK_SHSTK)) + return -EPERM; + + /* Already enabled/disabled? */ + if (features_enabled(ARCH_SHSTK_WRSS) == enable) + return 0; + + fpregs_lock_and_load(); + if (enable) { + set_clr_bits_msrl(MSR_IA32_U_CET, CET_WRSS_EN, 0); + features_set(ARCH_SHSTK_WRSS); + } else { + set_clr_bits_msrl(MSR_IA32_U_CET, 0, CET_WRSS_EN); + features_clr(ARCH_SHSTK_WRSS); + } + fpregs_unlock(); + + return 0; +} + static int shstk_disable(void) { if (!cpu_feature_enabled(X86_FEATURE_USER_SHSTK)) @@ -379,7 +409,7 @@ static int shstk_disable(void) fpregs_unlock(); shstk_free(current); - features_clr(ARCH_SHSTK_SHSTK); + features_clr(ARCH_SHSTK_SHSTK | ARCH_SHSTK_WRSS); return 0; }