xref: /optee_os/core/kernel/user_access.c (revision a8d59198fdc30b2d06667ea0129b983a89d35b02)
1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3  * Copyright (c) 2014, STMicroelectronics International N.V.
4  * Copyright (c) 2015-2020 Linaro Limited
5  */
6 
7 #include <initcall.h>
8 #include <kernel/linker.h>
9 #include <kernel/user_access.h>
10 #include <mm/tee_mmu.h>
11 #include <string.h>
12 #include <tee_api_types.h>
13 #include <types_ext.h>
14 
15 static TEE_Result check_access(uint32_t flags, vaddr_t va, size_t len)
16 {
17 	struct tee_ta_session *s = NULL;
18 	TEE_Result res = tee_ta_get_current_session(&s);
19 
20 	if (res)
21 		return res;
22 
23 	return tee_mmu_check_access_rights(&to_user_ta_ctx(s->ctx)->uctx,
24 					   flags, va, len);
25 }
26 
27 TEE_Result copy_from_user(void *kaddr, const void *uaddr, size_t len)
28 {
29 	uint32_t flags = TEE_MEMORY_ACCESS_READ | TEE_MEMORY_ACCESS_ANY_OWNER;
30 	TEE_Result res = check_access(flags, (vaddr_t)uaddr, len);
31 
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 = check_access(flags, (vaddr_t)uaddr, len);
42 
43 	if (!res)
44 		memcpy(uaddr, kaddr, len);
45 
46 	return res;
47 }
48 
49 TEE_Result copy_from_user_private(void *kaddr, const void *uaddr, size_t len)
50 {
51 	uint32_t flags = TEE_MEMORY_ACCESS_READ;
52 	TEE_Result res = check_access(flags, (vaddr_t)uaddr, len);
53 
54 	if (!res)
55 		memcpy(kaddr, uaddr, len);
56 
57 	return res;
58 }
59 
60 TEE_Result copy_to_user_private(void *uaddr, const void *kaddr, size_t len)
61 {
62 	uint32_t flags = TEE_MEMORY_ACCESS_WRITE;
63 	TEE_Result res = check_access(flags, (vaddr_t)uaddr, len);
64 
65 	if (!res)
66 		memcpy(uaddr, kaddr, len);
67 
68 	return res;
69 }
70 
71 TEE_Result copy_kaddr_to_uref(uint32_t *uref, void *kaddr)
72 {
73 	uint32_t ref = kaddr_to_uref(kaddr);
74 
75 	return copy_to_user_private(uref, &ref, sizeof(ref));
76 }
77 
78 uint32_t kaddr_to_uref(void *kaddr)
79 {
80 	assert(((vaddr_t)kaddr - VCORE_START_VA) < UINT32_MAX);
81 	return (vaddr_t)kaddr - VCORE_START_VA;
82 }
83 
84 vaddr_t uref_to_vaddr(uint32_t uref)
85 {
86 	return VCORE_START_VA + uref;
87 }
88