From 03cd392eb1bb027cf70421e4e9f0eb6e5180637b Mon Sep 17 00:00:00 2001 From: lidongyan <502024330056@smail.nju.edu.cn> Date: Mon, 31 Mar 2025 15:14:45 +0800 Subject: [PATCH 1/6] Poison last word of FakeFrame --- compiler-rt/lib/asan/asan_fake_stack.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/compiler-rt/lib/asan/asan_fake_stack.cpp b/compiler-rt/lib/asan/asan_fake_stack.cpp index 7443ff166984d..f68dd31ab1610 100644 --- a/compiler-rt/lib/asan/asan_fake_stack.cpp +++ b/compiler-rt/lib/asan/asan_fake_stack.cpp @@ -107,7 +107,12 @@ FakeFrame *FakeStack::Allocate(uptr stack_size_log, uptr class_id, FakeFrame *res = reinterpret_cast( GetFrame(stack_size_log, class_id, pos)); res->real_stack = real_stack; - *SavedFlagPtr(reinterpret_cast(res), class_id) = &flags[pos]; + u8 **saved_flag_ptr = SavedFlagPtr(reinterpret_cast(res), class_id); + *saved_flag_ptr = &flags[pos]; + + // Poison the last word of FakeFrame + u8 *shadow = reinterpret_cast(MemToShadow(reinterpret_cast(saved_flag_ptr))); + *shadow = kMagic1; return res; } return nullptr; // We are out of fake stack. From be3221b82d9c12bceaa16236be9df191e1a0f5f3 Mon Sep 17 00:00:00 2001 From: brandb97 <77328395+brandb97@users.noreply.github.com> Date: Wed, 2 Apr 2025 20:43:09 +0800 Subject: [PATCH 2/6] replace oxf5 with 0xf3 replace kAsanAfterReturnMagic with kAsanStackRightRedzoneMagic --- compiler-rt/lib/asan/asan_fake_stack.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler-rt/lib/asan/asan_fake_stack.cpp b/compiler-rt/lib/asan/asan_fake_stack.cpp index f68dd31ab1610..590c759d76078 100644 --- a/compiler-rt/lib/asan/asan_fake_stack.cpp +++ b/compiler-rt/lib/asan/asan_fake_stack.cpp @@ -112,7 +112,7 @@ FakeFrame *FakeStack::Allocate(uptr stack_size_log, uptr class_id, // Poison the last word of FakeFrame u8 *shadow = reinterpret_cast(MemToShadow(reinterpret_cast(saved_flag_ptr))); - *shadow = kMagic1; + *shadow = kAsanStackRightRedzoneMagic; return res; } return nullptr; // We are out of fake stack. From 568c2c8a0c5c18441957ee6bc38225cdafaf81cc Mon Sep 17 00:00:00 2001 From: lidongyan <502024330056@smail.nju.edu.cn> Date: Tue, 8 Apr 2025 14:52:27 +0800 Subject: [PATCH 3/6] add test & use SetShadow --- compiler-rt/lib/asan/asan_fake_stack.cpp | 22 ++++++++---- .../asan/TestCases/fakeframe-left-redzone.cpp | 36 +++++++++++++++++++ 2 files changed, 52 insertions(+), 6 deletions(-) create mode 100644 compiler-rt/test/asan/TestCases/fakeframe-left-redzone.cpp diff --git a/compiler-rt/lib/asan/asan_fake_stack.cpp b/compiler-rt/lib/asan/asan_fake_stack.cpp index 590c759d76078..7ce7c527a7167 100644 --- a/compiler-rt/lib/asan/asan_fake_stack.cpp +++ b/compiler-rt/lib/asan/asan_fake_stack.cpp @@ -27,6 +27,7 @@ static const u64 kAllocaRedzoneMask = 31UL; // For small size classes inline PoisonShadow for better performance. ALWAYS_INLINE void SetShadow(uptr ptr, uptr size, uptr class_id, u64 magic) { + CHECK(AddrIsAlignedByGranularity(ptr + size)); u64 *shadow = reinterpret_cast(MemToShadow(ptr)); if (ASAN_SHADOW_SCALE == 3 && class_id <= 6) { // This code expects ASAN_SHADOW_SCALE=3. @@ -107,12 +108,7 @@ FakeFrame *FakeStack::Allocate(uptr stack_size_log, uptr class_id, FakeFrame *res = reinterpret_cast( GetFrame(stack_size_log, class_id, pos)); res->real_stack = real_stack; - u8 **saved_flag_ptr = SavedFlagPtr(reinterpret_cast(res), class_id); - *saved_flag_ptr = &flags[pos]; - - // Poison the last word of FakeFrame - u8 *shadow = reinterpret_cast(MemToShadow(reinterpret_cast(saved_flag_ptr))); - *shadow = kAsanStackRightRedzoneMagic; + *SavedFlagPtr(reinterpret_cast(res), class_id) = &flags[pos]; return res; } return nullptr; // We are out of fake stack. @@ -236,6 +232,13 @@ static ALWAYS_INLINE uptr OnMalloc(uptr class_id, uptr size) { return 0; // Out of fake stack. uptr ptr = reinterpret_cast(ff); SetShadow(ptr, size, class_id, 0); + + // Poison everything beyond user size, use kNumberOfSizeClasses to prevent + // SetShadow from inlining PoisonShadow + SetShadow(reinterpret_cast(ptr + size), + FakeStack::BytesInSizeClass(class_id) - size, kNumberOfSizeClasses, + kAsanStackRightRedzoneMagic); + return ptr; } @@ -249,6 +252,13 @@ static ALWAYS_INLINE uptr OnMallocAlways(uptr class_id, uptr size) { return 0; // Out of fake stack. uptr ptr = reinterpret_cast(ff); SetShadow(ptr, size, class_id, 0); + + // Poison everything beyond user size, use kNumberOfSizeClasses to prevent + // SetShadow from inlining PoisonShadow + SetShadow(reinterpret_cast(ptr + size), + FakeStack::BytesInSizeClass(class_id) - size, kNumberOfSizeClasses, + kAsanStackRightRedzoneMagic); + return ptr; } diff --git a/compiler-rt/test/asan/TestCases/fakeframe-left-redzone.cpp b/compiler-rt/test/asan/TestCases/fakeframe-left-redzone.cpp new file mode 100644 index 0000000000000..2ce050236e3dc --- /dev/null +++ b/compiler-rt/test/asan/TestCases/fakeframe-left-redzone.cpp @@ -0,0 +1,36 @@ +// RUN: %clangxx_asan -O0 %s -o %t && %env_asan_opts=detect_stack_use_after_return=1 not %run %t 2>&1 | FileCheck %s +// RUN: %clangxx_asan -O0 %s -o %t -fsanitize-address-use-after-return=always && not %run %t 2>&1 | FileCheck %s + +#include "defines.h" +#include +#include + +#define kFrameSize (2048) +#define KFrameSizeMask (0x07ff) + +ATTRIBUTE_NOINLINE +char *pretend_to_do_something(char *x) { + __asm__ __volatile__("" : : "r"(x) : "memory"); + return x; +} + +ATTRIBUTE_NOINLINE +char *OverwriteFakeFrameLastWord() { + char x[1024]; + memset(x, 0, sizeof(x)); + uint64_t ptr_int = (reinterpret_cast(x) & ~KFrameSizeMask) + + kFrameSize - sizeof(char **); + char **ptr = reinterpret_cast(ptr_int); + *ptr = nullptr; + return pretend_to_do_something(x); +} + +int main(int argc, char **argv) { + char *x = OverwriteFakeFrameLastWord(); + // CHECK: ERROR: AddressSanitizer: stack-buffer-overflow on address + // CHECK: is located in stack of thread T0 at offset {{2040|2044}} in frame + // CHECK: in OverwriteFakeFrameLastWord{{.*}}fakeframe-left-redzone.cpp: + // CHECK: [{{16|32}}, {{1040|1056}}) 'x' + pretend_to_do_something(x); + return 0; +} \ No newline at end of file From 5ef1e62f94f6ead641eb1a02b0521129a7176d83 Mon Sep 17 00:00:00 2001 From: lidongyan <502024330056@smail.nju.edu.cn> Date: Wed, 9 Apr 2025 08:51:49 +0800 Subject: [PATCH 4/6] move Poison code inside SetShadow --- compiler-rt/lib/asan/asan_fake_stack.cpp | 19 +++++-------------- ...edzone.cpp => fakeframe-right-redzone.cpp} | 2 +- .../test/ubsan/TestCases/Integer/bit-int.c | 8 -------- 3 files changed, 6 insertions(+), 23 deletions(-) rename compiler-rt/test/asan/TestCases/{fakeframe-left-redzone.cpp => fakeframe-right-redzone.cpp} (93%) diff --git a/compiler-rt/lib/asan/asan_fake_stack.cpp b/compiler-rt/lib/asan/asan_fake_stack.cpp index 7ce7c527a7167..0f696075fb78d 100644 --- a/compiler-rt/lib/asan/asan_fake_stack.cpp +++ b/compiler-rt/lib/asan/asan_fake_stack.cpp @@ -40,6 +40,11 @@ ALWAYS_INLINE void SetShadow(uptr ptr, uptr size, uptr class_id, u64 magic) { // The size class is too big, it's cheaper to poison only size bytes. PoisonShadow(ptr, size, static_cast(magic)); } + + if (magic == 0) { + uptr redzone_size = FakeStack::BytesInSizeClass(class_id) - size; + PoisonShadow(ptr + size, redzone_size, kAsanStackRightRedzoneMagic); + } } FakeStack *FakeStack::Create(uptr stack_size_log) { @@ -232,13 +237,6 @@ static ALWAYS_INLINE uptr OnMalloc(uptr class_id, uptr size) { return 0; // Out of fake stack. uptr ptr = reinterpret_cast(ff); SetShadow(ptr, size, class_id, 0); - - // Poison everything beyond user size, use kNumberOfSizeClasses to prevent - // SetShadow from inlining PoisonShadow - SetShadow(reinterpret_cast(ptr + size), - FakeStack::BytesInSizeClass(class_id) - size, kNumberOfSizeClasses, - kAsanStackRightRedzoneMagic); - return ptr; } @@ -252,13 +250,6 @@ static ALWAYS_INLINE uptr OnMallocAlways(uptr class_id, uptr size) { return 0; // Out of fake stack. uptr ptr = reinterpret_cast(ff); SetShadow(ptr, size, class_id, 0); - - // Poison everything beyond user size, use kNumberOfSizeClasses to prevent - // SetShadow from inlining PoisonShadow - SetShadow(reinterpret_cast(ptr + size), - FakeStack::BytesInSizeClass(class_id) - size, kNumberOfSizeClasses, - kAsanStackRightRedzoneMagic); - return ptr; } diff --git a/compiler-rt/test/asan/TestCases/fakeframe-left-redzone.cpp b/compiler-rt/test/asan/TestCases/fakeframe-right-redzone.cpp similarity index 93% rename from compiler-rt/test/asan/TestCases/fakeframe-left-redzone.cpp rename to compiler-rt/test/asan/TestCases/fakeframe-right-redzone.cpp index 2ce050236e3dc..68128a72c2d6f 100644 --- a/compiler-rt/test/asan/TestCases/fakeframe-left-redzone.cpp +++ b/compiler-rt/test/asan/TestCases/fakeframe-right-redzone.cpp @@ -29,7 +29,7 @@ int main(int argc, char **argv) { char *x = OverwriteFakeFrameLastWord(); // CHECK: ERROR: AddressSanitizer: stack-buffer-overflow on address // CHECK: is located in stack of thread T0 at offset {{2040|2044}} in frame - // CHECK: in OverwriteFakeFrameLastWord{{.*}}fakeframe-left-redzone.cpp: + // CHECK: in OverwriteFakeFrameLastWord{{.*}}fakeframe-right-redzone.cpp: // CHECK: [{{16|32}}, {{1040|1056}}) 'x' pretend_to_do_something(x); return 0; diff --git a/compiler-rt/test/ubsan/TestCases/Integer/bit-int.c b/compiler-rt/test/ubsan/TestCases/Integer/bit-int.c index d7e2c6dc60aa0..33382f63752b2 100644 --- a/compiler-rt/test/ubsan/TestCases/Integer/bit-int.c +++ b/compiler-rt/test/ubsan/TestCases/Integer/bit-int.c @@ -49,13 +49,6 @@ uint32_t unsigned_shift_base() { return x; } -uint32_t array_bounds() { - _BitInt(37) x[4]; - _BitInt(37) y = x[10]; - // CHECK: {{.*}}bit-int.c:[[#@LINE-1]]:19: runtime error: index 10 out of bounds for type - return (uint32_t)y; -} - uint32_t float_cast_overflow() { float a = 100000000.0f; _BitInt(7) b = (_BitInt(7))a; @@ -154,7 +147,6 @@ int main(int argc, char **argv) { pointer_overflow() + vla_bound(argc) + unsigned_shift_base() + - (uint32_t)array_bounds() + float_cast_overflow() + implicit_integer_sign_change((unsigned _BitInt(37))(argc - 2)) + (uint64_t)implicit_signed_integer_truncation() + From dc6e06d281caf49c60f5dade5ea2709d0a81cc15 Mon Sep 17 00:00:00 2001 From: brandb97 <77328395+brandb97@users.noreply.github.com> Date: Wed, 9 Apr 2025 09:04:22 +0800 Subject: [PATCH 5/6] Update fakeframe-right-redzone.cpp --- compiler-rt/test/asan/TestCases/fakeframe-right-redzone.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler-rt/test/asan/TestCases/fakeframe-right-redzone.cpp b/compiler-rt/test/asan/TestCases/fakeframe-right-redzone.cpp index 68128a72c2d6f..da1f5f2fb9789 100644 --- a/compiler-rt/test/asan/TestCases/fakeframe-right-redzone.cpp +++ b/compiler-rt/test/asan/TestCases/fakeframe-right-redzone.cpp @@ -33,4 +33,4 @@ int main(int argc, char **argv) { // CHECK: [{{16|32}}, {{1040|1056}}) 'x' pretend_to_do_something(x); return 0; -} \ No newline at end of file +} From 88f95a2ff1f3805373859cf4068b2b6a66cb2028 Mon Sep 17 00:00:00 2001 From: lidongyan <502024330056@smail.nju.edu.cn> Date: Wed, 9 Apr 2025 09:14:54 +0800 Subject: [PATCH 6/6] force no sanitize uar in ubsan bit-int.c test --- compiler-rt/test/ubsan/TestCases/Integer/bit-int.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/compiler-rt/test/ubsan/TestCases/Integer/bit-int.c b/compiler-rt/test/ubsan/TestCases/Integer/bit-int.c index 33382f63752b2..e15c6e6e1756a 100644 --- a/compiler-rt/test/ubsan/TestCases/Integer/bit-int.c +++ b/compiler-rt/test/ubsan/TestCases/Integer/bit-int.c @@ -1,6 +1,6 @@ // REQUIRES: x86_64-target-arch // REQUIRES: !windows -// RUN: %clang -Wno-constant-conversion -Wno-array-bounds -Wno-division-by-zero -Wno-shift-negative-value -Wno-shift-count-negative -Wno-int-to-pointer-cast -O0 -fsanitize=array-bounds,float-cast-overflow,implicit-integer-sign-change,implicit-signed-integer-truncation,implicit-unsigned-integer-truncation,integer-divide-by-zero,pointer-overflow,shift-base,shift-exponent,signed-integer-overflow,unsigned-integer-overflow,unsigned-shift-base,vla-bound %s -o %t1 && %run %t1 2>&1 | FileCheck %s +// RUN: %clang -Wno-constant-conversion -Wno-array-bounds -Wno-division-by-zero -Wno-shift-negative-value -Wno-shift-count-negative -Wno-int-to-pointer-cast -O0 -fsanitize=array-bounds,float-cast-overflow,implicit-integer-sign-change,implicit-signed-integer-truncation,implicit-unsigned-integer-truncation,integer-divide-by-zero,pointer-overflow,shift-base,shift-exponent,signed-integer-overflow,unsigned-integer-overflow,unsigned-shift-base,vla-bound -fsanitize-address-use-after-return=never %s -o %t1 && %run %t1 2>&1 | FileCheck %s #include #include @@ -49,6 +49,13 @@ uint32_t unsigned_shift_base() { return x; } +uint32_t array_bounds() { + _BitInt(37) x[4]; + _BitInt(37) y = x[10]; + // CHECK: {{.*}}bit-int.c:[[#@LINE-1]]:19: runtime error: index 10 out of bounds for type + return (uint32_t)y; +} + uint32_t float_cast_overflow() { float a = 100000000.0f; _BitInt(7) b = (_BitInt(7))a; @@ -147,6 +154,7 @@ int main(int argc, char **argv) { pointer_overflow() + vla_bound(argc) + unsigned_shift_base() + + (uint32_t)array_bounds() + float_cast_overflow() + implicit_integer_sign_change((unsigned _BitInt(37))(argc - 2)) + (uint64_t)implicit_signed_integer_truncation() +