xref: /optee_os/core/tee/tee_fs_rpc.c (revision 8dceff9b18e7c2e0cb879ea458e85a1806dff447)
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/thread.h>
30 #include <mm/core_memprot.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <tee/tee_fs.h>
34 #include <tee/tee_fs_rpc.h>
35 #include <trace.h>
36 #include <util.h>
37 
38 #define RPC_FAILED -1
39 
40 /* TEE FS operation */
41 #define TEE_FS_OPEN       1
42 #define TEE_FS_CLOSE      2
43 #define TEE_FS_READ       3
44 #define TEE_FS_WRITE      4
45 #define TEE_FS_SEEK       5
46 #define TEE_FS_UNLINK     6
47 #define TEE_FS_RENAME     7
48 #define TEE_FS_TRUNC      8
49 #define TEE_FS_MKDIR      9
50 #define TEE_FS_OPENDIR   10
51 #define TEE_FS_CLOSEDIR  11
52 #define TEE_FS_READDIR   12
53 #define TEE_FS_RMDIR     13
54 #define TEE_FS_ACCESS    14
55 #define TEE_FS_LINK      15
56 #define TEE_FS_BEGIN     16 /* SQL FS: begin transaction */
57 #define TEE_FS_END       17 /* SQL FS: end transaction */
58 
59 #define TEE_FS_MODE_NONE 0
60 #define TEE_FS_MODE_IN   1
61 #define TEE_FS_MODE_OUT  2
62 
63 struct tee_fs_rpc {
64 	int op;
65 	int flags;
66 	int arg;
67 	int fd;
68 	uint32_t len;
69 	int res;
70 };
71 
72 struct tee_fs_dir {
73 	int nw_dir;
74 	struct tee_fs_dirent d;
75 };
76 
77 static TEE_Result tee_fs_rpc_send_cmd(int cmd_id, struct tee_fs_rpc *bf_cmd,
78 				      void *data, uint32_t len, uint32_t mode)
79 {
80 	TEE_Result ret;
81 	struct optee_msg_param params;
82 	paddr_t phpayload = 0;
83 	uint64_t cpayload = 0;
84 	struct tee_fs_rpc *bf;
85 	int res = TEE_ERROR_GENERIC;
86 
87 	assert(cmd_id == OPTEE_MSG_RPC_CMD_FS ||
88 	       cmd_id == OPTEE_MSG_RPC_CMD_SQL_FS);
89 
90 	bf = tee_fs_rpc_cache_alloc(sizeof(struct tee_fs_rpc) + len,
91 				    &phpayload, &cpayload);
92 	if (!bf)
93 		goto exit;
94 
95 	memset(&params, 0, sizeof(params));
96 	params.attr = OPTEE_MSG_ATTR_TYPE_TMEM_INOUT;
97 	params.u.tmem.buf_ptr = phpayload;
98 	params.u.tmem.size = sizeof(struct tee_fs_rpc) + len;
99 	params.u.tmem.shm_ref = cpayload;
100 
101 	/* fill in parameters */
102 	*bf = *bf_cmd;
103 
104 	if (mode & TEE_FS_MODE_IN)
105 		memcpy((void *)(bf + 1), data, len);
106 
107 	ret = thread_rpc_cmd(cmd_id, 1, &params);
108 	/* update result */
109 	*bf_cmd = *bf;
110 	if (ret != TEE_SUCCESS)
111 		goto exit;
112 
113 	if (mode & TEE_FS_MODE_OUT) {
114 		uint32_t olen = MIN(len, bf->len);
115 
116 		memcpy(data, (void *)(bf + 1), olen);
117 	}
118 
119 	res = TEE_SUCCESS;
120 
121 exit:
122 	return res;
123 }
124 
125 int tee_fs_rpc_access(int id, const char *name, int mode)
126 {
127 	struct tee_fs_rpc head = { 0 };
128 	TEE_Result res;
129 	int rc = RPC_FAILED;
130 	size_t len;
131 
132 	DMSG("(id: %d, name: %s, mode: %d)...", id, name, mode);
133 
134 	if (!name)
135 		goto exit;
136 
137 	len = strlen(name) + 1;
138 	if (len <= 1)
139 		goto exit;
140 
141 	head.op = TEE_FS_ACCESS;
142 	head.flags = mode;
143 
144 	res = tee_fs_rpc_send_cmd(id, &head, (void *)name, len, TEE_FS_MODE_IN);
145 	if (res != TEE_SUCCESS)
146 		goto exit;
147 
148 	rc = head.res;
149 exit:
150 	DMSG("...%d", rc);
151 	return rc;
152 }
153 
154 int tee_fs_rpc_begin_transaction(int id)
155 {
156 	struct tee_fs_rpc head = { 0 };
157 	TEE_Result res;
158 	int rc = RPC_FAILED;
159 
160 	assert(id == OPTEE_MSG_RPC_CMD_SQL_FS);
161 
162 	DMSG("(id: %d)...", id);
163 
164 	/* fill in parameters */
165 	head.op = TEE_FS_BEGIN;
166 	head.fd = -1;
167 
168 	res = tee_fs_rpc_send_cmd(id, &head, NULL, 0,
169 				  TEE_FS_MODE_NONE);
170 	if (res != TEE_SUCCESS)
171 		goto exit;
172 
173 	rc = head.res;
174 exit:
175 	DMSG("...%d", rc);
176 	return rc;
177 }
178 
179 int tee_fs_rpc_close(int id, int fd)
180 {
181 	struct tee_fs_rpc head = { 0 };
182 	TEE_Result res;
183 	int rc = RPC_FAILED;
184 
185 	DMSG("(id: %d, fd: %d)...", id, fd);
186 
187 	head.op = TEE_FS_CLOSE;
188 	head.fd = fd;
189 
190 	res = tee_fs_rpc_send_cmd(id, &head, NULL, 0, TEE_FS_MODE_NONE);
191 	if (res != TEE_SUCCESS)
192 		goto exit;
193 
194 	rc = head.res;
195 exit:
196 	DMSG("...%d", rc);
197 	return rc;
198 }
199 
200 int tee_fs_rpc_end_transaction(int id, bool rollback)
201 {
202 	struct tee_fs_rpc head = { 0 };
203 	TEE_Result res;
204 	int rc = RPC_FAILED;
205 
206 	assert(id == OPTEE_MSG_RPC_CMD_SQL_FS);
207 
208 	DMSG("(id: %d, rollback: %d)...", id, rollback);
209 
210 	head.op = TEE_FS_END;
211 	head.arg = rollback;
212 	head.fd = -1;
213 
214 	res = tee_fs_rpc_send_cmd(id, &head, NULL, 0, TEE_FS_MODE_NONE);
215 	if (res != TEE_SUCCESS)
216 		goto exit;
217 
218 	rc = head.res;
219 exit:
220 	DMSG("...%d", rc);
221 	return rc;
222 }
223 
224 int tee_fs_rpc_ftruncate(int id, int fd, tee_fs_off_t length)
225 {
226 	struct tee_fs_rpc head = { 0 };
227 	TEE_Result res;
228 	int rc = RPC_FAILED;
229 
230 	DMSG("(id: %d, fd: %d, length: %" PRId64 ")...", id, fd, length);
231 
232 	head.op = TEE_FS_TRUNC;
233 	head.fd = fd;
234 	head.arg = length;
235 
236 	res = tee_fs_rpc_send_cmd(id, &head, NULL, 0, TEE_FS_MODE_NONE);
237 	if (res != TEE_SUCCESS)
238 		goto exit;
239 
240 	rc = head.res;
241 exit:
242 	DMSG("...%d", rc);
243 	return rc;
244 }
245 
246 int tee_fs_rpc_link(int id, const char *old, const char *nw)
247 {
248 	size_t len_old;
249 	size_t len_new;
250 	size_t len;
251 	struct tee_fs_rpc head = { 0 };
252 	char *tmp = NULL;
253 	TEE_Result res;
254 	int rc = RPC_FAILED;
255 
256 	DMSG("(id: %d, old: %s, nw: %s)...", id, old, nw);
257 
258 	if (!old || !nw)
259 		goto exit;
260 
261 	len_old = strlen(old) + 1;
262 	len_new = strlen(nw) + 1;
263 	len = len_old + len_new;
264 
265 	tmp = malloc(len);
266 	if (!tmp)
267 		goto exit;
268 	memcpy(tmp, old, len_old);
269 	memcpy(tmp + len_old, nw, len_new);
270 
271 	head.op = TEE_FS_LINK;
272 
273 	res = tee_fs_rpc_send_cmd(id, &head, tmp, len, TEE_FS_MODE_IN);
274 	if (res != TEE_SUCCESS)
275 		goto exit;
276 
277 	rc = head.res;
278 exit:
279 	free(tmp);
280 	DMSG("...%d", rc);
281 	return rc;
282 }
283 
284 tee_fs_off_t tee_fs_rpc_lseek(int id, int fd, tee_fs_off_t offset,
285 				  int whence)
286 {
287 	struct tee_fs_rpc head = { 0 };
288 	tee_fs_off_t rc = RPC_FAILED;
289 	TEE_Result res;
290 
291 	DMSG("(id: %d, fd: %d, offset: %" PRId64 ", whence: %d)...", id, fd,
292 	     offset, whence);
293 
294 	head.op = TEE_FS_SEEK;
295 	head.fd = fd;
296 	head.arg = offset;
297 	head.flags = whence;
298 
299 	res = tee_fs_rpc_send_cmd(id, &head, NULL, 0, TEE_FS_MODE_NONE);
300 	if (res != TEE_SUCCESS)
301 		goto exit;
302 
303 	rc = head.res;
304 exit:
305 	DMSG("...%" PRId64, rc);
306 	return rc;
307 }
308 
309 int tee_fs_rpc_mkdir(int id, const char *path, tee_fs_mode_t mode)
310 {
311 	struct tee_fs_rpc head = { 0 };
312 	TEE_Result res;
313 	uint32_t len;
314 	int rc = RPC_FAILED;
315 
316 	DMSG("(id: %d, path: %s, mode: %d)...", id, path, mode);
317 
318 	if (!path)
319 		goto exit;
320 
321 	len = strlen(path) + 1;
322 	if (len <= 1)
323 		goto exit;
324 
325 	head.op = TEE_FS_MKDIR;
326 	head.flags = mode;
327 
328 	res = tee_fs_rpc_send_cmd(id, &head, (void *)path, len,
329 				  TEE_FS_MODE_IN);
330 	if (res != TEE_SUCCESS)
331 		goto exit;
332 
333 	rc = head.res;
334 exit:
335 	DMSG("...%d", rc);
336 	return rc;
337 }
338 
339 int tee_fs_rpc_open(int id, const char *file, int flags)
340 {
341 	struct tee_fs_rpc head = { 0 };
342 	TEE_Result res;
343 	int rc = RPC_FAILED;
344 	size_t len;
345 
346 	DMSG("(id: %d, file: %s, flags: %d)...", id, file, flags);
347 
348 	if (!file)
349 		goto exit;
350 
351 	len = strlen(file) + 1;
352 	if (len <= 1)
353 		goto exit;
354 
355 	head.op = TEE_FS_OPEN;
356 	head.flags = flags;
357 
358 	res = tee_fs_rpc_send_cmd(id, &head, (void *)file, len,
359 				  TEE_FS_MODE_IN);
360 	if (res != TEE_SUCCESS)
361 		goto exit;
362 
363 	rc = head.res;
364 exit:
365 	DMSG("...%d", rc);
366 	return rc;
367 }
368 
369 struct tee_fs_dir *tee_fs_rpc_opendir(int id, const char *name)
370 {
371 	struct tee_fs_rpc head = { 0 };
372 	struct tee_fs_dir *dir = NULL;
373 	size_t len;
374 	TEE_Result res = TEE_SUCCESS;
375 
376 	DMSG("(id: %d, name: %s)...", id, name);
377 
378 	if (!name)
379 		goto exit;
380 
381 	len = strlen(name) + 1;
382 	if (len <= 1)
383 		goto exit;
384 
385 	dir = malloc(sizeof(struct tee_fs_dir));
386 	if (!dir)
387 		goto exit;
388 
389 	head.op = TEE_FS_OPENDIR;
390 
391 	res = tee_fs_rpc_send_cmd(id, &head, (void *)name, len,
392 				  TEE_FS_MODE_IN);
393 	if (res != TEE_SUCCESS)
394 		goto free_and_exit;
395 	if (head.res < 0)
396 		goto free_and_exit;
397 
398 	dir->nw_dir = head.res;
399 	dir->d.d_name = NULL;
400 
401 	goto exit;
402 
403 free_and_exit:
404 	free(dir);
405 	dir = NULL;
406 exit:
407 	DMSG("...%p", (void *)dir);
408 	return dir;
409 }
410 
411 int tee_fs_rpc_read(int id, int fd, void *buf, size_t len)
412 {
413 	struct tee_fs_rpc head = { 0 };
414 	TEE_Result res;
415 	int rc = RPC_FAILED;
416 
417 	DMSG("(id: %d, fd: %d, buf: %p, len: %zu)...", id, fd, (void *)buf,
418 	     len);
419 
420 	if (!len) {
421 		res = 0;
422 		goto exit;
423 	}
424 
425 	if (!buf)
426 		goto exit;
427 
428 	head.op = TEE_FS_READ;
429 	head.fd = fd;
430 	head.len = (uint32_t)len;
431 
432 	res = tee_fs_rpc_send_cmd(id, &head, (void *)buf, len,
433 				  TEE_FS_MODE_OUT);
434 	if (res != TEE_SUCCESS)
435 		goto exit;
436 
437 	rc = head.res;
438 exit:
439 	DMSG("...%d", rc);
440 	return rc;
441 }
442 
443 struct tee_fs_dirent *tee_fs_rpc_readdir(int id, struct tee_fs_dir *d)
444 {
445 	struct tee_fs_dirent *rc = NULL;
446 	char fname[TEE_FS_NAME_MAX + 1];
447 	struct tee_fs_rpc head = { 0 };
448 	TEE_Result res;
449 
450 	DMSG("(id: %d, d: %p)...", id, (void *)d);
451 
452 	if (!d)
453 		goto exit;
454 
455 	head.op = TEE_FS_READDIR;
456 	head.arg = (int)d->nw_dir;
457 	head.len = sizeof(fname);
458 
459 	res = tee_fs_rpc_send_cmd(id, &head, fname, sizeof(fname),
460 				  TEE_FS_MODE_OUT);
461 	if (res != TEE_SUCCESS)
462 		goto exit;
463 
464 	if (head.res < 0)
465 		goto exit;
466 
467 	if (!head.len || head.len > sizeof(fname))
468 		goto exit;
469 
470 	fname[head.len - 1] = '\0'; /* make sure it's zero terminated */
471 	free(d->d.d_name);
472 	d->d.d_name = strdup(fname);
473 	if (!d->d.d_name)
474 		goto exit;
475 
476 	rc = &d->d;
477 exit:
478 	DMSG("...%p", (void *)rc);
479 	return rc;
480 }
481 
482 int tee_fs_rpc_rename(int id, const char *old, const char *nw)
483 {
484 	size_t len_old;
485 	size_t len_new;
486 	size_t len;
487 	struct tee_fs_rpc head = { 0 };
488 	char *tmp = NULL;
489 	TEE_Result res;
490 	int rc = RPC_FAILED;
491 
492 	DMSG("(id: %d, old: %s, nw: %s)...", id, old, nw);
493 
494 	if (!old || !nw)
495 		goto exit;
496 
497 	len_old = strlen(old) + 1;
498 	len_new = strlen(nw) + 1;
499 	len = len_old + len_new;
500 
501 	tmp = malloc(len);
502 	if (!tmp)
503 		goto exit;
504 
505 	memcpy(tmp, old, len_old);
506 	memcpy(tmp + len_old, nw, len_new);
507 
508 	head.op = TEE_FS_RENAME;
509 
510 	res = tee_fs_rpc_send_cmd(id, &head, tmp, len, TEE_FS_MODE_IN);
511 	if (res != TEE_SUCCESS)
512 		goto exit;
513 
514 	rc = head.res;
515 exit:
516 	free(tmp);
517 	DMSG("...%d", rc);
518 	return rc;
519 }
520 
521 int tee_fs_rpc_write(int id, int fd, const void *buf, size_t len)
522 {
523 	struct tee_fs_rpc head = { 0 };
524 	TEE_Result res;
525 	int rc = RPC_FAILED;
526 
527 	DMSG("(id: %d, fd: %d, buf: %p, len: %zu)...", id, fd, buf, len);
528 
529 	if (!len) {
530 		res = 0;
531 		goto exit;
532 	}
533 
534 	if (!buf)
535 		goto exit;
536 
537 	head.op = TEE_FS_WRITE;
538 	head.fd = fd;
539 	head.len = (uint32_t)len;
540 
541 	res = tee_fs_rpc_send_cmd(id, &head, (void *)buf, len, TEE_FS_MODE_IN);
542 	if (res != TEE_SUCCESS)
543 		goto exit;
544 
545 	rc = head.res;
546 exit:
547 	DMSG("...%d", rc);
548 	return rc;
549 }
550 
551 int tee_fs_rpc_closedir(int id, struct tee_fs_dir *d)
552 {
553 	struct tee_fs_rpc head = { 0 };
554 	TEE_Result res;
555 	int rc = RPC_FAILED;
556 
557 	DMSG("(id: %d, d: %p)...", id, (void *)d);
558 
559 	if (!d) {
560 		rc = 0;
561 		goto exit;
562 	}
563 
564 	head.op = TEE_FS_CLOSEDIR;
565 	head.arg = (int)d->nw_dir;
566 
567 	res = tee_fs_rpc_send_cmd(id, &head, NULL, 0, TEE_FS_MODE_NONE);
568 	if (res != TEE_SUCCESS)
569 		goto exit;
570 
571 	rc = head.res;
572 exit:
573 	if (d)
574 		free(d->d.d_name);
575 	free(d);
576 
577 	DMSG("...%d", rc);
578 	return rc;
579 }
580 
581 int tee_fs_rpc_rmdir(int id, const char *name)
582 {
583 	struct tee_fs_rpc head = { 0 };
584 	TEE_Result res;
585 	int rc = RPC_FAILED;
586 	size_t len;
587 
588 	DMSG("(id: %d, name: %s)...", id, name);
589 
590 	if (!name)
591 		goto exit;
592 
593 	len = strlen(name) + 1;
594 	if (len <= 1)
595 		goto exit;
596 
597 	head.op = TEE_FS_RMDIR;
598 
599 	res = tee_fs_rpc_send_cmd(id, &head, (void *)name, len,
600 				  TEE_FS_MODE_IN);
601 	if (res != TEE_SUCCESS)
602 		goto exit;
603 
604 	rc = head.res;
605 exit:
606 	DMSG("...%d", rc);
607 	return rc;
608 }
609 
610 int tee_fs_rpc_unlink(int id, const char *file)
611 {
612 	struct tee_fs_rpc head = { 0 };
613 	size_t len;
614 	TEE_Result res;
615 	int rc = RPC_FAILED;
616 
617 	DMSG("(id: %d, file: %s)...", id, file);
618 
619 	if (!file)
620 		goto exit;
621 
622 	len = strlen(file) + 1;
623 	if (len <= 1)
624 		goto exit;
625 
626 	head.op = TEE_FS_UNLINK;
627 
628 	res = tee_fs_rpc_send_cmd(id, &head, (void *)file, len,
629 				  TEE_FS_MODE_IN);
630 	if (res != TEE_SUCCESS)
631 		goto exit;
632 
633 	rc = head.res;
634 exit:
635 	DMSG("...%d", rc);
636 	return rc;
637 }
638