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