Skip to content

Commit 5f32e78

Browse files
mralephCommit Queue
authored andcommitted
[vm] Fix running under HWASAN
HWASAN tags stack regions (and stack pointers) with 0, but also selectively tags some stack allocations with non-zero tags. These tags need to be cleared when allocation goes out of scope so that stack can be later safely reused - otherwise stale tags confuse HWASAN instrumentation later. This CL teaches Exceptions::JumpToFrame to do that. CL also adds basic build changes to support building with HWASAN, though I don't wire it into CI for now as it can only really run on Android ARM64 TEST=manually on Android phone and on internal tests Bug: b/374433249 Change-Id: I678443dc1de693c999a226bee0d71a6f3582d4f9 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/421180 Commit-Queue: Ryan Macnak <[email protected]> Reviewed-by: Ryan Macnak <[email protected]> Auto-Submit: Slava Egorov <[email protected]>
1 parent a3e2431 commit 5f32e78

File tree

9 files changed

+41
-5
lines changed

9 files changed

+41
-5
lines changed

build/config/BUILDCONFIG.gn

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,10 @@ declare_args() {
122122
# Compile for Address Sanitizer to find memory bugs.
123123
is_asan = false
124124

125+
# Compile with HWAddress Sanitizer to find memory bugs.
126+
# Requires ARM64 hardware
127+
is_hwasan = false
128+
125129
# Compile for Leak Sanitizer to find leaks.
126130
is_lsan = false
127131

build/config/compiler/BUILD.gn

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,8 @@ config("default_include_dirs") {
3939
}
4040

4141
if (!is_win) {
42-
using_sanitizer = is_asan || is_lsan || is_msan || is_tsan || is_ubsan
42+
using_sanitizer =
43+
is_asan || is_hwasan || is_lsan || is_msan || is_tsan || is_ubsan
4344
}
4445

4546
# compiler ---------------------------------------------------------------------
@@ -117,6 +118,10 @@ config("compiler") {
117118
cflags += [ "-fsanitize=address" ]
118119
ldflags += [ "-fsanitize=address" ]
119120
}
121+
if (is_hwasan && is_android && current_cpu == "arm64") {
122+
cflags += [ "-fsanitize=hwaddress" ]
123+
ldflags += [ "-fsanitize=hwaddress" ]
124+
}
120125
if (is_lsan) {
121126
cflags += [ "-fsanitize=leak" ]
122127
ldflags += [ "-fsanitize=leak" ]

build/config/sanitizers/BUILD.gn

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import("//build/config/sanitizers/sanitizers.gni")
99
# |is_asan|, |is_lsan|, |is_tsan|, |is_msan| and |use_custom_libcxx| are false.
1010
group("deps") {
1111
deps = [ "//third_party/instrumented_libraries:deps" ]
12-
if (is_asan || is_lsan || is_msan || is_tsan || is_ubsan) {
12+
if (is_asan || is_hwasan || is_lsan || is_msan || is_tsan || is_ubsan) {
1313
public_configs = [ ":sanitizer_options_link_helper" ]
1414
deps += [ ":options_sources" ]
1515
}
@@ -23,6 +23,9 @@ config("sanitizer_options_link_helper") {
2323
if (is_asan) {
2424
ldflags += [ "-fsanitize=address" ]
2525
}
26+
if (is_hwasan && is_android && current_cpu == "arm64") {
27+
ldflags += [ "-fsanitize=hwaddress" ]
28+
}
2629
if (is_lsan) {
2730
ldflags += [ "-fsanitize=leak" ]
2831
}

pkg/smith/lib/configuration.dart

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -962,6 +962,7 @@ class Mode extends NamedEnum {
962962
class Sanitizer extends NamedEnum {
963963
static const none = Sanitizer._('none');
964964
static const asan = Sanitizer._('asan');
965+
static const hwasan = Sanitizer._('hwasan');
965966
static const lsan = Sanitizer._('lsan');
966967
static const msan = Sanitizer._('msan');
967968
static const tsan = Sanitizer._('tsan');
@@ -970,7 +971,7 @@ class Sanitizer extends NamedEnum {
970971
static final List<String> names = _all.keys.toList();
971972

972973
static final _all = Map<String, Sanitizer>.fromIterable(
973-
[none, asan, lsan, msan, tsan, ubsan],
974+
[none, asan, hwasan, lsan, msan, tsan, ubsan],
974975
key: (mode) => (mode as Sanitizer).name);
975976

976977
static Sanitizer find(String name) {

runtime/bin/BUILD.gn

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,8 @@ config("libdart_builtin_config") {
3636
config("export_api_symbols") {
3737
if (is_win) {
3838
ldflags = [ "/EXPORT:Dart_True" ]
39-
} else if (is_asan || is_lsan || is_msan || is_tsan || is_ubsan) {
39+
} else if (is_asan || is_hwasan || is_lsan || is_msan || is_tsan ||
40+
is_ubsan) {
4041
# Export everything so the sanitizers can intercept whatever they want.
4142
ldflags = [ "-rdynamic" ]
4243
} else if (is_mac || is_ios) {

runtime/platform/memory_sanitizer.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,18 @@
1313
#if __has_feature(memory_sanitizer)
1414
#define USING_MEMORY_SANITIZER
1515
#endif
16+
#if __has_feature(hwaddress_sanitizer)
17+
#define USING_HWADDRESS_SANITIZER
18+
#endif
19+
#endif
20+
21+
#if defined(USING_HWADDRESS_SANITIZER)
22+
extern "C" void __hwasan_handle_longjmp(const void* sp_dst);
23+
#define HWASAN_HANDLE_LONGJMP(sp_dst) __hwasan_handle_longjmp(sp_dst)
24+
#else
25+
#define HWASAN_HANDLE_LONGJMP(sp_dst) \
26+
do { \
27+
} while (false && (sp_dst) == nullptr)
1628
#endif
1729

1830
#if defined(USING_MEMORY_SANITIZER)

runtime/vm/exceptions.cc

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -632,6 +632,14 @@ NO_SANITIZE_SAFE_STACK // This function manipulates the safestack pointer.
632632
frame_pointer, thread);
633633
#else
634634

635+
// Zero out HWASAN tags from the current stack pointer to the destination.
636+
//
637+
// Stack region is by default tagged with 0 (including SP and all pointers
638+
// derived from it via arithmetic), however HWASAN also selectively tags
639+
// some stack allocations - which means these tags need to be zeroed out
640+
// when the stack is unwound so that it could be safely reused later.
641+
HWASAN_HANDLE_LONGJMP(reinterpret_cast<void*>(stack_pointer));
642+
635643
// Unpoison the stack before we tear it down in the generated stub code.
636644
uword current_sp = OSThread::GetCurrentStackPointer() - 1024;
637645
ASAN_UNPOISON(reinterpret_cast<void*>(current_sp),

tools/gn.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,7 @@ def ToGnArgs(args, mode, arch, target_os, sanitizer, verify_sdk_hash,
266266
gn_args['is_msan'] = sanitizer == 'msan'
267267
gn_args['is_tsan'] = sanitizer == 'tsan'
268268
gn_args['is_ubsan'] = sanitizer == 'ubsan'
269+
gn_args['is_hwasan'] = sanitizer == 'hwasan'
269270
gn_args['is_qemu'] = args.use_qemu
270271

271272
if not args.platform_sdk:
@@ -569,7 +570,7 @@ def AddCommonConfigurationArgs(parser):
569570
parser.add_argument('--sanitizer',
570571
type=str,
571572
help='Build variants (comma-separated).',
572-
metavar='[all,none,asan,lsan,msan,tsan,ubsan]',
573+
metavar='[all,none,asan,hwasan,lsan,msan,tsan,ubsan]',
573574
default='none')
574575

575576

tools/utils.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
None: '',
5151
'none': '',
5252
'asan': 'ASAN',
53+
'hwasan': 'HWASAN',
5354
'lsan': 'LSAN',
5455
'msan': 'MSAN',
5556
'tsan': 'TSAN',

0 commit comments

Comments
 (0)