11#include " libraryPatcher.h"
22
33#ifdef __linux__
4+ #include " counters.h"
45#include " profiler.h"
56#include " vmStructs.h"
67#include " guards.h"
@@ -17,6 +18,8 @@ SpinLock LibraryPatcher::_lock;
1718const char * LibraryPatcher::_profiler_name = nullptr ;
1819PatchEntry LibraryPatcher::_patched_entries[MAX_NATIVE_LIBS ];
1920int LibraryPatcher::_size = 0 ;
21+ PatchEntry LibraryPatcher::_sigaction_entries[MAX_NATIVE_LIBS ];
22+ int LibraryPatcher::_sigaction_size = 0 ;
2023
2124void LibraryPatcher::initialize () {
2225 if (_profiler_name == nullptr ) {
@@ -238,8 +241,59 @@ void LibraryPatcher::patch_pthread_create() {
238241 }
239242 }
240243}
241- #endif // __linux__
242244
245+ // Patch sigaction in all libraries to prevent any library from overwriting
246+ // our SIGSEGV/SIGBUS handlers. This protects against misbehaving libraries
247+ // (like wasmtime) that install broken signal handlers calling malloc().
248+ void LibraryPatcher::patch_sigaction_in_library (CodeCache* lib) {
249+ if (lib->name () == nullptr ) return ;
250+ if (_profiler_name == nullptr ) return ; // Not initialized yet
251+
252+ // Don't patch ourselves
253+ char path[PATH_MAX ];
254+ char * resolved_path = realpath (lib->name (), path);
255+ if (resolved_path != nullptr && strcmp (resolved_path, _profiler_name) == 0 ) {
256+ return ;
257+ }
258+
259+ // Note: We intentionally patch sanitizer libraries (libasan, libtsan, libubsan) here.
260+ // This keeps our handler on top for recoverable SIGSEGVs (e.g., safefetch) while
261+ // still chaining to the sanitizer's handler for unexpected crashes.
262+
263+ void ** sigaction_location = (void **)lib->findImport (im_sigaction);
264+ if (sigaction_location == nullptr ) {
265+ return ;
266+ }
267+
268+ // Check if already patched or array is full
269+ if (_sigaction_size >= MAX_NATIVE_LIBS ) {
270+ return ;
271+ }
272+ for (int index = 0 ; index < _sigaction_size; index++) {
273+ if (_sigaction_entries[index]._lib == lib) {
274+ return ;
275+ }
276+ }
243277
278+ void * hook = OS::getSigactionHook ();
279+ _sigaction_entries[_sigaction_size]._lib = lib;
280+ _sigaction_entries[_sigaction_size]._location = sigaction_location;
281+ _sigaction_entries[_sigaction_size]._func = (void *)__atomic_load_n (sigaction_location, __ATOMIC_RELAXED);
282+ __atomic_store_n (sigaction_location, hook, __ATOMIC_RELAXED);
283+ _sigaction_size++;
284+ Counters::increment (SIGACTION_PATCHED_LIBS );
285+ }
244286
287+ void LibraryPatcher::patch_sigaction () {
288+ const CodeCacheArray& native_libs = Libraries::instance ()->native_libs ();
289+ int num_of_libs = native_libs.count ();
290+ ExclusiveLockGuard locker (&_lock);
291+ for (int index = 0 ; index < num_of_libs; index++) {
292+ CodeCache* lib = native_libs.at (index);
293+ if (lib != nullptr ) {
294+ patch_sigaction_in_library (lib);
295+ }
296+ }
297+ }
245298
299+ #endif // __linux__
0 commit comments