core: system_pta: refuse changing kernel mappings

Adds checks in system_unmap(), system_set_prot() and system_remap() to
refuse making changes to kernel mappings.

Acked-by: Pipat Methavanitpong <pipat.methavanitpong@linaro.org>
Reviewed-by: Jerome Forissier <jerome@forissier.org>
Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
diff --git a/core/pta/system.c b/core/pta/system.c
index 34530cc..6b60141 100644
--- a/core/pta/system.c
+++ b/core/pta/system.c
@@ -183,6 +183,11 @@
 					  TEE_PARAM_TYPE_VALUE_INPUT,
 					  TEE_PARAM_TYPE_NONE,
 					  TEE_PARAM_TYPE_NONE);
+	struct user_ta_ctx *utc = to_user_ta_ctx(s->ctx);
+	TEE_Result res = TEE_SUCCESS;
+	uint32_t vm_flags = 0;
+	vaddr_t va = 0;
+	size_t sz = 0;
 
 	if (exp_pt != param_types)
 		return TEE_ERROR_BAD_PARAMETERS;
@@ -190,9 +195,16 @@
 	if (params[0].value.b)
 		return TEE_ERROR_BAD_PARAMETERS;
 
-	return vm_unmap(&to_user_ta_ctx(s->ctx)->uctx,
-			reg_pair_to_64(params[1].value.a, params[1].value.b),
-			ROUNDUP(params[0].value.a, SMALL_PAGE_SIZE));
+	va = reg_pair_to_64(params[1].value.a, params[1].value.b);
+	sz = ROUNDUP(params[0].value.a, SMALL_PAGE_SIZE);
+
+	res = vm_get_flags(&utc->uctx, va, sz, &vm_flags);
+	if (res)
+		return res;
+	if (vm_flags & VM_FLAG_PERMANENT)
+		return TEE_ERROR_ACCESS_DENIED;
+
+	return vm_unmap(&to_user_ta_ctx(s->ctx)->uctx, va, sz);
 }
 
 static void ta_bin_close(void *ptr)
@@ -559,6 +571,8 @@
 	res = vm_get_flags(&utc->uctx, va, sz, &vm_flags);
 	if (res)
 		return res;
+	if (vm_flags & VM_FLAG_PERMANENT)
+		return TEE_ERROR_ACCESS_DENIED;
 
 	/*
 	 * If the segment is a mapping of a part of a file (vm_flags &
@@ -583,6 +597,7 @@
 	TEE_Result res = TEE_SUCCESS;
 	uint32_t num_bytes = 0;
 	uint32_t pad_begin = 0;
+	uint32_t vm_flags = 0;
 	uint32_t pad_end = 0;
 	vaddr_t old_va = 0;
 	vaddr_t new_va = 0;
@@ -596,6 +611,12 @@
 	pad_begin = params[3].value.a;
 	pad_end = params[3].value.b;
 
+	res = vm_get_flags(&utc->uctx, old_va, num_bytes, &vm_flags);
+	if (res)
+		return res;
+	if (vm_flags & VM_FLAG_PERMANENT)
+		return TEE_ERROR_ACCESS_DENIED;
+
 	res = vm_remap(&utc->uctx, &new_va, old_va, num_bytes, pad_begin,
 		       pad_end);
 	if (!res)