1 // SPDX-License-Identifier: GPL-2.0 2 /* Copyright(c) 2016-20 Intel Corporation. */ 3 4 #include <linux/acpi.h> 5 #include <linux/miscdevice.h> 6 #include <linux/mman.h> 7 #include <linux/security.h> 8 #include <linux/suspend.h> 9 #include <asm/traps.h> 10 #include "driver.h" 11 #include "encl.h" 12 13 static int sgx_open(struct inode *inode, struct file *file) 14 { 15 struct sgx_encl *encl; 16 17 encl = kzalloc(sizeof(*encl), GFP_KERNEL); 18 if (!encl) 19 return -ENOMEM; 20 21 xa_init(&encl->page_array); 22 mutex_init(&encl->lock); 23 24 file->private_data = encl; 25 26 return 0; 27 } 28 29 static int sgx_release(struct inode *inode, struct file *file) 30 { 31 struct sgx_encl *encl = file->private_data; 32 struct sgx_encl_page *entry; 33 unsigned long index; 34 35 xa_for_each(&encl->page_array, index, entry) { 36 if (entry->epc_page) { 37 sgx_free_epc_page(entry->epc_page); 38 encl->secs_child_cnt--; 39 entry->epc_page = NULL; 40 } 41 42 kfree(entry); 43 } 44 45 xa_destroy(&encl->page_array); 46 47 if (!encl->secs_child_cnt && encl->secs.epc_page) { 48 sgx_free_epc_page(encl->secs.epc_page); 49 encl->secs.epc_page = NULL; 50 } 51 52 /* Detect EPC page leaks. */ 53 WARN_ON_ONCE(encl->secs_child_cnt); 54 WARN_ON_ONCE(encl->secs.epc_page); 55 56 kfree(encl); 57 return 0; 58 } 59 60 static int sgx_mmap(struct file *file, struct vm_area_struct *vma) 61 { 62 struct sgx_encl *encl = file->private_data; 63 int ret; 64 65 ret = sgx_encl_may_map(encl, vma->vm_start, vma->vm_end, vma->vm_flags); 66 if (ret) 67 return ret; 68 69 vma->vm_ops = &sgx_vm_ops; 70 vma->vm_flags |= VM_PFNMAP | VM_DONTEXPAND | VM_DONTDUMP | VM_IO; 71 vma->vm_private_data = encl; 72 73 return 0; 74 } 75 76 static unsigned long sgx_get_unmapped_area(struct file *file, 77 unsigned long addr, 78 unsigned long len, 79 unsigned long pgoff, 80 unsigned long flags) 81 { 82 if ((flags & MAP_TYPE) == MAP_PRIVATE) 83 return -EINVAL; 84 85 if (flags & MAP_FIXED) 86 return addr; 87 88 return current->mm->get_unmapped_area(file, addr, len, pgoff, flags); 89 } 90 91 static const struct file_operations sgx_encl_fops = { 92 .owner = THIS_MODULE, 93 .open = sgx_open, 94 .release = sgx_release, 95 .mmap = sgx_mmap, 96 .get_unmapped_area = sgx_get_unmapped_area, 97 }; 98 99 static struct miscdevice sgx_dev_enclave = { 100 .minor = MISC_DYNAMIC_MINOR, 101 .name = "sgx_enclave", 102 .nodename = "sgx_enclave", 103 .fops = &sgx_encl_fops, 104 }; 105 106 int __init sgx_drv_init(void) 107 { 108 if (!cpu_feature_enabled(X86_FEATURE_SGX_LC)) 109 return -ENODEV; 110 111 return misc_register(&sgx_dev_enclave); 112 } 113