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