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 list_add(&va_page->list, &encl->va_pages); in sgx_encl_create()
75 encl_size = secs->size + PAGE_SIZE; in sgx_encl_create()
84 encl->backing = backing; in sgx_encl_create()
86 secs_epc = sgx_alloc_epc_page(&encl->secs, true); in sgx_encl_create()
92 encl->secs.epc_page = secs_epc; in sgx_encl_create()
102 ret = -EIO; in sgx_encl_create()
106 if (secs->attributes & SGX_ATTR_DEBUG) in sgx_encl_create()
107 set_bit(SGX_ENCL_DEBUG, &encl->flags); in sgx_encl_create()
109 encl->secs.encl = encl; in sgx_encl_create()
110 encl->secs.type = SGX_PAGE_TYPE_SECS; in sgx_encl_create()
111 encl->base = secs->base; in sgx_encl_create()
112 encl->size = secs->size; in sgx_encl_create()
113 encl->attributes = secs->attributes; in sgx_encl_create()
114 encl->attributes_mask = SGX_ATTR_UNPRIV_MASK; in sgx_encl_create()
116 /* Set only after completion, as encl->lock has not been taken. */ in sgx_encl_create()
117 set_bit(SGX_ENCL_CREATED, &encl->flags); in sgx_encl_create()
122 sgx_encl_free_epc_page(encl->secs.epc_page); in sgx_encl_create()
123 encl->secs.epc_page = NULL; in sgx_encl_create()
126 fput(encl->backing); in sgx_encl_create()
127 encl->backing = NULL; in sgx_encl_create()
136 * sgx_ioc_enclave_create() - handler for %SGX_IOC_ENCLAVE_CREATE
143 * - 0: Success.
144 * - -EIO: ECREATE failed.
145 * - -errno: POSIX error.
153 if (test_bit(SGX_ENCL_CREATED, &encl->flags)) in sgx_ioc_enclave_create()
154 return -EINVAL; in sgx_ioc_enclave_create()
157 return -EFAULT; in sgx_ioc_enclave_create()
161 return -ENOMEM; in sgx_ioc_enclave_create()
164 ret = -EFAULT; in sgx_ioc_enclave_create()
174 u64 perm = secinfo->flags & SGX_SECINFO_PERMISSION_MASK; in sgx_validate_secinfo()
175 u64 pt = secinfo->flags & SGX_SECINFO_PAGE_TYPE_MASK; in sgx_validate_secinfo()
178 return -EINVAL; in sgx_validate_secinfo()
181 return -EINVAL; in sgx_validate_secinfo()
188 return -EINVAL; in sgx_validate_secinfo()
190 if (secinfo->flags & SGX_SECINFO_RESERVED_MASK) in sgx_validate_secinfo()
191 return -EINVAL; in sgx_validate_secinfo()
193 if (memchr_inv(secinfo->reserved, 0, sizeof(secinfo->reserved))) in sgx_validate_secinfo()
194 return -EINVAL; in sgx_validate_secinfo()
210 vma = find_vma(current->mm, src); in __sgx_encl_add_page()
212 return -EFAULT; in __sgx_encl_add_page()
214 if (!(vma->vm_flags & VM_MAYEXEC)) in __sgx_encl_add_page()
215 return -EACCES; in __sgx_encl_add_page()
219 return -EFAULT; in __sgx_encl_add_page()
221 pginfo.secs = (unsigned long)sgx_get_epc_virt_addr(encl->secs.epc_page); in __sgx_encl_add_page()
222 pginfo.addr = encl_page->desc & PAGE_MASK; in __sgx_encl_add_page()
231 return ret ? -EIO : 0; in __sgx_encl_add_page()
242 unsigned long offset; in __sgx_encl_extend() local
245 for (offset = 0; offset < PAGE_SIZE; offset += SGX_EEXTEND_BLOCK_SIZE) { in __sgx_encl_extend()
246 ret = __eextend(sgx_get_epc_virt_addr(encl->secs.epc_page), in __sgx_encl_extend()
247 sgx_get_epc_virt_addr(epc_page) + offset); in __sgx_encl_extend()
252 return -EIO; in __sgx_encl_extend()
260 unsigned long offset, struct sgx_secinfo *secinfo, in sgx_encl_add_page() argument
268 encl_page = sgx_encl_page_alloc(encl, offset, secinfo->flags); in sgx_encl_add_page()
284 mmap_read_lock(current->mm); in sgx_encl_add_page()
285 mutex_lock(&encl->lock); in sgx_encl_add_page()
288 * Adding to encl->va_pages must be done under encl->lock. Ditto for in sgx_encl_add_page()
292 list_add(&va_page->list, &encl->va_pages); in sgx_encl_add_page()
299 ret = xa_insert(&encl->page_array, PFN_DOWN(encl_page->desc), in sgx_encl_add_page()
311 * isn't in a half-baked state in the extremely unlikely scenario in sgx_encl_add_page()
314 encl_page->encl = encl; in sgx_encl_add_page()
315 encl_page->epc_page = epc_page; in sgx_encl_add_page()
316 encl_page->type = (secinfo->flags & SGX_SECINFO_PAGE_TYPE_MASK) >> 8; in sgx_encl_add_page()
317 encl->secs_child_cnt++; in sgx_encl_add_page()
325 sgx_mark_page_reclaimable(encl_page->epc_page); in sgx_encl_add_page()
326 mutex_unlock(&encl->lock); in sgx_encl_add_page()
327 mmap_read_unlock(current->mm); in sgx_encl_add_page()
331 xa_erase(&encl->page_array, PFN_DOWN(encl_page->desc)); in sgx_encl_add_page()
335 mutex_unlock(&encl->lock); in sgx_encl_add_page()
336 mmap_read_unlock(current->mm); in sgx_encl_add_page()
346 * Ensure user provided offset and length values are valid for
350 unsigned long offset, in sgx_validate_offset_length() argument
353 if (!IS_ALIGNED(offset, PAGE_SIZE)) in sgx_validate_offset_length()
354 return -EINVAL; in sgx_validate_offset_length()
357 return -EINVAL; in sgx_validate_offset_length()
359 if (offset + length < offset) in sgx_validate_offset_length()
360 return -EINVAL; in sgx_validate_offset_length()
362 if (offset + length - PAGE_SIZE >= encl->size) in sgx_validate_offset_length()
363 return -EINVAL; in sgx_validate_offset_length()
369 * sgx_ioc_enclave_add_pages() - The handler for %SGX_IOC_ENCLAVE_ADD_PAGES
377 * A SECINFO for a TCS is required to always contain zero permissions because
386 * 2. A TCS page: PROT_R | PROT_W.
392 * -EIO in any of the following conditions:
394 * - Enclave Page Cache (EPC), the physical memory holding enclaves, has
396 * - If the source address is corrupted somehow when executing EADD.
399 * - 0: Success.
400 * - -EACCES: The source page is located in a noexec partition.
401 * - -ENOMEM: Out of EPC pages.
402 * - -EINTR: The call was interrupted before data was processed.
403 * - -EIO: Either EADD or EEXTEND failed because invalid source address
405 * - -errno: POSIX error.
414 if (!test_bit(SGX_ENCL_CREATED, &encl->flags) || in sgx_ioc_enclave_add_pages()
415 test_bit(SGX_ENCL_INITIALIZED, &encl->flags)) in sgx_ioc_enclave_add_pages()
416 return -EINVAL; in sgx_ioc_enclave_add_pages()
419 return -EFAULT; in sgx_ioc_enclave_add_pages()
422 return -EINVAL; in sgx_ioc_enclave_add_pages()
424 if (sgx_validate_offset_length(encl, add_arg.offset, add_arg.length)) in sgx_ioc_enclave_add_pages()
425 return -EINVAL; in sgx_ioc_enclave_add_pages()
429 return -EFAULT; in sgx_ioc_enclave_add_pages()
432 return -EINVAL; in sgx_ioc_enclave_add_pages()
437 ret = -ERESTARTSYS; in sgx_ioc_enclave_add_pages()
445 ret = sgx_encl_add_page(encl, add_arg.src + c, add_arg.offset + c, in sgx_ioc_enclave_add_pages()
454 return -EFAULT; in sgx_ioc_enclave_add_pages()
464 shash->tfm = tfm; in __sgx_get_key_hash()
496 if (encl->attributes & ~encl->attributes_mask) in sgx_encl_init()
497 return -EACCES; in sgx_encl_init()
504 * without it if the sigstruct->body.attributes_mask does not turn that in sgx_encl_init()
507 if (sigstruct->body.attributes & sigstruct->body.attributes_mask & in sgx_encl_init()
509 return -EINVAL; in sgx_encl_init()
511 if (sigstruct->body.miscselect & sigstruct->body.misc_mask & in sgx_encl_init()
513 return -EINVAL; in sgx_encl_init()
515 if (sigstruct->body.xfrm & sigstruct->body.xfrm_mask & in sgx_encl_init()
517 return -EINVAL; in sgx_encl_init()
519 ret = sgx_get_key_hash(sigstruct->modulus, mrsigner); in sgx_encl_init()
523 mutex_lock(&encl->lock); in sgx_encl_init()
533 addr = sgx_get_epc_virt_addr(encl->secs.epc_page); in sgx_encl_init()
555 ret = -ERESTARTSYS; in sgx_encl_init()
564 ret = -EIO; in sgx_encl_init()
567 ret = -EPERM; in sgx_encl_init()
569 set_bit(SGX_ENCL_INITIALIZED, &encl->flags); in sgx_encl_init()
573 mutex_unlock(&encl->lock); in sgx_encl_init()
578 * sgx_ioc_enclave_init() - handler for %SGX_IOC_ENCLAVE_INIT
587 * - 0: Success.
588 * - -EPERM: Invalid SIGSTRUCT.
589 * - -EIO: EINIT failed because of a power cycle.
590 * - -errno: POSIX error.
599 if (!test_bit(SGX_ENCL_CREATED, &encl->flags) || in sgx_ioc_enclave_init()
600 test_bit(SGX_ENCL_INITIALIZED, &encl->flags)) in sgx_ioc_enclave_init()
601 return -EINVAL; in sgx_ioc_enclave_init()
604 return -EFAULT; in sgx_ioc_enclave_init()
613 return -ENOMEM; in sgx_ioc_enclave_init()
620 ret = -EFAULT; in sgx_ioc_enclave_init()
631 if (sigstruct->header.vendor != 0x0000 && in sgx_ioc_enclave_init()
632 sigstruct->header.vendor != 0x8086) { in sgx_ioc_enclave_init()
633 ret = -EINVAL; in sgx_ioc_enclave_init()
645 * sgx_ioc_enclave_provision() - handler for %SGX_IOC_ENCLAVE_PROVISION
653 * - 0: Success.
654 * - -errno: Otherwise.
661 return -EFAULT; in sgx_ioc_enclave_provision()
663 return sgx_set_attribute(&encl->attributes_mask, params.fd); in sgx_ioc_enclave_provision()
674 return -ENODEV; in sgx_ioc_sgx2_ready()
676 if (!test_bit(SGX_ENCL_INITIALIZED, &encl->flags)) in sgx_ioc_sgx2_ready()
677 return -EINVAL; in sgx_ioc_sgx2_ready()
683 * Some SGX functions require that no cached linear-to-physical address
686 * linear-to-physical address mappings belonging to all threads of
690 * SGX function requiring that no cached linear-to-physical mappings
698 epc_virt = sgx_get_epc_virt_addr(encl->secs.epc_page); in sgx_enclave_etrack()
716 return -EFAULT; in sgx_enclave_etrack()
725 * sgx_enclave_restrict_permissions() - Restrict EPCM permissions
731 * - 0: Success.
732 * - -errno: Otherwise.
746 secinfo.flags = modp->permissions & SGX_SECINFO_PERMISSION_MASK; in sgx_enclave_restrict_permissions()
748 for (c = 0 ; c < modp->length; c += PAGE_SIZE) { in sgx_enclave_restrict_permissions()
749 addr = encl->base + modp->offset + c; in sgx_enclave_restrict_permissions()
753 mutex_lock(&encl->lock); in sgx_enclave_restrict_permissions()
757 ret = PTR_ERR(entry) == -EBUSY ? -EAGAIN : -EFAULT; in sgx_enclave_restrict_permissions()
766 if (entry->type != SGX_PAGE_TYPE_REG) { in sgx_enclave_restrict_permissions()
767 ret = -EINVAL; in sgx_enclave_restrict_permissions()
772 * Apart from ensuring that read-access remains, do not verify in sgx_enclave_restrict_permissions()
781 epc_virt = sgx_get_epc_virt_addr(entry->epc_page); in sgx_enclave_restrict_permissions()
793 ret = -EFAULT; in sgx_enclave_restrict_permissions()
797 modp->result = ret; in sgx_enclave_restrict_permissions()
798 ret = -EFAULT; in sgx_enclave_restrict_permissions()
804 ret = -EFAULT; in sgx_enclave_restrict_permissions()
808 mutex_unlock(&encl->lock); in sgx_enclave_restrict_permissions()
815 mutex_unlock(&encl->lock); in sgx_enclave_restrict_permissions()
817 modp->count = c; in sgx_enclave_restrict_permissions()
823 * sgx_ioc_enclave_restrict_permissions() - handler for
839 * - 0: Success
840 * - -errno: Otherwise
853 return -EFAULT; in sgx_ioc_enclave_restrict_permissions()
855 if (sgx_validate_offset_length(encl, params.offset, params.length)) in sgx_ioc_enclave_restrict_permissions()
856 return -EINVAL; in sgx_ioc_enclave_restrict_permissions()
859 return -EINVAL; in sgx_ioc_enclave_restrict_permissions()
867 return -EINVAL; in sgx_ioc_enclave_restrict_permissions()
870 return -EINVAL; in sgx_ioc_enclave_restrict_permissions()
875 return -EFAULT; in sgx_ioc_enclave_restrict_permissions()
881 * sgx_enclave_modify_types() - Modify type of SGX enclave pages
887 * - 0: Success
888 * - -errno: Otherwise
903 page_type = modt->page_type & SGX_PAGE_TYPE_MASK; in sgx_enclave_modify_types()
909 return -EINVAL; in sgx_enclave_modify_types()
915 for (c = 0 ; c < modt->length; c += PAGE_SIZE) { in sgx_enclave_modify_types()
916 addr = encl->base + modt->offset + c; in sgx_enclave_modify_types()
920 mutex_lock(&encl->lock); in sgx_enclave_modify_types()
924 ret = PTR_ERR(entry) == -EBUSY ? -EAGAIN : -EFAULT; in sgx_enclave_modify_types()
931 * or SGX_PAGE_TYPE_TRIM but TCS pages can only be trimmed. in sgx_enclave_modify_types()
934 if (!(entry->type == SGX_PAGE_TYPE_REG || in sgx_enclave_modify_types()
935 (entry->type == SGX_PAGE_TYPE_TCS && in sgx_enclave_modify_types()
937 ret = -EINVAL; in sgx_enclave_modify_types()
941 max_prot_restore = entry->vm_max_prot_bits; in sgx_enclave_modify_types()
944 * Once a regular page becomes a TCS page it cannot be in sgx_enclave_modify_types()
946 * the TCS page that is always RW from kernel perspective but in sgx_enclave_modify_types()
951 if (entry->type == SGX_PAGE_TYPE_REG && in sgx_enclave_modify_types()
953 if (~entry->vm_max_prot_bits & (VM_READ | VM_WRITE)) { in sgx_enclave_modify_types()
954 ret = -EPERM; in sgx_enclave_modify_types()
958 entry->vm_max_prot_bits = calc_vm_prot_bits(prot, 0); in sgx_enclave_modify_types()
964 if (sgx_unmark_page_reclaimable(entry->epc_page)) { in sgx_enclave_modify_types()
965 ret = -EAGAIN; in sgx_enclave_modify_types()
970 * Do not keep encl->lock because of dependency on in sgx_enclave_modify_types()
973 mutex_unlock(&encl->lock); in sgx_enclave_modify_types()
977 mutex_lock(&encl->lock); in sgx_enclave_modify_types()
979 sgx_mark_page_reclaimable(entry->epc_page); in sgx_enclave_modify_types()
983 epc_virt = sgx_get_epc_virt_addr(entry->epc_page); in sgx_enclave_modify_types()
995 ret = -EFAULT; in sgx_enclave_modify_types()
999 modt->result = ret; in sgx_enclave_modify_types()
1000 ret = -EFAULT; in sgx_enclave_modify_types()
1006 ret = -EFAULT; in sgx_enclave_modify_types()
1010 entry->type = page_type; in sgx_enclave_modify_types()
1012 mutex_unlock(&encl->lock); in sgx_enclave_modify_types()
1019 entry->vm_max_prot_bits = max_prot_restore; in sgx_enclave_modify_types()
1021 mutex_unlock(&encl->lock); in sgx_enclave_modify_types()
1023 modt->count = c; in sgx_enclave_modify_types()
1029 * sgx_ioc_enclave_modify_types() - handler for %SGX_IOC_ENCLAVE_MODIFY_TYPES
1035 * * It is possible to add TCS pages to an enclave by changing the type of
1036 * regular pages (%SGX_PAGE_TYPE_REG) to TCS (%SGX_PAGE_TYPE_TCS) pages.
1040 * * Regular or TCS pages can dynamically be removed from an initialized
1048 * - 0: Success
1049 * - -errno: Otherwise
1062 return -EFAULT; in sgx_ioc_enclave_modify_types()
1064 if (sgx_validate_offset_length(encl, params.offset, params.length)) in sgx_ioc_enclave_modify_types()
1065 return -EINVAL; in sgx_ioc_enclave_modify_types()
1068 return -EINVAL; in sgx_ioc_enclave_modify_types()
1071 return -EINVAL; in sgx_ioc_enclave_modify_types()
1076 return -EFAULT; in sgx_ioc_enclave_modify_types()
1082 * sgx_encl_remove_pages() - Remove trimmed pages from SGX enclave
1087 * - 0: Success.
1088 * - -errno: Otherwise.
1103 for (c = 0 ; c < params->length; c += PAGE_SIZE) { in sgx_encl_remove_pages()
1104 addr = encl->base + params->offset + c; in sgx_encl_remove_pages()
1108 mutex_lock(&encl->lock); in sgx_encl_remove_pages()
1112 ret = PTR_ERR(entry) == -EBUSY ? -EAGAIN : -EFAULT; in sgx_encl_remove_pages()
1116 if (entry->type != SGX_PAGE_TYPE_TRIM) { in sgx_encl_remove_pages()
1117 ret = -EPERM; in sgx_encl_remove_pages()
1122 * ENCLS[EMODPR] is a no-op instruction used to inform if in sgx_encl_remove_pages()
1129 epc_virt = sgx_get_epc_virt_addr(entry->epc_page); in sgx_encl_remove_pages()
1132 ret = -EPERM; in sgx_encl_remove_pages()
1136 if (sgx_unmark_page_reclaimable(entry->epc_page)) { in sgx_encl_remove_pages()
1137 ret = -EBUSY; in sgx_encl_remove_pages()
1142 * Do not keep encl->lock because of dependency on in sgx_encl_remove_pages()
1145 mutex_unlock(&encl->lock); in sgx_encl_remove_pages()
1149 mutex_lock(&encl->lock); in sgx_encl_remove_pages()
1151 sgx_encl_free_epc_page(entry->epc_page); in sgx_encl_remove_pages()
1152 encl->secs_child_cnt--; in sgx_encl_remove_pages()
1153 entry->epc_page = NULL; in sgx_encl_remove_pages()
1154 xa_erase(&encl->page_array, PFN_DOWN(entry->desc)); in sgx_encl_remove_pages()
1158 mutex_unlock(&encl->lock); in sgx_encl_remove_pages()
1165 mutex_unlock(&encl->lock); in sgx_encl_remove_pages()
1167 params->count = c; in sgx_encl_remove_pages()
1173 * sgx_ioc_enclave_remove_pages() - handler for %SGX_IOC_ENCLAVE_REMOVE_PAGES
1195 * - 0: Success
1196 * - -errno: Otherwise
1209 return -EFAULT; in sgx_ioc_enclave_remove_pages()
1211 if (sgx_validate_offset_length(encl, params.offset, params.length)) in sgx_ioc_enclave_remove_pages()
1212 return -EINVAL; in sgx_ioc_enclave_remove_pages()
1215 return -EINVAL; in sgx_ioc_enclave_remove_pages()
1220 return -EFAULT; in sgx_ioc_enclave_remove_pages()
1227 struct sgx_encl *encl = filep->private_data; in sgx_ioctl()
1230 if (test_and_set_bit(SGX_ENCL_IOCTL, &encl->flags)) in sgx_ioctl()
1231 return -EBUSY; in sgx_ioctl()
1257 ret = -ENOIOCTLCMD; in sgx_ioctl()
1261 clear_bit(SGX_ENCL_IOCTL, &encl->flags); in sgx_ioctl()