-
Notifications
You must be signed in to change notification settings - Fork 13.6k
[sanitizer_common] Intercept timespec_get except for hwasan #117080
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Intercept timespec_get for all sanitizers except for hwasan
@llvm/pr-subscribers-compiler-rt-sanitizer Author: Thurston Dang (thurstond) ChangesIntercept timespec_get for all sanitizers except for hwasan Full diff: https://github.com/llvm/llvm-project/pull/117080.diff 3 Files Affected:
diff --git a/compiler-rt/lib/hwasan/hwasan_platform_interceptors.h b/compiler-rt/lib/hwasan/hwasan_platform_interceptors.h
index e8011014c2331d..8a653d83dec651 100644
--- a/compiler-rt/lib/hwasan/hwasan_platform_interceptors.h
+++ b/compiler-rt/lib/hwasan/hwasan_platform_interceptors.h
@@ -209,6 +209,9 @@
#undef SANITIZER_INTERCEPT_TIME
#define SANITIZER_INTERCEPT_TIME 0
+#undef SANITIZER_INTERCEPT_TIMESPEC_GET
+#define SANITIZER_INTERCEPT_TIMESPEC_GET 0
+
#undef SANITIZER_INTERCEPT_GLOB
#define SANITIZER_INTERCEPT_GLOB 0
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc
index 99fa737adfaf26..07b65a1f0c15ee 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc
@@ -2389,6 +2389,24 @@ INTERCEPTOR(int, setitimer, int which, const void *new_value, void *old_value) {
#define INIT_GETITIMER
#endif
+#if SANITIZER_INTERCEPT_TIMESPEC_GET
+INTERCEPTOR(int, timespec_get, struct __sanitizer_timespec *ts, int base) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, timespec_get, ts, base);
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ int res = REAL(timespec_get)(ts, base);
+ if (res) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ts, sizeof(struct __sanitizer_timespec));
+ }
+ return res;
+}
+#define INIT_TIMESPEC_GET COMMON_INTERCEPT_FUNCTION(timespec_get);
+#else
+#define INIT_TIMESPEC_GET
+#endif
+
#if SANITIZER_INTERCEPT_GLOB
static void unpoison_glob_t(void *ctx, __sanitizer_glob_t *pglob) {
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pglob, sizeof(*pglob));
@@ -10324,6 +10342,7 @@ static void InitializeCommonInterceptors() {
INIT_TIMER_CREATE;
INIT_GETITIMER;
INIT_TIME;
+ INIT_TIMESPEC_GET;
INIT_GLOB;
INIT_GLOB64;
INIT___B64_TO;
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h b/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h
index 1f78b1af8e2c6f..36f18acc15fe14 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h
@@ -210,8 +210,6 @@ SANITIZER_WEAK_IMPORT void *aligned_alloc(__sanitizer::usize __alignment,
#define SANITIZER_INTERCEPT_PREAD64 (SI_GLIBC || SI_SOLARIS32)
#define SANITIZER_INTERCEPT_PWRITE64 (SI_GLIBC || SI_SOLARIS32)
-#define SANITIZER_INTERCEPT_LSEEK64 (SI_GLIBC || SI_SOLARIS32)
-
#define SANITIZER_INTERCEPT_READV SI_POSIX
#define SANITIZER_INTERCEPT_WRITEV SI_POSIX
@@ -263,6 +261,7 @@ SANITIZER_WEAK_IMPORT void *aligned_alloc(__sanitizer::usize __alignment,
#define SANITIZER_INTERCEPT_TIMER_CREATE SI_GLIBC
#define SANITIZER_INTERCEPT_GETITIMER SI_POSIX
#define SANITIZER_INTERCEPT_TIME SI_POSIX
+#define SANITIZER_INTERCEPT_TIMESPEC_GET SI_LINUX
#define SANITIZER_INTERCEPT_GLOB (SI_GLIBC || SI_SOLARIS)
#define SANITIZER_INTERCEPT_GLOB64 SI_GLIBC
#define SANITIZER_INTERCEPT___B64_TO SI_LINUX_NOT_ANDROID
|
✅ With the latest revision this PR passed the C/C++ code formatter. |
INTERCEPTOR(int, timespec_get, struct __sanitizer_timespec *ts, int base) { | ||
void *ctx; | ||
COMMON_INTERCEPTOR_ENTER(ctx, timespec_get, ts, base); | ||
// FIXME: under ASan the call below may write to freed memory and corrupt |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
confirming: if this is a uaf, then asan might corrupt the metadata? is that correct?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With this test:
struct timespec* tp = (struct timespec*)malloc(sizeof(struct timespec));
free (tp);
int res = timespec_get(tp, TIME_UTC);
and 6865d0a, ASan gives an error message something like this:
==2764516==ERROR: AddressSanitizer: heap-use-after-free on address 0x7bdeeae20010 at pc 0x55fe6d1f968d bp 0x7ffefcc6ad30 sp 0x7ffefcc6a508
WRITE of size 16 at 0x7bdeeae20010 thread T0
#0 0x55fe6d1f968c (/tmp/t-uaf+0x5b68c)
#1 0x55fe6d2ae3c3 (/tmp/t-uaf+0x1103c3)
...
0x7bdeeae20010 is located 0 bytes inside of 16-byte region [0x7bdeeae20010,0x7bdeeae20020)
freed by thread T0 here:
AddressSanitizer: CHECK failed: asan_descriptions.cpp:178 "((res.trace)) != (0)" (0x0, 0x0) (tid=2764516)
#0 0x55fe6d275691 (/tmp/t-uaf+0xd7691)
#1 0x55fe6d290712 (/tmp/t-uaf+0xf2712)
...
which is not the usual backtrace / sanitizer report. (I think the corruption is relatively mild - it still showed "heap-use-after-free" - because timespec_get only writes 16 bytes.)
In any case, I've fixed the issue in 97834fa:
==2773902==ERROR: AddressSanitizer: heap-use-after-free on address 0x7bc8d0e20010 at pc 0x5646802e96da bp 0x7ffc27901ec0 sp 0x7ffc27901678
WRITE of size 16 at 0x7bc8d0e20010 thread T0
#0 0x5646802e96d9 (/tmp/t-uaf+0x5b6d9)
#1 0x56468039e403 (/tmp/t-uaf+0x110403)
#2 0x7fa8d1d43b89 (/lib/x86_64-linux-gnu/libc.so.6+0x27b89) (BuildId: 3ddd476a0eddfeb6390b2791bd945afaa13978ff)
#3 0x7fa8d1d43c44 (/lib/x86_64-linux-gnu/libc.so.6+0x27c44) (BuildId: 3ddd476a0eddfeb6390b2791bd945afaa13978ff)
#4 0x5646802ba360 (/tmp/t-uaf+0x2c360)
0x7bc8d0e20010 is located 0 bytes inside of 16-byte region [0x7bc8d0e20010,0x7bc8d0e20020)
freed by thread T0 here:
#0 0x5646803599d6 (/tmp/t-uaf+0xcb9d6)
#1 0x56468039e3f5 (/tmp/t-uaf+0x1103f5)
#2 0x7fa8d1d43b89 (/lib/x86_64-linux-gnu/libc.so.6+0x27b89) (BuildId: 3ddd476a0eddfeb6390b2791bd945afaa13978ff)
previously allocated by thread T0 here:
#0 0x564680359c74 (/tmp/t-uaf+0xcbc74)
#1 0x56468039e3e8 (/tmp/t-uaf+0x1103e8)
#2 0x7fa8d1d43b89 (/lib/x86_64-linux-gnu/libc.so.6+0x27b89) (BuildId: 3ddd476a0eddfeb6390b2791bd945afaa13978ff)
SUMMARY: AddressSanitizer: heap-use-after-free (/tmp/t-uaf+0x5b6d9)
Shadow bytes around the buggy address:
0x7bc8d0e1fd80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x7bc8d0e1fe00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x7bc8d0e1fe80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x7bc8d0e1ff00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x7bc8d0e1ff80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x7bc8d0e20000: fa fa[fd]fd fa fa fa fa fa fa fa fa fa fa fa fa
0x7bc8d0e20080: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x7bc8d0e20100: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x7bc8d0e20180: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x7bc8d0e20200: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x7bc8d0e20280: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
==2773902==ABORTING
Intercept timespec_get for all sanitizers except for hwasan