1 /*
2  * Copyright (c) 2014, STMicroelectronics International N.V.
3  * All rights reserved.
4  * Copyright (c) 2015, Linaro Limited
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright notice,
11  * this list of conditions and the following disclaimer.
12  *
13  * 2. Redistributions in binary form must reproduce the above copyright notice,
14  * this list of conditions and the following disclaimer in the documentation
15  * and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
21  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27  * POSSIBILITY OF SUCH DAMAGE.
28  */
29 
30 #include <assert.h>
31 #include <dirent.h>
32 #include <errno.h>
33 #include <fcntl.h>
34 #include <getopt.h>
35 #include <inttypes.h>
36 #include <prof.h>
37 #include <plugin.h>
38 #include <pthread.h>
39 #include <rpmb.h>
40 #include <stdbool.h>
41 #include <stdint.h>
42 #include <stdio.h>
43 #include <stdlib.h>
44 #include <string.h>
45 #include <sys/ioctl.h>
46 #include <sys/mman.h>
47 #include <sys/stat.h>
48 #include <sys/time.h>
49 #include <sys/types.h>
50 #include <tee_client_api.h>
51 #include <teec_ta_load.h>
52 #include <teec_trace.h>
53 #include <tee_socket.h>
54 #include <tee_supp_fs.h>
55 #include <tee_supplicant.h>
56 #include <unistd.h>
57 
58 #include "optee_msg_supplicant.h"
59 
60 #ifndef __aligned
61 #define __aligned(x) __attribute__((__aligned__(x)))
62 #endif
63 #include <linux/tee.h>
64 
65 #define RPC_NUM_PARAMS	5
66 
67 #define RPC_BUF_SIZE	(sizeof(struct tee_iocl_supp_send_arg) + \
68 			 RPC_NUM_PARAMS * sizeof(struct tee_ioctl_param))
69 
70 char **ta_path;
71 char *ta_path_str;
72 
73 union tee_rpc_invoke {
74 	uint64_t buf[(RPC_BUF_SIZE - 1) / sizeof(uint64_t) + 1];
75 	struct tee_iocl_supp_recv_arg recv;
76 	struct tee_iocl_supp_send_arg send;
77 };
78 
79 struct tee_shm {
80 	int id;
81 	void *p;
82 	size_t size;
83 	bool registered;
84 	int fd;
85 	struct tee_shm *next;
86 };
87 
88 struct thread_arg {
89 	int fd;
90 	uint32_t gen_caps;
91 	bool abort;
92 	size_t num_waiters;
93 	pthread_mutex_t mutex;
94 };
95 
96 struct param_value {
97 	uint64_t a;
98 	uint64_t b;
99 	uint64_t c;
100 };
101 
102 static pthread_mutex_t shm_mutex = PTHREAD_MUTEX_INITIALIZER;
103 static struct tee_shm *shm_head;
104 
105 struct tee_supplicant_params supplicant_params = {
106 	.ta_dir = "optee_armtz",
107 #ifdef TEE_PLUGIN_LOAD_PATH
108 	.plugin_load_path = TEE_PLUGIN_LOAD_PATH,
109 #endif
110 	.fs_parent_path  = TEE_FS_PARENT_PATH,
111 };
112 
113 static void *thread_main(void *a);
114 
num_waiters_inc(struct thread_arg * arg)115 static size_t num_waiters_inc(struct thread_arg *arg)
116 {
117 	size_t ret = 0;
118 
119 	tee_supp_mutex_lock(&arg->mutex);
120 	arg->num_waiters++;
121 	assert(arg->num_waiters);
122 	ret = arg->num_waiters;
123 	tee_supp_mutex_unlock(&arg->mutex);
124 
125 	return ret;
126 }
127 
num_waiters_dec(struct thread_arg * arg)128 static size_t num_waiters_dec(struct thread_arg *arg)
129 {
130 	size_t ret = 0;
131 
132 	tee_supp_mutex_lock(&arg->mutex);
133 	assert(arg->num_waiters);
134 	arg->num_waiters--;
135 	ret = arg->num_waiters;
136 	tee_supp_mutex_unlock(&arg->mutex);
137 
138 	return ret;
139 }
140 
paged_aligned_alloc(size_t sz)141 static void *paged_aligned_alloc(size_t sz)
142 {
143 	void *p = NULL;
144 
145 	if (!posix_memalign(&p, sysconf(_SC_PAGESIZE), sz))
146 		return p;
147 
148 	return NULL;
149 }
150 
get_value(size_t num_params,struct tee_ioctl_param * params,const uint32_t idx,struct param_value ** value)151 static int get_value(size_t num_params, struct tee_ioctl_param *params,
152 		     const uint32_t idx, struct param_value **value)
153 {
154 	if (idx >= num_params)
155 		return -1;
156 
157 	switch (params[idx].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) {
158 	case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT:
159 	case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT:
160 	case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT:
161 		*value = (void *)&params[idx].a;
162 		return 0;
163 	default:
164 		return -1;
165 	}
166 }
167 
find_tshm(int id)168 static struct tee_shm *find_tshm(int id)
169 {
170 	struct tee_shm *tshm = NULL;
171 
172 	tee_supp_mutex_lock(&shm_mutex);
173 
174 	tshm = shm_head;
175 	while (tshm && tshm->id != id)
176 		tshm = tshm->next;
177 
178 	tee_supp_mutex_unlock(&shm_mutex);
179 
180 	return tshm;
181 }
182 
pop_tshm(int id)183 static struct tee_shm *pop_tshm(int id)
184 {
185 	struct tee_shm *tshm = NULL;
186 	struct tee_shm *prev = NULL;
187 
188 	tee_supp_mutex_lock(&shm_mutex);
189 
190 	tshm = shm_head;
191 	if (!tshm)
192 		goto out;
193 
194 	if (tshm->id == id) {
195 		shm_head = tshm->next;
196 		goto out;
197 	}
198 
199 	do {
200 		prev = tshm;
201 		tshm = tshm->next;
202 		if (!tshm)
203 			goto out;
204 	} while (tshm->id != id);
205 	prev->next = tshm->next;
206 
207 out:
208 	tee_supp_mutex_unlock(&shm_mutex);
209 
210 	return tshm;
211 }
212 
push_tshm(struct tee_shm * tshm)213 static void push_tshm(struct tee_shm *tshm)
214 {
215 	tee_supp_mutex_lock(&shm_mutex);
216 
217 	tshm->next = shm_head;
218 	shm_head = tshm;
219 
220 	tee_supp_mutex_unlock(&shm_mutex);
221 }
222 
223 /* Get parameter allocated by secure world */
get_param(size_t num_params,struct tee_ioctl_param * params,const uint32_t idx,TEEC_SharedMemory * shm)224 static int get_param(size_t num_params, struct tee_ioctl_param *params,
225 		     const uint32_t idx, TEEC_SharedMemory *shm)
226 {
227 	struct tee_shm *tshm = NULL;
228 	size_t offs = 0;
229 	size_t sz = 0;
230 
231 	if (idx >= num_params)
232 		return -1;
233 
234 	switch (params[idx].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) {
235 	case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT:
236 	case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT:
237 	case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT:
238 		break;
239 	default:
240 		return -1;
241 	}
242 
243 	memset(shm, 0, sizeof(*shm));
244 
245 	tshm = find_tshm(MEMREF_SHM_ID(params + idx));
246 	if (!tshm) {
247 		/*
248 		 * It doesn't make sense to query required size of an
249 		 * input buffer.
250 		 */
251 		if ((params[idx].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) ==
252 		    TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT)
253 			return -1;
254 
255 		/*
256 		 * Buffer isn't found, the caller is querying required size
257 		 * of the buffer.
258 		 */
259 		return 0;
260 	}
261 
262 	sz = MEMREF_SIZE(params + idx);
263 	offs = MEMREF_SHM_OFFS(params + idx);
264 	if ((sz + offs) < sz)
265 		return -1;
266 	if ((sz + offs) > tshm->size)
267 		return -1;
268 
269 	shm->flags = TEEC_MEM_INPUT | TEEC_MEM_OUTPUT;
270 	shm->size = sz;
271 	shm->id = MEMREF_SHM_ID(params + idx);
272 	shm->buffer = (uint8_t *)tshm->p + offs;
273 
274 	return 0;
275 }
276 
uuid_from_octets(TEEC_UUID * d,const uint8_t s[TEE_IOCTL_UUID_LEN])277 static void uuid_from_octets(TEEC_UUID *d, const uint8_t s[TEE_IOCTL_UUID_LEN])
278 {
279 	d->timeLow = (s[0] << 24) | (s[1] << 16) | (s[2] << 8) | s[3];
280 	d->timeMid = (s[4] << 8) | s[5];
281 	d->timeHiAndVersion = (s[6] << 8) | s[7];
282 	memcpy(d->clockSeqAndNode, s + 8, sizeof(d->clockSeqAndNode));
283 }
284 
load_ta(size_t num_params,struct tee_ioctl_param * params)285 static uint32_t load_ta(size_t num_params, struct tee_ioctl_param *params)
286 {
287 	int ta_found = 0;
288 	size_t size = 0;
289 	struct param_value *val_cmd = NULL;
290 	TEEC_UUID uuid;
291 	TEEC_SharedMemory shm_ta;
292 
293 	memset(&uuid, 0, sizeof(uuid));
294 	memset(&shm_ta, 0, sizeof(shm_ta));
295 
296 	if (num_params != 2 || get_value(num_params, params, 0, &val_cmd) ||
297 	    get_param(num_params, params, 1, &shm_ta))
298 		return TEEC_ERROR_BAD_PARAMETERS;
299 
300 	uuid_from_octets(&uuid, (void *)val_cmd);
301 
302 	size = shm_ta.size;
303 	ta_found = TEECI_LoadSecureModule(supplicant_params.ta_dir, &uuid, shm_ta.buffer, &size);
304 	if (ta_found != TA_BINARY_FOUND) {
305 		EMSG("  TA not found");
306 		return TEEC_ERROR_ITEM_NOT_FOUND;
307 	}
308 
309 	MEMREF_SIZE(params + 1) = size;
310 
311 	/*
312 	 * If a buffer wasn't provided, just tell which size it should be.
313 	 * If it was provided but isn't big enough, report an error.
314 	 */
315 	if (shm_ta.buffer && size > shm_ta.size)
316 		return TEEC_ERROR_SHORT_BUFFER;
317 
318 	return TEEC_SUCCESS;
319 }
320 
alloc_shm(int fd,size_t size)321 static struct tee_shm *alloc_shm(int fd, size_t size)
322 {
323 	struct tee_shm *shm = NULL;
324 	struct tee_ioctl_shm_alloc_data data;
325 
326 	memset(&data, 0, sizeof(data));
327 
328 	shm = calloc(1, sizeof(*shm));
329 	if (!shm)
330 		return NULL;
331 
332 	data.size = size;
333 	shm->fd = ioctl(fd, TEE_IOC_SHM_ALLOC, &data);
334 	if (shm->fd < 0) {
335 		free(shm);
336 		return NULL;
337 	}
338 
339 	shm->p = mmap(NULL, data.size, PROT_READ | PROT_WRITE, MAP_SHARED,
340 		      shm->fd, 0);
341 	if (shm->p == (void *)MAP_FAILED) {
342 		close(shm->fd);
343 		free(shm);
344 		return NULL;
345 	}
346 
347 	shm->id = data.id;
348 	shm->registered = false;
349 	return shm;
350 }
351 
register_local_shm(int fd,size_t size)352 static struct tee_shm *register_local_shm(int fd, size_t size)
353 {
354 	struct tee_shm *shm = NULL;
355 	void *buf = NULL;
356 	struct tee_ioctl_shm_register_data data;
357 
358 	memset(&data, 0, sizeof(data));
359 
360 	buf = paged_aligned_alloc(size);
361 	if (!buf)
362 		return NULL;
363 
364 	shm = calloc(1, sizeof(*shm));
365 	if (!shm) {
366 		free(buf);
367 		return NULL;
368 	}
369 
370 	data.addr = (uintptr_t)buf;
371 	data.length = size;
372 
373 	shm->fd = ioctl(fd, TEE_IOC_SHM_REGISTER, &data);
374 	if (shm->fd < 0) {
375 		free(shm);
376 		free(buf);
377 		return NULL;
378 	}
379 
380 	shm->p = buf;
381 	shm->registered = true;
382 	shm->id = data.id;
383 
384 	return shm;
385 }
386 
process_alloc(struct thread_arg * arg,size_t num_params,struct tee_ioctl_param * params)387 static uint32_t process_alloc(struct thread_arg *arg, size_t num_params,
388 			      struct tee_ioctl_param *params)
389 {
390 	struct param_value *val = NULL;
391 	struct tee_shm *shm = NULL;
392 
393 	if (num_params != 1 || get_value(num_params, params, 0, &val))
394 		return TEEC_ERROR_BAD_PARAMETERS;
395 
396 	if (arg->gen_caps & TEE_GEN_CAP_REG_MEM)
397 		shm = register_local_shm(arg->fd, val->b);
398 	else
399 		shm = alloc_shm(arg->fd, val->b);
400 
401 	if (!shm)
402 		return TEEC_ERROR_OUT_OF_MEMORY;
403 
404 	shm->size = val->b;
405 	val->c = shm->id;
406 	push_tshm(shm);
407 
408 	return TEEC_SUCCESS;
409 }
410 
process_free(size_t num_params,struct tee_ioctl_param * params)411 static uint32_t process_free(size_t num_params, struct tee_ioctl_param *params)
412 {
413 	struct param_value *val = NULL;
414 	struct tee_shm *shm = NULL;
415 	int id = 0;
416 
417 	if (num_params != 1 || get_value(num_params, params, 0, &val))
418 		return TEEC_ERROR_BAD_PARAMETERS;
419 
420 	id = val->b;
421 
422 	shm = pop_tshm(id);
423 	if (!shm)
424 		return TEEC_ERROR_BAD_PARAMETERS;
425 
426 	close(shm->fd);
427 	if (shm->registered) {
428 		free(shm->p);
429 	} else  {
430 		if (munmap(shm->p, shm->size) != 0) {
431 			EMSG("munmap(%p, %zu) failed - Error = %s",
432 			     shm->p, shm->size, strerror(errno));
433 			free(shm);
434 			return TEEC_ERROR_BAD_PARAMETERS;
435 		}
436 	}
437 
438 	free(shm);
439 	return TEEC_SUCCESS;
440 }
441 
442 
443 
444 /* How many device sequence numbers will be tried before giving up */
445 #define MAX_DEV_SEQ	10
446 
open_dev(const char * devname,uint32_t * gen_caps)447 static int open_dev(const char *devname, uint32_t *gen_caps)
448 {
449 	int fd = 0;
450 	struct tee_ioctl_version_data vers;
451 
452 	memset(&vers, 0, sizeof(vers));
453 
454 	fd = open(devname, O_RDWR);
455 	if (fd < 0)
456 		return -1;
457 
458 	if (ioctl(fd, TEE_IOC_VERSION, &vers))
459 		goto err;
460 
461 	/* Only OP-TEE supported */
462 	if (vers.impl_id != TEE_IMPL_ID_OPTEE)
463 		goto err;
464 
465 	if (gen_caps)
466 		*gen_caps = vers.gen_caps;
467 
468 	DMSG("using device \"%s\"", devname);
469 	return fd;
470 err:
471 	close(fd);
472 	return -1;
473 }
474 
get_dev_fd(uint32_t * gen_caps)475 static int get_dev_fd(uint32_t *gen_caps)
476 {
477 	int fd = 0;
478 	char name[PATH_MAX] = { 0 };
479 	size_t n = 0;
480 
481 	for (n = 0; n < MAX_DEV_SEQ; n++) {
482 		snprintf(name, sizeof(name), "/dev/teepriv%zu", n);
483 		fd = open_dev(name, gen_caps);
484 		if (fd >= 0)
485 			return fd;
486 	}
487 	return -1;
488 }
489 
usage(int status)490 static int usage(int status)
491 {
492 	fprintf(stderr, "Usage: tee-supplicant [options] [<device-name>]\n");
493 	fprintf(stderr, "\t-h, --help: this help\n");
494 	fprintf(stderr, "\t-d, --daemonize: run as a daemon (fork and return "
495 			"after child has opened the TEE device or on error)\n");
496 	fprintf(stderr, "\t-f, --fs-parent-path: secure fs parent path [%s]\n",
497 			supplicant_params.fs_parent_path);
498 	fprintf(stderr, "\t-t, --ta-dir: TAs dirname under %s [%s]\n", TEEC_LOAD_PATH,
499 			supplicant_params.ta_dir);
500 	fprintf(stderr, "\t-p, --plugin-path: plugin load path [%s]\n",
501 			supplicant_params.plugin_load_path);
502 	fprintf(stderr, "\t-r, --rpmb-cid: RPMB device identification register "
503 			"(CID) in hexadecimal\n");
504 	return status;
505 }
506 
process_rpmb(size_t num_params,struct tee_ioctl_param * params)507 static uint32_t process_rpmb(size_t num_params, struct tee_ioctl_param *params)
508 {
509 	TEEC_SharedMemory req;
510 	TEEC_SharedMemory rsp;
511 
512 	memset(&req, 0, sizeof(req));
513 	memset(&rsp, 0, sizeof(rsp));
514 
515 	if (get_param(num_params, params, 0, &req) ||
516 	    get_param(num_params, params, 1, &rsp))
517 		return TEEC_ERROR_BAD_PARAMETERS;
518 
519 	return rpmb_process_request(req.buffer, req.size, rsp.buffer, rsp.size);
520 }
521 
read_request(int fd,union tee_rpc_invoke * request)522 static bool read_request(int fd, union tee_rpc_invoke *request)
523 {
524 	struct tee_ioctl_buf_data data;
525 
526 	memset(&data, 0, sizeof(data));
527 
528 	data.buf_ptr = (uintptr_t)request;
529 	data.buf_len = sizeof(*request);
530 	if (ioctl(fd, TEE_IOC_SUPPL_RECV, &data)) {
531 		EMSG("TEE_IOC_SUPPL_RECV: %s", strerror(errno));
532 		return false;
533 	}
534 	return true;
535 }
536 
write_response(int fd,union tee_rpc_invoke * request)537 static bool write_response(int fd, union tee_rpc_invoke *request)
538 {
539 	struct tee_ioctl_buf_data data;
540 
541 	memset(&data, 0, sizeof(data));
542 
543 	data.buf_ptr = (uintptr_t)&request->send;
544 	data.buf_len = sizeof(struct tee_iocl_supp_send_arg) +
545 		       sizeof(struct tee_ioctl_param) *
546 				(__u64)request->send.num_params;
547 	if (ioctl(fd, TEE_IOC_SUPPL_SEND, &data)) {
548 		EMSG("TEE_IOC_SUPPL_SEND: %s", strerror(errno));
549 		return false;
550 	}
551 	return true;
552 }
553 
find_params(union tee_rpc_invoke * request,uint32_t * func,size_t * num_params,struct tee_ioctl_param ** params,size_t * num_meta)554 static bool find_params(union tee_rpc_invoke *request, uint32_t *func,
555 			size_t *num_params, struct tee_ioctl_param **params,
556 			size_t *num_meta)
557 {
558 	struct tee_ioctl_param *p = NULL;
559 	size_t n = 0;
560 
561 	p = (struct tee_ioctl_param *)(&request->recv + 1);
562 
563 	/* Skip meta parameters in the front */
564 	for (n = 0; n < request->recv.num_params; n++)
565 		if (!(p[n].attr & TEE_IOCTL_PARAM_ATTR_META))
566 			break;
567 
568 	*func = request->recv.func;
569 	*num_params = request->recv.num_params - n;
570 	*params = p + n;
571 	*num_meta = n;
572 
573 	/* Make sure that no meta parameters follows a non-meta parameter */
574 	for (; n < request->recv.num_params; n++) {
575 		if (p[n].attr & TEE_IOCTL_PARAM_ATTR_META) {
576 			EMSG("Unexpected meta parameter");
577 			return false;
578 		}
579 	}
580 
581 	return true;
582 }
583 
spawn_thread(struct thread_arg * arg)584 static bool spawn_thread(struct thread_arg *arg)
585 {
586 	int e = 0;
587 	pthread_t tid;
588 
589 	memset(&tid, 0, sizeof(tid));
590 
591 	DMSG("Spawning a new thread");
592 
593 	/*
594 	 * Increase number of waiters now to avoid starting another thread
595 	 * before this thread has been scheduled.
596 	 */
597 	num_waiters_inc(arg);
598 
599 	e = pthread_create(&tid, NULL, thread_main, arg);
600 	if (e) {
601 		EMSG("pthread_create: %s", strerror(e));
602 		num_waiters_dec(arg);
603 		return false;
604 	}
605 
606 	e = pthread_detach(tid);
607 	if (e)
608 		EMSG("pthread_detach: %s", strerror(e));
609 
610 	return true;
611 }
612 
process_one_request(struct thread_arg * arg)613 static bool process_one_request(struct thread_arg *arg)
614 {
615 	size_t num_params = 0;
616 	size_t num_meta = 0;
617 	struct tee_ioctl_param *params = NULL;
618 	uint32_t func = 0;
619 	uint32_t ret = 0;
620 	union tee_rpc_invoke request;
621 
622 	memset(&request, 0, sizeof(request));
623 
624 	DMSG("looping");
625 	request.recv.num_params = RPC_NUM_PARAMS;
626 
627 	/* Let it be known that we can deal with meta parameters */
628 	params = (struct tee_ioctl_param *)(&request.send + 1);
629 	params->attr = TEE_IOCTL_PARAM_ATTR_META;
630 
631 	num_waiters_inc(arg);
632 
633 	if (!read_request(arg->fd, &request))
634 		return false;
635 
636 	if (!find_params(&request, &func, &num_params, &params, &num_meta))
637 		return false;
638 
639 	if (num_meta && !num_waiters_dec(arg) && !spawn_thread(arg))
640 		return false;
641 
642 	switch (func) {
643 	case OPTEE_MSG_RPC_CMD_LOAD_TA:
644 		ret = load_ta(num_params, params);
645 		break;
646 	case OPTEE_MSG_RPC_CMD_FS:
647 		ret = tee_supp_fs_process(num_params, params);
648 		break;
649 	case OPTEE_MSG_RPC_CMD_RPMB:
650 		ret = process_rpmb(num_params, params);
651 		break;
652 	case OPTEE_MSG_RPC_CMD_SHM_ALLOC:
653 		ret = process_alloc(arg, num_params, params);
654 		break;
655 	case OPTEE_MSG_RPC_CMD_SHM_FREE:
656 		ret = process_free(num_params, params);
657 		break;
658 	case OPTEE_MSG_RPC_CMD_GPROF:
659 		ret = prof_process(num_params, params, "gmon-");
660 		break;
661 	case OPTEE_MSG_RPC_CMD_SOCKET:
662 		ret = tee_socket_process(num_params, params);
663 		break;
664 	case OPTEE_MSG_RPC_CMD_FTRACE:
665 		ret = prof_process(num_params, params, "ftrace-");
666 		break;
667 	case OPTEE_MSG_RPC_CMD_PLUGIN:
668 		ret = plugin_process(num_params, params);
669 		break;
670 	default:
671 		EMSG("Cmd [0x%" PRIx32 "] not supported", func);
672 		/* Not supported. */
673 		ret = TEEC_ERROR_NOT_SUPPORTED;
674 		break;
675 	}
676 
677 	request.send.ret = ret;
678 	return write_response(arg->fd, &request);
679 }
680 
thread_main(void * a)681 static void *thread_main(void *a)
682 {
683 	struct thread_arg *arg = a;
684 
685 	/*
686 	 * Now that this thread has been scheduled, compensate for the
687 	 * initial increase in spawn_thread() before.
688 	 */
689 	num_waiters_dec(arg);
690 
691 	while (!arg->abort) {
692 		if (!process_one_request(arg))
693 			arg->abort = true;
694 	}
695 
696 	return NULL;
697 }
698 
699 #define TEEC_TEST_LOAD_PATH "/foo:/bar::/baz"
700 
set_ta_path(void)701 static void set_ta_path(void)
702 {
703 	char *p = NULL;
704 	char *saveptr = NULL;
705 	const char *path = (char *)
706 #ifdef TEEC_TEST_LOAD_PATH
707 		TEEC_TEST_LOAD_PATH ":"
708 #endif
709 		TEEC_LOAD_PATH;
710 	size_t n = 0;
711 
712 	ta_path_str = strdup(path);
713 	if (!ta_path_str)
714 		goto err;
715 
716 	p = ta_path_str;
717 	while (strtok_r(p, ":", &saveptr)) {
718 		p = NULL;
719 		n++;
720 	}
721 	n++; /* NULL terminator */
722 
723 	ta_path = malloc(n * sizeof(char *));
724 	if (!ta_path)
725 		goto err;
726 
727 	n = 0;
728 	strcpy(ta_path_str, path);
729 	p = ta_path_str;
730 	while ((ta_path[n++] = strtok_r(p, ":", &saveptr)))
731 	       p = NULL;
732 
733 	return;
734 err:
735 	EMSG("out of memory");
736 	exit(EXIT_FAILURE);
737 }
738 
739 /*
740  * Similar to the standard libc function daemon(0, 0) but the parent process
741  * issues a blocking read on pipefd[0] before exiting.
742  * Returns 0 on success, <0 on error.
743  */
make_daemon(int pipefd[2])744 static int make_daemon(int pipefd[2])
745 {
746 	int fd = 0;
747 	char c = 0;
748 	int n = 0;
749 
750 	switch (fork()) {
751 	case -1:
752 		return -1;
753 	case 0:
754 		/* In child */
755 		close(pipefd[0]);
756 		break;
757 	default:
758 		/* In parent */
759 		close(pipefd[1]);
760 		n = read(pipefd[0], &c, 1);
761 		close(pipefd[0]);
762 		if (!n) {
763 			/*
764 			 * Nothing has been read: child has closed without
765 			 * writing (either exited on error or crashed)
766 			 */
767 			return -1;
768 		}
769 		/* Child is done with the opening of the TEE device */
770 		_exit(EXIT_SUCCESS);
771 	}
772 
773 	if (setsid() < 0)
774 		return -2;
775 
776 	if (chdir("/") < 0)
777 		return -3;
778 
779 	fd = open("/dev/null", O_RDWR);
780 	if (fd < 0)
781 		return -4;
782 	dup2(fd, 0);
783 	dup2(fd, 1);
784 	dup2(fd, 2);
785 	close(fd);
786 
787 	return 0;
788 }
789 
main(int argc,char * argv[])790 int main(int argc, char *argv[])
791 {
792 	struct thread_arg arg = { .fd = -1 };
793 	int pipefd[2] = { 0, };
794 	bool daemonize = false;
795 	char *dev = NULL;
796 	int e = 0;
797 	int long_index = 0;
798 	int opt = 0;
799 
800 	e = pthread_mutex_init(&arg.mutex, NULL);
801 	if (e) {
802 		EMSG("pthread_mutex_init: %s", strerror(e));
803 		EMSG("terminating...");
804 		exit(EXIT_FAILURE);
805 	}
806 
807 	static struct option long_options[] = {
808 		/* long name      | has argument  | flag | short value */
809 		{ "help",            no_argument,       0, 'h' },
810 		{ "daemonize",       no_argument,       0, 'd' },
811 		{ "fs-parent-path",  required_argument, 0, 'f' },
812 		{ "ta-dir",          required_argument, 0, 't' },
813 		{ "plugin-path",     required_argument, 0, 'p' },
814 		{ "rpmb-cid",        required_argument, 0, 'r' },
815 		{ 0, 0, 0, 0 }
816 	};
817 
818 	while ((opt = getopt_long(argc, argv, "hdf:t:p:r:",
819 				long_options, &long_index )) != -1) {
820 		switch (opt) {
821 			case 'h' :
822 				return usage(EXIT_SUCCESS);
823 				break;
824 			case 'd':
825 				daemonize = true;
826 				break;
827 			case 'f':
828 				supplicant_params.fs_parent_path = optarg;
829 				break;
830 			case 't':
831 				supplicant_params.ta_dir = optarg;
832 				break;
833 			case 'p':
834 				supplicant_params.plugin_load_path = optarg;
835 				break;
836 			case 'r':
837 				supplicant_params.rpmb_cid = optarg;
838 				break;
839 			default:
840 				return usage(EXIT_FAILURE);
841 		}
842 	}
843 	/* check for non option argument, which is device name */
844 	if (argv[optind]) {
845 		fprintf(stderr, "Using device %s.\n", argv[optind]);
846 		dev = argv[optind];
847 		/* check that we do not have too many arguments */
848 		if (argv[optind + 1]) {
849 			fprintf(stderr, "Too many arguments passed: extra argument: %s.\n",
850 					argv[optind+1]);
851 			return usage(EXIT_FAILURE);
852 		}
853 	}
854 
855 
856 	set_ta_path();
857 
858 	if (plugin_load_all() != 0) {
859 		EMSG("failed to load plugins");
860 		exit(EXIT_FAILURE);
861 	}
862 
863 	if (daemonize) {
864 		if (pipe(pipefd) < 0) {
865 			EMSG("pipe(): %s", strerror(errno));
866 			exit(EXIT_FAILURE);
867 		}
868 		e = make_daemon(pipefd);
869 		if (e < 0) {
870 			EMSG("make_daemon(): %d", e);
871 			exit(EXIT_FAILURE);
872 		}
873 	}
874 
875 	if (dev) {
876 		arg.fd = open_dev(dev, &arg.gen_caps);
877 		if (arg.fd < 0) {
878 			EMSG("failed to open \"%s\"", argv[1]);
879 			exit(EXIT_FAILURE);
880 		}
881 	} else {
882 		arg.fd = get_dev_fd(&arg.gen_caps);
883 		if (arg.fd < 0) {
884 			EMSG("failed to find an OP-TEE supplicant device");
885 			exit(EXIT_FAILURE);
886 		}
887 	}
888 
889 	if (daemonize) {
890 		/* Release parent */
891 		if (write(pipefd[1], "", 1) != 1) {
892 			EMSG("write(): %s", strerror(errno));
893 			exit(EXIT_FAILURE);
894 		}
895 		close(pipefd[1]);
896 	}
897 
898 	while (!arg.abort) {
899 		if (!process_one_request(&arg))
900 			arg.abort = true;
901 	}
902 
903 	close(arg.fd);
904 
905 	return EXIT_FAILURE;
906 }
907 
tee_supp_param_is_memref(struct tee_ioctl_param * param)908 bool tee_supp_param_is_memref(struct tee_ioctl_param *param)
909 {
910 	switch (param->attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) {
911 	case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT:
912 	case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT:
913 	case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT:
914 		return true;
915 	default:
916 		return false;
917 	}
918 }
919 
tee_supp_param_is_value(struct tee_ioctl_param * param)920 bool tee_supp_param_is_value(struct tee_ioctl_param *param)
921 {
922 	switch (param->attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) {
923 	case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT:
924 	case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT:
925 	case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT:
926 		return true;
927 	default:
928 		return false;
929 	}
930 }
931 
tee_supp_param_to_va(struct tee_ioctl_param * param)932 void *tee_supp_param_to_va(struct tee_ioctl_param *param)
933 {
934 	struct tee_shm *tshm = NULL;
935 	size_t end_offs = 0;
936 
937 	if (!tee_supp_param_is_memref(param))
938 		return NULL;
939 
940 	end_offs = MEMREF_SIZE(param) + MEMREF_SHM_OFFS(param);
941 	if (end_offs < MEMREF_SIZE(param) || end_offs < MEMREF_SHM_OFFS(param))
942 		return NULL;
943 
944 	tshm = find_tshm(MEMREF_SHM_ID(param));
945 	if (!tshm)
946 		return NULL;
947 
948 	if (end_offs > tshm->size)
949 		return NULL;
950 
951 	return (uint8_t *)tshm->p + MEMREF_SHM_OFFS(param);
952 }
953 
tee_supp_mutex_lock(pthread_mutex_t * mu)954 void tee_supp_mutex_lock(pthread_mutex_t *mu)
955 {
956 	int e = pthread_mutex_lock(mu);
957 
958 	if (e) {
959 		EMSG("pthread_mutex_lock: %s", strerror(e));
960 		EMSG("terminating...");
961 		exit(EXIT_FAILURE);
962 	}
963 }
964 
tee_supp_mutex_unlock(pthread_mutex_t * mu)965 void tee_supp_mutex_unlock(pthread_mutex_t *mu)
966 {
967 	int e = pthread_mutex_unlock(mu);
968 
969 	if (e) {
970 		EMSG("pthread_mutex_unlock: %s", strerror(e));
971 		EMSG("terminating...");
972 		exit(EXIT_FAILURE);
973 	}
974 }
975