From 00cfba73fce954b7e5e8da24fccae48537a0af49 Mon Sep 17 00:00:00 2001 From: Jia Zhang Date: Sun, 26 Jul 2020 19:01:24 +0800 Subject: [PATCH] sgx: Support SGX1 machine even without FLC support There are still lots of SGX1 machines without FLC support deployed in filed. These machines eventually needs to be migrated to be supported by SGX in-tree driver which is product-ready and well-maintained. This patch targets to address the gap between SGX1 machine and SGX in-tree driver. Signed-off-by: Jia Zhang --- arch/x86/include/uapi/asm/sgx.h | 15 ++++++++++ arch/x86/kernel/cpu/feat_ctl.c | 15 ++++------ arch/x86/kernel/cpu/sgx/driver.c | 5 ---- arch/x86/kernel/cpu/sgx/ioctl.c | 63 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 84 insertions(+), 14 deletions(-) diff --git a/arch/x86/include/uapi/asm/sgx.h b/arch/x86/include/uapi/asm/sgx.h index 3760e5d..df24dd9 100644 --- a/arch/x86/include/uapi/asm/sgx.h +++ b/arch/x86/include/uapi/asm/sgx.h @@ -25,6 +25,8 @@ enum sgx_page_flags { _IOWR(SGX_MAGIC, 0x01, struct sgx_enclave_add_pages) #define SGX_IOC_ENCLAVE_INIT \ _IOW(SGX_MAGIC, 0x02, struct sgx_enclave_init) +#define SGX_IOC_ENCLAVE_INIT_WITH_TOKEN \ + _IOW(SGX_MAGIC, 0x02, struct sgx_enclave_init_with_token) #define SGX_IOC_ENCLAVE_SET_ATTRIBUTE \ _IOW(SGX_MAGIC, 0x03, struct sgx_enclave_set_attribute) @@ -66,6 +68,19 @@ struct sgx_enclave_init { }; /** + * struct sgx_enclave_init_with_token - parameter structure for the + * %SGX_IOC_ENCLAVE_INIT_WITH_TOKEN ioctl + * @addr: address in the ELRANGE + * @sigstruct: address for the SIGSTRUCT data + * @einittoken: address for the EINITTOKEN data + */ +struct sgx_enclave_init_with_token { + __u64 addr; + __u64 sigstruct; + __u64 einittoken; +} __packed; + +/** * struct sgx_enclave_set_attribute - parameter structure for the * %SGX_IOC_ENCLAVE_SET_ATTRIBUTE ioctl * @attribute_fd: file handle of the attribute file in the securityfs diff --git a/arch/x86/kernel/cpu/feat_ctl.c b/arch/x86/kernel/cpu/feat_ctl.c index 1837df3..dad2f1b 100644 --- a/arch/x86/kernel/cpu/feat_ctl.c +++ b/arch/x86/kernel/cpu/feat_ctl.c @@ -122,13 +122,8 @@ void init_ia32_feat_ctl(struct cpuinfo_x86 *c) return; } - /* - * Enable SGX if and only if the kernel supports SGX and Launch Control - * is supported, i.e. disable SGX if the LE hash MSRs can't be written. - */ enable_sgx = cpu_has(c, X86_FEATURE_SGX) && cpu_has(c, X86_FEATURE_SGX1) && - cpu_has(c, X86_FEATURE_SGX_LC) && IS_ENABLED(CONFIG_INTEL_SGX); if (msr & FEAT_CTL_LOCKED) @@ -152,8 +147,11 @@ void init_ia32_feat_ctl(struct cpuinfo_x86 *c) msr |= FEAT_CTL_VMX_ENABLED_INSIDE_SMX; } - if (enable_sgx) - msr |= FEAT_CTL_SGX_ENABLED | FEAT_CTL_SGX_LC_ENABLED; + if (enable_sgx) { + msr |= FEAT_CTL_SGX_ENABLED; + if (cpu_has(c, X86_FEATURE_SGX_LC)) + msr |= FEAT_CTL_SGX_LC_ENABLED; + } wrmsrl(MSR_IA32_FEAT_CTL, msr); @@ -176,8 +174,7 @@ void init_ia32_feat_ctl(struct cpuinfo_x86 *c) } update_sgx: - if (!(msr & FEAT_CTL_SGX_ENABLED) || - !(msr & FEAT_CTL_SGX_LC_ENABLED) || !enable_sgx) { + if (!(msr & FEAT_CTL_SGX_ENABLED) || !enable_sgx) { if (enable_sgx) pr_err_once("SGX disabled by BIOS\n"); clear_sgx_caps(); diff --git a/arch/x86/kernel/cpu/sgx/driver.c b/arch/x86/kernel/cpu/sgx/driver.c index 997a7f4..4397d72 100644 --- a/arch/x86/kernel/cpu/sgx/driver.c +++ b/arch/x86/kernel/cpu/sgx/driver.c @@ -165,11 +165,6 @@ int __init sgx_drv_init(void) int ret; int i; - if (!boot_cpu_has(X86_FEATURE_SGX_LC)) { - pr_info("The public key MSRs are not writable.\n"); - return -ENODEV; - } - cpuid_count(SGX_CPUID, 0, &eax, &ebx, &ecx, &edx); sgx_misc_reserved_mask = ~ebx | SGX_MISC_RESERVED_MASK; sgx_encl_size_max_64 = 1ULL << ((edx >> 8) & 0xFF); diff --git a/arch/x86/kernel/cpu/sgx/ioctl.c b/arch/x86/kernel/cpu/sgx/ioctl.c index 9227ba9..0eb79b7 100644 --- a/arch/x86/kernel/cpu/sgx/ioctl.c +++ b/arch/x86/kernel/cpu/sgx/ioctl.c @@ -209,6 +209,8 @@ static int sgx_encl_create(struct sgx_encl *encl, struct sgx_secs *secs) encl->secs.encl = encl; encl->secs_attributes = secs->attributes; encl->allowed_attributes |= SGX_ATTR_ALLOWED_MASK; + if (!boot_cpu_has(X86_FEATURE_SGX_LC)) + encl->allowed_attributes |= SGX_ATTR_EINITTOKENKEY; encl->base = secs->base; encl->size = secs->size; encl->ssaframesize = secs->ssa_frame_size; @@ -694,6 +696,11 @@ static long sgx_ioc_enclave_init(struct sgx_encl *encl, void __user *arg) void *token; int ret; + if (!boot_cpu_has(X86_FEATURE_SGX_LC)) { + pr_info("The public key MSRs are not writable.\n"); + return -ENODEV; + } + if (!(atomic_read(&encl->flags) & SGX_ENCL_CREATED)) return -EINVAL; @@ -735,6 +742,59 @@ static long sgx_ioc_enclave_init(struct sgx_encl *encl, void __user *arg) return ret; } +static long sgx_ioc_enclave_init_with_token(struct sgx_encl *encl, void __user *arg) +{ + struct sgx_sigstruct *sigstruct; + struct sgx_enclave_init_with_token einit; + struct page *initp_page; + void *token; + int ret; + + if (!(atomic_read(&encl->flags) & SGX_ENCL_CREATED)) + return -EINVAL; + + if (copy_from_user(&einit, arg, sizeof(einit))) + return -EFAULT; + + initp_page = alloc_page(GFP_KERNEL); + if (!initp_page) + return -ENOMEM; + + sigstruct = kmap(initp_page); + token = (void *)((unsigned long)sigstruct + PAGE_SIZE / 2); + + if (copy_from_user(token, (void __user *)einit.einittoken, + SGX_LAUNCH_TOKEN_SIZE)) { + ret = -EFAULT; + goto out; + } + + if (copy_from_user(sigstruct, (void __user *)einit.sigstruct, + sizeof(*sigstruct))) { + ret = -EFAULT; + goto out; + } + + /* + * A legacy field used with Intel signed enclaves. These used to mean + * regular and architectural enclaves. The CPU only accepts these values + * but they do not have any other meaning. + * + * Thus, reject any other values. + */ + if (sigstruct->header.vendor != 0x0000 && + sigstruct->header.vendor != 0x8086) { + ret = -EINVAL; + goto out; + } + + ret = sgx_encl_init(encl, sigstruct, token); +out: + kunmap(initp_page); + __free_page(initp_page); + return ret; +} + /** * sgx_ioc_enclave_set_attribute - handler for %SGX_IOC_ENCLAVE_SET_ATTRIBUTE * @filep: open file to /dev/sgx @@ -804,6 +864,9 @@ long sgx_ioctl(struct file *filep, unsigned int cmd, unsigned long arg) case SGX_IOC_ENCLAVE_INIT: ret = sgx_ioc_enclave_init(encl, (void __user *)arg); break; + case SGX_IOC_ENCLAVE_INIT_WITH_TOKEN: + ret = sgx_ioc_enclave_init_with_token(encl, (void __user *)arg); + break; case SGX_IOC_ENCLAVE_SET_ATTRIBUTE: ret = sgx_ioc_enclave_set_attribute(encl, (void __user *)arg); break; -- 1.8.3.1