summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEvgeniy Stepanov <eugeni.stepanov@gmail.com>2019-10-17 20:32:54 +0000
committerEvgeniy Stepanov <eugeni.stepanov@gmail.com>2019-10-17 20:32:54 +0000
commit6e86c1660cd0c8f0af4575b41f83150a560d3941 (patch)
treec8a57e634bb86935da969757daf7eaaa3f0713cb
parent45c83da934bc2f2f7cb68b2602753753cb0929f4 (diff)
downloadcompiler-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.cpp2
-rw-r--r--lib/hwasan/hwasan.h1
-rw-r--r--lib/hwasan/hwasan_linux.cpp39
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();