Skip to content

use after free when attempting to lock RawMutex in a TLS destructor #114

@mtak-

Description

@mtak-

This is a repro for the crash, but the real code is hitting the "use-after-free" error without the deadlock_detection feature on.

Repro:

  • Enable feature deadlock_detection.
  • OSX 10.14
  • RUSTFLAGS="-Z sanitizer=address" cargo run

Code to run:

use crossbeam::thread;
use lock_api::RawMutex as RawMutexTrait;
use parking_lot::RawMutex;

struct A(RawMutex);

impl Drop for A {
    fn drop(&mut self) {
        self.0.lock();
        self.0.unlock();
    }
}

thread_local! {
    static THREAD_A: A = A(RawMutex::INIT);
}

fn main() {
    thread::scope(|scope| {
        scope.spawn(|_| THREAD_A.try_with(|_| {}).unwrap());
    })
    .unwrap();
}
Address Sanitizer Log

==38676==ERROR: AddressSanitizer: heap-use-after-free on address 0x62100000f271 at pc 0x000108cb0a3f bp 0x700001dd06b0 sp 0x700001dcfe60
READ of size 1 at 0x62100000f271 thread T1
    #0 0x108cb0a3e in __asan_memcpy (lib__rustc__clang_rt.asan_osx_dynamic.dylib:x86_64+0x56a3e)
    #1 0x108929436 in core::ptr::read::h69853cfc127d2fa3 ptr.rs:575
    #2 0x108928b12 in core::ptr::swap_nonoverlapping_one::hdc3f73c43de28674 ptr.rs:359
    #3 0x1089097cc in core::mem::swap::h29ed98af3b97fafa mem.rs:653
    #4 0x10890a45d in core::mem::replace::hb63429c87d6fb322 mem.rs:711
    #5 0x108912232 in _$LT$core..cell..Cell$LT$T$GT$$GT$::replace::ha28d1cc8f9cf199c cell.rs:432
    #6 0x108912034 in _$LT$core..cell..Cell$LT$T$GT$$GT$::set::hf913a1c43ebc649b cell.rs:389
    #7 0x108888192 in std::thread::local::fast::destroy_value::hcb1e71b279f15ded local.rs:397
    #8 0x7fff7cc45d7e in tlv_finalize (libdyld.dylib:x86_64+0x16d7e)
    #9 0x7fff7ce386ae in _pthread_tsd_cleanup (libsystem_pthread.dylib:x86_64+0x36ae)
    #10 0x7fff7ce3b6b0 in _pthread_exit (libsystem_pthread.dylib:x86_64+0x66b0)
    #11 0x7fff7ce38347 in _pthread_body (libsystem_pthread.dylib:x86_64+0x3347)
    #12 0x7fff7ce3b2a6 in _pthread_start (libsystem_pthread.dylib:x86_64+0x62a6)
    #13 0x7fff7ce37424 in thread_start (libsystem_pthread.dylib:x86_64+0x2424)

0x62100000f271 is located 369 bytes inside of 4792-byte region [0x62100000f100,0x6210000103b8)
freed by thread T1 here:
    #0 0x108cb367d in wrap_free (lib__rustc__clang_rt.asan_osx_dynamic.dylib:x86_64+0x5967d)
    #1 0x7fff7ce386ae in _pthread_tsd_cleanup (libsystem_pthread.dylib:x86_64+0x36ae)
    #2 0x7fff7ce3b6b0 in _pthread_exit (libsystem_pthread.dylib:x86_64+0x66b0)
    #3 0x7fff7ce38347 in _pthread_body (libsystem_pthread.dylib:x86_64+0x3347)
    #4 0x7fff7ce3b2a6 in _pthread_start (libsystem_pthread.dylib:x86_64+0x62a6)
    #5 0x7fff7ce37424 in thread_start (libsystem_pthread.dylib:x86_64+0x2424)

previously allocated by thread T1 here:
    #0 0x108cb34c3 in wrap_malloc (lib__rustc__clang_rt.asan_osx_dynamic.dylib:x86_64+0x594c3)
    #1 0x7fff7cc32611 in tlv_allocate_and_initialize_for_key (libdyld.dylib:x86_64+0x3611)
    #2 0x7fff7cc32440 in tlv_get_addr (libdyld.dylib:x86_64+0x3440)
    #3 0x108a1ee3d in std::sys_common::thread_info::set::h515643561df38c4d local.rs:296
    #4 0x108833d87 in std::thread::Builder::spawn_unchecked::_$u7b$$u7b$closure$u7d$$u7d$::h4c68fcd5d4a72494 mod.rs:466
    #5 0x108834f68 in _$LT$F$u20$as$u20$alloc..boxed..FnBox$LT$A$GT$$GT$::call_box::h9f84365d026ca6d7 boxed.rs:734
    #6 0x108a228db in std::sys::unix::thread::Thread::new::thread_start::h0b558311a1802cc0 thread.rs:14
    #7 0x7fff7ce3833c in _pthread_body (libsystem_pthread.dylib:x86_64+0x333c)
    #8 0x7fff7ce3b2a6 in _pthread_start (libsystem_pthread.dylib:x86_64+0x62a6)
    #9 0x7fff7ce37424 in thread_start (libsystem_pthread.dylib:x86_64+0x2424)

Thread T1 created by T0 here:
    #0 0x108cab43d in wrap_pthread_create (lib__rustc__clang_rt.asan_osx_dynamic.dylib:x86_64+0x5143d)
    #1 0x108a225ac in std::sys::unix::thread::Thread::new::hcbffd486872edde6 thread.rs:69
    #2 0x108832b87 in std::thread::Builder::spawn_unchecked::h8bf7fa5d5eca2d59 mod.rs:488
    #3 0x1088348e6 in std::thread::Builder::spawn::h53846c93ac11fde9 mod.rs:382
    #4 0x1087d16b1 in crossbeam_utils::thread::ScopedThreadBuilder::spawn::h992371d1eb421459 thread.rs:274
    #5 0x1087d38af in crossbeam_utils::thread::Scope::spawn::h92a5da7d2f39fca7 thread.rs:189
    #6 0x1087fabb3 in parking_lot_test::main::_$u7b$$u7b$closure$u7d$$u7d$::h420e1eebf573289a main.rs:20
    #7 0x1087d5911 in crossbeam_utils::thread::scope::_$u7b$$u7b$closure$u7d$$u7d$::hecfbf052e0360245 thread.rs:125
    #8 0x1087ffce4 in _$LT$std..panic..AssertUnwindSafe$LT$F$GT$$u20$as$u20$core..ops..function..FnOnce$LT$$LP$$RP$$GT$$GT$::call_once::h49cdf5bf74f8e419 panic.rs:309
    #9 0x1087b80f1 in std::panicking::try::do_call::h8fa6bd88d86b93b4 panicking.rs:297
    #10 0x108a22ece in __rust_maybe_catch_panic lib.rs:92
    #11 0x1087b74cf in std::panicking::try::h0eeb96c6b7a03e6d panicking.rs:276
    #12 0x1087ffd04 in std::panic::catch_unwind::h63b6c77bd28f7def panic.rs:388
    #13 0x1087d42c9 in crossbeam_utils::thread::scope::hd21e0af38ff3c0fe thread.rs:125
    #14 0x10882e12c in parking_lot_test::main::h13f22ce88d17c69a main.rs:19
    #15 0x1087b723d in std::rt::lang_start::_$u7b$$u7b$closure$u7d$$u7d$::h318104fd7b4997f7 rt.rs:64
    #16 0x108a20217 in std::panicking::try::do_call::hbeca4642433c0ede panicking.rs:297
    #17 0x108a22ece in __rust_maybe_catch_panic lib.rs:92
    #18 0x108a20d0c in std::rt::lang_start_internal::h8e4e8fac3cfbbe81 rt.rs:48
    #19 0x1087b71ae in std::rt::lang_start::ha4d7e73cc0b47d5d rt.rs:64
    #20 0x10882e301 in main (parking_lot_test:x86_64+0x100078301)
    #21 0x7fff7cc46084 in start (libdyld.dylib:x86_64+0x17084)

SUMMARY: AddressSanitizer: heap-use-after-free (lib__rustc__clang_rt.asan_osx_dynamic.dylib:x86_64+0x56a3e) in __asan_memcpy
Shadow bytes around the buggy address:
  0x1c4200001df0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x1c4200001e00: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x1c4200001e10: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x1c4200001e20: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x1c4200001e30: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
=>0x1c4200001e40: fd fd fd fd fd fd fd fd fd fd fd fd fd fd[fd]fd
  0x1c4200001e50: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x1c4200001e60: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x1c4200001e70: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x1c4200001e80: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x1c4200001e90: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
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
  Shadow gap:              cc
==38676==ABORTING
Illegal instruction: 4

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions