pthread_mutex_unlock potentially cause invalid access

KOSAKI Motohiro kosaki.motohiro@gmail.com
Mon Feb 13 15:29:00 GMT 2012


>>    obj_done(struct obj *op)
>>    {
>>        pthread_mutex_lock(&op->om);
>>        if (--op->refcnt == 0) {
>>            pthread_mutex_unlock(&op->om);
>>    (A)     pthread_mutex_destroy(&op->om);
>>    (B)     free(op);
>>        } else
>>    (C)     pthread_mutex_unlock(&op->om);
>>    }
>>
>>    In this case obj is reference counted and obj_done() is called
>>    whenever a reference to the object is dropped. Implementations are
>>    required to allow an object to be destroyed and freed and potentially
>>    unmapped (for example, lines A and B) immediately after the object is
>>    unlocked (line C).
>> ------------------------------------------------------------------------
>>
>> In this example, (A) and (B) can be executed in middle of (C) execution.
>> Thus, problem can be happen even on a fully conforming program, no?
>
> No. (A) and (B) can not be executed in the middle of (C).

It can.
Look again, lll_unlock() call atomic_exchange_rel() _before_
(mutex)->__data dereference.

>   int *__futex = &(mutex->__data.__lock);
>   int __val = atomic_exchange_rel (__futex, 0);
>   if (__builtin_expect (__val > 1, 0))                /* A */
>     lll_futex_wake (__futex, 1, ((mutex)->__data.__kind & 128)); /* B */


1) Thread-1) atomic_exchange_rel(0)
2) preempt
3) Thread-2) call mutex_lock(). (ok, it's success)
4) Thread-2) call mutex_unlock()
5) Thread-2) call mutex_destroy()
6) Thread-2) free(mutex)
7) preempt
8) Thread-3)  reuse memory of the mutex
9) preempt
10) Thread-1) dereference (mutex)->__data__.__kind

I don't think this example code makes much sense. but it is a part of
the standard. I believe people suspect libc honor the standard.



More information about the Libc-alpha mailing list