Received: by 2002:a05:6a10:1a4d:0:0:0:0 with SMTP id nk13csp620221pxb; Tue, 1 Feb 2022 07:08:35 -0800 (PST) X-Google-Smtp-Source: ABdhPJxT4UEHHbAu+5PzoVfGi385xA912bl/+hSAsNiB6hGaJdgTUZA7AvpWf3MMK0UaUKwVugWs X-Received: by 2002:a05:6402:518e:: with SMTP id q14mr25428341edd.155.1643728115017; Tue, 01 Feb 2022 07:08:35 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1643728115; cv=none; d=google.com; s=arc-20160816; b=nemJv8aaSU4CDFTRWmkl25d0rUgjozbu/0iGdHSXdsHEjmODMO4FVOfFCPH3G0euBx 383VSQ/jjLoEKlqSegjZC9lcg4Xhv29xLMbOzaIa0m+yPis2zH+nwIkJoMF9F62Cb4Hf 7Gk5svPLg62n7PtsZCodc5DgzImzQjCXn4HuwQk9GTsvwXGPn5E7/0dRPv3qPrqlpD7a CIXSetD3WTKwtuUrXwMaAyP+wCyiPLbF9ow2y1rFXgCneina9/fo6f5PG/+daRMDdib1 hdUqP4u9p4X1I0oTSYlOAP6V30LAXBk5LMfiwoI+JSQk7VOvwCX9tInI/uGUf5g7ylv+ 3ThA== 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=pby3HdDWWfuGLkc5GTRW7B1JG4hCNiMBsMmITUDB2fk=; b=ndPnWDN0vKytB7dFbKYfyIef2bve3TCg7ux2xmCVbgKoxBAbENtrj4eOfHz3qs6KRg Auqdsgug1SBAvC//U8uDxUSXUu4R/Ernygz3bpfJ3hYSszYa3VxrF926J4JQeNQkoEsk LWspuSoFjqb3bmp8m/2JULHLRBO8D/SE6UFtBsAowgHNRv2M0aChqsa2IHCBaVDIlStV jkxFug9tw6nkjyCfL5MHcFimM0OMuIm3MnpkSYclg86FcPUbRxYHH1q7e122ZBRvj1/3 F4Z8YMNWeRPf2fot43Kg6IXGefE/Iy5e8EtDIo2Q6uTYaQbUCa0qd2FkkEnoq83yS8BF cawg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@intel.com header.s=Intel header.b=PhvrEzIB; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=intel.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id ht11si5678477ejc.275.2022.02.01.07.08.07; Tue, 01 Feb 2022 07:08:34 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@intel.com header.s=Intel header.b=PhvrEzIB; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 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 S1356932AbiA3VZh (ORCPT + 99 others); Sun, 30 Jan 2022 16:25:37 -0500 Received: from mga07.intel.com ([134.134.136.100]:9049 "EHLO mga07.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1356642AbiA3VYB (ORCPT ); Sun, 30 Jan 2022 16:24:01 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1643577841; x=1675113841; h=from:to:cc:subject:date:message-id:in-reply-to: references; bh=Em5mNWM4OERuM6Gg1HCpB/weTfMZ74vCRnQkfPKE0BY=; b=PhvrEzIBP2v2icfMzi5/YAojt6eKstTVynL0TFtCobpH0EWNXXbgdEQe q8QFP66iJb8UPugmMnnJlZw4ZYYZCKUIkQ9BQMp+GWkgpUqPj8FhnvVOe 51VyviuGPDNf5/Bt44C4rwub8cvpaQwIF77Iroe6BHwi5j8ySVDlBEHgt QVufsG6Or2+oxmdMEZl901mr3eosjQS60AXk8lDAGJ1YTXNRW84qgxV20 MLeMyiaxwoT7kPbG5uA9YPETOTffL5htrmzzAQi2dV+snqvZT3N4dJd0L kPqDR99kFFacFruJWOVXAZp4j/VdoQ9aTV/+ikEMQi/t66BUWhyIV8U+9 Q==; X-IronPort-AV: E=McAfee;i="6200,9189,10243"; a="310685828" X-IronPort-AV: E=Sophos;i="5.88,329,1635231600"; d="scan'208";a="310685828" Received: from orsmga008.jf.intel.com ([10.7.209.65]) by orsmga105.jf.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> Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 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)); } -- 2.17.1