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