diff options
author | Evgeniy Stepanov <eugeni.stepanov@gmail.com> | 2019-10-17 20:32:54 +0000 |
---|---|---|
committer | Evgeniy Stepanov <eugeni.stepanov@gmail.com> | 2019-10-17 20:32:54 +0000 |
commit | 6e86c1660cd0c8f0af4575b41f83150a560d3941 (patch) | |
tree | c8a57e634bb86935da969757daf7eaaa3f0713cb | |
parent | 45c83da934bc2f2f7cb68b2602753753cb0929f4 (diff) | |
download | compiler-rt-6e86c1660cd0c8f0af4575b41f83150a560d3941.tar.gz |
libhwasan initialisation include kernel syscall ABI relaxation
Summary:
Until now AArch64 development has been on patched kernels that have an always
on relaxed syscall ABI where tagged pointers are accepted.
The patches that have gone into the mainline kernel rely on each process opting
in to this relaxed ABI.
This commit adds code to choose that ABI into __hwasan_init.
The idea has already been agreed with one of the hwasan developers
(http://lists.llvm.org/pipermail/llvm-dev/2019-September/135328.html).
The patch ignores failures of `EINVAL` for Android, since there are older versions of the Android kernel that don't require this `prctl` or even have the relevant values. Avoiding EINVAL will let the library run on them.
I've tested this on an AArch64 VM running a kernel that requires this
prctl, having compiled both with clang and gcc.
Patch by Matthew Malcomson.
Reviewers: eugenis, kcc, pcc
Reviewed By: eugenis
Subscribers: srhines, kristof.beyls, #sanitizers, llvm-commits
Tags: #sanitizers, #llvm
Differential Revision: https://reviews.llvm.org/D68794
git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@375166 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/hwasan/hwasan.cpp | 2 | ||||
-rw-r--r-- | lib/hwasan/hwasan.h | 1 | ||||
-rw-r--r-- | lib/hwasan/hwasan_linux.cpp | 39 |
3 files changed, 42 insertions, 0 deletions
diff --git a/lib/hwasan/hwasan.cpp b/lib/hwasan/hwasan.cpp index 3a5b8791a..7b5c6c694 100644 --- a/lib/hwasan/hwasan.cpp +++ b/lib/hwasan/hwasan.cpp @@ -312,6 +312,8 @@ static void InitLoadedGlobals() { static void InitInstrumentation() { if (hwasan_instrumentation_inited) return; + InitPrctl(); + if (!InitShadow()) { Printf("FATAL: HWAddressSanitizer cannot mmap the shadow memory.\n"); DumpProcessMap(); diff --git a/lib/hwasan/hwasan.h b/lib/hwasan/hwasan.h index 817cee650..9e0ced93b 100644 --- a/lib/hwasan/hwasan.h +++ b/lib/hwasan/hwasan.h @@ -74,6 +74,7 @@ extern int hwasan_report_count; bool ProtectRange(uptr beg, uptr end); bool InitShadow(); +void InitPrctl(); void InitThreads(); void MadviseShadow(); char *GetProcSelfMaps(); diff --git a/lib/hwasan/hwasan_linux.cpp b/lib/hwasan/hwasan_linux.cpp index 051ec2fb9..948e40154 100644 --- a/lib/hwasan/hwasan_linux.cpp +++ b/lib/hwasan/hwasan_linux.cpp @@ -34,6 +34,8 @@ #include <sys/time.h> #include <unistd.h> #include <unwind.h> +#include <sys/prctl.h> +#include <errno.h> #include "sanitizer_common/sanitizer_common.h" #include "sanitizer_common/sanitizer_procmaps.h" @@ -144,6 +146,43 @@ static void InitializeShadowBaseAddress(uptr shadow_size_bytes) { FindDynamicShadowStart(shadow_size_bytes); } +void InitPrctl() { +#define PR_SET_TAGGED_ADDR_CTRL 55 +#define PR_GET_TAGGED_ADDR_CTRL 56 +#define PR_TAGGED_ADDR_ENABLE (1UL << 0) + // Check we're running on a kernel that can use the tagged address ABI. + if (internal_prctl(PR_GET_TAGGED_ADDR_CTRL, 0, 0, 0, 0) == (uptr)-1 && + errno == EINVAL) { +#if SANITIZER_ANDROID + // Some older Android kernels have the tagged pointer ABI on + // unconditionally, and hence don't have the tagged-addr prctl while still + // allow the ABI. + // If targeting Android and the prctl is not around we assume this is the + // case. + return; +#else + Printf( + "FATAL: " + "HWAddressSanitizer requires a kernel with tagged address ABI.\n"); + Die(); +#endif + } + + // Turn on the tagged address ABI. + if (internal_prctl(PR_SET_TAGGED_ADDR_CTRL, PR_TAGGED_ADDR_ENABLE, 0, 0, 0) == + (uptr)-1 || + !internal_prctl(PR_GET_TAGGED_ADDR_CTRL, 0, 0, 0, 0)) { + Printf( + "FATAL: HWAddressSanitizer failed to enable tagged address syscall " + "ABI.\nSuggest check `sysctl abi.tagged_addr_disabled` " + "configuration.\n"); + Die(); + } +#undef PR_SET_TAGGED_ADDR_CTRL +#undef PR_GET_TAGGED_ADDR_CTRL +#undef PR_TAGGED_ADDR_ENABLE +} + bool InitShadow() { // Define the entire memory range. kHighMemEnd = GetHighMemEnd(); |