From 1bbc50d1384ae466d93a1565fd288f455005605c Mon Sep 17 00:00:00 2001 From: JingMatrix Date: Wed, 28 Jan 2026 18:04:02 +0100 Subject: [PATCH] Prevent recursion when configured to intercept system UID (#100) When the TEESimulator is configured to intercept UID 1000, accessing the `lazy` `bootKey` property causes a StackOverflowError. The property's initializer sends a key generation request (UID 0) to probe real hardware. Previously, the C++ layer hijacked this request and spoofed it to UID 1000. This sent the request back to the Kotlin interceptor (if configured so), which attempted to access `bootKey` again to build the response, creating an infinite loop. This change spoofs UID 0 requests to 1000 (to pass Keystore permissions) but explicitly bypasses hijacking, ensuring the probe request hits the real hardware. --- app/src/main/cpp/binder_interceptor.cpp | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/app/src/main/cpp/binder_interceptor.cpp b/app/src/main/cpp/binder_interceptor.cpp index 43b9a68..4a337b9 100644 --- a/app/src/main/cpp/binder_interceptor.cpp +++ b/app/src/main/cpp/binder_interceptor.cpp @@ -359,9 +359,15 @@ void inspectAndRewriteTransaction(binder_transaction_data *txn_data) { info.transaction_code = intercept::kBackdoorCode; info.target_binder = nullptr; hijack = true; - } - // Check 2: Normal interception based on registry of monitored binders - else { + // Check 2: Spoof uid of KeyStore requests from the daemon to bypass permission check + } else if (txn_data->sender_euid == 0) { + // The kernel driver fills sender_euid. + // libbinder.so trusts this value to populate IPCThreadState. + txn_data->sender_euid = 1000; + LOGV("[Hook] Spoofing UID for transaction: 0 -> %d", txn_data->sender_euid); + hijack = false; // Never hijack to avoid recursion + // Check 3: Normal interception based on registry of monitored binders + } else { // Safe casting based on Binder driver ABI RefBase::weakref_type *weak_ref = reinterpret_cast(txn_data->target.ptr); @@ -386,15 +392,6 @@ void inspectAndRewriteTransaction(binder_transaction_data *txn_data) { } if (hijack) { - // The kernel driver fills sender_euid. libbinder trusts this value - // to populate IPCThreadState. By changing it here, we fool the - // entire process (including the TEE implementation) into thinking - // the call came from system (1000). - if (txn_data->sender_euid == 0) { - LOGV("[Hook] Spoofing UID for transaction: 0 -> 1000"); - txn_data->sender_euid = 1000; - } - uint64_t tx_id = ++g_transaction_id_counter; info.transaction_id = tx_id;