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