When creating an enclave attach it to an anonymous file. This prepares the code to have a separate interface at runtime, which can be published to the user space after the enclave has been fully initialized. Cc: luto@xxxxxxxxxx Cc: Stephen Smalley <sds@xxxxxxxxxxxxx> Cc: Casey Schaufler <casey@xxxxxxxxxxxxxxxx> Cc: Haitao Huang <haitao.huang@xxxxxxxxxxxxxxx> Cc: Sean Christopherson <sean.j.christopherson@xxxxxxxxx> Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@xxxxxxxxxxxxxxx> --- arch/x86/kernel/cpu/sgx/driver.c | 102 +++++++++++++++++++++---------- arch/x86/kernel/cpu/sgx/ioctl.c | 3 +- 2 files changed, 71 insertions(+), 34 deletions(-) diff --git a/arch/x86/kernel/cpu/sgx/driver.c b/arch/x86/kernel/cpu/sgx/driver.c index 997a7f4117c5..1c825ef957db 100644 --- a/arch/x86/kernel/cpu/sgx/driver.c +++ b/arch/x86/kernel/cpu/sgx/driver.c @@ -6,6 +6,7 @@ #include <linux/mman.h> #include <linux/security.h> #include <linux/suspend.h> +#include <linux/anon_inodes.h> #include <asm/traps.h> #include "driver.h" #include "encl.h" @@ -21,35 +22,7 @@ u64 sgx_attributes_reserved_mask; u64 sgx_xfrm_reserved_mask = ~0x3; u32 sgx_xsave_size_tbl[64]; -static int sgx_open(struct inode *inode, struct file *file) -{ - struct sgx_encl *encl; - int ret; - - encl = kzalloc(sizeof(*encl), GFP_KERNEL); - if (!encl) - return -ENOMEM; - - atomic_set(&encl->flags, 0); - kref_init(&encl->refcount); - INIT_LIST_HEAD(&encl->va_pages); - INIT_RADIX_TREE(&encl->page_tree, GFP_KERNEL); - mutex_init(&encl->lock); - INIT_LIST_HEAD(&encl->mm_list); - spin_lock_init(&encl->mm_lock); - - ret = init_srcu_struct(&encl->srcu); - if (ret) { - kfree(encl); - return ret; - } - - file->private_data = encl; - - return 0; -} - -static int sgx_release(struct inode *inode, struct file *file) +static int sgx_encl_file_release(struct inode *inode, struct file *file) { struct sgx_encl *encl = file->private_data; struct sgx_encl_mm *encl_mm; @@ -84,6 +57,68 @@ static int sgx_release(struct inode *inode, struct file *file) return 0; } +static const struct file_operations sgx_encl_file_fops = { + .owner = THIS_MODULE, + .release = sgx_encl_file_release, +}; + +static int sgx_open(struct inode *inode, struct file *file) +{ + struct file *encl_file = NULL; + struct sgx_encl *encl = NULL; + int ret; + + encl = kzalloc(sizeof(*encl), GFP_KERNEL); + if (!encl) { + ret = -ENOMEM; + goto err; + } + + encl_file = anon_inode_getfile("[sgx]", &sgx_encl_file_fops, encl, + O_RDWR); + if (IS_ERR(encl_file)) { + ret = PTR_ERR(encl_file); + goto err; + } + + ret = init_srcu_struct(&encl->srcu); + if (ret) + goto err; + + atomic_set(&encl->flags, 0); + kref_init(&encl->refcount); + INIT_LIST_HEAD(&encl->va_pages); + INIT_RADIX_TREE(&encl->page_tree, GFP_KERNEL); + mutex_init(&encl->lock); + INIT_LIST_HEAD(&encl->mm_list); + spin_lock_init(&encl->mm_lock); + + file->private_data = encl_file; + + return 0; + +err: + if (encl_file) + fput(encl_file); + + kfree(encl); + return ret; +} + +static int sgx_encl_dev_release(struct inode *inode, struct file *file) +{ + struct file *encl_file = file->private_data; + + /* + * Can be NULL when the enclave file has been handed over to the + * user space. + */ + if (encl_file) + fput(encl_file); + + return 0; +} + #ifdef CONFIG_COMPAT static long sgx_compat_ioctl(struct file *filep, unsigned int cmd, unsigned long arg) @@ -94,7 +129,8 @@ static long sgx_compat_ioctl(struct file *filep, unsigned int cmd, static int sgx_mmap(struct file *file, struct vm_area_struct *vma) { - struct sgx_encl *encl = file->private_data; + struct file *encl_file = file->private_data; + struct sgx_encl *encl = encl_file->private_data; int ret; ret = sgx_encl_may_map(encl, vma->vm_start, vma->vm_end, @@ -128,10 +164,10 @@ static unsigned long sgx_get_unmapped_area(struct file *file, return current->mm->get_unmapped_area(file, addr, len, pgoff, flags); } -static const struct file_operations sgx_encl_fops = { +static const struct file_operations sgx_encl_dev_fops = { .owner = THIS_MODULE, .open = sgx_open, - .release = sgx_release, + .release = sgx_encl_dev_release, .unlocked_ioctl = sgx_ioctl, #ifdef CONFIG_COMPAT .compat_ioctl = sgx_compat_ioctl, @@ -148,7 +184,7 @@ static struct miscdevice sgx_dev_enclave = { .minor = MISC_DYNAMIC_MINOR, .name = "enclave", .nodename = "sgx/enclave", - .fops = &sgx_encl_fops, + .fops = &sgx_encl_dev_fops, }; static struct miscdevice sgx_dev_provision = { diff --git a/arch/x86/kernel/cpu/sgx/ioctl.c b/arch/x86/kernel/cpu/sgx/ioctl.c index 3af0596530a8..891aa9395907 100644 --- a/arch/x86/kernel/cpu/sgx/ioctl.c +++ b/arch/x86/kernel/cpu/sgx/ioctl.c @@ -766,7 +766,8 @@ static long sgx_ioc_enclave_set_attribute(struct sgx_encl *encl, long sgx_ioctl(struct file *filep, unsigned int cmd, unsigned long arg) { - struct sgx_encl *encl = filep->private_data; + struct file *encl_file = filep->private_data; + struct sgx_encl *encl = encl_file->private_data; int ret, encl_flags; encl_flags = atomic_fetch_or(SGX_ENCL_IOCTL, &encl->flags); -- 2.25.1