Vulnerability: Linaro/OP-TEE OP-TEE 3.3.0 and earlier is affected by: Buffer Overflow. The impact is: Code execution in the context of TEE core (kernel). The component is: optee_os. The fixed version is: 3.4.0 and later.
Vulnerability ID: CVE-2019-1010298
CWE: CWE-787
Severity score: 10
Project: https://github.com/OP-TEE/optee_os
Published: 2019-07-15
File: core/tee/tee_svc_cryp.c
Commit message: svc: check for allocation overflow in crypto calls part 2

Without checking for overflow there is a risk of allocating a buffer
with size smaller than anticipated and as a consequence of that it might
lead to a heap based overflow with attacker controlled data written
outside the boundaries of the buffer.

Fixes: OP-TEE-2018-0011: "Integer overflow in crypto system calls (x2)"

Signed-off-by: Joakim Bech <joakim.bech@linaro.org>
Tested-by: Joakim Bech <joakim.bech@linaro.org> (QEMU v7, v8)
Reviewed-by: Jens Wiklander <jens.wiklander@linaro.org>
Reported-by: Riscure <inforequest@riscure.com>
Reported-by: Alyssa Milburn <a.a.milburn@vu.nl>
Acked-by: Etienne Carriere <etienne.carriere@linaro.org>
Commit author: Joakim Bech

Vulnerable version (before fix):
 TEE_Result syscall_asymm_operate(unsigned long state, 	if (res != TEE_SUCCESS) 		return res;  	params = malloc(sizeof(TEE_Attribute) * num_params); 	if (!params) 		return TEE_ERROR_OUT_OF_MEMORY; 	res = copy_in_attrs(utc, usr_params, num_params, params); TEE_Result syscall_asymm_verify(unsigned long state, 	if (res != TEE_SUCCESS) 		return res;  	params = malloc(sizeof(TEE_Attribute) * num_params); 	if (!params) 		return TEE_ERROR_OUT_OF_MEMORY; 	res = copy_in_attrs(utc, usr_params, num_params, params);

Fixed version (after fix):
 TEE_Result syscall_asymm_operate(unsigned long state, 	if (res != TEE_SUCCESS) 		return res;  	size_t alloc_size = 0;  	if (MUL_OVERFLOW(sizeof(TEE_Attribute), num_params, &alloc_size)) 		return TEE_ERROR_OVERFLOW;  	params = malloc(alloc_size); 	if (!params) 		return TEE_ERROR_OUT_OF_MEMORY; 	res = copy_in_attrs(utc, usr_params, num_params, params); TEE_Result syscall_asymm_verify(unsigned long state, 	if (res != TEE_SUCCESS) 		return res;  	size_t alloc_size = 0;  	if (MUL_OVERFLOW(sizeof(TEE_Attribute), num_params, &alloc_size)) 		return TEE_ERROR_OVERFLOW;  	params = malloc(alloc_size); 	if (!params) 		return TEE_ERROR_OUT_OF_MEMORY; 	res = copy_in_attrs(utc, usr_params, num_params, params);

Patch:
patch: @@ -3274,7 +3274,12 @@ TEE_Result syscall_asymm_operate(unsigned long state,
 	if (res != TEE_SUCCESS)
 		return res;
 
-	params = malloc(sizeof(TEE_Attribute) * num_params);
+	size_t alloc_size = 0;
+
+	if (MUL_OVERFLOW(sizeof(TEE_Attribute), num_params, &alloc_size))
+		return TEE_ERROR_OVERFLOW;
+
+	params = malloc(alloc_size);
 	if (!params)
 		return TEE_ERROR_OUT_OF_MEMORY;
 	res = copy_in_attrs(utc, usr_params, num_params, params);
@@ -3436,7 +3441,12 @@ TEE_Result syscall_asymm_verify(unsigned long state,
 	if (res != TEE_SUCCESS)
 		return res;
 
-	params = malloc(sizeof(TEE_Attribute) * num_params);
+	size_t alloc_size = 0;
+
+	if (MUL_OVERFLOW(sizeof(TEE_Attribute), num_params, &alloc_size))
+		return TEE_ERROR_OVERFLOW;
+
+	params = malloc(alloc_size);
 	if (!params)
 		return TEE_ERROR_OUT_OF_MEMORY;
 	res = copy_in_attrs(utc, usr_params, num_params, params);
path: core/tee/tee_svc_cryp.c