Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions compiler-rt/lib/hwasan/hwasan_platform_interceptors.h
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
19 changes: 19 additions & 0 deletions compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc
Original file line number Diff line number Diff line change
Expand Up @@ -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
Copy link
Contributor

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?

Copy link
Contributor Author

@thurstond thurstond Nov 21, 2024

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

// 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));
Expand Down Expand Up @@ -10324,6 +10342,7 @@ static void InitializeCommonInterceptors() {
INIT_TIMER_CREATE;
INIT_GETITIMER;
INIT_TIME;
INIT_TIMESPEC_GET;
INIT_GLOB;
INIT_GLOB64;
INIT___B64_TO;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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
Expand Down
Loading