xref: /optee_os/core/tee/tee_fs_rpc.c (revision 40ea51dee3aa8ae6f07ff8bf1299bfe7799a4db5)
1 /*
2  * Copyright (c) 2016, Linaro Limited
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright notice,
9  * this list of conditions and the following disclaimer.
10  *
11  * 2. Redistributions in binary form must reproduce the above copyright notice,
12  * this list of conditions and the following disclaimer in the documentation
13  * and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
19  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25  * POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 #include <assert.h>
29 #include <kernel/tee_misc.h>
30 #include <kernel/thread.h>
31 #include <mm/core_memprot.h>
32 #include <optee_msg_supplicant.h>
33 #include <stdlib.h>
34 #include <string_ext.h>
35 #include <string.h>
36 #include <tee/tee_fs.h>
37 #include <tee/tee_fs_rpc.h>
38 #include <tee/tee_pobj.h>
39 #include <tee/tee_svc_storage.h>
40 #include <trace.h>
41 #include <util.h>
42 
43 struct tee_fs_dir {
44 	int nw_dir;
45 	struct tee_fs_dirent d;
46 };
47 
48 static TEE_Result operation_commit(struct tee_fs_rpc_operation *op)
49 {
50 	return thread_rpc_cmd(op->id, op->num_params, op->params);
51 }
52 
53 static TEE_Result operation_open(uint32_t id, unsigned int cmd,
54 				 struct tee_pobj *po, int *fd)
55 {
56 	struct tee_fs_rpc_operation op = { .id = id, .num_params = 3 };
57 	TEE_Result res;
58 	void *va;
59 	paddr_t pa;
60 	uint64_t cookie;
61 
62 	va = tee_fs_rpc_cache_alloc(TEE_FS_NAME_MAX, &pa, &cookie);
63 	if (!va)
64 		return TEE_ERROR_OUT_OF_MEMORY;
65 
66 	op.params[0].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
67 	op.params[0].u.value.a = cmd;
68 
69 	op.params[1].attr = OPTEE_MSG_ATTR_TYPE_TMEM_INPUT;
70 	op.params[1].u.tmem.buf_ptr = pa;
71 	op.params[1].u.tmem.size = TEE_FS_NAME_MAX;
72 	op.params[1].u.tmem.shm_ref = cookie;
73 	res = tee_svc_storage_create_filename(va, TEE_FS_NAME_MAX,
74 					      po, po->temporary);
75 	if (res != TEE_SUCCESS)
76 		return res;
77 
78 	op.params[2].attr = OPTEE_MSG_ATTR_TYPE_VALUE_OUTPUT;
79 
80 	res = operation_commit(&op);
81 	if (res == TEE_SUCCESS)
82 		*fd = op.params[2].u.value.a;
83 
84 	return res;
85 }
86 
87 TEE_Result tee_fs_rpc_open(uint32_t id, struct tee_pobj *po, int *fd)
88 {
89 	return operation_open(id, OPTEE_MRF_OPEN, po, fd);
90 }
91 
92 TEE_Result tee_fs_rpc_create(uint32_t id, struct tee_pobj *po, int *fd)
93 {
94 	return operation_open(id, OPTEE_MRF_CREATE, po, fd);
95 }
96 
97 TEE_Result tee_fs_rpc_close(uint32_t id, int fd)
98 {
99 	struct tee_fs_rpc_operation op = { .id = id, .num_params = 1 };
100 
101 	op.params[0].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
102 	op.params[0].u.value.a = OPTEE_MRF_CLOSE;
103 	op.params[0].u.value.b = fd;
104 
105 	return operation_commit(&op);
106 }
107 
108 TEE_Result tee_fs_rpc_read_init(struct tee_fs_rpc_operation *op,
109 				uint32_t id, int fd, tee_fs_off_t offset,
110 				size_t data_len, void **out_data)
111 {
112 	uint8_t *va;
113 	paddr_t pa;
114 	uint64_t cookie;
115 
116 	if (offset < 0)
117 		return TEE_ERROR_BAD_PARAMETERS;
118 
119 	va = tee_fs_rpc_cache_alloc(data_len, &pa, &cookie);
120 	if (!va)
121 		return TEE_ERROR_OUT_OF_MEMORY;
122 
123 	memset(op, 0, sizeof(*op));
124 	op->id = id;
125 	op->num_params = 2;
126 
127 	op->params[0].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
128 	op->params[0].u.value.a = OPTEE_MRF_READ;
129 	op->params[0].u.value.b = fd;
130 	op->params[0].u.value.c = offset;
131 
132 	op->params[1].attr = OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT;
133 	op->params[1].u.tmem.buf_ptr = pa;
134 	op->params[1].u.tmem.size = data_len;
135 	op->params[1].u.tmem.shm_ref = cookie;
136 
137 	*out_data = va;
138 
139 	return TEE_SUCCESS;
140 }
141 
142 TEE_Result tee_fs_rpc_read_final(struct tee_fs_rpc_operation *op,
143 				 size_t *data_len)
144 {
145 	TEE_Result res = operation_commit(op);
146 
147 	if (res == TEE_SUCCESS)
148 		*data_len = op->params[1].u.tmem.size;
149 	return res;
150 }
151 
152 TEE_Result tee_fs_rpc_write_init(struct tee_fs_rpc_operation *op,
153 				 uint32_t id, int fd, tee_fs_off_t offset,
154 				 size_t data_len, void **data)
155 {
156 	uint8_t *va;
157 	paddr_t pa;
158 	uint64_t cookie;
159 
160 	if (offset < 0)
161 		return TEE_ERROR_BAD_PARAMETERS;
162 
163 	va = tee_fs_rpc_cache_alloc(data_len, &pa, &cookie);
164 	if (!va)
165 		return TEE_ERROR_OUT_OF_MEMORY;
166 
167 	memset(op, 0, sizeof(*op));
168 	op->id = id;
169 	op->num_params = 2;
170 
171 
172 	op->params[0].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
173 	op->params[0].u.value.a = OPTEE_MRF_WRITE;
174 	op->params[0].u.value.b = fd;
175 	op->params[0].u.value.c = offset;
176 
177 	op->params[1].attr = OPTEE_MSG_ATTR_TYPE_TMEM_INPUT;
178 	op->params[1].u.tmem.buf_ptr = pa;
179 	op->params[1].u.tmem.size = data_len;
180 	op->params[1].u.tmem.shm_ref = cookie;
181 
182 	*data = va;
183 
184 	return TEE_SUCCESS;
185 }
186 
187 TEE_Result tee_fs_rpc_write_final(struct tee_fs_rpc_operation *op)
188 {
189 	return operation_commit(op);
190 }
191 
192 TEE_Result tee_fs_rpc_truncate(uint32_t id, int fd, size_t len)
193 {
194 	struct tee_fs_rpc_operation op = { .id = id, .num_params = 1 };
195 
196 	op.params[0].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
197 	op.params[0].u.value.a = OPTEE_MRF_TRUNCATE;
198 	op.params[0].u.value.b = fd;
199 	op.params[0].u.value.c = len;
200 
201 	return operation_commit(&op);
202 }
203 
204 TEE_Result tee_fs_rpc_remove(uint32_t id, struct tee_pobj *po)
205 {
206 	TEE_Result res;
207 	struct tee_fs_rpc_operation op = { .id = id, .num_params = 2 };
208 	void *va;
209 	paddr_t pa;
210 	uint64_t cookie;
211 
212 	va = tee_fs_rpc_cache_alloc(TEE_FS_NAME_MAX, &pa, &cookie);
213 	if (!va)
214 		return TEE_ERROR_OUT_OF_MEMORY;
215 
216 	op.params[0].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
217 	op.params[0].u.value.a = OPTEE_MRF_REMOVE;
218 
219 	op.params[1].attr = OPTEE_MSG_ATTR_TYPE_TMEM_INPUT;
220 	op.params[1].u.tmem.buf_ptr = pa;
221 	op.params[1].u.tmem.size = TEE_FS_NAME_MAX;
222 	op.params[1].u.tmem.shm_ref = cookie;
223 	res = tee_svc_storage_create_filename(va, TEE_FS_NAME_MAX,
224 					      po, po->temporary);
225 	if (res != TEE_SUCCESS)
226 		return res;
227 
228 	return operation_commit(&op);
229 }
230 
231 TEE_Result tee_fs_rpc_rename(uint32_t id, struct tee_pobj *old,
232 			     struct tee_pobj *new, bool overwrite)
233 {
234 	TEE_Result res;
235 	struct tee_fs_rpc_operation op = { .id = id, .num_params = 3 };
236 	char *va;
237 	paddr_t pa;
238 	uint64_t cookie;
239 	bool temp;
240 
241 	va = tee_fs_rpc_cache_alloc(TEE_FS_NAME_MAX * 2, &pa, &cookie);
242 	if (!va)
243 		return TEE_ERROR_OUT_OF_MEMORY;
244 
245 	op.params[0].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
246 	op.params[0].u.value.a = OPTEE_MRF_RENAME;
247 	op.params[0].u.value.b = overwrite;
248 
249 	op.params[1].attr = OPTEE_MSG_ATTR_TYPE_TMEM_INPUT;
250 	op.params[1].u.tmem.buf_ptr = pa;
251 	op.params[1].u.tmem.size = TEE_FS_NAME_MAX;
252 	op.params[1].u.tmem.shm_ref = cookie;
253 	if (new)
254 		temp = old->temporary;
255 	else
256 		temp = true;
257 	res = tee_svc_storage_create_filename(va, TEE_FS_NAME_MAX,
258 					      old, temp);
259 	if (res != TEE_SUCCESS)
260 		return res;
261 
262 	op.params[2].attr = OPTEE_MSG_ATTR_TYPE_TMEM_INPUT;
263 	op.params[2].u.tmem.buf_ptr = pa + TEE_FS_NAME_MAX;
264 	op.params[2].u.tmem.size = TEE_FS_NAME_MAX;
265 	op.params[2].u.tmem.shm_ref = cookie;
266 	if (new) {
267 		res = tee_svc_storage_create_filename(va + TEE_FS_NAME_MAX,
268 						      TEE_FS_NAME_MAX,
269 						      new, new->temporary);
270 	} else {
271 		res = tee_svc_storage_create_filename(va + TEE_FS_NAME_MAX,
272 						      TEE_FS_NAME_MAX,
273 						      old, false);
274 	}
275 	if (res != TEE_SUCCESS)
276 		return res;
277 
278 	return operation_commit(&op);
279 }
280 
281 TEE_Result tee_fs_rpc_opendir(uint32_t id, const TEE_UUID *uuid,
282 			      struct tee_fs_dir **d)
283 {
284 	TEE_Result res;
285 	struct tee_fs_rpc_operation op = { .id = id, .num_params = 3 };
286 	void *va;
287 	paddr_t pa;
288 	uint64_t cookie;
289 	struct tee_fs_dir *dir = calloc(1, sizeof(*dir));
290 
291 	if (!dir)
292 		return TEE_ERROR_OUT_OF_MEMORY;
293 
294 	va = tee_fs_rpc_cache_alloc(TEE_FS_NAME_MAX, &pa, &cookie);
295 	if (!va) {
296 		res = TEE_ERROR_OUT_OF_MEMORY;
297 		goto err_exit;
298 	}
299 
300 	op.params[0].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
301 	op.params[0].u.value.a = OPTEE_MRF_OPENDIR;
302 
303 	op.params[1].attr = OPTEE_MSG_ATTR_TYPE_TMEM_INPUT;
304 	op.params[1].u.tmem.buf_ptr = pa;
305 	op.params[1].u.tmem.size = TEE_FS_NAME_MAX;
306 	op.params[1].u.tmem.shm_ref = cookie;
307 	res = tee_svc_storage_create_dirname(va, TEE_FS_NAME_MAX, uuid);
308 	if (res != TEE_SUCCESS)
309 		return res;
310 
311 	op.params[2].attr = OPTEE_MSG_ATTR_TYPE_VALUE_OUTPUT;
312 
313 	res = operation_commit(&op);
314 
315 	if (res != TEE_SUCCESS)
316 		goto err_exit;
317 
318 	dir->nw_dir = op.params[2].u.value.a;
319 	*d = dir;
320 
321 	return TEE_SUCCESS;
322 err_exit:
323 	free(dir);
324 
325 	return res;
326 }
327 
328 TEE_Result tee_fs_rpc_closedir(uint32_t id, struct tee_fs_dir *d)
329 {
330 	struct tee_fs_rpc_operation op = { .id = id, .num_params = 1 };
331 
332 	op.params[0].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
333 	op.params[0].u.value.a = OPTEE_MRF_CLOSEDIR;
334 	op.params[0].u.value.b = d->nw_dir;
335 
336 	free(d);
337 	return operation_commit(&op);
338 }
339 
340 TEE_Result tee_fs_rpc_readdir(uint32_t id, struct tee_fs_dir *d,
341 			      struct tee_fs_dirent **ent)
342 {
343 	TEE_Result res;
344 	struct tee_fs_rpc_operation op = { .id = id, .num_params = 2 };
345 	void *va;
346 	paddr_t pa;
347 	uint64_t cookie;
348 	const size_t max_name_len = TEE_FS_NAME_MAX + 1;
349 
350 	if (!d)
351 		return TEE_ERROR_ITEM_NOT_FOUND;
352 
353 	va = tee_fs_rpc_cache_alloc(max_name_len, &pa, &cookie);
354 	if (!va)
355 		return TEE_ERROR_OUT_OF_MEMORY;
356 
357 	op.params[0].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
358 	op.params[0].u.value.a = OPTEE_MRF_READDIR;
359 	op.params[0].u.value.b = d->nw_dir;
360 
361 	op.params[1].attr = OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT;
362 	op.params[1].u.tmem.buf_ptr = pa;
363 	op.params[1].u.tmem.size = max_name_len;
364 	op.params[1].u.tmem.shm_ref = cookie;
365 
366 	res = operation_commit(&op);
367 	if (res != TEE_SUCCESS)
368 		return res;
369 
370 	d->d.oidlen = tee_hs2b(va, d->d.oid, strnlen(va, max_name_len),
371 			       sizeof(d->d.oid));
372 	if (!d->d.oidlen)
373 		return TEE_ERROR_OUT_OF_MEMORY;
374 
375 	*ent = &d->d;
376 	return TEE_SUCCESS;
377 }
378 
379 TEE_Result tee_fs_rpc_begin_transaction(uint32_t id)
380 {
381 	struct tee_fs_rpc_operation op = { .id = id, .num_params = 1 };
382 
383 	op.params[0].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
384 	op.params[0].u.value.a = OPTEE_MRF_BEGIN_TRANSACTION;
385 
386 	return operation_commit(&op);
387 }
388 
389 TEE_Result tee_fs_rpc_end_transaction(uint32_t id, bool rollback)
390 {
391 	struct tee_fs_rpc_operation op = { .id = id, .num_params = 1 };
392 
393 	op.params[0].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
394 	op.params[0].u.value.a = OPTEE_MRF_END_TRANSACTION;
395 	op.params[0].u.value.b = rollback;
396 
397 	return operation_commit(&op);
398 }
399