From 70b613102ce72808f6a0ad9f6f97f0545fd6ad02 Mon Sep 17 00:00:00 2001 From: Jerome Forissier Date: Tue, 29 Jan 2019 17:44:51 +0100 Subject: [PATCH] core: scrub user-tainted kernel heap memory before freeing it Some syscalls can be used to poison kernel heap memory. Data copied from userland is not wiped when the syscall returns. For instance, when doing syscall_log() one can copy arbitrary data of variable length onto kernel memory. When free() is called, the block is returned to the memory pool, tainted with that userland data. This might be used in combination with some other vulnerability to produce an exploit. This patch uses free_wipe() to clear the buffers that have been used to store user-provided data before returning them to the heap. Signed-off-by: Jerome Forissier Reported-by: Bastien Simondi [1.4] Reviewed-by: Jens Wiklander Reviewed-by: Joakim Bech Acked-by: Etienne Carriere --- core/tee/tee_svc.c | 38 +++++++++++++++++++------------------- core/tee/tee_svc_cryp.c | 11 ++++++----- 2 files changed, 25 insertions(+), 24 deletions(-) diff --git a/core/tee/tee_svc.c b/core/tee/tee_svc.c index a7d4be3d850..8915cb52fc4 100644 --- a/core/tee/tee_svc.c +++ b/core/tee/tee_svc.c @@ -2,25 +2,25 @@ /* * Copyright (c) 2014, STMicroelectronics International N.V. */ -#include -#include +#include +#include #include -#include +#include #include -#include -#include -#include -#include -#include -#include #include - -#include -#include #include -#include -#include +#include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include vaddr_t tee_svc_uref_base; @@ -41,7 +41,7 @@ void syscall_log(const void *buf __maybe_unused, size_t len __maybe_unused) trace_ext_puts(kbuf); } - free(kbuf); + free_wipe(kbuf); #endif } @@ -490,7 +490,7 @@ TEE_Result syscall_get_property_name_to_index(unsigned long prop_set, } out: - free(kname); + free_wipe(kname); return res; } @@ -793,9 +793,9 @@ TEE_Result syscall_open_ta_session(const TEE_UUID *dest, tee_svc_copy_to_user(ret_orig, &ret_o, sizeof(ret_o)); out_free_only: - free(param); - free(uuid); - free(clnt_id); + free_wipe(param); + free_wipe(uuid); + free_wipe(clnt_id); return res; } diff --git a/core/tee/tee_svc_cryp.c b/core/tee/tee_svc_cryp.c index 46879ab810c..860617b4bf6 100644 --- a/core/tee/tee_svc_cryp.c +++ b/core/tee/tee_svc_cryp.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -1597,7 +1598,7 @@ TEE_Result syscall_cryp_obj_populate(unsigned long obj, o->info.handleFlags |= TEE_HANDLE_FLAG_INITIALIZED; out: - free(attrs); + free_wipe(attrs); return res; } @@ -1874,7 +1875,7 @@ TEE_Result syscall_obj_generate_key(unsigned long obj, unsigned long key_size, } out: - free(params); + free_wipe(params); if (res == TEE_SUCCESS) { o->info.keySize = key_size; o->info.handleFlags |= TEE_HANDLE_FLAG_INITIALIZED; @@ -2916,7 +2917,7 @@ TEE_Result syscall_cryp_derive_key(unsigned long state, res = TEE_ERROR_NOT_SUPPORTED; out: - free(params); + free_wipe(params); return res; } @@ -3402,7 +3403,7 @@ TEE_Result syscall_asymm_operate(unsigned long state, } out: - free(params); + free_wipe(params); if (res == TEE_SUCCESS || res == TEE_ERROR_SHORT_BUFFER) { TEE_Result res2 = put_user_u64(dst_len, dlen); @@ -3523,6 +3524,6 @@ TEE_Result syscall_asymm_verify(unsigned long state, } out: - free(params); + free_wipe(params); return res; }