Reviewed-by: Bamvor Zhang bamvor.zhang@suse.com
在 2/15/22 11:05 AM, Laibin Qiu 写道:
From: Jarkko Sakkinen jarkko@kernel.org
mainline inclusion from mainline-v5.11-rc1 commit 888d249117876239593fe3039b6ead8ad6849035 category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I4SIGI CVE: NA
Add an ioctl() that performs the ECREATE function of the ENCLS instruction, which creates an SGX Enclave Control Structure (SECS).
Although the SECS is an in-memory data structure, it is present in enclave memory and is not directly accessible by software.
Intel-SIG: commit 888d24911787 x86/sgx: Add SGX_IOC_ENCLAVE_CREATE Backport for SGX Foundations support
Co-developed-by: Sean Christopherson sean.j.christopherson@intel.com Signed-off-by: Sean Christopherson sean.j.christopherson@intel.com Signed-off-by: Jarkko Sakkinen jarkko@kernel.org Signed-off-by: Borislav Petkov bp@suse.de Tested-by: Jethro Beekman jethro@fortanix.com Link: https://lkml.kernel.org/r/20201112220135.165028-13-jarkko@kernel.org Signed-off-by: Fan Du fan.du@intel.com #openEuler_contributor Signed-off-by: Laibin Qiu qiulaibin@huawei.com
.../userspace-api/ioctl/ioctl-number.rst | 1 + arch/x86/include/uapi/asm/sgx.h | 25 ++++ arch/x86/kernel/cpu/sgx/Makefile | 1 + arch/x86/kernel/cpu/sgx/driver.c | 12 ++ arch/x86/kernel/cpu/sgx/driver.h | 3 + arch/x86/kernel/cpu/sgx/encl.c | 8 ++ arch/x86/kernel/cpu/sgx/encl.h | 7 + arch/x86/kernel/cpu/sgx/ioctl.c | 123 ++++++++++++++++++ 8 files changed, 180 insertions(+) create mode 100644 arch/x86/include/uapi/asm/sgx.h create mode 100644 arch/x86/kernel/cpu/sgx/ioctl.c
diff --git a/Documentation/userspace-api/ioctl/ioctl-number.rst b/Documentation/userspace-api/ioctl/ioctl-number.rst index 55a2d9b2ce33..a4c75a28c839 100644 --- a/Documentation/userspace-api/ioctl/ioctl-number.rst +++ b/Documentation/userspace-api/ioctl/ioctl-number.rst @@ -323,6 +323,7 @@ Code Seq# Include File Comments mailto:tlewis@mindspring.com 0xA3 90-9F linux/dtlk.h 0xA4 00-1F uapi/linux/tee.h Generic TEE subsystem +0xA4 00-1F uapi/asm/sgx.h mailto:linux-sgx@vger.kernel.org 0xAA 00-3F linux/uapi/linux/userfaultfd.h 0xAB 00-1F linux/nbd.h 0xAC 00-1F linux/raw.h diff --git a/arch/x86/include/uapi/asm/sgx.h b/arch/x86/include/uapi/asm/sgx.h new file mode 100644 index 000000000000..f31bb17e27c3 --- /dev/null +++ b/arch/x86/include/uapi/asm/sgx.h @@ -0,0 +1,25 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +/*
- Copyright(c) 2016-20 Intel Corporation.
- */
+#ifndef _UAPI_ASM_X86_SGX_H +#define _UAPI_ASM_X86_SGX_H
+#include <linux/types.h> +#include <linux/ioctl.h>
+#define SGX_MAGIC 0xA4
+#define SGX_IOC_ENCLAVE_CREATE \
- _IOW(SGX_MAGIC, 0x00, struct sgx_enclave_create)
+/**
- struct sgx_enclave_create - parameter structure for the
%SGX_IOC_ENCLAVE_CREATE ioctl
- @src: address for the SECS page data
- */
+struct sgx_enclave_create {
- __u64 src;
+};
+#endif /* _UAPI_ASM_X86_SGX_H */ diff --git a/arch/x86/kernel/cpu/sgx/Makefile b/arch/x86/kernel/cpu/sgx/Makefile index 3fc451120735..91d3dc784a29 100644 --- a/arch/x86/kernel/cpu/sgx/Makefile +++ b/arch/x86/kernel/cpu/sgx/Makefile @@ -1,4 +1,5 @@ obj-y += \ driver.o \ encl.o \
- ioctl.o \ main.o
diff --git a/arch/x86/kernel/cpu/sgx/driver.c b/arch/x86/kernel/cpu/sgx/driver.c index c2810e1c7cf1..ee947b721d8d 100644 --- a/arch/x86/kernel/cpu/sgx/driver.c +++ b/arch/x86/kernel/cpu/sgx/driver.c @@ -88,10 +88,22 @@ static unsigned long sgx_get_unmapped_area(struct file *file, return current->mm->get_unmapped_area(file, addr, len, pgoff, flags); }
+#ifdef CONFIG_COMPAT +static long sgx_compat_ioctl(struct file *filep, unsigned int cmd,
unsigned long arg)
+{
- return sgx_ioctl(filep, cmd, arg);
+} +#endif
- static const struct file_operations sgx_encl_fops = { .owner = THIS_MODULE, .open = sgx_open, .release = sgx_release,
- .unlocked_ioctl = sgx_ioctl,
+#ifdef CONFIG_COMPAT
- .compat_ioctl = sgx_compat_ioctl,
+#endif .mmap = sgx_mmap, .get_unmapped_area = sgx_get_unmapped_area, }; diff --git a/arch/x86/kernel/cpu/sgx/driver.h b/arch/x86/kernel/cpu/sgx/driver.h index cda9c43b7543..a728e8e848bd 100644 --- a/arch/x86/kernel/cpu/sgx/driver.h +++ b/arch/x86/kernel/cpu/sgx/driver.h @@ -9,8 +9,11 @@ #include <linux/rwsem.h> #include <linux/sched.h> #include <linux/workqueue.h> +#include <uapi/asm/sgx.h> #include "sgx.h"
+long sgx_ioctl(struct file *filep, unsigned int cmd, unsigned long arg);
int sgx_drv_init(void);
#endif /* __ARCH_X86_SGX_DRIVER_H__ */
diff --git a/arch/x86/kernel/cpu/sgx/encl.c b/arch/x86/kernel/cpu/sgx/encl.c index b9d445db7ff1..57eff300f487 100644 --- a/arch/x86/kernel/cpu/sgx/encl.c +++ b/arch/x86/kernel/cpu/sgx/encl.c @@ -46,6 +46,7 @@ static vm_fault_t sgx_vma_fault(struct vm_fault *vmf) struct sgx_encl_page *entry; unsigned long phys_addr; struct sgx_encl *encl;
unsigned long pfn; vm_fault_t ret;
encl = vma->vm_private_data;
@@ -61,6 +62,13 @@ static vm_fault_t sgx_vma_fault(struct vm_fault *vmf)
phys_addr = sgx_get_epc_phys_addr(entry->epc_page);
- /* Check if another thread got here first to insert the PTE. */
- if (!follow_pfn(vma, addr, &pfn)) {
mutex_unlock(&encl->lock);
return VM_FAULT_NOPAGE;
- }
- ret = vmf_insert_pfn(vma, addr, PFN_DOWN(phys_addr)); if (ret != VM_FAULT_NOPAGE) { mutex_unlock(&encl->lock);
diff --git a/arch/x86/kernel/cpu/sgx/encl.h b/arch/x86/kernel/cpu/sgx/encl.h index 1df8011fa23d..7cc175825b01 100644 --- a/arch/x86/kernel/cpu/sgx/encl.h +++ b/arch/x86/kernel/cpu/sgx/encl.h @@ -26,9 +26,16 @@ struct sgx_encl_page { struct sgx_encl *encl; };
+enum sgx_encl_flags {
- SGX_ENCL_IOCTL = BIT(0),
- SGX_ENCL_DEBUG = BIT(1),
- SGX_ENCL_CREATED = BIT(2),
+};
- struct sgx_encl { unsigned long base; unsigned long size;
- unsigned long flags; unsigned int page_cnt; unsigned int secs_child_cnt; struct mutex lock;
diff --git a/arch/x86/kernel/cpu/sgx/ioctl.c b/arch/x86/kernel/cpu/sgx/ioctl.c new file mode 100644 index 000000000000..1355490843d1 --- /dev/null +++ b/arch/x86/kernel/cpu/sgx/ioctl.c @@ -0,0 +1,123 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2016-20 Intel Corporation. */
+#include <asm/mman.h> +#include <linux/mman.h> +#include <linux/delay.h> +#include <linux/file.h> +#include <linux/hashtable.h> +#include <linux/highmem.h> +#include <linux/ratelimit.h> +#include <linux/sched/signal.h> +#include <linux/shmem_fs.h> +#include <linux/slab.h> +#include <linux/suspend.h> +#include "driver.h" +#include "encl.h" +#include "encls.h"
+static int sgx_encl_create(struct sgx_encl *encl, struct sgx_secs *secs) +{
- struct sgx_epc_page *secs_epc;
- struct sgx_pageinfo pginfo;
- struct sgx_secinfo secinfo;
- unsigned long encl_size;
- long ret;
- /* The extra page goes to SECS. */
- encl_size = secs->size + PAGE_SIZE;
- secs_epc = __sgx_alloc_epc_page();
- if (IS_ERR(secs_epc))
return PTR_ERR(secs_epc);
- encl->secs.epc_page = secs_epc;
- pginfo.addr = 0;
- pginfo.contents = (unsigned long)secs;
- pginfo.metadata = (unsigned long)&secinfo;
- pginfo.secs = 0;
- memset(&secinfo, 0, sizeof(secinfo));
- ret = __ecreate((void *)&pginfo, sgx_get_epc_virt_addr(secs_epc));
- if (ret) {
ret = -EIO;
goto err_out;
- }
- if (secs->attributes & SGX_ATTR_DEBUG)
set_bit(SGX_ENCL_DEBUG, &encl->flags);
- encl->secs.encl = encl;
- encl->base = secs->base;
- encl->size = secs->size;
- /* Set only after completion, as encl->lock has not been taken. */
- set_bit(SGX_ENCL_CREATED, &encl->flags);
- return 0;
+err_out:
- sgx_free_epc_page(encl->secs.epc_page);
- encl->secs.epc_page = NULL;
- return ret;
+}
+/**
- sgx_ioc_enclave_create() - handler for %SGX_IOC_ENCLAVE_CREATE
- @encl: An enclave pointer.
- @arg: The ioctl argument.
- Allocate kernel data structures for the enclave and invoke ECREATE.
- Return:
- 0: Success.
- -EIO: ECREATE failed.
- -errno: POSIX error.
- */
+static long sgx_ioc_enclave_create(struct sgx_encl *encl, void __user *arg) +{
- struct sgx_enclave_create create_arg;
- void *secs;
- int ret;
- if (test_bit(SGX_ENCL_CREATED, &encl->flags))
return -EINVAL;
- if (copy_from_user(&create_arg, arg, sizeof(create_arg)))
return -EFAULT;
- secs = kmalloc(PAGE_SIZE, GFP_KERNEL);
- if (!secs)
return -ENOMEM;
- if (copy_from_user(secs, (void __user *)create_arg.src, PAGE_SIZE))
ret = -EFAULT;
- else
ret = sgx_encl_create(encl, secs);
- kfree(secs);
- return ret;
+}
+long sgx_ioctl(struct file *filep, unsigned int cmd, unsigned long arg) +{
- struct sgx_encl *encl = filep->private_data;
- int ret;
- if (test_and_set_bit(SGX_ENCL_IOCTL, &encl->flags))
return -EBUSY;
- switch (cmd) {
- case SGX_IOC_ENCLAVE_CREATE:
ret = sgx_ioc_enclave_create(encl, (void __user *)arg);
break;
- default:
ret = -ENOIOCTLCMD;
break;
- }
- clear_bit(SGX_ENCL_IOCTL, &encl->flags);
- return ret;
+}