From patchwork Sun Jan 30 21:18:34 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Edgecombe, Rick P" X-Patchwork-Id: 12730161 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id 6900AC433FE for ; Sun, 30 Jan 2022 21:22:42 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 269706B00BD; Sun, 30 Jan 2022 16:22:14 -0500 (EST) Received: by kanga.kvack.org (Postfix, from userid 40) id 1CDE76B00BF; Sun, 30 Jan 2022 16:22:14 -0500 (EST) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id E259E6B00C1; Sun, 30 Jan 2022 16:22:13 -0500 (EST) X-Delivered-To: linux-mm@kvack.org Received: from forelay.hostedemail.com (smtprelay0117.hostedemail.com [216.40.44.117]) by kanga.kvack.org (Postfix) with ESMTP id CA1A96B00BD for ; Sun, 30 Jan 2022 16:22:13 -0500 (EST) Received: from smtpin11.hostedemail.com (10.5.19.251.rfc1918.com [10.5.19.251]) by forelay01.hostedemail.com (Postfix) with ESMTP id 93F17181E7875 for ; Sun, 30 Jan 2022 21:22:13 +0000 (UTC) X-FDA: 79088226546.11.46FD61A Received: from mga11.intel.com (mga11.intel.com [192.55.52.93]) by imf08.hostedemail.com (Postfix) with ESMTP id E883A160003 for ; Sun, 30 Jan 2022 21:22:12 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1643577733; x=1675113733; h=from:to:cc:subject:date:message-id:in-reply-to: references; bh=Em5mNWM4OERuM6Gg1HCpB/weTfMZ74vCRnQkfPKE0BY=; b=kOl5Lqr2i2DyEK0vqGOyRvfjJUGvacP6GGNtuHw+zboAaVAURSa7CQHh aaMyhIFrlFbkmmxl4RaU93+5PFV8+84UU2HN0FDTEDap6nYzrg61qijeo QKRDqj1kNuVF1KQz+kBBQyGyW/O59eNj9YjMNcafL/D/6XXN3gOLt35v0 YZnFvlryHh8Q5rQfewlsCzdqJoY0/WrYOx+7tCz/i502a+MHBplkNcpeF OiWvidcjE3fHp9Jrswg6L7QWoQwQ8WdliVF1EvJfHEiVbjSw0AqUAb+I9 9O9gqIgZawPh72cFP4JdaGzRZIG+00+AKRon0PU03YP3xKoHTE61z54fZ w==; X-IronPort-AV: E=McAfee;i="6200,9189,10243"; a="244970232" X-IronPort-AV: E=Sophos;i="5.88,329,1635231600"; d="scan'208";a="244970232" Received: from orsmga008.jf.intel.com ([10.7.209.65]) by fmsmga102.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 30 Jan 2022 13:22:11 -0800 X-IronPort-AV: E=Sophos;i="5.88,329,1635231600"; d="scan'208";a="536856983" Received: from avmallar-mobl1.amr.corp.intel.com (HELO rpedgeco-desk.amr.corp.intel.com) ([10.209.123.171]) by orsmga008-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 30 Jan 2022 13:22:10 -0800 From: Rick Edgecombe To: x86@kernel.org, "H . Peter Anvin" , Thomas Gleixner , Ingo Molnar , 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 , Andy Lutomirski , Balbir Singh , Borislav Petkov , Cyrill Gorcunov , Dave Hansen , Eugene Syromiatnikov , Florian Weimer , "H . J . Lu" , Jann Horn , Jonathan Corbet , Kees Cook , Mike Kravetz , Nadav Amit , Oleg Nesterov , Pavel Machek , Peter Zijlstra , Randy Dunlap , "Ravi V . Shankar" , Dave Martin , Weijiang Yang , "Kirill A . Shutemov" , joao.moreira@intel.com, John Allen , kcc@google.com, eranian@google.com Cc: rick.p.edgecombe@intel.com, Yu-cheng Yu Subject: [PATCH 31/35] x86/cet/shstk: Add arch_prctl elf feature functions Date: Sun, 30 Jan 2022 13:18:34 -0800 Message-Id: <20220130211838.8382-32-rick.p.edgecombe@intel.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20220130211838.8382-1-rick.p.edgecombe@intel.com> References: <20220130211838.8382-1-rick.p.edgecombe@intel.com> X-Rspamd-Queue-Id: E883A160003 X-Rspam-User: nil Authentication-Results: imf08.hostedemail.com; dkim=pass header.d=intel.com header.s=Intel header.b=kOl5Lqr2; dmarc=pass (policy=none) header.from=intel.com; spf=none (imf08.hostedemail.com: domain of rick.p.edgecombe@intel.com has no SPF policy when checking 192.55.52.93) smtp.mailfrom=rick.p.edgecombe@intel.com X-Stat-Signature: 9xq6bo4qgrubsxdh8u6mz7ktbr67pwsp X-Rspamd-Server: rspam08 X-HE-Tag: 1643577732-655954 X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: From: Yu-cheng Yu Some CPU features that adjust the behavior of existing instructions should be enabled only if the application supports these modifications. Provide a per-thread arch_prctl interface for modifying, checking and locking the enablement status of features like these. This interface operates on the per-thread state which is copied for new threads. It is intended to be mostly used early in an application (i.e. a dynamic loader) such that the behavior will be inherited for new threads created by the application. Today the only user is shadow stack, but keep the names generic because other features like LAM can use it as well. The interface is as below: arch_prctl(ARCH_X86_FEATURE_STATUS, u64 *args) Get feature status. The parameter 'args' is a pointer to a user buffer. The kernel returns the following information: *args = shadow stack/IBT status *(args + 1) = shadow stack base address *(args + 2) = shadow stack size 32-bit binaries use the same interface, but only lower 32-bits of each item. arch_prctl(ARCH_X86_FEATURE_DISABLE, unsigned int features) Disable features specified in 'features'. Return -EPERM if any of the passed feature are locked. Return -ECANCELED if any of the features failed to disable. In this case call ARCH_X86_FEATURE_STATUS to find out which features are still enabled. arch_prctl(ARCH_X86_FEATURE_ENABLE, unsigned int features) Enable feature specified in 'features'. Return -EPERM if any of the passed feature are locked. Return -ECANCELED if any of the features failed to enable. In this case call ARCH_X86_FEATURE_STATUS to find out which features were enabled. arch_prctl(ARCH_X86_FEATURE_LOCK, unsigned int features) Lock in all features at their current enabled or disabled status. Signed-off-by: Yu-cheng Yu Signed-off-by: Rick Edgecombe --- v1: - Changed from ENOSYS and ENOTSUPP error codes per checkpatch. - Changed interface/filename to be more generic so it can be shared with LAM. - Add lock mask, such that some features can be locked, while leaving others to be enabled later. - Add ARCH_X86_FEATURE_ENABLE to use instead of parsing the elf header - Change ARCH_X86_FEATURE_DISABLE to actually return an error on failure. arch/x86/include/asm/cet.h | 6 +++ arch/x86/include/asm/processor.h | 1 + arch/x86/include/uapi/asm/prctl.h | 10 +++++ arch/x86/kernel/Makefile | 2 +- arch/x86/kernel/elf_feature_prctl.c | 66 +++++++++++++++++++++++++++++ arch/x86/kernel/process.c | 2 +- arch/x86/kernel/shstk.c | 1 + 7 files changed, 86 insertions(+), 2 deletions(-) create mode 100644 arch/x86/kernel/elf_feature_prctl.c diff --git a/arch/x86/include/asm/cet.h b/arch/x86/include/asm/cet.h index faff8dc86159..cbc7cfcba5dc 100644 --- a/arch/x86/include/asm/cet.h +++ b/arch/x86/include/asm/cet.h @@ -40,6 +40,12 @@ static inline int setup_signal_shadow_stack(int proc32, void __user *restorer) { static inline int restore_signal_shadow_stack(void) { return 0; } #endif /* CONFIG_X86_SHADOW_STACK */ +#ifdef CONFIG_X86_SHADOW_STACK +int prctl_elf_feature(int option, u64 arg2); +#else +static inline int prctl_elf_feature(int option, u64 arg2) { return -EINVAL; } +#endif + #endif /* __ASSEMBLY__ */ #endif /* _ASM_X86_CET_H */ diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h index a9f4e9c4ca81..100af0f570c9 100644 --- a/arch/x86/include/asm/processor.h +++ b/arch/x86/include/asm/processor.h @@ -531,6 +531,7 @@ struct thread_struct { #ifdef CONFIG_X86_SHADOW_STACK struct thread_shstk shstk; + u64 feat_prctl_locked; #endif /* Floating point and extended processor state */ diff --git a/arch/x86/include/uapi/asm/prctl.h b/arch/x86/include/uapi/asm/prctl.h index 500b96e71f18..aa294c7bcf41 100644 --- a/arch/x86/include/uapi/asm/prctl.h +++ b/arch/x86/include/uapi/asm/prctl.h @@ -20,4 +20,14 @@ #define ARCH_MAP_VDSO_32 0x2002 #define ARCH_MAP_VDSO_64 0x2003 +#define ARCH_X86_FEATURE_STATUS 0x3001 +#define ARCH_X86_FEATURE_DISABLE 0x3002 +#define ARCH_X86_FEATURE_LOCK 0x3003 +#define ARCH_X86_FEATURE_ENABLE 0x3004 + +/* x86 feature bits to be used with ARCH_X86_FEATURE arch_prctl()s */ +#define LINUX_X86_FEATURE_IBT 0x00000001 +#define LINUX_X86_FEATURE_SHSTK 0x00000002 + + #endif /* _ASM_X86_PRCTL_H */ diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile index d60ae6c365c7..531dba96d4dc 100644 --- a/arch/x86/kernel/Makefile +++ b/arch/x86/kernel/Makefile @@ -153,7 +153,7 @@ obj-$(CONFIG_AMD_MEM_ENCRYPT) += sev.o obj-$(CONFIG_ARCH_HAS_CC_PLATFORM) += cc_platform.o -obj-$(CONFIG_X86_SHADOW_STACK) += shstk.o +obj-$(CONFIG_X86_SHADOW_STACK) += shstk.o elf_feature_prctl.o ### # 64 bit specific files ifeq ($(CONFIG_X86_64),y) diff --git a/arch/x86/kernel/elf_feature_prctl.c b/arch/x86/kernel/elf_feature_prctl.c new file mode 100644 index 000000000000..47de201db3f7 --- /dev/null +++ b/arch/x86/kernel/elf_feature_prctl.c @@ -0,0 +1,66 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* See Documentation/x86/intel_cet.rst. */ + +static int elf_feat_copy_status_to_user(struct thread_shstk *shstk, u64 __user *ubuf) +{ + u64 buf[3] = {}; + + if (shstk->size) { + buf[0] = LINUX_X86_FEATURE_SHSTK; + buf[1] = shstk->base; + buf[2] = shstk->size; + } + + return copy_to_user(ubuf, buf, sizeof(buf)); +} + +int prctl_elf_feature(int option, u64 arg2) +{ + struct thread_struct *thread = ¤t->thread; + u64 feat_succ = 0; + + if (!cpu_feature_enabled(X86_FEATURE_SHSTK)) + return -EOPNOTSUPP; + + switch (option) { + case ARCH_X86_FEATURE_STATUS: + return elf_feat_copy_status_to_user(&thread->shstk, (u64 __user *)arg2); + case ARCH_X86_FEATURE_DISABLE: + if (arg2 & thread->feat_prctl_locked) + return -EPERM; + + if (arg2 & LINUX_X86_FEATURE_SHSTK && !shstk_disable()) + feat_succ |= LINUX_X86_FEATURE_SHSTK; + + if (feat_succ != arg2) + return -ECANCELED; + return 0; + case ARCH_X86_FEATURE_ENABLE: + if (arg2 & thread->feat_prctl_locked) + return -EPERM; + + if (arg2 & LINUX_X86_FEATURE_SHSTK && !shstk_setup()) + feat_succ |= LINUX_X86_FEATURE_SHSTK; + + if (feat_succ != arg2) + return -ECANCELED; + return 0; + case ARCH_X86_FEATURE_LOCK: + thread->feat_prctl_locked |= arg2; + return 0; + + default: + return -EINVAL; + } +} diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c index 0fbcf33255fa..11bf09b60f9d 100644 --- a/arch/x86/kernel/process.c +++ b/arch/x86/kernel/process.c @@ -1005,5 +1005,5 @@ long do_arch_prctl_common(struct task_struct *task, int option, return fpu_xstate_prctl(task, option, arg2); } - return -EINVAL; + return prctl_elf_feature(option, arg2); } diff --git a/arch/x86/kernel/shstk.c b/arch/x86/kernel/shstk.c index 682d85a63a1d..f330be17e2d1 100644 --- a/arch/x86/kernel/shstk.c +++ b/arch/x86/kernel/shstk.c @@ -130,6 +130,7 @@ int shstk_setup(void) void reset_thread_shstk(void) { + current->thread.feat_prctl_locked = 0; memset(¤t->thread.shstk, 0, sizeof(struct thread_shstk)); }