Lines Matching +full:tcs +full:- +full:offset
1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright(c) 2016-20 Intel Corporation. */
28 if (!(encl->page_cnt % SGX_VA_SLOT_COUNT)) { in sgx_encl_grow()
31 return ERR_PTR(-ENOMEM); in sgx_encl_grow()
33 va_page->epc_page = sgx_alloc_va_page(reclaim); in sgx_encl_grow()
34 if (IS_ERR(va_page->epc_page)) { in sgx_encl_grow()
35 err = ERR_CAST(va_page->epc_page); in sgx_encl_grow()
40 WARN_ON_ONCE(encl->page_cnt % SGX_VA_SLOT_COUNT); in sgx_encl_grow()
42 encl->page_cnt++; in sgx_encl_grow()
48 encl->page_cnt--; in sgx_encl_shrink()
51 sgx_encl_free_epc_page(va_page->epc_page); in sgx_encl_shrink()
52 list_del(&va_page->list); in sgx_encl_shrink()
71 if (!is_power_of_2(secs->size)) in sgx_encl_create()
72 return -EINVAL; in sgx_encl_create()
78 list_add(&va_page->list, &encl->va_pages); in sgx_encl_create()
82 encl_size = secs->size + PAGE_SIZE; in sgx_encl_create()
91 encl->backing = backing; in sgx_encl_create()
93 secs_epc = sgx_alloc_epc_page(&encl->secs, true); in sgx_encl_create()
99 encl->secs.epc_page = secs_epc; in sgx_encl_create()
109 ret = -EIO; in sgx_encl_create()
113 if (secs->attributes & SGX_ATTR_DEBUG) in sgx_encl_create()
114 set_bit(SGX_ENCL_DEBUG, &encl->flags); in sgx_encl_create()
116 encl->secs.encl = encl; in sgx_encl_create()
117 encl->secs.type = SGX_PAGE_TYPE_SECS; in sgx_encl_create()
118 encl->base = secs->base; in sgx_encl_create()
119 encl->size = secs->size; in sgx_encl_create()
120 encl->attributes = secs->attributes; in sgx_encl_create()
121 encl->attributes_mask = SGX_ATTR_UNPRIV_MASK; in sgx_encl_create()
123 /* Set only after completion, as encl->lock has not been taken. */ in sgx_encl_create()
124 set_bit(SGX_ENCL_CREATED, &encl->flags); in sgx_encl_create()
129 sgx_encl_free_epc_page(encl->secs.epc_page); in sgx_encl_create()
130 encl->secs.epc_page = NULL; in sgx_encl_create()
133 fput(encl->backing); in sgx_encl_create()
134 encl->backing = NULL; in sgx_encl_create()
143 * sgx_ioc_enclave_create() - handler for %SGX_IOC_ENCLAVE_CREATE
150 * - 0: Success.
151 * - -EIO: ECREATE failed.
152 * - -errno: POSIX error.
160 if (test_bit(SGX_ENCL_CREATED, &encl->flags)) in sgx_ioc_enclave_create()
161 return -EINVAL; in sgx_ioc_enclave_create()
164 return -EFAULT; in sgx_ioc_enclave_create()
168 return -ENOMEM; in sgx_ioc_enclave_create()
171 ret = -EFAULT; in sgx_ioc_enclave_create()
181 u64 perm = secinfo->flags & SGX_SECINFO_PERMISSION_MASK; in sgx_validate_secinfo()
182 u64 pt = secinfo->flags & SGX_SECINFO_PAGE_TYPE_MASK; in sgx_validate_secinfo()
185 return -EINVAL; in sgx_validate_secinfo()
188 return -EINVAL; in sgx_validate_secinfo()
195 return -EINVAL; in sgx_validate_secinfo()
197 if (secinfo->flags & SGX_SECINFO_RESERVED_MASK) in sgx_validate_secinfo()
198 return -EINVAL; in sgx_validate_secinfo()
200 if (memchr_inv(secinfo->reserved, 0, sizeof(secinfo->reserved))) in sgx_validate_secinfo()
201 return -EINVAL; in sgx_validate_secinfo()
217 vma = find_vma(current->mm, src); in __sgx_encl_add_page()
219 return -EFAULT; in __sgx_encl_add_page()
221 if (!(vma->vm_flags & VM_MAYEXEC)) in __sgx_encl_add_page()
222 return -EACCES; in __sgx_encl_add_page()
226 return -EFAULT; in __sgx_encl_add_page()
228 pginfo.secs = (unsigned long)sgx_get_epc_virt_addr(encl->secs.epc_page); in __sgx_encl_add_page()
229 pginfo.addr = encl_page->desc & PAGE_MASK; in __sgx_encl_add_page()
238 return ret ? -EIO : 0; in __sgx_encl_add_page()
249 unsigned long offset; in __sgx_encl_extend() local
252 for (offset = 0; offset < PAGE_SIZE; offset += SGX_EEXTEND_BLOCK_SIZE) { in __sgx_encl_extend()
253 ret = __eextend(sgx_get_epc_virt_addr(encl->secs.epc_page), in __sgx_encl_extend()
254 sgx_get_epc_virt_addr(epc_page) + offset); in __sgx_encl_extend()
259 return -EIO; in __sgx_encl_extend()
267 unsigned long offset, struct sgx_secinfo *secinfo, in sgx_encl_add_page() argument
275 encl_page = sgx_encl_page_alloc(encl, offset, secinfo->flags); in sgx_encl_add_page()
291 mmap_read_lock(current->mm); in sgx_encl_add_page()
292 mutex_lock(&encl->lock); in sgx_encl_add_page()
295 * Adding to encl->va_pages must be done under encl->lock. Ditto for in sgx_encl_add_page()
299 list_add(&va_page->list, &encl->va_pages); in sgx_encl_add_page()
306 ret = xa_insert(&encl->page_array, PFN_DOWN(encl_page->desc), in sgx_encl_add_page()
318 * isn't in a half-baked state in the extremely unlikely scenario in sgx_encl_add_page()
321 encl_page->encl = encl; in sgx_encl_add_page()
322 encl_page->epc_page = epc_page; in sgx_encl_add_page()
323 encl_page->type = (secinfo->flags & SGX_SECINFO_PAGE_TYPE_MASK) >> 8; in sgx_encl_add_page()
324 encl->secs_child_cnt++; in sgx_encl_add_page()
332 sgx_mark_page_reclaimable(encl_page->epc_page); in sgx_encl_add_page()
333 mutex_unlock(&encl->lock); in sgx_encl_add_page()
334 mmap_read_unlock(current->mm); in sgx_encl_add_page()
338 xa_erase(&encl->page_array, PFN_DOWN(encl_page->desc)); in sgx_encl_add_page()
342 mutex_unlock(&encl->lock); in sgx_encl_add_page()
343 mmap_read_unlock(current->mm); in sgx_encl_add_page()
353 * Ensure user provided offset and length values are valid for
357 unsigned long offset, in sgx_validate_offset_length() argument
360 if (!IS_ALIGNED(offset, PAGE_SIZE)) in sgx_validate_offset_length()
361 return -EINVAL; in sgx_validate_offset_length()
364 return -EINVAL; in sgx_validate_offset_length()
366 if (offset + length < offset) in sgx_validate_offset_length()
367 return -EINVAL; in sgx_validate_offset_length()
369 if (offset + length - PAGE_SIZE >= encl->size) in sgx_validate_offset_length()
370 return -EINVAL; in sgx_validate_offset_length()
376 * sgx_ioc_enclave_add_pages() - The handler for %SGX_IOC_ENCLAVE_ADD_PAGES
384 * A SECINFO for a TCS is required to always contain zero permissions because
393 * 2. A TCS page: PROT_R | PROT_W.
399 * -EIO in any of the following conditions:
401 * - Enclave Page Cache (EPC), the physical memory holding enclaves, has
403 * - If the source address is corrupted somehow when executing EADD.
406 * - 0: Success.
407 * - -EACCES: The source page is located in a noexec partition.
408 * - -ENOMEM: Out of EPC pages.
409 * - -EINTR: The call was interrupted before data was processed.
410 * - -EIO: Either EADD or EEXTEND failed because invalid source address
412 * - -errno: POSIX error.
421 if (!test_bit(SGX_ENCL_CREATED, &encl->flags) || in sgx_ioc_enclave_add_pages()
422 test_bit(SGX_ENCL_INITIALIZED, &encl->flags)) in sgx_ioc_enclave_add_pages()
423 return -EINVAL; in sgx_ioc_enclave_add_pages()
426 return -EFAULT; in sgx_ioc_enclave_add_pages()
429 return -EINVAL; in sgx_ioc_enclave_add_pages()
431 if (sgx_validate_offset_length(encl, add_arg.offset, add_arg.length)) in sgx_ioc_enclave_add_pages()
432 return -EINVAL; in sgx_ioc_enclave_add_pages()
436 return -EFAULT; in sgx_ioc_enclave_add_pages()
439 return -EINVAL; in sgx_ioc_enclave_add_pages()
444 ret = -ERESTARTSYS; in sgx_ioc_enclave_add_pages()
452 ret = sgx_encl_add_page(encl, add_arg.src + c, add_arg.offset + c, in sgx_ioc_enclave_add_pages()
461 return -EFAULT; in sgx_ioc_enclave_add_pages()
471 shash->tfm = tfm; in __sgx_get_key_hash()
503 if (encl->attributes & ~encl->attributes_mask) in sgx_encl_init()
504 return -EACCES; in sgx_encl_init()
511 * without it if the sigstruct->body.attributes_mask does not turn that in sgx_encl_init()
514 if (sigstruct->body.attributes & sigstruct->body.attributes_mask & in sgx_encl_init()
516 return -EINVAL; in sgx_encl_init()
518 if (sigstruct->body.miscselect & sigstruct->body.misc_mask & in sgx_encl_init()
520 return -EINVAL; in sgx_encl_init()
522 if (sigstruct->body.xfrm & sigstruct->body.xfrm_mask & in sgx_encl_init()
524 return -EINVAL; in sgx_encl_init()
526 ret = sgx_get_key_hash(sigstruct->modulus, mrsigner); in sgx_encl_init()
530 mutex_lock(&encl->lock); in sgx_encl_init()
540 addr = sgx_get_epc_virt_addr(encl->secs.epc_page); in sgx_encl_init()
562 ret = -ERESTARTSYS; in sgx_encl_init()
571 ret = -EIO; in sgx_encl_init()
574 ret = -EPERM; in sgx_encl_init()
576 set_bit(SGX_ENCL_INITIALIZED, &encl->flags); in sgx_encl_init()
580 mutex_unlock(&encl->lock); in sgx_encl_init()
585 * sgx_ioc_enclave_init() - handler for %SGX_IOC_ENCLAVE_INIT
594 * - 0: Success.
595 * - -EPERM: Invalid SIGSTRUCT.
596 * - -EIO: EINIT failed because of a power cycle.
597 * - -errno: POSIX error.
606 if (!test_bit(SGX_ENCL_CREATED, &encl->flags) || in sgx_ioc_enclave_init()
607 test_bit(SGX_ENCL_INITIALIZED, &encl->flags)) in sgx_ioc_enclave_init()
608 return -EINVAL; in sgx_ioc_enclave_init()
611 return -EFAULT; in sgx_ioc_enclave_init()
620 return -ENOMEM; in sgx_ioc_enclave_init()
627 ret = -EFAULT; in sgx_ioc_enclave_init()
638 if (sigstruct->header.vendor != 0x0000 && in sgx_ioc_enclave_init()
639 sigstruct->header.vendor != 0x8086) { in sgx_ioc_enclave_init()
640 ret = -EINVAL; in sgx_ioc_enclave_init()
652 * sgx_ioc_enclave_provision() - handler for %SGX_IOC_ENCLAVE_PROVISION
660 * - 0: Success.
661 * - -errno: Otherwise.
668 return -EFAULT; in sgx_ioc_enclave_provision()
670 return sgx_set_attribute(&encl->attributes_mask, params.fd); in sgx_ioc_enclave_provision()
681 return -ENODEV; in sgx_ioc_sgx2_ready()
683 if (!test_bit(SGX_ENCL_INITIALIZED, &encl->flags)) in sgx_ioc_sgx2_ready()
684 return -EINVAL; in sgx_ioc_sgx2_ready()
690 * Some SGX functions require that no cached linear-to-physical address
693 * linear-to-physical address mappings belonging to all threads of
697 * SGX function requiring that no cached linear-to-physical mappings
705 epc_virt = sgx_get_epc_virt_addr(encl->secs.epc_page); in sgx_enclave_etrack()
723 return -EFAULT; in sgx_enclave_etrack()
732 * sgx_enclave_restrict_permissions() - Restrict EPCM permissions
738 * - 0: Success.
739 * - -errno: Otherwise.
753 secinfo.flags = modp->permissions & SGX_SECINFO_PERMISSION_MASK; in sgx_enclave_restrict_permissions()
755 for (c = 0 ; c < modp->length; c += PAGE_SIZE) { in sgx_enclave_restrict_permissions()
756 addr = encl->base + modp->offset + c; in sgx_enclave_restrict_permissions()
760 mutex_lock(&encl->lock); in sgx_enclave_restrict_permissions()
764 ret = PTR_ERR(entry) == -EBUSY ? -EAGAIN : -EFAULT; in sgx_enclave_restrict_permissions()
773 if (entry->type != SGX_PAGE_TYPE_REG) { in sgx_enclave_restrict_permissions()
774 ret = -EINVAL; in sgx_enclave_restrict_permissions()
779 * Apart from ensuring that read-access remains, do not verify in sgx_enclave_restrict_permissions()
788 epc_virt = sgx_get_epc_virt_addr(entry->epc_page); in sgx_enclave_restrict_permissions()
800 ret = -EFAULT; in sgx_enclave_restrict_permissions()
804 modp->result = ret; in sgx_enclave_restrict_permissions()
805 ret = -EFAULT; in sgx_enclave_restrict_permissions()
811 ret = -EFAULT; in sgx_enclave_restrict_permissions()
815 mutex_unlock(&encl->lock); in sgx_enclave_restrict_permissions()
822 mutex_unlock(&encl->lock); in sgx_enclave_restrict_permissions()
824 modp->count = c; in sgx_enclave_restrict_permissions()
830 * sgx_ioc_enclave_restrict_permissions() - handler for
846 * - 0: Success
847 * - -errno: Otherwise
860 return -EFAULT; in sgx_ioc_enclave_restrict_permissions()
862 if (sgx_validate_offset_length(encl, params.offset, params.length)) in sgx_ioc_enclave_restrict_permissions()
863 return -EINVAL; in sgx_ioc_enclave_restrict_permissions()
866 return -EINVAL; in sgx_ioc_enclave_restrict_permissions()
874 return -EINVAL; in sgx_ioc_enclave_restrict_permissions()
877 return -EINVAL; in sgx_ioc_enclave_restrict_permissions()
882 return -EFAULT; in sgx_ioc_enclave_restrict_permissions()
888 * sgx_enclave_modify_types() - Modify type of SGX enclave pages
894 * - 0: Success
895 * - -errno: Otherwise
910 page_type = modt->page_type & SGX_PAGE_TYPE_MASK; in sgx_enclave_modify_types()
916 return -EINVAL; in sgx_enclave_modify_types()
922 for (c = 0 ; c < modt->length; c += PAGE_SIZE) { in sgx_enclave_modify_types()
923 addr = encl->base + modt->offset + c; in sgx_enclave_modify_types()
927 mutex_lock(&encl->lock); in sgx_enclave_modify_types()
931 ret = PTR_ERR(entry) == -EBUSY ? -EAGAIN : -EFAULT; in sgx_enclave_modify_types()
938 * or SGX_PAGE_TYPE_TRIM but TCS pages can only be trimmed. in sgx_enclave_modify_types()
941 if (!(entry->type == SGX_PAGE_TYPE_REG || in sgx_enclave_modify_types()
942 (entry->type == SGX_PAGE_TYPE_TCS && in sgx_enclave_modify_types()
944 ret = -EINVAL; in sgx_enclave_modify_types()
948 max_prot_restore = entry->vm_max_prot_bits; in sgx_enclave_modify_types()
951 * Once a regular page becomes a TCS page it cannot be in sgx_enclave_modify_types()
953 * the TCS page that is always RW from kernel perspective but in sgx_enclave_modify_types()
958 if (entry->type == SGX_PAGE_TYPE_REG && in sgx_enclave_modify_types()
960 if (~entry->vm_max_prot_bits & (VM_READ | VM_WRITE)) { in sgx_enclave_modify_types()
961 ret = -EPERM; in sgx_enclave_modify_types()
965 entry->vm_max_prot_bits = calc_vm_prot_bits(prot, 0); in sgx_enclave_modify_types()
971 if (sgx_unmark_page_reclaimable(entry->epc_page)) { in sgx_enclave_modify_types()
972 ret = -EAGAIN; in sgx_enclave_modify_types()
977 * Do not keep encl->lock because of dependency on in sgx_enclave_modify_types()
980 mutex_unlock(&encl->lock); in sgx_enclave_modify_types()
984 mutex_lock(&encl->lock); in sgx_enclave_modify_types()
986 sgx_mark_page_reclaimable(entry->epc_page); in sgx_enclave_modify_types()
990 epc_virt = sgx_get_epc_virt_addr(entry->epc_page); in sgx_enclave_modify_types()
1002 ret = -EFAULT; in sgx_enclave_modify_types()
1006 modt->result = ret; in sgx_enclave_modify_types()
1007 ret = -EFAULT; in sgx_enclave_modify_types()
1013 ret = -EFAULT; in sgx_enclave_modify_types()
1017 entry->type = page_type; in sgx_enclave_modify_types()
1019 mutex_unlock(&encl->lock); in sgx_enclave_modify_types()
1026 entry->vm_max_prot_bits = max_prot_restore; in sgx_enclave_modify_types()
1028 mutex_unlock(&encl->lock); in sgx_enclave_modify_types()
1030 modt->count = c; in sgx_enclave_modify_types()
1036 * sgx_ioc_enclave_modify_types() - handler for %SGX_IOC_ENCLAVE_MODIFY_TYPES
1042 * * It is possible to add TCS pages to an enclave by changing the type of
1043 * regular pages (%SGX_PAGE_TYPE_REG) to TCS (%SGX_PAGE_TYPE_TCS) pages.
1047 * * Regular or TCS pages can dynamically be removed from an initialized
1055 * - 0: Success
1056 * - -errno: Otherwise
1069 return -EFAULT; in sgx_ioc_enclave_modify_types()
1071 if (sgx_validate_offset_length(encl, params.offset, params.length)) in sgx_ioc_enclave_modify_types()
1072 return -EINVAL; in sgx_ioc_enclave_modify_types()
1075 return -EINVAL; in sgx_ioc_enclave_modify_types()
1078 return -EINVAL; in sgx_ioc_enclave_modify_types()
1083 return -EFAULT; in sgx_ioc_enclave_modify_types()
1089 * sgx_encl_remove_pages() - Remove trimmed pages from SGX enclave
1094 * - 0: Success.
1095 * - -errno: Otherwise.
1110 for (c = 0 ; c < params->length; c += PAGE_SIZE) { in sgx_encl_remove_pages()
1111 addr = encl->base + params->offset + c; in sgx_encl_remove_pages()
1115 mutex_lock(&encl->lock); in sgx_encl_remove_pages()
1119 ret = PTR_ERR(entry) == -EBUSY ? -EAGAIN : -EFAULT; in sgx_encl_remove_pages()
1123 if (entry->type != SGX_PAGE_TYPE_TRIM) { in sgx_encl_remove_pages()
1124 ret = -EPERM; in sgx_encl_remove_pages()
1129 * ENCLS[EMODPR] is a no-op instruction used to inform if in sgx_encl_remove_pages()
1136 epc_virt = sgx_get_epc_virt_addr(entry->epc_page); in sgx_encl_remove_pages()
1139 ret = -EPERM; in sgx_encl_remove_pages()
1143 if (sgx_unmark_page_reclaimable(entry->epc_page)) { in sgx_encl_remove_pages()
1144 ret = -EBUSY; in sgx_encl_remove_pages()
1149 * Do not keep encl->lock because of dependency on in sgx_encl_remove_pages()
1152 mutex_unlock(&encl->lock); in sgx_encl_remove_pages()
1156 mutex_lock(&encl->lock); in sgx_encl_remove_pages()
1158 sgx_encl_free_epc_page(entry->epc_page); in sgx_encl_remove_pages()
1159 encl->secs_child_cnt--; in sgx_encl_remove_pages()
1160 entry->epc_page = NULL; in sgx_encl_remove_pages()
1161 xa_erase(&encl->page_array, PFN_DOWN(entry->desc)); in sgx_encl_remove_pages()
1165 mutex_unlock(&encl->lock); in sgx_encl_remove_pages()
1172 mutex_unlock(&encl->lock); in sgx_encl_remove_pages()
1174 params->count = c; in sgx_encl_remove_pages()
1180 * sgx_ioc_enclave_remove_pages() - handler for %SGX_IOC_ENCLAVE_REMOVE_PAGES
1202 * - 0: Success
1203 * - -errno: Otherwise
1216 return -EFAULT; in sgx_ioc_enclave_remove_pages()
1218 if (sgx_validate_offset_length(encl, params.offset, params.length)) in sgx_ioc_enclave_remove_pages()
1219 return -EINVAL; in sgx_ioc_enclave_remove_pages()
1222 return -EINVAL; in sgx_ioc_enclave_remove_pages()
1227 return -EFAULT; in sgx_ioc_enclave_remove_pages()
1234 struct sgx_encl *encl = filep->private_data; in sgx_ioctl()
1237 if (test_and_set_bit(SGX_ENCL_IOCTL, &encl->flags)) in sgx_ioctl()
1238 return -EBUSY; in sgx_ioctl()
1264 ret = -ENOIOCTLCMD; in sgx_ioctl()
1268 clear_bit(SGX_ENCL_IOCTL, &encl->flags); in sgx_ioctl()