From d1d1791f826491d2211fd78593483e8cf48a18f2 Mon Sep 17 00:00:00 2001 From: Aleksandr Iashchenko Date: Fri, 7 Nov 2025 16:18:20 +0100 Subject: [PATCH] xtest/os_test: add ASAN self-tests (regression 1042) Add regression case 1042 to exercise ASAN in TA: - stack overflow - global (ro/static/regular) - malloc (including overflow) - use-after-free - memcpy/memset bounds Wire new commands in os_test TA and expose entry points. The host test opens os_test TA and runs the subcases, skipping gracefully when ASAN is not supported (CFG_TA_SANITIZE_KADDRESS=n). Signed-off-by: Aleksandr Iashchenko --- host/xtest/regression_1000.c | 54 ++++++++++++++ ta/os_test/include/os_test.h | 5 ++ ta/os_test/include/ta_os_test.h | 5 ++ ta/os_test/os_test.c | 120 ++++++++++++++++++++++++++++++++ ta/os_test/ta_entry.c | 10 +++ 5 files changed, 194 insertions(+) diff --git a/host/xtest/regression_1000.c b/host/xtest/regression_1000.c index a4277890d..da5c444e2 100644 --- a/host/xtest/regression_1000.c +++ b/host/xtest/regression_1000.c @@ -3421,3 +3421,57 @@ static void xtest_tee_test_1041(ADBG_Case_t *c) Do_ADBG_Log("Expected \"%s\" to be a character device", fname); } ADBG_CASE_DEFINE(regression, 1041, xtest_tee_test_1041, "Test fTPM sanity"); + +static void xtest_tee_test_1042(ADBG_Case_t *c) +{ + TEEC_Session session = { }; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t ret_orig = 0; + TEEC_Result res = TEEC_SUCCESS; + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_NONE, TEEC_NONE, TEEC_NONE, + TEEC_NONE); + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + xtest_teec_open_session(&session, &os_test_ta_uuid, + NULL, &ret_orig))) + return; + Do_ADBG_BeginSubCase(c, "ASAN stack"); + + res = TEEC_InvokeCommand(&session, TA_OS_TEST_CMD_ASAN_STACK, + &op, &ret_orig); + if (res == TEEC_ERROR_NOT_SUPPORTED) { + Do_ADBG_Log("Binary doesn't support ASAN - skip tests"); + goto out; + } + ADBG_EXPECT_TEEC_SUCCESS(c, res); + Do_ADBG_EndSubCase(c, "ASAN stack"); + + Do_ADBG_BeginSubCase(c, "ASAN global"); + res = TEEC_InvokeCommand(&session, TA_OS_TEST_CMD_ASAN_GLOBAL, + &op, &ret_orig); + ADBG_EXPECT_TEEC_SUCCESS(c, res); + Do_ADBG_EndSubCase(c, "ASAN global"); + Do_ADBG_BeginSubCase(c, "ASAN malloc"); + res = TEEC_InvokeCommand(&session, TA_OS_TEST_CMD_ASAN_MALLOC, + &op, &ret_orig); + ADBG_EXPECT_TEEC_SUCCESS(c, res); + Do_ADBG_EndSubCase(c, "ASAN malloc"); + + Do_ADBG_BeginSubCase(c, "ASAN use after free"); + res = TEEC_InvokeCommand(&session, TA_OS_TEST_CMD_ASAN_UAF, + &op, &ret_orig); + ADBG_EXPECT_TEEC_SUCCESS(c, res); + Do_ADBG_EndSubCase(c, "ASAN use after free"); + + Do_ADBG_BeginSubCase(c, "ASAN memory funcs"); + res = TEEC_InvokeCommand(&session, TA_OS_TEST_CMD_ASAN_MEMFUNC, + &op, &ret_orig); + ADBG_EXPECT_TEEC_SUCCESS(c, res); + Do_ADBG_EndSubCase(c, "ASAN memory funcs"); + +out: + TEEC_CloseSession(&session); +} +ADBG_CASE_DEFINE(regression, 1042, xtest_tee_test_1042, + "Test ASAN (Memory address sanitizer)"); diff --git a/ta/os_test/include/os_test.h b/ta/os_test/include/os_test.h index 62c237852..cddcc604d 100644 --- a/ta/os_test/include/os_test.h +++ b/ta/os_test/include/os_test.h @@ -46,5 +46,10 @@ TEE_Result ta_entry_memtag_use_after_free(void); TEE_Result ta_entry_memtag_invalid_tag(void); TEE_Result ta_entry_memtag_double_free(void); TEE_Result ta_entry_memtag_buffer_overrun(void); +TEE_Result ta_entry_asan_stack(void); +TEE_Result ta_entry_asan_global(void); +TEE_Result ta_entry_asan_malloc(void); +TEE_Result ta_entry_asan_memfunc(void); +TEE_Result ta_entry_asan_uaf(void); #endif /*OS_TEST_H */ diff --git a/ta/os_test/include/ta_os_test.h b/ta/os_test/include/ta_os_test.h index 93785e2d9..a6b71a699 100644 --- a/ta/os_test/include/ta_os_test.h +++ b/ta/os_test/include/ta_os_test.h @@ -47,5 +47,10 @@ #define TA_OS_TEST_CMD_MEMTAG_DOUBLE_FREE 35 #define TA_OS_TEST_CMD_MEMTAG_BUFFER_OVERRUN 36 #define TA_OS_TEST_CMD_TA2TA_MEMREF_SIZE0 37 +#define TA_OS_TEST_CMD_ASAN_STACK 38 +#define TA_OS_TEST_CMD_ASAN_GLOBAL 39 +#define TA_OS_TEST_CMD_ASAN_MALLOC 40 +#define TA_OS_TEST_CMD_ASAN_UAF 41 +#define TA_OS_TEST_CMD_ASAN_MEMFUNC 42 #endif /*TA_OS_TEST_H */ diff --git a/ta/os_test/os_test.c b/ta/os_test/os_test.c index 6833e0c3e..e7ec254e8 100644 --- a/ta/os_test/os_test.c +++ b/ta/os_test/os_test.c @@ -4,6 +4,7 @@ * All rights reserved. * Copyright (c) 2022, Linaro Limited. */ +#include #include #include #include @@ -1601,3 +1602,122 @@ TEE_Result ta_entry_memtag_buffer_overrun(void) TEE_Free(p); return TEE_ERROR_GENERIC; } + +#ifdef CFG_TA_SANITIZE_KADDRESS +TEE_Result ta_entry_asan_stack(void) +{ + TEE_Result rc = TEE_SUCCESS; + struct asan_test_ctx ctx = {0}; + + asan_test_init(&ctx); + if (asan_call_test(&ctx, asan_test_stack, "stack overflow")) { + rc = TEE_ERROR_GENERIC; + } + asan_test_deinit(&ctx); + return rc; +} + +TEE_Result ta_entry_asan_global(void) +{ + TEE_Result rc = TEE_SUCCESS; + struct asan_test_ctx ctx = {0}; + + asan_test_init(&ctx); + if (asan_call_test(&ctx, asan_test_global_stat, "global static")) { + rc = TEE_ERROR_GENERIC; + goto out; + } + if (asan_call_test(&ctx, asan_test_global_ro, "global ro")) { + rc = TEE_ERROR_GENERIC; + goto out; + } + if (asan_call_test(&ctx, asan_test_global, "global")) { + rc = TEE_ERROR_GENERIC; + goto out; + } +out: + asan_test_deinit(&ctx); + return rc; +} + +TEE_Result ta_entry_asan_malloc(void) +{ + TEE_Result rc = TEE_SUCCESS; + struct asan_test_ctx ctx = {0}; + + asan_test_init(&ctx); + if (asan_call_test(&ctx, asan_test_malloc, "malloc")) { + rc = TEE_ERROR_GENERIC; + goto out; + } + if (asan_call_test(&ctx, asan_test_malloc2, "malloc2")) { + rc = TEE_ERROR_GENERIC; + goto out; + } +out: + asan_test_deinit(&ctx); + return rc; +} + +TEE_Result ta_entry_asan_uaf(void) +{ + TEE_Result rc = TEE_SUCCESS; + struct asan_test_ctx ctx = {0}; + + asan_test_init(&ctx); + if (asan_call_test(&ctx, asan_test_use_after_free, "use after free")) { + rc = TEE_ERROR_GENERIC; + } + asan_test_deinit(&ctx); + return rc; +} + +TEE_Result ta_entry_asan_memfunc(void) +{ + TEE_Result rc = TEE_SUCCESS; + struct asan_test_ctx ctx = {0}; + + asan_test_init(&ctx); + if (asan_call_test(&ctx, asan_test_memcpy_dst, "memcpy dst")) { + rc = TEE_ERROR_GENERIC; + goto out; + } + if (asan_call_test(&ctx, asan_test_memcpy_src, "memcpy src")) { + rc = TEE_ERROR_GENERIC; + goto out; + } + if (asan_call_test(&ctx, asan_test_memset, "memset")) { + rc = TEE_ERROR_GENERIC; + goto out; + } +out: + asan_test_deinit(&ctx); + return rc; +} + +#else +TEE_Result ta_entry_asan_stack(void) +{ + return TEE_ERROR_NOT_SUPPORTED; +} + +TEE_Result ta_entry_asan_global(void) +{ + return TEE_ERROR_NOT_SUPPORTED; +} + +TEE_Result ta_entry_asan_malloc(void) +{ + return TEE_ERROR_NOT_SUPPORTED; +} + +TEE_Result ta_entry_asan_memfunc(void) +{ + return TEE_ERROR_NOT_SUPPORTED; +} + +TEE_Result ta_entry_asan_uaf(void) +{ + return TEE_ERROR_NOT_SUPPORTED; +} +#endif diff --git a/ta/os_test/ta_entry.c b/ta/os_test/ta_entry.c index 56f3ef0ae..069e39ac8 100644 --- a/ta/os_test/ta_entry.c +++ b/ta/os_test/ta_entry.c @@ -180,6 +180,16 @@ TEE_Result TA_InvokeCommandEntryPoint(void *pSessionContext, case TA_OS_TEST_CMD_ATTESTATION: return ta_entry_attestation(nParamTypes, pParams); + case TA_OS_TEST_CMD_ASAN_STACK: + return ta_entry_asan_stack(); + case TA_OS_TEST_CMD_ASAN_GLOBAL: + return ta_entry_asan_global(); + case TA_OS_TEST_CMD_ASAN_MALLOC: + return ta_entry_asan_malloc(); + case TA_OS_TEST_CMD_ASAN_UAF: + return ta_entry_asan_uaf(); + case TA_OS_TEST_CMD_ASAN_MEMFUNC: + return ta_entry_asan_memfunc(); default: return TEE_ERROR_BAD_PARAMETERS;