[compiler-rt] 7be8682 - [tsan] Fix "failed to intercept sysctlnametomib" on FreeBSD

Alex Richardson via llvm-commits llvm-commits at lists.llvm.org
Tue Sep 1 10:25:54 PDT 2020


Author: Alex Richardson
Date: 2020-09-01T18:25:22+01:00
New Revision: 7be86829216698b6f4d0e083d48d7095898fc9c8

URL: https://github.com/llvm/llvm-project/commit/7be86829216698b6f4d0e083d48d7095898fc9c8
DIFF: https://github.com/llvm/llvm-project/commit/7be86829216698b6f4d0e083d48d7095898fc9c8.diff

LOG: [tsan] Fix "failed to intercept sysctlnametomib" on FreeBSD

The sysctlnametomib function is called from __tsan::Initialize via
__sanitizer::internal_sysctlbyname (see stack trace below). This results
in a fatal error since sysctlnametomib has not been intercepted yet.
This patch allows internal_sysctlbyname to be called before
__tsan::Initialize() has completed. On FreeBSD >= 1300045 sysctlbyname()
is a real syscall, but for older versions it calls sysctlnametomib()
followed by sysctl(). To avoid calling the intercepted version, look up
the real sysctlnametomib() followed by internal_sysctl() if the
syscall is not available.

This reduces check-sanitizer failures from 62 to 11 for me.

==34433==FATAL: ThreadSanitizer: failed to intercept sysctlnametomib
    at /exports/users/alr48/sources/upstream-llvm-project/compiler-rt/lib/sanitizer_common/sanitizer_termination.cpp:51
    name=0x7fffffffce10, namelenp=0x7fffffffce08)
    at /exports/users/alr48/sources/upstream-llvm-project/compiler-rt/lib/tsan/../sanitizer_common/sanitizer_common_interceptors.inc:7908
    oldp=0x7fffffffcf2c, oldlenp=0x7fffffffcf20, newp=0x0, newlen=0)
    at /exports/users/alr48/sources/upstream-llvm-project/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp:803
    at /exports/users/alr48/sources/upstream-llvm-project/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp:2152
    at /exports/users/alr48/sources/upstream-llvm-project/compiler-rt/lib/tsan/rtl/tsan_rtl.cpp:367
    fname=0x21c731 "readlink", pc=34366042556)
    at /exports/users/alr48/sources/upstream-llvm-project/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp:255
    bufsiz=1024)
    at /exports/users/alr48/sources/upstream-llvm-project/compiler-rt/lib/tsan/../sanitizer_common/sanitizer_common_interceptors.inc:7151

Reviewed By: #sanitizers, vitalybuka

Differential Revision: https://reviews.llvm.org/D85292

Added: 
    

Modified: 
    compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp

Removed: 
    


################################################################################
diff  --git a/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp
index ac7af74a2f94..111592d4a0a6 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp
@@ -800,11 +800,29 @@ int internal_sysctl(const int *name, unsigned int namelen, void *oldp,
 #if SANITIZER_FREEBSD
 int internal_sysctlbyname(const char *sname, void *oldp, uptr *oldlenp,
                           const void *newp, uptr newlen) {
-  static decltype(sysctlbyname) *real = nullptr;
-  if (!real)
-    real = (decltype(sysctlbyname) *)dlsym(RTLD_NEXT, "sysctlbyname");
-  CHECK(real);
-  return real(sname, oldp, (size_t *)oldlenp, newp, (size_t)newlen);
+  // Note: this function can be called during startup, so we need to avoid
+  // calling any interceptable functions. On FreeBSD >= 1300045 sysctlbyname()
+  // is a real syscall, but for older versions it calls sysctlnametomib()
+  // followed by sysctl(). To avoid calling the intercepted version and
+  // asserting if this happens during startup, call the real sysctlnametomib()
+  // followed by internal_sysctl() if the syscall is not available.
+#ifdef SYS___sysctlbyname
+  return internal_syscall(SYSCALL(__sysctlbyname), sname,
+                          internal_strlen(sname), oldp, (size_t *)oldlenp, newp,
+                          (size_t)newlen);
+#else
+  static decltype(sysctlnametomib) *real_sysctlnametomib = nullptr;
+  if (!real_sysctlnametomib)
+    real_sysctlnametomib =
+        (decltype(sysctlnametomib) *)dlsym(RTLD_NEXT, "sysctlnametomib");
+  CHECK(real_sysctlnametomib);
+
+  int oid[CTL_MAXNAME];
+  size_t len = CTL_MAXNAME;
+  if (real_sysctlnametomib(sname, oid, &len) == -1)
+    return (-1);
+  return internal_sysctl(oid, len, oldp, oldlenp, newp, newlen);
+#endif
 }
 #endif
 #endif


        


More information about the llvm-commits mailing list