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)