1 // SPDX-License-Identifier: BSD-2-Clause 2 /* 3 * Copyright (c) 2014, STMicroelectronics International N.V. 4 * Copyright (c) 2015-2020, 2022 Linaro Limited 5 */ 6 7 #include <initcall.h> 8 #include <kernel/linker.h> 9 #include <kernel/user_access.h> 10 #include <kernel/user_mode_ctx.h> 11 #include <memtag.h> 12 #include <mm/vm.h> 13 #include <string.h> 14 #include <tee_api_types.h> 15 #include <types_ext.h> 16 17 static TEE_Result check_access(uint32_t flags, const void *uaddr, size_t len) 18 { 19 struct ts_session *s = ts_get_current_session(); 20 21 return vm_check_access_rights(to_user_mode_ctx(s->ctx), flags, 22 (vaddr_t)uaddr, len); 23 } 24 25 TEE_Result copy_from_user(void *kaddr, const void *uaddr, size_t len) 26 { 27 uint32_t flags = TEE_MEMORY_ACCESS_READ | TEE_MEMORY_ACCESS_ANY_OWNER; 28 TEE_Result res = TEE_SUCCESS; 29 30 uaddr = memtag_strip_tag_const(uaddr); 31 res = check_access(flags, uaddr, len); 32 if (!res) 33 memcpy(kaddr, uaddr, len); 34 35 return res; 36 } 37 38 TEE_Result copy_to_user(void *uaddr, const void *kaddr, size_t len) 39 { 40 uint32_t flags = TEE_MEMORY_ACCESS_WRITE | TEE_MEMORY_ACCESS_ANY_OWNER; 41 TEE_Result res = TEE_SUCCESS; 42 43 uaddr = memtag_strip_tag(uaddr); 44 res = check_access(flags, uaddr, len); 45 if (!res) 46 memcpy(uaddr, kaddr, len); 47 48 return res; 49 } 50 51 TEE_Result copy_from_user_private(void *kaddr, const void *uaddr, size_t len) 52 { 53 uint32_t flags = TEE_MEMORY_ACCESS_READ; 54 TEE_Result res = TEE_SUCCESS; 55 56 uaddr = memtag_strip_tag_const(uaddr); 57 res = check_access(flags, uaddr, len); 58 if (!res) 59 memcpy(kaddr, uaddr, len); 60 61 return res; 62 } 63 64 TEE_Result copy_to_user_private(void *uaddr, const void *kaddr, size_t len) 65 { 66 uint32_t flags = TEE_MEMORY_ACCESS_WRITE; 67 TEE_Result res = TEE_SUCCESS; 68 69 uaddr = memtag_strip_tag(uaddr); 70 res = check_access(flags, uaddr, len); 71 if (!res) 72 memcpy(uaddr, kaddr, len); 73 74 return res; 75 } 76 77 TEE_Result copy_kaddr_to_uref(uint32_t *uref, void *kaddr) 78 { 79 uint32_t ref = kaddr_to_uref(kaddr); 80 81 return copy_to_user_private(uref, &ref, sizeof(ref)); 82 } 83 84 uint32_t kaddr_to_uref(void *kaddr) 85 { 86 if (MEMTAG_IS_ENABLED) { 87 unsigned int uref_tag_shift = 32 - MEMTAG_TAG_WIDTH; 88 vaddr_t uref = memtag_strip_tag_vaddr(kaddr); 89 90 uref -= VCORE_START_VA; 91 assert(uref < (UINT32_MAX >> MEMTAG_TAG_WIDTH)); 92 uref |= memtag_get_tag(kaddr) << uref_tag_shift; 93 return uref; 94 } 95 96 assert(((vaddr_t)kaddr - VCORE_START_VA) < UINT32_MAX); 97 return (vaddr_t)kaddr - VCORE_START_VA; 98 } 99 100 vaddr_t uref_to_vaddr(uint32_t uref) 101 { 102 if (MEMTAG_IS_ENABLED) { 103 vaddr_t u = uref & (UINT32_MAX >> MEMTAG_TAG_WIDTH); 104 unsigned int uref_tag_shift = 32 - MEMTAG_TAG_WIDTH; 105 uint8_t tag = uref >> uref_tag_shift; 106 107 return memtag_insert_tag_vaddr(VCORE_START_VA + u, tag); 108 } 109 110 return VCORE_START_VA + uref; 111 } 112