bytecodealliance / bytecodealliance/wasmtime

Signal handler violates async-signal-safety by calling malloc via TLS access

Open
#12,787 6 comments 0 reactions 0 assignees View on GitHub
Dominant language
Rust
Stars
18.6k
Forks
1.8k
Avg merge
1d 18h
Merged PRs (30d)
126

Description

## Summary

Wasmtime's SIGSEGV/SIGBUS trap handler (trap_handler in crates/wasmtime/src/runtime/vm/sys/unix/signals.rs) violates POSIX async-signal-safety requirements by:

1. Accessing thread-local storage via tls::with(), which can trigger __tls_get_addr
2. __tls_get_addr calls malloc() on first TLS access for a thread
3. malloc() is not async-signal-safe and can deadlock if the interrupted code was holding malloc's internal lock

## Reproduction

This causes deadlocks when wasmtime is used alongside other software that:
- Installs its own SIGSEGV handlers (e.g., Java profilers using safefetch)
- Triggers SIGSEGV intentionally for safe memory probing

The deadlock occurs when:
1. Thread A is inside malloc() holding its internal lock
2. SIGSEGV arrives (from safefetch or other intentional fault)
3. Wasmtime's trap_handler runs
4. tls::with() → __tls_get_addr → malloc()
5. malloc() tries to acquire the lock already held → DEADLOCK

### Stack trace from deadlock

```
#7 __tls_get_addr () at ../sysdeps/x86_64/tls_get_addr.S:55
#8 wasmtime_runtime::traphandlers::tls::raw::get ()
#9 wasmtime_runtime::traphandlers::unix::trap_handler ()
#10
#11 safefetch64_impl () // intentional SIGSEGV for safe memory access
...
#27 sysmalloc ()
#28 _int_malloc ()
#29 __GI___libc_malloc () // original malloc call that holds the lock
```

The code comment acknowledges this

From signals.rs:
"The main current requirement of the signal handler in terms of stack space is that malloc/realloc are called to create a Backtrace of wasm frames."

## Suggested fix
1. Use tls_eager_initialize() on thread creation to ensure TLS is initialized before any signal can arrive
2. Consider using a signal-safe TLS mechanism (e.g., dedicated pthread key with pre-allocated storage)
3. Avoid any allocation in the signal handler fast path - defer backtrace creation

## Environment
- wasmtime-jni 0.19.0
- Linux x86_64
- glibc

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.