[compiler-rt] [sanitizer] Add re-execution on FreeBSD when ASLR is detected (PR #73439)
via llvm-commits
llvm-commits at lists.llvm.org
Sun Nov 26 03:06:08 PST 2023
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-compiler-rt-sanitizer
Author: Dimitry Andric (DimitryAndric)
<details>
<summary>Changes</summary>
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.
---
Full diff: https://github.com/llvm/llvm-project/pull/73439.diff
2 Files Affected:
- (modified) compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp (+6-3)
- (modified) compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cpp (+11-1)
``````````diff
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp
index d2b3b63f3a7a3bd..8759d96609e567c 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp
+++ b/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 a/compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cpp
index fcfaa0c36c2251b..ea816eacd980249 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cpp
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cpp
@@ -47,13 +47,16 @@
#if SANITIZER_FREEBSD
#include <pthread_np.h>
+#include <stdlib.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 +944,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,
``````````
</details>
https://github.com/llvm/llvm-project/pull/73439
More information about the llvm-commits
mailing list