Open yinchuang-code opened 4 months ago
Demo:
#include <fcntl.h>
#include <setjmp.h>
#include <signal.h>
#include <sys/mman.h>
#include <cstdint>
#include <iostream>
#include <optional>
namespace {
sigjmp_buf jump_buffer;
void safe_handler(int) {
siglongjmp(jump_buffer, 1);
}
std::optional<uint8_t> read_under_sighandler(const uint8_t *p) {
struct sigaction segv_act{}, old_act{};
segv_act.sa_handler = &safe_handler;
sigemptyset(&segv_act.sa_mask);
sigaction(SIGSEGV, &segv_act, &old_act);
std::optional<uint8_t> res;
if (sigsetjmp(jump_buffer, 1) == 0) {
res = *p;
}
sigaction(SIGSEGV, &old_act, NULL);
return res;
}
}
struct dummy_t {
dummy_t() {
auto opt = read_under_sighandler(nullptr);
if (!opt.has_value()) {
puts("null opt - ok");
} else {
printf("opt: %d", *opt);
}
}
} dummy;
#include <dlfcn.h>
#include <cstdio>
int main() {
auto lib = dlopen("liblib.so", RTLD_NOW | RTLD_GLOBAL);
printf("%p\n", lib);
dlclose(lib);
return 0;
}
./main
null opt - ok
ThreadSanitizer: CHECK failed: tsan_rtl.cpp:1046 "((thr->ignore_reads_and_writes)) > ((0))" (0x0, 0x0) (tid=4515)
#0 __tsan::CheckUnwind() <null> (main+0xd5c68) (BuildId: f6725f3b5ec1829614f9ff48e0780b27120e0c50)
#1 __sanitizer::CheckFailed(char const*, int, char const*, unsigned long long, unsigned long long) <null> (main+0x47d00) (BuildId: f6725f3b5ec1829614f9ff48e0780b27120e0c50)
#2 __tsan::ThreadIgnoreEnd(__tsan::ThreadState*) <null> (main+0xda8e1) (BuildId: f6725f3b5ec1829614f9ff48e0780b27120e0c50)
#3 dlopen <null> (main+0xa5c43) (BuildId: f6725f3b5ec1829614f9ff48e0780b27120e0c50)
#4 main <null> (main+0xf8d98) (BuildId: f6725f3b5ec1829614f9ff48e0780b27120e0c50)
#5 <null> <null> (libc.so.6+0x25ccf) (BuildId: 6542915cee3354fbcf2b3ac5542201faec43b5c9)
#6 __libc_start_main <null> (libc.so.6+0x25d89) (BuildId: 6542915cee3354fbcf2b3ac5542201faec43b5c9)
#7 _start <null> (main+0x2f0b4) (BuildId: f6725f3b5ec1829614f9ff48e0780b27120e0c50)
Tsan disable ignores in CallUserSignalHandler when ignores are enabled before call signal handler,but it will make "CHECK_GT(thr->ignore_reads_and_writes, 0);" failed in ThreadIgnoreEnd if someone use siglongjmp in signal handler:
dlopen