xref: /optee_os/core/tee/tee_fs_rpc.c (revision ba6d8df98e3cf376aab45d0d958204c498a94123)
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 static TEE_Result operation_open_dfh(uint32_t id, unsigned int cmd,
98 				 const struct tee_fs_dirfile_fileh *dfh,
99 				 int *fd)
100 {
101 	struct tee_fs_rpc_operation op = { .id = id, .num_params = 3 };
102 	TEE_Result res;
103 	void *va;
104 	paddr_t pa;
105 	uint64_t cookie;
106 
107 	va = tee_fs_rpc_cache_alloc(TEE_FS_NAME_MAX, &pa, &cookie);
108 	if (!va)
109 		return TEE_ERROR_OUT_OF_MEMORY;
110 
111 	op.params[0].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
112 	op.params[0].u.value.a = cmd;
113 
114 	op.params[1].attr = OPTEE_MSG_ATTR_TYPE_TMEM_INPUT;
115 	op.params[1].u.tmem.buf_ptr = pa;
116 	op.params[1].u.tmem.size = TEE_FS_NAME_MAX;
117 	op.params[1].u.tmem.shm_ref = cookie;
118 	res = tee_svc_storage_create_filename_dfh(va, TEE_FS_NAME_MAX, dfh);
119 	if (res != TEE_SUCCESS)
120 		return res;
121 
122 	op.params[2].attr = OPTEE_MSG_ATTR_TYPE_VALUE_OUTPUT;
123 
124 	res = operation_commit(&op);
125 	if (res == TEE_SUCCESS)
126 		*fd = op.params[2].u.value.a;
127 
128 	return res;
129 }
130 
131 
132 
133 TEE_Result tee_fs_rpc_open_dfh(uint32_t id,
134 			       const struct tee_fs_dirfile_fileh *dfh, int *fd)
135 {
136 	return operation_open_dfh(id, OPTEE_MRF_OPEN, dfh, fd);
137 }
138 
139 TEE_Result tee_fs_rpc_create_dfh(uint32_t id,
140 				 const struct tee_fs_dirfile_fileh *dfh,
141 				 int *fd)
142 {
143 	return operation_open_dfh(id, OPTEE_MRF_CREATE, dfh, fd);
144 }
145 
146 TEE_Result tee_fs_rpc_close(uint32_t id, int fd)
147 {
148 	struct tee_fs_rpc_operation op = { .id = id, .num_params = 1 };
149 
150 	op.params[0].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
151 	op.params[0].u.value.a = OPTEE_MRF_CLOSE;
152 	op.params[0].u.value.b = fd;
153 
154 	return operation_commit(&op);
155 }
156 
157 TEE_Result tee_fs_rpc_read_init(struct tee_fs_rpc_operation *op,
158 				uint32_t id, int fd, tee_fs_off_t offset,
159 				size_t data_len, void **out_data)
160 {
161 	uint8_t *va;
162 	paddr_t pa;
163 	uint64_t cookie;
164 
165 	if (offset < 0)
166 		return TEE_ERROR_BAD_PARAMETERS;
167 
168 	va = tee_fs_rpc_cache_alloc(data_len, &pa, &cookie);
169 	if (!va)
170 		return TEE_ERROR_OUT_OF_MEMORY;
171 
172 	memset(op, 0, sizeof(*op));
173 	op->id = id;
174 	op->num_params = 2;
175 
176 	op->params[0].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
177 	op->params[0].u.value.a = OPTEE_MRF_READ;
178 	op->params[0].u.value.b = fd;
179 	op->params[0].u.value.c = offset;
180 
181 	op->params[1].attr = OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT;
182 	op->params[1].u.tmem.buf_ptr = pa;
183 	op->params[1].u.tmem.size = data_len;
184 	op->params[1].u.tmem.shm_ref = cookie;
185 
186 	*out_data = va;
187 
188 	return TEE_SUCCESS;
189 }
190 
191 TEE_Result tee_fs_rpc_read_final(struct tee_fs_rpc_operation *op,
192 				 size_t *data_len)
193 {
194 	TEE_Result res = operation_commit(op);
195 
196 	if (res == TEE_SUCCESS)
197 		*data_len = op->params[1].u.tmem.size;
198 	return res;
199 }
200 
201 TEE_Result tee_fs_rpc_write_init(struct tee_fs_rpc_operation *op,
202 				 uint32_t id, int fd, tee_fs_off_t offset,
203 				 size_t data_len, void **data)
204 {
205 	uint8_t *va;
206 	paddr_t pa;
207 	uint64_t cookie;
208 
209 	if (offset < 0)
210 		return TEE_ERROR_BAD_PARAMETERS;
211 
212 	va = tee_fs_rpc_cache_alloc(data_len, &pa, &cookie);
213 	if (!va)
214 		return TEE_ERROR_OUT_OF_MEMORY;
215 
216 	memset(op, 0, sizeof(*op));
217 	op->id = id;
218 	op->num_params = 2;
219 
220 
221 	op->params[0].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
222 	op->params[0].u.value.a = OPTEE_MRF_WRITE;
223 	op->params[0].u.value.b = fd;
224 	op->params[0].u.value.c = offset;
225 
226 	op->params[1].attr = OPTEE_MSG_ATTR_TYPE_TMEM_INPUT;
227 	op->params[1].u.tmem.buf_ptr = pa;
228 	op->params[1].u.tmem.size = data_len;
229 	op->params[1].u.tmem.shm_ref = cookie;
230 
231 	*data = va;
232 
233 	return TEE_SUCCESS;
234 }
235 
236 TEE_Result tee_fs_rpc_write_final(struct tee_fs_rpc_operation *op)
237 {
238 	return operation_commit(op);
239 }
240 
241 TEE_Result tee_fs_rpc_truncate(uint32_t id, int fd, size_t len)
242 {
243 	struct tee_fs_rpc_operation op = { .id = id, .num_params = 1 };
244 
245 	op.params[0].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
246 	op.params[0].u.value.a = OPTEE_MRF_TRUNCATE;
247 	op.params[0].u.value.b = fd;
248 	op.params[0].u.value.c = len;
249 
250 	return operation_commit(&op);
251 }
252 
253 TEE_Result tee_fs_rpc_remove(uint32_t id, struct tee_pobj *po)
254 {
255 	TEE_Result res;
256 	struct tee_fs_rpc_operation op = { .id = id, .num_params = 2 };
257 	void *va;
258 	paddr_t pa;
259 	uint64_t cookie;
260 
261 	va = tee_fs_rpc_cache_alloc(TEE_FS_NAME_MAX, &pa, &cookie);
262 	if (!va)
263 		return TEE_ERROR_OUT_OF_MEMORY;
264 
265 	op.params[0].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
266 	op.params[0].u.value.a = OPTEE_MRF_REMOVE;
267 
268 	op.params[1].attr = OPTEE_MSG_ATTR_TYPE_TMEM_INPUT;
269 	op.params[1].u.tmem.buf_ptr = pa;
270 	op.params[1].u.tmem.size = TEE_FS_NAME_MAX;
271 	op.params[1].u.tmem.shm_ref = cookie;
272 	res = tee_svc_storage_create_filename(va, TEE_FS_NAME_MAX,
273 					      po, po->temporary);
274 	if (res != TEE_SUCCESS)
275 		return res;
276 
277 	return operation_commit(&op);
278 }
279 
280 TEE_Result tee_fs_rpc_remove_dfh(uint32_t id,
281 				 const struct tee_fs_dirfile_fileh *dfh)
282 {
283 	TEE_Result res;
284 	struct tee_fs_rpc_operation op = { .id = id, .num_params = 2 };
285 	void *va;
286 	paddr_t pa;
287 	uint64_t cookie;
288 
289 	va = tee_fs_rpc_cache_alloc(TEE_FS_NAME_MAX, &pa, &cookie);
290 	if (!va)
291 		return TEE_ERROR_OUT_OF_MEMORY;
292 
293 	op.params[0].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
294 	op.params[0].u.value.a = OPTEE_MRF_REMOVE;
295 
296 	op.params[1].attr = OPTEE_MSG_ATTR_TYPE_TMEM_INPUT;
297 	op.params[1].u.tmem.buf_ptr = pa;
298 	op.params[1].u.tmem.size = TEE_FS_NAME_MAX;
299 	op.params[1].u.tmem.shm_ref = cookie;
300 	res = tee_svc_storage_create_filename_dfh(va, TEE_FS_NAME_MAX, dfh);
301 	if (res != TEE_SUCCESS)
302 		return res;
303 
304 	return operation_commit(&op);
305 }
306 
307 TEE_Result tee_fs_rpc_rename(uint32_t id, struct tee_pobj *old,
308 			     struct tee_pobj *new, bool overwrite)
309 {
310 	TEE_Result res;
311 	struct tee_fs_rpc_operation op = { .id = id, .num_params = 3 };
312 	char *va;
313 	paddr_t pa;
314 	uint64_t cookie;
315 	bool temp;
316 
317 	va = tee_fs_rpc_cache_alloc(TEE_FS_NAME_MAX * 2, &pa, &cookie);
318 	if (!va)
319 		return TEE_ERROR_OUT_OF_MEMORY;
320 
321 	op.params[0].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
322 	op.params[0].u.value.a = OPTEE_MRF_RENAME;
323 	op.params[0].u.value.b = overwrite;
324 
325 	op.params[1].attr = OPTEE_MSG_ATTR_TYPE_TMEM_INPUT;
326 	op.params[1].u.tmem.buf_ptr = pa;
327 	op.params[1].u.tmem.size = TEE_FS_NAME_MAX;
328 	op.params[1].u.tmem.shm_ref = cookie;
329 	if (new)
330 		temp = old->temporary;
331 	else
332 		temp = true;
333 	res = tee_svc_storage_create_filename(va, TEE_FS_NAME_MAX,
334 					      old, temp);
335 	if (res != TEE_SUCCESS)
336 		return res;
337 
338 	op.params[2].attr = OPTEE_MSG_ATTR_TYPE_TMEM_INPUT;
339 	op.params[2].u.tmem.buf_ptr = pa + TEE_FS_NAME_MAX;
340 	op.params[2].u.tmem.size = TEE_FS_NAME_MAX;
341 	op.params[2].u.tmem.shm_ref = cookie;
342 	if (new) {
343 		res = tee_svc_storage_create_filename(va + TEE_FS_NAME_MAX,
344 						      TEE_FS_NAME_MAX,
345 						      new, new->temporary);
346 	} else {
347 		res = tee_svc_storage_create_filename(va + TEE_FS_NAME_MAX,
348 						      TEE_FS_NAME_MAX,
349 						      old, false);
350 	}
351 	if (res != TEE_SUCCESS)
352 		return res;
353 
354 	return operation_commit(&op);
355 }
356 
357 TEE_Result tee_fs_rpc_opendir(uint32_t id, const TEE_UUID *uuid,
358 			      struct tee_fs_dir **d)
359 {
360 	TEE_Result res;
361 	struct tee_fs_rpc_operation op = { .id = id, .num_params = 3 };
362 	void *va;
363 	paddr_t pa;
364 	uint64_t cookie;
365 	struct tee_fs_dir *dir = calloc(1, sizeof(*dir));
366 
367 	if (!dir)
368 		return TEE_ERROR_OUT_OF_MEMORY;
369 
370 	va = tee_fs_rpc_cache_alloc(TEE_FS_NAME_MAX, &pa, &cookie);
371 	if (!va) {
372 		res = TEE_ERROR_OUT_OF_MEMORY;
373 		goto err_exit;
374 	}
375 
376 	op.params[0].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
377 	op.params[0].u.value.a = OPTEE_MRF_OPENDIR;
378 
379 	op.params[1].attr = OPTEE_MSG_ATTR_TYPE_TMEM_INPUT;
380 	op.params[1].u.tmem.buf_ptr = pa;
381 	op.params[1].u.tmem.size = TEE_FS_NAME_MAX;
382 	op.params[1].u.tmem.shm_ref = cookie;
383 	res = tee_svc_storage_create_dirname(va, TEE_FS_NAME_MAX, uuid);
384 	if (res != TEE_SUCCESS)
385 		return res;
386 
387 	op.params[2].attr = OPTEE_MSG_ATTR_TYPE_VALUE_OUTPUT;
388 
389 	res = operation_commit(&op);
390 
391 	if (res != TEE_SUCCESS)
392 		goto err_exit;
393 
394 	dir->nw_dir = op.params[2].u.value.a;
395 	*d = dir;
396 
397 	return TEE_SUCCESS;
398 err_exit:
399 	free(dir);
400 
401 	return res;
402 }
403 
404 TEE_Result tee_fs_rpc_closedir(uint32_t id, struct tee_fs_dir *d)
405 {
406 	struct tee_fs_rpc_operation op = { .id = id, .num_params = 1 };
407 
408 	op.params[0].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
409 	op.params[0].u.value.a = OPTEE_MRF_CLOSEDIR;
410 	op.params[0].u.value.b = d->nw_dir;
411 
412 	free(d);
413 	return operation_commit(&op);
414 }
415 
416 TEE_Result tee_fs_rpc_readdir(uint32_t id, struct tee_fs_dir *d,
417 			      struct tee_fs_dirent **ent)
418 {
419 	TEE_Result res;
420 	struct tee_fs_rpc_operation op = { .id = id, .num_params = 2 };
421 	void *va;
422 	paddr_t pa;
423 	uint64_t cookie;
424 	const size_t max_name_len = TEE_FS_NAME_MAX + 1;
425 
426 	if (!d)
427 		return TEE_ERROR_ITEM_NOT_FOUND;
428 
429 	va = tee_fs_rpc_cache_alloc(max_name_len, &pa, &cookie);
430 	if (!va)
431 		return TEE_ERROR_OUT_OF_MEMORY;
432 
433 	op.params[0].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
434 	op.params[0].u.value.a = OPTEE_MRF_READDIR;
435 	op.params[0].u.value.b = d->nw_dir;
436 
437 	op.params[1].attr = OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT;
438 	op.params[1].u.tmem.buf_ptr = pa;
439 	op.params[1].u.tmem.size = max_name_len;
440 	op.params[1].u.tmem.shm_ref = cookie;
441 
442 	res = operation_commit(&op);
443 	if (res != TEE_SUCCESS)
444 		return res;
445 
446 	d->d.oidlen = tee_hs2b(va, d->d.oid, strnlen(va, max_name_len),
447 			       sizeof(d->d.oid));
448 	if (!d->d.oidlen)
449 		return TEE_ERROR_OUT_OF_MEMORY;
450 
451 	*ent = &d->d;
452 	return TEE_SUCCESS;
453 }
454