Skip to content
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

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

Closed
mtak- opened this issue Jan 11, 2019 · 2 comments
Closed

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

mtak- opened this issue Jan 11, 2019 · 2 comments

Comments

@mtak-
Copy link

mtak- commented Jan 11, 2019

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

@mtak- mtak- changed the title use after free when attempt to lock RawMutex in a TLS destructor use after free when attempting to lock RawMutex in a TLS destructor Jan 11, 2019
@Amanieu
Copy link
Owner

Amanieu commented Jan 11, 2019

This looks more like a Rust/OSX bug than a parking_lot bug. If I understand the ASAN log correctly, it seems that thread-local storage is being freed before functions registered with _tlv_atexit are called?

You should re-submit this as a bug to rust-lang/rust. (Also I can't test it myself since I don't have access to an OSX machine)

@mtak-
Copy link
Author

mtak- commented Jan 11, 2019

You are correct. I'm able to repro it without parking_lot.

I'll post it in rust-lang/rust

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants