git: b63281884e0e - main - ptrace(): p_xthread could be NULL for P_STOPPED_TRACE
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Sun, 27 Apr 2025 21:52:47 UTC
The branch main has been updated by kib:
URL: https://cgit.FreeBSD.org/src/commit/?id=b63281884e0e1530de999723532f2d536cb32477
commit b63281884e0e1530de999723532f2d536cb32477
Author: Konstantin Belousov <kib@FreeBSD.org>
AuthorDate: 2025-04-20 23:19:35 +0000
Commit: Konstantin Belousov <kib@FreeBSD.org>
CommitDate: 2025-04-27 21:52:04 +0000
ptrace(): p_xthread could be NULL for P_STOPPED_TRACE
Suppose that ptrace(PT_ATTACH) is called on mt process, and the thread
arbitrary selected as leader (p_xthread) by the attach code, is already
in kernel preparing to exit as the process lock becomes available. Then
the thread_exit() function clears p->p_xthread, and we end up with the
traced signal-stopped process with NULL p_xthread.
This state is legitimate, and really p_xthread must point to a thread
that is inside ptracestop(). If p_xthread is NULL, but ptrace code
requires some leader thread, arbitrarly designate it as needed.
Reported and tested by: pho
Reviewed by: markj
Sponsored by: The FreeBSD Foundation
MFC after: 2 weeks
Differential revision: https://reviews.freebsd.org/D49961
---
sys/kern/sys_process.c | 23 ++++++++++++-----------
1 file changed, 12 insertions(+), 11 deletions(-)
diff --git a/sys/kern/sys_process.c b/sys/kern/sys_process.c
index 5126f34e3dc3..69ea3d97d505 100644
--- a/sys/kern/sys_process.c
+++ b/sys/kern/sys_process.c
@@ -930,12 +930,10 @@ kern_ptrace(struct thread *td, int req, pid_t pid, void *addr, int data)
}
if (tid == 0) {
- if ((p->p_flag & P_STOPPED_TRACE) != 0) {
- KASSERT(p->p_xthread != NULL, ("NULL p_xthread"));
+ if ((p->p_flag & P_STOPPED_TRACE) != 0)
td2 = p->p_xthread;
- } else {
+ if (td2 == NULL)
td2 = FIRST_THREAD_IN_PROC(p);
- }
tid = td2->td_tid;
}
@@ -1322,16 +1320,19 @@ kern_ptrace(struct thread *td, int req, pid_t pid, void *addr, int data)
/*
* Clear the pending event for the thread that just
- * reported its event (p_xthread). This may not be
- * the thread passed to PT_CONTINUE, PT_STEP, etc. if
- * the debugger is resuming a different thread.
+ * reported its event (p_xthread), if any. This may
+ * not be the thread passed to PT_CONTINUE, PT_STEP,
+ * etc. if the debugger is resuming a different
+ * thread. There might be no reporting thread if
+ * the process was just attached.
*
* Deliver any pending signal via the reporting thread.
*/
- MPASS(p->p_xthread != NULL);
- p->p_xthread->td_dbgflags &= ~TDB_XSIG;
- p->p_xthread->td_xsig = data;
- p->p_xthread = NULL;
+ if (p->p_xthread != NULL) {
+ p->p_xthread->td_dbgflags &= ~TDB_XSIG;
+ p->p_xthread->td_xsig = data;
+ p->p_xthread = NULL;
+ }
p->p_xsig = data;
/*