xref: /optee_os/core/pta/system.c (revision f5a70e3efb80be4b9bff2c9c811ddc139058e05a)
1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3  * Copyright (c) 2018-2019, Linaro Limited
4  */
5 
6 #include <assert.h>
7 #include <crypto/crypto.h>
8 #include <kernel/handle.h>
9 #include <kernel/huk_subkey.h>
10 #include <kernel/misc.h>
11 #include <kernel/msg_param.h>
12 #include <kernel/pseudo_ta.h>
13 #include <kernel/user_ta.h>
14 #include <kernel/user_ta_store.h>
15 #include <ldelf.h>
16 #include <mm/file.h>
17 #include <mm/fobj.h>
18 #include <mm/tee_mmu.h>
19 #include <pta_system.h>
20 #include <string.h>
21 #include <tee_api_defines_extensions.h>
22 #include <tee_api_defines.h>
23 #include <util.h>
24 #include <kernel/tpm.h>
25 
26 #define MAX_ENTROPY_IN			32u
27 
28 struct bin_handle {
29 	const struct user_ta_store_ops *op;
30 	struct user_ta_store_handle *h;
31 	struct file *f;
32 	size_t offs_bytes;
33 	size_t size_bytes;
34 };
35 
36 struct system_ctx {
37 	struct handle_db db;
38 	const struct user_ta_store_ops *store_op;
39 };
40 
41 static unsigned int system_pnum;
42 
43 static TEE_Result system_rng_reseed(struct tee_ta_session *s __unused,
44 				uint32_t param_types,
45 				TEE_Param params[TEE_NUM_PARAMS])
46 {
47 	size_t entropy_sz;
48 	uint8_t *entropy_input;
49 	uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT,
50 					  TEE_PARAM_TYPE_NONE,
51 					  TEE_PARAM_TYPE_NONE,
52 					  TEE_PARAM_TYPE_NONE);
53 
54 	if (exp_pt != param_types)
55 		return TEE_ERROR_BAD_PARAMETERS;
56 	entropy_input = params[0].memref.buffer;
57 	entropy_sz = params[0].memref.size;
58 
59 	/* Fortuna PRNG requires seed <= 32 bytes */
60 	if (!entropy_sz)
61 		return TEE_ERROR_BAD_PARAMETERS;
62 
63 	entropy_sz = MIN(entropy_sz, MAX_ENTROPY_IN);
64 
65 	crypto_rng_add_event(CRYPTO_RNG_SRC_NONSECURE, &system_pnum,
66 			     entropy_input, entropy_sz);
67 	return TEE_SUCCESS;
68 }
69 
70 static TEE_Result system_derive_ta_unique_key(struct tee_ta_session *s,
71 					      uint32_t param_types,
72 					      TEE_Param params[TEE_NUM_PARAMS])
73 {
74 	size_t data_len = sizeof(TEE_UUID);
75 	TEE_Result res = TEE_ERROR_GENERIC;
76 	uint8_t *data = NULL;
77 	uint32_t access_flags = 0;
78 	uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT,
79 					  TEE_PARAM_TYPE_MEMREF_OUTPUT,
80 					  TEE_PARAM_TYPE_NONE,
81 					  TEE_PARAM_TYPE_NONE);
82 	struct user_ta_ctx *utc = NULL;
83 
84 	if (exp_pt != param_types)
85 		return TEE_ERROR_BAD_PARAMETERS;
86 
87 	if (params[0].memref.size > TA_DERIVED_EXTRA_DATA_MAX_SIZE ||
88 	    params[1].memref.size < TA_DERIVED_KEY_MIN_SIZE ||
89 	    params[1].memref.size > TA_DERIVED_KEY_MAX_SIZE)
90 		return TEE_ERROR_BAD_PARAMETERS;
91 
92 	utc = to_user_ta_ctx(s->ctx);
93 
94 	/*
95 	 * The derived key shall not end up in non-secure memory by
96 	 * mistake.
97 	 *
98 	 * Note that we're allowing shared memory as long as it's
99 	 * secure. This is needed because a TA always uses shared memory
100 	 * when communicating with another TA.
101 	 */
102 	access_flags = TEE_MEMORY_ACCESS_WRITE | TEE_MEMORY_ACCESS_ANY_OWNER |
103 		       TEE_MEMORY_ACCESS_SECURE;
104 	res = tee_mmu_check_access_rights(&utc->uctx, access_flags,
105 					  (uaddr_t)params[1].memref.buffer,
106 					  params[1].memref.size);
107 	if (res != TEE_SUCCESS)
108 		return TEE_ERROR_SECURITY;
109 
110 	/* Take extra data into account. */
111 	if (ADD_OVERFLOW(data_len, params[0].memref.size, &data_len))
112 		return TEE_ERROR_SECURITY;
113 
114 	data = calloc(data_len, 1);
115 	if (!data)
116 		return TEE_ERROR_OUT_OF_MEMORY;
117 
118 	memcpy(data, &s->ctx->uuid, sizeof(TEE_UUID));
119 
120 	/* Append the user provided data */
121 	memcpy(data + sizeof(TEE_UUID), params[0].memref.buffer,
122 	       params[0].memref.size);
123 
124 	res = huk_subkey_derive(HUK_SUBKEY_UNIQUE_TA, data, data_len,
125 				params[1].memref.buffer,
126 				params[1].memref.size);
127 	free(data);
128 
129 	return res;
130 }
131 
132 static TEE_Result system_map_zi(struct tee_ta_session *s, uint32_t param_types,
133 				TEE_Param params[TEE_NUM_PARAMS])
134 {
135 	uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
136 					  TEE_PARAM_TYPE_VALUE_INOUT,
137 					  TEE_PARAM_TYPE_VALUE_INPUT,
138 					  TEE_PARAM_TYPE_NONE);
139 	struct user_ta_ctx *utc = to_user_ta_ctx(s->ctx);
140 	uint32_t prot = TEE_MATTR_URW | TEE_MATTR_PRW;
141 	TEE_Result res = TEE_ERROR_GENERIC;
142 	struct mobj *mobj = NULL;
143 	uint32_t pad_begin = 0;
144 	uint32_t vm_flags = 0;
145 	struct fobj *f = NULL;
146 	uint32_t pad_end = 0;
147 	size_t num_bytes = 0;
148 	vaddr_t va = 0;
149 
150 	if (exp_pt != param_types)
151 		return TEE_ERROR_BAD_PARAMETERS;
152 	if (params[0].value.b & ~PTA_SYSTEM_MAP_FLAG_SHAREABLE)
153 		return TEE_ERROR_BAD_PARAMETERS;
154 
155 	if (params[0].value.b & PTA_SYSTEM_MAP_FLAG_SHAREABLE)
156 		vm_flags |= VM_FLAG_SHAREABLE;
157 
158 	num_bytes = params[0].value.a;
159 	va = reg_pair_to_64(params[1].value.a, params[1].value.b);
160 	pad_begin = params[2].value.a;
161 	pad_end = params[2].value.b;
162 
163 	f = fobj_ta_mem_alloc(ROUNDUP(num_bytes, SMALL_PAGE_SIZE) /
164 			      SMALL_PAGE_SIZE);
165 	if (!f)
166 		return TEE_ERROR_OUT_OF_MEMORY;
167 	mobj = mobj_with_fobj_alloc(f, NULL);
168 	fobj_put(f);
169 	if (!mobj)
170 		return TEE_ERROR_OUT_OF_MEMORY;
171 	res = vm_map_pad(&utc->uctx, &va, num_bytes, prot, vm_flags,
172 			 mobj, 0, pad_begin, pad_end);
173 	mobj_put(mobj);
174 	if (!res)
175 		reg_pair_from_64(va, &params[1].value.a, &params[1].value.b);
176 
177 	return res;
178 }
179 
180 static TEE_Result system_unmap(struct tee_ta_session *s, uint32_t param_types,
181 			       TEE_Param params[TEE_NUM_PARAMS])
182 {
183 	uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
184 					  TEE_PARAM_TYPE_VALUE_INPUT,
185 					  TEE_PARAM_TYPE_NONE,
186 					  TEE_PARAM_TYPE_NONE);
187 	struct user_ta_ctx *utc = to_user_ta_ctx(s->ctx);
188 	TEE_Result res = TEE_SUCCESS;
189 	uint32_t vm_flags = 0;
190 	vaddr_t va = 0;
191 	size_t sz = 0;
192 
193 	if (exp_pt != param_types)
194 		return TEE_ERROR_BAD_PARAMETERS;
195 
196 	if (params[0].value.b)
197 		return TEE_ERROR_BAD_PARAMETERS;
198 
199 	va = reg_pair_to_64(params[1].value.a, params[1].value.b);
200 	sz = ROUNDUP(params[0].value.a, SMALL_PAGE_SIZE);
201 
202 	res = vm_get_flags(&utc->uctx, va, sz, &vm_flags);
203 	if (res)
204 		return res;
205 	if (vm_flags & VM_FLAG_PERMANENT)
206 		return TEE_ERROR_ACCESS_DENIED;
207 
208 	return vm_unmap(&to_user_ta_ctx(s->ctx)->uctx, va, sz);
209 }
210 
211 static void ta_bin_close(void *ptr)
212 {
213 	struct bin_handle *binh = ptr;
214 
215 	if (binh) {
216 		if (binh->op && binh->h)
217 			binh->op->close(binh->h);
218 		file_put(binh->f);
219 	}
220 	free(binh);
221 }
222 
223 static TEE_Result system_open_ta_binary(struct system_ctx *ctx,
224 					uint32_t param_types,
225 					TEE_Param params[TEE_NUM_PARAMS])
226 {
227 	TEE_Result res = TEE_SUCCESS;
228 	struct bin_handle *binh = NULL;
229 	int h = 0;
230 	TEE_UUID *uuid = NULL;
231 	uint8_t tag[FILE_TAG_SIZE] = { 0 };
232 	unsigned int tag_len = sizeof(tag);
233 	uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT,
234 					  TEE_PARAM_TYPE_VALUE_OUTPUT,
235 					  TEE_PARAM_TYPE_NONE,
236 					  TEE_PARAM_TYPE_NONE);
237 
238 	if (exp_pt != param_types)
239 		return TEE_ERROR_BAD_PARAMETERS;
240 	if (params[0].memref.size != sizeof(*uuid))
241 		return TEE_ERROR_BAD_PARAMETERS;
242 
243 	uuid = params[0].memref.buffer;
244 
245 	binh = calloc(1, sizeof(*binh));
246 	if (!binh)
247 		return TEE_ERROR_OUT_OF_MEMORY;
248 
249 	SCATTERED_ARRAY_FOREACH(binh->op, ta_stores, struct user_ta_store_ops) {
250 		DMSG("Lookup user TA ELF %pUl (%s)",
251 		     (void *)uuid, binh->op->description);
252 
253 		res = binh->op->open(uuid, &binh->h);
254 		DMSG("res=0x%x", res);
255 		if (res != TEE_ERROR_ITEM_NOT_FOUND &&
256 		    res != TEE_ERROR_STORAGE_NOT_AVAILABLE)
257 			break;
258 	}
259 	if (res)
260 		goto err;
261 
262 	res = binh->op->get_size(binh->h, &binh->size_bytes);
263 	if (res)
264 		goto err;
265 	res = binh->op->get_tag(binh->h, tag, &tag_len);
266 	if (res)
267 		goto err;
268 	binh->f = file_get_by_tag(tag, tag_len);
269 	if (!binh->f)
270 		goto err_oom;
271 
272 	h = handle_get(&ctx->db, binh);
273 	if (h < 0)
274 		goto err_oom;
275 
276 	return TEE_SUCCESS;
277 err_oom:
278 	res = TEE_ERROR_OUT_OF_MEMORY;
279 err:
280 	ta_bin_close(binh);
281 	return res;
282 }
283 
284 static TEE_Result system_close_ta_binary(struct system_ctx *ctx,
285 					 uint32_t param_types,
286 					 TEE_Param params[TEE_NUM_PARAMS])
287 {
288 	TEE_Result res = TEE_SUCCESS;
289 	struct bin_handle *binh = NULL;
290 	uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
291 					  TEE_PARAM_TYPE_NONE,
292 					  TEE_PARAM_TYPE_NONE,
293 					  TEE_PARAM_TYPE_NONE);
294 
295 	if (exp_pt != param_types)
296 		return TEE_ERROR_BAD_PARAMETERS;
297 
298 	if (params[0].value.b)
299 		return TEE_ERROR_BAD_PARAMETERS;
300 
301 	binh = handle_put(&ctx->db, params[0].value.a);
302 	if (!binh)
303 		return TEE_ERROR_BAD_PARAMETERS;
304 
305 	if (binh->offs_bytes < binh->size_bytes)
306 		res = binh->op->read(binh->h, NULL,
307 				     binh->size_bytes - binh->offs_bytes);
308 
309 	ta_bin_close(binh);
310 	return res;
311 }
312 
313 static TEE_Result binh_copy_to(struct bin_handle *binh, vaddr_t va,
314 			       size_t offs_bytes, size_t num_bytes)
315 {
316 	TEE_Result res = TEE_SUCCESS;
317 	size_t l =  num_bytes;
318 
319 	if (offs_bytes < binh->offs_bytes)
320 		return TEE_ERROR_BAD_STATE;
321 	if (offs_bytes > binh->offs_bytes) {
322 		res = binh->op->read(binh->h, NULL,
323 				     offs_bytes - binh->offs_bytes);
324 		if (res)
325 			return res;
326 		binh->offs_bytes = offs_bytes;
327 	}
328 
329 	if (binh->offs_bytes + l > binh->size_bytes) {
330 		size_t rb = binh->size_bytes - binh->offs_bytes;
331 
332 		res = binh->op->read(binh->h, (void *)va, rb);
333 		if (res)
334 			return res;
335 		memset((uint8_t *)va + rb, 0, l - rb);
336 		binh->offs_bytes = binh->size_bytes;
337 	} else {
338 		res = binh->op->read(binh->h, (void *)va, l);
339 		if (res)
340 			return res;
341 		binh->offs_bytes += l;
342 	}
343 
344 	return TEE_SUCCESS;
345 }
346 
347 static TEE_Result system_map_ta_binary(struct system_ctx *ctx,
348 				       struct tee_ta_session *s,
349 				       uint32_t param_types,
350 				       TEE_Param params[TEE_NUM_PARAMS])
351 {
352 	const uint32_t accept_flags = PTA_SYSTEM_MAP_FLAG_SHAREABLE |
353 				      PTA_SYSTEM_MAP_FLAG_WRITEABLE |
354 				      PTA_SYSTEM_MAP_FLAG_EXECUTABLE;
355 	uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
356 					  TEE_PARAM_TYPE_VALUE_INPUT,
357 					  TEE_PARAM_TYPE_VALUE_INOUT,
358 					  TEE_PARAM_TYPE_VALUE_INPUT);
359 	struct user_ta_ctx *utc = to_user_ta_ctx(s->ctx);
360 	struct bin_handle *binh = NULL;
361 	TEE_Result res = TEE_SUCCESS;
362 	struct file_slice *fs = NULL;
363 	bool file_is_locked = false;
364 	struct mobj *mobj = NULL;
365 	uint32_t offs_bytes = 0;
366 	uint32_t offs_pages = 0;
367 	uint32_t num_bytes = 0;
368 	uint32_t pad_begin = 0;
369 	uint32_t pad_end = 0;
370 	size_t num_pages = 0;
371 	uint32_t flags = 0;
372 	uint32_t prot = 0;
373 	vaddr_t va = 0;
374 
375 	if (exp_pt != param_types)
376 		return TEE_ERROR_BAD_PARAMETERS;
377 
378 	binh = handle_lookup(&ctx->db, params[0].value.a);
379 	if (!binh)
380 		return TEE_ERROR_BAD_PARAMETERS;
381 	flags = params[0].value.b;
382 	offs_bytes = params[1].value.a;
383 	num_bytes = params[1].value.b;
384 	va = reg_pair_to_64(params[2].value.a, params[2].value.b);
385 	pad_begin = params[3].value.a;
386 	pad_end = params[3].value.b;
387 
388 	if ((flags & accept_flags) != flags)
389 		return TEE_ERROR_BAD_PARAMETERS;
390 
391 	if ((flags & PTA_SYSTEM_MAP_FLAG_SHAREABLE) &&
392 	    (flags & PTA_SYSTEM_MAP_FLAG_WRITEABLE))
393 		return TEE_ERROR_BAD_PARAMETERS;
394 
395 	if ((flags & PTA_SYSTEM_MAP_FLAG_EXECUTABLE) &&
396 	    (flags & PTA_SYSTEM_MAP_FLAG_WRITEABLE))
397 		return TEE_ERROR_BAD_PARAMETERS;
398 
399 	if (offs_bytes & SMALL_PAGE_MASK)
400 		return TEE_ERROR_BAD_PARAMETERS;
401 
402 	prot = TEE_MATTR_UR | TEE_MATTR_PR;
403 	if (flags & PTA_SYSTEM_MAP_FLAG_WRITEABLE)
404 		prot |= TEE_MATTR_UW | TEE_MATTR_PW;
405 	if (flags & PTA_SYSTEM_MAP_FLAG_EXECUTABLE)
406 		prot |= TEE_MATTR_UX;
407 
408 	offs_pages = offs_bytes >> SMALL_PAGE_SHIFT;
409 	num_pages = ROUNDUP(num_bytes, SMALL_PAGE_SIZE) / SMALL_PAGE_SIZE;
410 
411 	if (!file_trylock(binh->f)) {
412 		/*
413 		 * Before we can block on the file lock we must make all
414 		 * our page tables available for reclaiming in order to
415 		 * avoid a dead-lock with the other thread (which already
416 		 * is holding the file lock) mapping lots of memory below.
417 		 */
418 		tee_mmu_set_ctx(NULL);
419 		file_lock(binh->f);
420 		tee_mmu_set_ctx(s->ctx);
421 	}
422 	file_is_locked = true;
423 	fs = file_find_slice(binh->f, offs_pages);
424 	if (fs) {
425 		/* If there's registered slice it has to match */
426 		if (fs->page_offset != offs_pages ||
427 		    num_pages > fs->fobj->num_pages) {
428 			res = TEE_ERROR_BAD_PARAMETERS;
429 			goto err;
430 		}
431 
432 		/* If there's a slice we must be mapping shareable */
433 		if (!(flags & PTA_SYSTEM_MAP_FLAG_SHAREABLE)) {
434 			res = TEE_ERROR_BAD_PARAMETERS;
435 			goto err;
436 		}
437 
438 		mobj = mobj_with_fobj_alloc(fs->fobj, binh->f);
439 		if (!mobj) {
440 			res = TEE_ERROR_OUT_OF_MEMORY;
441 			goto err;
442 		}
443 		res = vm_map_pad(&utc->uctx, &va, num_pages * SMALL_PAGE_SIZE,
444 				 prot, VM_FLAG_READONLY,
445 				 mobj, 0, pad_begin, pad_end);
446 		mobj_put(mobj);
447 		if (res)
448 			goto err;
449 	} else {
450 		struct fobj *f = fobj_ta_mem_alloc(num_pages);
451 		struct file *file = NULL;
452 		uint32_t vm_flags = 0;
453 
454 		if (!f) {
455 			res = TEE_ERROR_OUT_OF_MEMORY;
456 			goto err;
457 		}
458 		if (!(flags & PTA_SYSTEM_MAP_FLAG_WRITEABLE)) {
459 			file = binh->f;
460 			vm_flags |= VM_FLAG_READONLY;
461 		}
462 
463 		mobj = mobj_with_fobj_alloc(f, file);
464 		fobj_put(f);
465 		if (!mobj) {
466 			res = TEE_ERROR_OUT_OF_MEMORY;
467 			goto err;
468 		}
469 		res = vm_map_pad(&utc->uctx, &va, num_pages * SMALL_PAGE_SIZE,
470 				 TEE_MATTR_PRW, vm_flags, mobj, 0,
471 				 pad_begin, pad_end);
472 		mobj_put(mobj);
473 		if (res)
474 			goto err;
475 		res = binh_copy_to(binh, va, offs_bytes, num_bytes);
476 		if (res)
477 			goto err_unmap_va;
478 		res = vm_set_prot(&utc->uctx, va, num_pages * SMALL_PAGE_SIZE,
479 				  prot);
480 		if (res)
481 			goto err_unmap_va;
482 
483 		/*
484 		 * The context currently is active set it again to update
485 		 * the mapping.
486 		 */
487 		tee_mmu_set_ctx(s->ctx);
488 
489 		if (!(flags & PTA_SYSTEM_MAP_FLAG_WRITEABLE)) {
490 			res = file_add_slice(binh->f, f, offs_pages);
491 			if (res)
492 				goto err_unmap_va;
493 		}
494 	}
495 
496 	file_unlock(binh->f);
497 
498 	reg_pair_from_64(va, &params[2].value.a, &params[2].value.b);
499 	return TEE_SUCCESS;
500 
501 err_unmap_va:
502 	if (vm_unmap(&utc->uctx, va, num_pages * SMALL_PAGE_SIZE))
503 		panic();
504 
505 	/*
506 	 * The context currently is active set it again to update
507 	 * the mapping.
508 	 */
509 	tee_mmu_set_ctx(s->ctx);
510 
511 err:
512 	if (file_is_locked)
513 		file_unlock(binh->f);
514 
515 	return res;
516 }
517 
518 static TEE_Result system_copy_from_ta_binary(struct system_ctx *ctx,
519 					     uint32_t param_types,
520 					     TEE_Param params[TEE_NUM_PARAMS])
521 {
522 	struct bin_handle *binh = NULL;
523 	uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
524 					  TEE_PARAM_TYPE_MEMREF_OUTPUT,
525 					  TEE_PARAM_TYPE_NONE,
526 					  TEE_PARAM_TYPE_NONE);
527 
528 	if (exp_pt != param_types)
529 		return TEE_ERROR_BAD_PARAMETERS;
530 
531 	binh = handle_lookup(&ctx->db, params[0].value.a);
532 	if (!binh)
533 		return TEE_ERROR_BAD_PARAMETERS;
534 
535 	return binh_copy_to(binh, (vaddr_t)params[1].memref.buffer,
536 			    params[0].value.b, params[1].memref.size);
537 }
538 
539 static TEE_Result system_set_prot(struct tee_ta_session *s,
540 				  uint32_t param_types,
541 				  TEE_Param params[TEE_NUM_PARAMS])
542 {
543 	const uint32_t accept_flags = PTA_SYSTEM_MAP_FLAG_WRITEABLE |
544 				      PTA_SYSTEM_MAP_FLAG_EXECUTABLE;
545 	uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
546 					  TEE_PARAM_TYPE_VALUE_INPUT,
547 					  TEE_PARAM_TYPE_NONE,
548 					  TEE_PARAM_TYPE_NONE);
549 	struct user_ta_ctx *utc = to_user_ta_ctx(s->ctx);
550 	uint32_t prot = TEE_MATTR_UR | TEE_MATTR_PR;
551 	TEE_Result res = TEE_SUCCESS;
552 	uint32_t vm_flags = 0;
553 	uint32_t flags = 0;
554 	vaddr_t va = 0;
555 	size_t sz = 0;
556 
557 	if (exp_pt != param_types)
558 		return TEE_ERROR_BAD_PARAMETERS;
559 
560 	flags = params[0].value.b;
561 
562 	if ((flags & accept_flags) != flags)
563 		return TEE_ERROR_BAD_PARAMETERS;
564 	if (flags & PTA_SYSTEM_MAP_FLAG_WRITEABLE)
565 		prot |= TEE_MATTR_UW | TEE_MATTR_PW;
566 	if (flags & PTA_SYSTEM_MAP_FLAG_EXECUTABLE)
567 		prot |= TEE_MATTR_UX;
568 
569 	va = reg_pair_to_64(params[1].value.a, params[1].value.b),
570 	sz = ROUNDUP(params[0].value.a, SMALL_PAGE_SIZE);
571 
572 	res = vm_get_flags(&utc->uctx, va, sz, &vm_flags);
573 	if (res)
574 		return res;
575 	if (vm_flags & VM_FLAG_PERMANENT)
576 		return TEE_ERROR_ACCESS_DENIED;
577 
578 	/*
579 	 * If the segment is a mapping of a part of a file (vm_flags &
580 	 * VM_FLAG_READONLY) it cannot be made writeable as all mapped
581 	 * files are mapped read-only.
582 	 */
583 	if ((vm_flags & VM_FLAG_READONLY) &&
584 	    (prot & (TEE_MATTR_UW | TEE_MATTR_PW)))
585 		return TEE_ERROR_ACCESS_DENIED;
586 
587 	return vm_set_prot(&utc->uctx, va, sz, prot);
588 }
589 
590 static TEE_Result system_remap(struct tee_ta_session *s, uint32_t param_types,
591 			       TEE_Param params[TEE_NUM_PARAMS])
592 {
593 	uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
594 					  TEE_PARAM_TYPE_VALUE_INPUT,
595 					  TEE_PARAM_TYPE_VALUE_INOUT,
596 					  TEE_PARAM_TYPE_VALUE_INPUT);
597 	struct user_ta_ctx *utc = to_user_ta_ctx(s->ctx);
598 	TEE_Result res = TEE_SUCCESS;
599 	uint32_t num_bytes = 0;
600 	uint32_t pad_begin = 0;
601 	uint32_t vm_flags = 0;
602 	uint32_t pad_end = 0;
603 	vaddr_t old_va = 0;
604 	vaddr_t new_va = 0;
605 
606 	if (exp_pt != param_types)
607 		return TEE_ERROR_BAD_PARAMETERS;
608 
609 	num_bytes = params[0].value.a;
610 	old_va = reg_pair_to_64(params[1].value.a, params[1].value.b);
611 	new_va = reg_pair_to_64(params[2].value.a, params[2].value.b);
612 	pad_begin = params[3].value.a;
613 	pad_end = params[3].value.b;
614 
615 	res = vm_get_flags(&utc->uctx, old_va, num_bytes, &vm_flags);
616 	if (res)
617 		return res;
618 	if (vm_flags & VM_FLAG_PERMANENT)
619 		return TEE_ERROR_ACCESS_DENIED;
620 
621 	res = vm_remap(&utc->uctx, &new_va, old_va, num_bytes, pad_begin,
622 		       pad_end);
623 	if (!res)
624 		reg_pair_from_64(new_va, &params[2].value.a,
625 				 &params[2].value.b);
626 
627 	return res;
628 }
629 
630 /* ldelf has the same architecture/register width as the kernel */
631 #ifdef ARM32
632 static const bool is_arm32 = true;
633 #else
634 static const bool is_arm32;
635 #endif
636 
637 static TEE_Result call_ldelf_dlopen(struct user_ta_ctx *utc, TEE_UUID *uuid,
638 				    uint32_t flags)
639 {
640 	uaddr_t usr_stack = utc->ldelf_stack_ptr;
641 	TEE_Result res = TEE_ERROR_GENERIC;
642 	struct dl_entry_arg *arg = NULL;
643 	uint32_t panic_code = 0;
644 	uint32_t panicked = 0;
645 
646 	assert(uuid);
647 
648 	usr_stack -= ROUNDUP(sizeof(*arg), STACK_ALIGNMENT);
649 	arg = (struct dl_entry_arg *)usr_stack;
650 
651 	res = tee_mmu_check_access_rights(&utc->uctx,
652 					  TEE_MEMORY_ACCESS_READ |
653 					  TEE_MEMORY_ACCESS_WRITE |
654 					  TEE_MEMORY_ACCESS_ANY_OWNER,
655 					  (uaddr_t)arg, sizeof(*arg));
656 	if (res) {
657 		EMSG("ldelf stack is inaccessible!");
658 		return res;
659 	}
660 
661 	memset(arg, 0, sizeof(*arg));
662 	arg->cmd = LDELF_DL_ENTRY_DLOPEN;
663 	arg->dlopen.uuid = *uuid;
664 	arg->dlopen.flags = flags;
665 
666 	res = thread_enter_user_mode((vaddr_t)arg, 0, 0, 0,
667 				     usr_stack, utc->dl_entry_func,
668 				     is_arm32, &panicked, &panic_code);
669 	if (panicked) {
670 		EMSG("ldelf dl_entry function panicked");
671 		abort_print_current_ta();
672 		res = TEE_ERROR_TARGET_DEAD;
673 	}
674 	if (!res)
675 		res = arg->ret;
676 
677 	return res;
678 }
679 
680 static TEE_Result call_ldelf_dlsym(struct user_ta_ctx *utc, TEE_UUID *uuid,
681 				   const char *sym, size_t maxlen, vaddr_t *val)
682 {
683 	uaddr_t usr_stack = utc->ldelf_stack_ptr;
684 	TEE_Result res = TEE_ERROR_GENERIC;
685 	struct dl_entry_arg *arg = NULL;
686 	uint32_t panic_code = 0;
687 	uint32_t panicked = 0;
688 	size_t len = strnlen(sym, maxlen);
689 
690 	if (len == maxlen)
691 		return TEE_ERROR_BAD_PARAMETERS;
692 
693 	usr_stack -= ROUNDUP(sizeof(*arg) + len + 1, STACK_ALIGNMENT);
694 	arg = (struct dl_entry_arg *)usr_stack;
695 
696 	res = tee_mmu_check_access_rights(&utc->uctx,
697 					  TEE_MEMORY_ACCESS_READ |
698 					  TEE_MEMORY_ACCESS_WRITE |
699 					  TEE_MEMORY_ACCESS_ANY_OWNER,
700 					  (uaddr_t)arg, sizeof(*arg) + len + 1);
701 	if (res) {
702 		EMSG("ldelf stack is inaccessible!");
703 		return res;
704 	}
705 
706 	memset(arg, 0, sizeof(*arg));
707 	arg->cmd = LDELF_DL_ENTRY_DLSYM;
708 	arg->dlsym.uuid = *uuid;
709 	memcpy(arg->dlsym.symbol, sym, len);
710 	arg->dlsym.symbol[len] = '\0';
711 
712 	res = thread_enter_user_mode((vaddr_t)arg, 0, 0, 0,
713 				     usr_stack, utc->dl_entry_func,
714 				     is_arm32, &panicked, &panic_code);
715 	if (panicked) {
716 		EMSG("ldelf dl_entry function panicked");
717 		abort_print_current_ta();
718 		res = TEE_ERROR_TARGET_DEAD;
719 	}
720 	if (!res) {
721 		res = arg->ret;
722 		if (!res)
723 			*val = arg->dlsym.val;
724 	}
725 
726 	return res;
727 }
728 
729 static TEE_Result system_dlopen(struct tee_ta_session *cs, uint32_t param_types,
730 				TEE_Param params[TEE_NUM_PARAMS])
731 {
732 	uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT,
733 					  TEE_PARAM_TYPE_VALUE_INPUT,
734 					  TEE_PARAM_TYPE_NONE,
735 					  TEE_PARAM_TYPE_NONE);
736 	TEE_Result res = TEE_ERROR_GENERIC;
737 	struct tee_ta_session *s = NULL;
738 	struct user_ta_ctx *utc = NULL;
739 	TEE_UUID *uuid = NULL;
740 	uint32_t flags = 0;
741 
742 	if (exp_pt != param_types)
743 		return TEE_ERROR_BAD_PARAMETERS;
744 
745 	uuid = params[0].memref.buffer;
746 	if (!uuid || params[0].memref.size != sizeof(*uuid))
747 		return TEE_ERROR_BAD_PARAMETERS;
748 
749 	flags = params[1].value.a;
750 
751 	utc = to_user_ta_ctx(cs->ctx);
752 
753 	s = tee_ta_pop_current_session();
754 	res = call_ldelf_dlopen(utc, uuid, flags);
755 	tee_ta_push_current_session(s);
756 
757 	return res;
758 }
759 
760 static TEE_Result system_dlsym(struct tee_ta_session *cs, uint32_t param_types,
761 			       TEE_Param params[TEE_NUM_PARAMS])
762 {
763 	uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT,
764 					  TEE_PARAM_TYPE_MEMREF_INPUT,
765 					  TEE_PARAM_TYPE_VALUE_OUTPUT,
766 					  TEE_PARAM_TYPE_NONE);
767 	TEE_Result res = TEE_ERROR_GENERIC;
768 	struct tee_ta_session *s = NULL;
769 	struct user_ta_ctx *utc = NULL;
770 	const char *sym = NULL;
771 	TEE_UUID *uuid = NULL;
772 	size_t maxlen = 0;
773 	vaddr_t va = 0;
774 
775 	if (exp_pt != param_types)
776 		return TEE_ERROR_BAD_PARAMETERS;
777 
778 	uuid = params[0].memref.buffer;
779 	if (uuid && params[0].memref.size != sizeof(*uuid))
780 		return TEE_ERROR_BAD_PARAMETERS;
781 
782 	sym = params[1].memref.buffer;
783 	if (!sym)
784 		return TEE_ERROR_BAD_PARAMETERS;
785 	maxlen = params[1].memref.size;
786 
787 	utc = to_user_ta_ctx(cs->ctx);
788 
789 	s = tee_ta_pop_current_session();
790 	res = call_ldelf_dlsym(utc, uuid, sym, maxlen, &va);
791 	tee_ta_push_current_session(s);
792 
793 	if (!res)
794 		reg_pair_from_64(va, &params[2].value.a, &params[2].value.b);
795 
796 	return res;
797 }
798 
799 static TEE_Result system_get_tpm_event_log(uint32_t param_types,
800 					   TEE_Param params[TEE_NUM_PARAMS])
801 {
802 	uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_OUTPUT,
803 					  TEE_PARAM_TYPE_NONE,
804 					  TEE_PARAM_TYPE_NONE,
805 					  TEE_PARAM_TYPE_NONE);
806 	size_t size = 0;
807 	TEE_Result res = TEE_SUCCESS;
808 
809 	if (exp_pt != param_types)
810 		return TEE_ERROR_BAD_PARAMETERS;
811 
812 	size = params[0].memref.size;
813 	res = tpm_get_event_log(params[0].memref.buffer, &size);
814 	params[0].memref.size = size;
815 
816 	return res;
817 }
818 
819 static TEE_Result open_session(uint32_t param_types __unused,
820 			       TEE_Param params[TEE_NUM_PARAMS] __unused,
821 			       void **sess_ctx)
822 {
823 	struct tee_ta_session *s = NULL;
824 	struct system_ctx *ctx = NULL;
825 
826 	/* Check that we're called from a user TA */
827 	s = tee_ta_get_calling_session();
828 	if (!s)
829 		return TEE_ERROR_ACCESS_DENIED;
830 	if (!is_user_ta_ctx(s->ctx))
831 		return TEE_ERROR_ACCESS_DENIED;
832 
833 	ctx = calloc(1, sizeof(*ctx));
834 	if (!ctx)
835 		return TEE_ERROR_OUT_OF_MEMORY;
836 
837 	*sess_ctx = ctx;
838 
839 	return TEE_SUCCESS;
840 }
841 
842 static void close_session(void *sess_ctx)
843 {
844 	struct system_ctx *ctx = sess_ctx;
845 
846 	handle_db_destroy(&ctx->db, ta_bin_close);
847 	free(ctx);
848 }
849 
850 static TEE_Result invoke_command(void *sess_ctx, uint32_t cmd_id,
851 				 uint32_t param_types,
852 				 TEE_Param params[TEE_NUM_PARAMS])
853 {
854 	struct tee_ta_session *s = tee_ta_get_calling_session();
855 
856 	switch (cmd_id) {
857 	case PTA_SYSTEM_ADD_RNG_ENTROPY:
858 		return system_rng_reseed(s, param_types, params);
859 	case PTA_SYSTEM_DERIVE_TA_UNIQUE_KEY:
860 		return system_derive_ta_unique_key(s, param_types, params);
861 	case PTA_SYSTEM_MAP_ZI:
862 		return system_map_zi(s, param_types, params);
863 	case PTA_SYSTEM_UNMAP:
864 		return system_unmap(s, param_types, params);
865 	case PTA_SYSTEM_OPEN_TA_BINARY:
866 		return system_open_ta_binary(sess_ctx, param_types, params);
867 	case PTA_SYSTEM_CLOSE_TA_BINARY:
868 		return system_close_ta_binary(sess_ctx, param_types, params);
869 	case PTA_SYSTEM_MAP_TA_BINARY:
870 		return system_map_ta_binary(sess_ctx, s, param_types, params);
871 	case PTA_SYSTEM_COPY_FROM_TA_BINARY:
872 		return system_copy_from_ta_binary(sess_ctx, param_types,
873 						  params);
874 	case PTA_SYSTEM_SET_PROT:
875 		return system_set_prot(s, param_types, params);
876 	case PTA_SYSTEM_REMAP:
877 		return system_remap(s, param_types, params);
878 	case PTA_SYSTEM_DLOPEN:
879 		return system_dlopen(s, param_types, params);
880 	case PTA_SYSTEM_DLSYM:
881 		return system_dlsym(s, param_types, params);
882 	case PTA_SYSTEM_GET_TPM_EVENT_LOG:
883 		return system_get_tpm_event_log(param_types, params);
884 	default:
885 		break;
886 	}
887 
888 	return TEE_ERROR_NOT_IMPLEMENTED;
889 }
890 
891 pseudo_ta_register(.uuid = PTA_SYSTEM_UUID, .name = "system.pta",
892 		   .flags = PTA_DEFAULT_FLAGS | TA_FLAG_CONCURRENT,
893 		   .open_session_entry_point = open_session,
894 		   .close_session_entry_point = close_session,
895 		   .invoke_command_entry_point = invoke_command);
896