google / sanitizers

AddressSanitizer, ThreadSanitizer, MemorySanitizer
Other
11.41k stars 1.03k forks source link

【Tsan】【Bug】Calling siglongjmp in signal handler will cause the ignore_reads_and_writes check to fail #1759

Open yinchuang-code opened 4 months ago

yinchuang-code commented 4 months ago

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

yinchuang-code commented 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)