diff --git a/src/thread/pthread_mutex_destroy.c b/src/thread/pthread_mutex_destroy.c index 8d1bf77b..c56e9fbd 100644 --- a/src/thread/pthread_mutex_destroy.c +++ b/src/thread/pthread_mutex_destroy.c @@ -6,5 +6,13 @@ int pthread_mutex_destroy(pthread_mutex_t *mutex) * type (tracking ownership), it might be in the pending slot of a * robust_list; wait for quiescence. */ if (mutex->_m_type > 128) __vm_wait(); + + /* Setup a non-robust errorchecking mutex in ownerdead state so + * use after destruction can be trapped. */ + mutex->_m_type = 3; + mutex->_m_prev = mutex->_m_next = 0; + mutex->_m_lock = 0x7fffffff; + mutex->_m_count = 0; + return 0; } diff --git a/src/thread/pthread_mutex_trylock.c b/src/thread/pthread_mutex_trylock.c index a24e7c58..8d6102cb 100644 --- a/src/thread/pthread_mutex_trylock.c +++ b/src/thread/pthread_mutex_trylock.c @@ -21,7 +21,11 @@ int __pthread_mutex_trylock_owner(pthread_mutex_t *m) return 0; } } - if (own == 0x3fffffff) return ENOTRECOVERABLE; + if (own == 0x3fffffff) { + /* Catch use-after-destroy */ + if (!(type & 8)) a_crash(); + return ENOTRECOVERABLE; + } if (own || (old && !(type & 4))) return EBUSY; if (type & 128) { diff --git a/src/thread/pthread_mutex_unlock.c b/src/thread/pthread_mutex_unlock.c index b66423e6..fe159804 100644 --- a/src/thread/pthread_mutex_unlock.c +++ b/src/thread/pthread_mutex_unlock.c @@ -14,8 +14,11 @@ int __pthread_mutex_unlock(pthread_mutex_t *m) self = __pthread_self(); old = m->_m_lock; int own = old & 0x3fffffff; - if (own != self->tid) + if (own != self->tid) { + /* Catch use-after-destroy */ + if (own == 0x3fffffff && !(type & 8)) a_crash(); return EPERM; + } if ((type&3) == PTHREAD_MUTEX_RECURSIVE && m->_m_count) return m->_m_count--, 0; if ((type&4) && (old&0x40000000))