[DTrace-devel] [PATCH 4/5] libproc: guard against Puntrace() of terminated processes
Nick Alcock
nick.alcock at oracle.com
Tue Dec 3 11:36:09 UTC 2024
If processes terminate while the main dtrace thread is doing something in
libproc, the process-control thread will clean up, releasing all resources,
including cancelling all ptraces. Unfortunately if the main thread is in
the middle of a Ptrace()-related operation at the time, it will finish off
by doing a balancing Puntrace(). This is of course now unbalanced, because
the process cleanup did all the Puntrace()s for us; it will then try to pop
a state vector that has already been freed, yielding a crash that looks like
this:
at libproc/rtld_db.c:1934
at libdtrace/dt_pid.c:987
at libdtrace/dt_pid.c:1265
rfunc=0x40419e <chewrec>, arg=0x0) at libdtrace/dt_work.c:377
(This can also kick in when DTrace erroneously considers a process dead even
though it isn't, which is actually what happened here: we fix that in a
later commit.)
Fixed by simply checking to see if the process has been Prelease()d in
Puntrace(), and returning early. The process is released and all
Puntrace()s have already been done: there is nothing left to do.
Signed-off-by: Nick Alcock <nick.alcock at oracle.com>
---
libproc/Pcontrol.c | 12 +++++++++++-
1 file changed, 11 insertions(+), 1 deletion(-)
diff --git a/libproc/Pcontrol.c b/libproc/Pcontrol.c
index a32a362eaa1fb..6a454ef86bc3b 100644
--- a/libproc/Pcontrol.c
+++ b/libproc/Pcontrol.c
@@ -1455,12 +1455,22 @@ Puntrace(struct ps_prochandle *P, int leave_stopped)
int prev_state;
/*
- * Protect against unbalanced Ptrace()/Puntrace().
+ * Protect against unbalanced Ptrace()/Puntrace() and already-
+ * terminated processes; operations interrupted by process termination
+ * might reasonably do a Puntrace() to balance out a previous Ptrace(),
+ * but everything is freed and we just want to drop out after balancing
+ * the ptrace() count.
*/
if ((!P->ptraced) || (P->ptrace_count == 0))
return;
P->ptrace_count--;
+
+ if (P->released) {
+ _dprintf("%i: Puntrace(): early return, process is released\n", P->pid);
+ return;
+ }
+
prev_state = Ppop_state(P);
/*
--
2.47.1.279.g84c5f4e78e
More information about the DTrace-devel
mailing list