[compiler-rt] [hwasan] Add fixed_shadow_base flag (PR #73980)
Thurston Dang via llvm-commits
llvm-commits at lists.llvm.org
Tue Dec 5 14:26:57 PST 2023
https://github.com/thurstond updated https://github.com/llvm/llvm-project/pull/73980
>From 294ed9bff3fd0d23d1b97c8a4be07b9168e69f69 Mon Sep 17 00:00:00 2001
From: Thurston Dang <thurston at google.com>
Date: Thu, 30 Nov 2023 20:14:00 +0000
Subject: [PATCH 1/4] [hwasan] Add fixed_shadow_base flag
When set to non-zero, the HWASan runtime will map the shadow base at the
specified constant address.
This is particularly useful in conjunction with the existing compiler option
'hwasan-mapping-offset', which bakes a hardcoded constant address into
the instrumentation.
---
compiler-rt/lib/hwasan/hwasan_flags.inc | 7 +++++++
compiler-rt/lib/hwasan/hwasan_linux.cpp | 10 ++++++++--
2 files changed, 15 insertions(+), 2 deletions(-)
diff --git a/compiler-rt/lib/hwasan/hwasan_flags.inc b/compiler-rt/lib/hwasan/hwasan_flags.inc
index 978fa46b705cb..bb224fbb8eaa8 100644
--- a/compiler-rt/lib/hwasan/hwasan_flags.inc
+++ b/compiler-rt/lib/hwasan/hwasan_flags.inc
@@ -84,3 +84,10 @@ HWASAN_FLAG(bool, malloc_bisect_dump, false,
// are untagged before the call.
HWASAN_FLAG(bool, fail_without_syscall_abi, true,
"Exit if fail to request relaxed syscall ABI.")
+
+HWASAN_FLAG(
+ uptr, fixed_shadow_base, 0,
+ "If non-zero, HWASan will attempt to allocate the shadow at this address, "
+ "instead of choosing one dynamically."
+ "Tip: this can be combined with the compiler option, "
+ "-hwasan-mapping-offset, to optimize the instrumentation.")
diff --git a/compiler-rt/lib/hwasan/hwasan_linux.cpp b/compiler-rt/lib/hwasan/hwasan_linux.cpp
index 81226da976d11..e7cf36ef3161c 100644
--- a/compiler-rt/lib/hwasan/hwasan_linux.cpp
+++ b/compiler-rt/lib/hwasan/hwasan_linux.cpp
@@ -106,8 +106,14 @@ static uptr GetHighMemEnd() {
}
static void InitializeShadowBaseAddress(uptr shadow_size_bytes) {
- __hwasan_shadow_memory_dynamic_address =
- FindDynamicShadowStart(shadow_size_bytes);
+ // NULL is generally address zero, so it is not a valid location for the
+ // shadow.
+ if (flags()->fixed_shadow_base != 0) {
+ __hwasan_shadow_memory_dynamic_address = flags()->fixed_shadow_base;
+ } else {
+ __hwasan_shadow_memory_dynamic_address =
+ FindDynamicShadowStart(shadow_size_bytes);
+ }
}
static void MaybeDieIfNoTaggingAbi(const char *message) {
>From 48eb300c1a0ee2233f6c2e2e0a3899f591befa94 Mon Sep 17 00:00:00 2001
From: Thurston Dang <thurston at google.com>
Date: Thu, 30 Nov 2023 20:56:08 +0000
Subject: [PATCH 2/4] Change "non-fixed shadow" magic value from 0 to -1, per
offline discussion with Vitaly
---
compiler-rt/lib/hwasan/hwasan_flags.inc | 4 ++--
compiler-rt/lib/hwasan/hwasan_linux.cpp | 4 +---
2 files changed, 3 insertions(+), 5 deletions(-)
diff --git a/compiler-rt/lib/hwasan/hwasan_flags.inc b/compiler-rt/lib/hwasan/hwasan_flags.inc
index bb224fbb8eaa8..058a0457b9e7f 100644
--- a/compiler-rt/lib/hwasan/hwasan_flags.inc
+++ b/compiler-rt/lib/hwasan/hwasan_flags.inc
@@ -86,8 +86,8 @@ HWASAN_FLAG(bool, fail_without_syscall_abi, true,
"Exit if fail to request relaxed syscall ABI.")
HWASAN_FLAG(
- uptr, fixed_shadow_base, 0,
- "If non-zero, HWASan will attempt to allocate the shadow at this address, "
+ uptr, fixed_shadow_base, -1,
+ "If not -1, HWASan will attempt to allocate the shadow at this address, "
"instead of choosing one dynamically."
"Tip: this can be combined with the compiler option, "
"-hwasan-mapping-offset, to optimize the instrumentation.")
diff --git a/compiler-rt/lib/hwasan/hwasan_linux.cpp b/compiler-rt/lib/hwasan/hwasan_linux.cpp
index e7cf36ef3161c..f01fa42764134 100644
--- a/compiler-rt/lib/hwasan/hwasan_linux.cpp
+++ b/compiler-rt/lib/hwasan/hwasan_linux.cpp
@@ -106,9 +106,7 @@ static uptr GetHighMemEnd() {
}
static void InitializeShadowBaseAddress(uptr shadow_size_bytes) {
- // NULL is generally address zero, so it is not a valid location for the
- // shadow.
- if (flags()->fixed_shadow_base != 0) {
+ if (flags()->fixed_shadow_base != (uptr)-1) {
__hwasan_shadow_memory_dynamic_address = flags()->fixed_shadow_base;
} else {
__hwasan_shadow_memory_dynamic_address =
>From 0896aa86ba9de0f1b681c3e4565cfe597294a0a7 Mon Sep 17 00:00:00 2001
From: Thurston Dang <thurston at google.com>
Date: Tue, 5 Dec 2023 22:25:11 +0000
Subject: [PATCH 3/4] Add test
---
.../hwasan/TestCases/Linux/fixed-shadow.c | 62 +++++++++++++++++++
1 file changed, 62 insertions(+)
create mode 100644 compiler-rt/test/hwasan/TestCases/Linux/fixed-shadow.c
diff --git a/compiler-rt/test/hwasan/TestCases/Linux/fixed-shadow.c b/compiler-rt/test/hwasan/TestCases/Linux/fixed-shadow.c
new file mode 100644
index 0000000000000..9ff57f27de4e1
--- /dev/null
+++ b/compiler-rt/test/hwasan/TestCases/Linux/fixed-shadow.c
@@ -0,0 +1,62 @@
+// Test fixed shadow base functionality.
+//
+// Default compiler instrumentation works with any shadow base (dynamic or fixed).
+// RUN: %clang_hwasan %s -o %t && %run %t
+// RUN: %clang_hwasan %s -o %t && HWASAN_OPTIONS=fixed_shadow_base=263878495698944 %run %t
+// RUN: %clang_hwasan %s -o %t && HWASAN_OPTIONS=fixed_shadow_base=4398046511104 %run %t
+//
+// If -hwasan-mapping-offset is set, then the fixed_shadow_base needs to match.
+// RUN: %clang_hwasan %s -mllvm -hwasan-mapping-offset=263878495698944 -o %t && HWASAN_OPTIONS=fixed_shadow_base=263878495698944 %run %t
+// RUN: %clang_hwasan %s -mllvm -hwasan-mapping-offset=4398046511104 -o %t && HWASAN_OPTIONS=fixed_shadow_base=4398046511104 %run %t
+// RUN: %clang_hwasan %s -mllvm -hwasan-mapping-offset=263878495698944 -o %t && HWASAN_OPTIONS=fixed_shadow_base=4398046511104 not %run %t
+// RUN: %clang_hwasan %s -mllvm -hwasan-mapping-offset=4398046511104 -o %t && HWASAN_OPTIONS=fixed_shadow_base=263878495698944 not %run %t
+//
+// Note: if fixed_shadow_base is not set, compiler-rt will dynamically choose a
+// shadow base, which has a tiny but non-zero probability of matching the
+// compiler instrumentation. To avoid test flake, we do not test this case.
+//
+// Assume 48-bit VMA
+// REQUIRES: aarch64-target-arch
+//
+// UNSUPPORTED: android
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <sys/mman.h>
+#include <sanitizer/hwasan_interface.h>
+#include <sanitizer/allocator_interface.h>
+
+int main() {
+ __hwasan_enable_allocator_tagging();
+
+ void** mmaps [256];
+ // 48-bit VMA
+ for (int i = 0; i < 256; i++) {
+ unsigned long long addr = (i * (1ULL << 40));
+
+ void *p = mmap ((void*)addr, 4096, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0);
+ mmaps [i] = p;
+ }
+
+ int failures = 0;
+ for (int i = 0; i < 256; i++) {
+ if (mmaps [i] == MAP_FAILED) {
+ failures++;
+ } else {
+ printf ("%d %p\n", i, mmaps [i]);
+ munmap (mmaps [i], 4096);
+ }
+ }
+
+ // We expect roughly 17 failures:
+ // - the page at address zero
+ // - 16 failures because the shadow memory takes up 1/16th of the address space
+ // We could also get unlucky e.g., if libraries or binaries are loaded into the
+ // exact addresses where we tried to map.
+ // To avoid test flake, we allow some margin of error.
+ printf ("Failed: %d\n", failures);
+ assert (failures < 32);
+ return 0;
+}
>From 2c9a4b43a927b6d20d9eacd3888103d80dfff382 Mon Sep 17 00:00:00 2001
From: Thurston Dang <thurston at google.com>
Date: Tue, 5 Dec 2023 22:26:39 +0000
Subject: [PATCH 4/4] clang-format test
---
.../hwasan/TestCases/Linux/fixed-shadow.c | 44 +++++++++----------
1 file changed, 22 insertions(+), 22 deletions(-)
diff --git a/compiler-rt/test/hwasan/TestCases/Linux/fixed-shadow.c b/compiler-rt/test/hwasan/TestCases/Linux/fixed-shadow.c
index 9ff57f27de4e1..154ef5cd44e6c 100644
--- a/compiler-rt/test/hwasan/TestCases/Linux/fixed-shadow.c
+++ b/compiler-rt/test/hwasan/TestCases/Linux/fixed-shadow.c
@@ -13,41 +13,41 @@
//
// Note: if fixed_shadow_base is not set, compiler-rt will dynamically choose a
// shadow base, which has a tiny but non-zero probability of matching the
-// compiler instrumentation. To avoid test flake, we do not test this case.
+// compiler instrumentation. To avoid test flake, we do not test this case.
//
// Assume 48-bit VMA
// REQUIRES: aarch64-target-arch
//
// UNSUPPORTED: android
-#include <stdio.h>
-#include <stdlib.h>
-#include <assert.h>
-#include <sys/mman.h>
-#include <sanitizer/hwasan_interface.h>
+#include <assert.h>
#include <sanitizer/allocator_interface.h>
+#include <sanitizer/hwasan_interface.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/mman.h>
-int main() {
+int main() {
__hwasan_enable_allocator_tagging();
- void** mmaps [256];
+ void **mmaps[256];
// 48-bit VMA
- for (int i = 0; i < 256; i++) {
- unsigned long long addr = (i * (1ULL << 40));
+ for (int i = 0; i < 256; i++) {
+ unsigned long long addr = (i * (1ULL << 40));
- void *p = mmap ((void*)addr, 4096, PROT_READ | PROT_WRITE,
- MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0);
- mmaps [i] = p;
+ void *p = mmap((void *)addr, 4096, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0);
+ mmaps[i] = p;
}
int failures = 0;
- for (int i = 0; i < 256; i++) {
- if (mmaps [i] == MAP_FAILED) {
- failures++;
- } else {
- printf ("%d %p\n", i, mmaps [i]);
- munmap (mmaps [i], 4096);
- }
+ for (int i = 0; i < 256; i++) {
+ if (mmaps[i] == MAP_FAILED) {
+ failures++;
+ } else {
+ printf("%d %p\n", i, mmaps[i]);
+ munmap(mmaps[i], 4096);
+ }
}
// We expect roughly 17 failures:
@@ -56,7 +56,7 @@ int main() {
// We could also get unlucky e.g., if libraries or binaries are loaded into the
// exact addresses where we tried to map.
// To avoid test flake, we allow some margin of error.
- printf ("Failed: %d\n", failures);
- assert (failures < 32);
+ printf("Failed: %d\n", failures);
+ assert(failures < 32);
return 0;
}
More information about the llvm-commits
mailing list