git: 78b4c762b20b - releng/14.0 - compiler-rt: avoid segfaults when re-exec'ing with ASLR

From: Gordon Tetlow <gordon_at_FreeBSD.org>
Date: Fri, 01 Dec 2023 00:38:35 UTC
The branch releng/14.0 has been updated by gordon:

URL: https://cgit.FreeBSD.org/src/commit/?id=78b4c762b20b188cd7bc65999ed44e431a8882ff

commit 78b4c762b20b188cd7bc65999ed44e431a8882ff
Author:     Dimitry Andric <dim@FreeBSD.org>
AuthorDate: 2023-11-22 18:23:06 +0000
Commit:     Gordon Tetlow <gordon@FreeBSD.org>
CommitDate: 2023-11-30 21:24:58 +0000

    compiler-rt: avoid segfaults when re-exec'ing with ASLR
    
    After 930a7c2ac67e ("compiler-rt: re-exec with ASLR disabled when
    necessary") and 96fe7c8ab0f6 ("compiler-rt: support ReExec() on
    FreeBSD"), binaries linked against the sanitizer libraries may segfault
    due to procctl(2) being intercepted. Instead, the non-intercepted
    internal_procctl() should be called.
    
    Similarly, the ReExec() function that re-executes the binary after
    turning off ASLR should not call elf_aux_info(3) and realpath(3), since
    these will also be intercepted. Instead, loop directly over the elf aux
    info vector to find the executable path, and avoid calling realpath(3)
    since it is actually unwanted for this use case.
    
    Fixes:          930a7c2ac67e, 96fe7c8ab0f6
    MFC after:      3 days
    Approved by:    so
    Security:       FreeBSD-EN-23:15.sanitizer
    
    (cherry picked from commit 4c9a0adad18263ec8725d9bfc5f560c6ad1da8bd)
    (cherry picked from commit 1e4798e9677f17a7cdc9a1873a0c6e008fc620d8)
---
 .../compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp      |  2 +-
 .../lib/sanitizer_common/sanitizer_linux_libcdep.cpp          | 11 ++++++-----
 2 files changed, 7 insertions(+), 6 deletions(-)

diff --git a/contrib/llvm-project/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp b/contrib/llvm-project/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp
index 3f544623c6fb..ebbd14eca72f 100644
--- a/contrib/llvm-project/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp
+++ b/contrib/llvm-project/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp
@@ -2323,7 +2323,7 @@ void CheckASLR() {
                "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(procctl(P_PID, 0, PROC_ASLR_CTL, &aslr_ctl), -1);
+    CHECK_NE(internal_procctl(P_PID, 0, PROC_ASLR_CTL, &aslr_ctl), -1);
     ReExec();
   }
 #  elif SANITIZER_PPC64V2
diff --git a/contrib/llvm-project/compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cpp b/contrib/llvm-project/compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cpp
index ff62fc4af430..58310e05b359 100644
--- a/contrib/llvm-project/compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cpp
+++ b/contrib/llvm-project/compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cpp
@@ -56,6 +56,7 @@
 // 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
@@ -947,11 +948,11 @@ void ReExec() {
   const char *pathname = "/proc/self/exe";
 
 #if SANITIZER_FREEBSD
-  char exe_path[PATH_MAX];
-  if (elf_aux_info(AT_EXECPATH, exe_path, sizeof(exe_path)) == 0) {
-    char link_path[PATH_MAX];
-    if (realpath(exe_path, link_path))
-      pathname = link_path;
+  for (const auto *aux = __elf_aux_vector; aux->a_type != AT_NULL; aux++) {
+    if (aux->a_type == AT_EXECPATH) {
+      pathname = static_cast<const char *>(aux->a_un.a_ptr);
+      break;
+    }
   }
 #elif SANITIZER_NETBSD
   static const int name[] = {