Skip to content

Glibc lock elision allows a value to be locked twice #33770

Closed
@Amanieu

Description

@Amanieu

When running on a processor which support Intel's Restricted Transactional Memory, glibc will not write to a lock (making it appear to be unlocked) and instead begin a transaction. The transaction will catch any conflicts from other threads and aborts, but this doesn't happen when re-locking from the same thread. Instead the lock gets acquired twice, which results in two mutable references to the same value.

Example code:

use std::sync::{Mutex, RwLock};

fn test_mutex() -> i32 {
    let m = Mutex::new(0);
    let mut g = m.lock().unwrap();
    let g2 = m.lock().unwrap();
    *g = 1;
    *g2
}

fn test_rwlock() -> i32 {
    let m = RwLock::new(0);
    let mut g = m.write().unwrap();
    let g2 = m.write().unwrap();
    *g = 1;
    *g2
}

fn main() {
    println!("{}", test_mutex());
    println!("{}", test_rwlock());
}

Output:

$ ./test
1
1

For Mutex, this can be solved by creating the mutex with pthread_mutexattr_settype(PTHREAD_MUTEX_NORMAL). However there is no way to disable this behavior for pthread rwlocks.

Metadata

Metadata

Assignees

No one assigned

    Labels

    I-unsoundIssue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/SoundnessO-linuxOperating system: LinuxP-highHigh priorityT-libs-apiRelevant to the library API team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions