git: 75be70064483 - main - umtx: Do not make an exiting thread the owner of a PI mutex
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Mon, 27 Jul 2026 23:14:56 UTC
The branch main has been updated by markj:
URL: https://cgit.FreeBSD.org/src/commit/?id=75be70064483158da2b89ab412f83a4694560e58
commit 75be70064483158da2b89ab412f83a4694560e58
Author: Mark Johnston <markj@FreeBSD.org>
AuthorDate: 2026-07-27 23:12:37 +0000
Commit: Mark Johnston <markj@FreeBSD.org>
CommitDate: 2026-07-27 23:12:37 +0000
umtx: Do not make an exiting thread the owner of a PI mutex
Otherwise an assertion in umtx_thread_alloc()
(TAILQ_EMPTY(&uq->uq_pi_contested)) is violated.
This use of TDB_EXIT is hacky, but I cannot see another way to check for
an exiting thread without adding some more overhead to kern_thr_exit().
Fixes: 2a339d9e3dc1
Reported by: Maik Muench of Secfault Security
Reviewed by: kib
MFC after: 1 week
Sponsored by: The FreeBSD Foundation
Differential Revision: https://reviews.freebsd.org/D58447
---
sys/kern/kern_umtx.c | 21 +++++++++++++++------
1 file changed, 15 insertions(+), 6 deletions(-)
diff --git a/sys/kern/kern_umtx.c b/sys/kern/kern_umtx.c
index ab6e578ab380..4f6e2b339ba6 100644
--- a/sys/kern/kern_umtx.c
+++ b/sys/kern/kern_umtx.c
@@ -2028,7 +2028,7 @@ int
umtxq_sleep_pi(struct umtx_q *uq, struct umtx_pi *pi, uint32_t owner,
const char *wmesg, struct umtx_abs_timeout *timo, bool shared)
{
- struct thread *td, *td1;
+ struct thread *td;
struct umtx_q *uq1;
int error, pri;
#ifdef INVARIANTS
@@ -2044,13 +2044,22 @@ umtxq_sleep_pi(struct umtx_q *uq, struct umtx_pi *pi, uint32_t owner,
umtxq_insert(uq);
mtx_lock(&umtx_lock);
if (pi->pi_owner == NULL) {
+ struct thread *ownertd;
+
mtx_unlock(&umtx_lock);
- td1 = tdfind(owner, shared ? -1 : td->td_proc->p_pid);
+ ownertd = tdfind(owner, shared ? -1 : td->td_proc->p_pid);
mtx_lock(&umtx_lock);
- if (td1 != NULL) {
- if (pi->pi_owner == NULL)
- umtx_pi_setowner(pi, td1);
- PROC_UNLOCK(td1->td_proc);
+ if (ownertd != NULL) {
+ /*
+ * An exiting thread that has already called
+ * umtx_thread_exit() must not be made the owner of a
+ * shared mutex.
+ */
+ if ((ownertd->td_proc->p_flag & P_WEXIT) == 0 &&
+ (ownertd->td_dbgflags & TDB_EXIT) == 0 &&
+ pi->pi_owner == NULL)
+ umtx_pi_setowner(pi, ownertd);
+ PROC_UNLOCK(ownertd->td_proc);
}
}