Skip to content

Force the emutls runtime into both interceptors and allow the staging fallback - #320

Merged
JingMatrix merged 1 commit into
devfrom
fix/emutls-injection-fallback
Oct 21, 2026
Merged

JingMatrix merged 1 commit into
devfrom
fix/emutls-injection-fallback

Conversation

@JingMatrix

Copy link
Copy Markdown
Owner

Injection on an Infinix X695C (Android 11, sdk=30, keystore1) fails at dlopen: the linker demands __emutls_get_address, which /system/bin/keystore does not export. The symbol is called by the NDK static libc++abi (cxa_thread_atexit.cpp.o, compiled with emulated TLS) and the only definition lives in Rust compiler_builtins emutls.o inside libteesim_km.a. Without --whole-archive the linker sees the definition as weak, drops it, and the version script turns the leftover reference into an undefined dynamic import. BIND_NOW forces resolution at dlopen time, so keystore never reaches entry and the inject loop retries forever.

Wrap the Rust archive in --whole-archive/--no-whole-archive on both teesim_keymint and teesim_keystore so emutls.o is always linked; --gc-sections still drops unreachable code. The bug has been latent since 7285ffc (the first interceptor commit) but only manifests on keystore1 targets where the host process has no emutls runtime of its own.

The staging fallback (inject_via_staging, /data/local/tmp) also failed on the same device: keystore was denied { search } on shell_data_file by SELinux. Add the dir and file permissions so the fallback path can succeed when the fd-passing primary path is blocked.

… fallback

Injection on an Infinix X695C (Android 11, sdk=30, keystore1) fails at
dlopen: the linker demands __emutls_get_address, which /system/bin/keystore
does not export. The symbol is called by the NDK static libc++abi
(cxa_thread_atexit.cpp.o, compiled with emulated TLS) and the only
definition lives in Rust compiler_builtins emutls.o inside libteesim_km.a.
Without --whole-archive the linker sees the definition as weak, drops it,
and the version script turns the leftover reference into an undefined
dynamic import. BIND_NOW forces resolution at dlopen time, so keystore
never reaches entry and the inject loop retries forever.

Wrap the Rust archive in --whole-archive/--no-whole-archive on both
teesim_keymint and teesim_keystore so emutls.o is always linked;
--gc-sections still drops unreachable code. The bug has been latent since
7285ffc (the first interceptor commit) but only manifests on keystore1
targets where the host process has no emutls runtime of its own.

The staging fallback (inject_via_staging, /data/local/tmp) also failed on
the same device: keystore was denied search on shell_data_file by SELinux.
Add the dir and file permissions so the fallback path can succeed when the
fd-passing primary path is blocked.
@JingMatrix
JingMatrix merged commit fcf1738 into dev Oct 21, 2026
1 check passed
Zhanfg added a commit to Zhanfg/TEESimulator that referenced this pull request Oct 22, 2026
…ingMatrix#320)

Adapt fcf1738 to the OnePlus/zh-CN integration candidate. No routing or OTA changes.
@JingMatrix
JingMatrix deleted the fix/emutls-injection-fallback branch October 24, 2026 09:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant