The branch main has been updated by markj:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=75be70064483158da2b89ab412f83a4694560e58

commit 75be70064483158da2b89ab412f83a4694560e58
Author:     Mark Johnston <[email protected]>
AuthorDate: 2026-07-27 23:12:37 +0000
Commit:     Mark Johnston <[email protected]>
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);
                }
        }
 

Reply via email to