commit 7440e4ed85aa992718d4b5ccd1c97724bc3bdd2c Author: Dimitry Andric Date: Mon Nov 27 22:43:33 2023 +0100 [sanitizer] Add re-execution on FreeBSD when ASLR is detected (#73439) In the FreeBSD base system, re-executing the main binary when ASLR is detected was implemented in the following commits: * freebsd/freebsd-src@7cafe89f9ce33 * freebsd/freebsd-src@96fe7c8ab0f65 * freebsd/freebsd-src@930a7c2ac67e1 * freebsd/freebsd-src@0a736f0a6aeb0 * freebsd/freebsd-src@4c9a0adad1826 Squash all these to bring them into upstream compiler-rt. When ASLR is detected to be enabled, this first force-disables ASLR for the current process, then calls ReExec(). The ReExec() function gets a FreeBSD specific implementation for finding the path of the executed program, via the ELF auxiliary vector. This is done without calling into the regular elf_aux_info(3) function, as that makes use of several already-intercepted functions. diff --git compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp index d2b3b63f3a7a..8759d96609e5 100644 --- compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp +++ compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp @@ -2323,9 +2323,12 @@ void CheckASLR() { return; } if ((aslr_status & PROC_ASLR_ACTIVE) != 0) { - Printf("This sanitizer is not compatible with enabled ASLR " - "and binaries compiled with PIE\n"); - Die(); + VReport(1, "This sanitizer is not compatible with enabled ASLR " + "and binaries compiled with PIE\n" + "ASLR will be disabled and the program re-executed.\n"); + int aslr_ctl = PROC_ASLR_FORCE_DISABLE; + CHECK_NE(internal_procctl(P_PID, 0, PROC_ASLR_CTL, &aslr_ctl), -1); + ReExec(); } # elif SANITIZER_PPC64V2 // Disable ASLR for Linux PPC64LE. diff --git compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cpp compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cpp index fcfaa0c36c22..b41f778ea94b 100644 --- compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cpp +++ compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cpp @@ -48,12 +48,14 @@ #if SANITIZER_FREEBSD #include #include +#include #include #define pthread_getattr_np pthread_attr_get_np // The MAP_NORESERVE define has been removed in FreeBSD 11.x, and even before // that, it was never implemented. So just define it to zero. #undef MAP_NORESERVE #define MAP_NORESERVE 0 +extern const Elf_Auxinfo *__elf_aux_vector; #endif #if SANITIZER_NETBSD @@ -941,7 +943,14 @@ u64 MonotonicNanoTime() { void ReExec() { const char *pathname = "/proc/self/exe"; -#if SANITIZER_NETBSD +#if SANITIZER_FREEBSD + for (const auto *aux = __elf_aux_vector; aux->a_type != AT_NULL; aux++) { + if (aux->a_type == AT_EXECPATH) { + pathname = static_cast(aux->a_un.a_ptr); + break; + } + } +#elif SANITIZER_NETBSD static const int name[] = { CTL_KERN, KERN_PROC_ARGS,