summaryrefslogtreecommitdiff
path: root/devel/llvm16/files/patch-backport-7440e4ed85aa
blob: ce6954226d56bbdb5c90bd57d836ef15a1983fbb (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
commit 7440e4ed85aa992718d4b5ccd1c97724bc3bdd2c
Author: Dimitry Andric <dimitry@andric.com>
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 <pthread_np.h>
 #include <osreldate.h>
+#include <sys/auxv.h>
 #include <sys/sysctl.h>
 #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<const char *>(aux->a_un.a_ptr);
+      break;
+    }
+  }
+#elif SANITIZER_NETBSD
   static const int name[] = {
       CTL_KERN,
       KERN_PROC_ARGS,