From cca59c4d757c99df14978d1778b6be562dd886cd Mon Sep 17 00:00:00 2001 From: Malfurious Date: Fri, 29 Sep 2023 18:48:41 -0400 Subject: Workaround SIGSTOP on child process startup The debugger design prefers to use PTRACE_SEIZE instead of PTRACE_ATTACH, due to the simpler thread control semantics that are available. However, to utilize the same featureset for forked processes, we can no longer use PTRACE_TRACEME to guarantee that the child becomes a tracee before it execs into the target program. Manually raising SIGSTOP to act as a synchronization point is problematic for a couple reasons: - We need to detect whether the special SIGSTOP was or was not yet encountered by the time our debugger module attaches and interrupts the thread. This complicates the dance of input controls to ensure we are at the exec (and nowhere else) when the real user takes over the controls. - The injection of an extra signal circumvents the benefits we hope to leverage by using the PTRACE_SEIZE semantics. We can no longer assume that all incoming signals are genuine. For the time being, sleep in the newly forked child for the scheduler delay period. This is not bullet-proof, but tends to allow the debugger module enough time to actually seize the thread before anything interesting happens. At this point a single dbg_cont() will cause the child to arrive and stop at the user's exec. Signed-off-by: Malfurious --- debugger.c | 3 ++- misplays.c | 7 ++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/debugger.c b/debugger.c index 572231c..d016076 100644 --- a/debugger.c +++ b/debugger.c @@ -17,7 +17,8 @@ static const int PTRACE_OPTIONS = PTRACE_O_TRACECLONE | - PTRACE_O_TRACEEXIT | + //PTRACE_O_TRACEEXIT | + PTRACE_O_TRACEEXEC | PTRACE_O_TRACESYSGOOD; static int detect_breakpoint(struct thread *th) { diff --git a/misplays.c b/misplays.c index da15a30..2f0ce8f 100644 --- a/misplays.c +++ b/misplays.c @@ -27,9 +27,10 @@ static pid_t dofork(char **argv, struct console *cons) { } if (pid == 0) { + usleep(100000); console_configslave(cons); close_range(STDERR_FILENO+1, ~0U, CLOSE_RANGE_UNSHARE); - raise(SIGSTOP); // ptrace(PTRACE_TRACEME, 0, NULL, NULL); + //raise(SIGSTOP); // ptrace(PTRACE_TRACEME, 0, NULL, NULL); execvp(argv[0], argv); exit(EXIT_FAILURE); } @@ -209,6 +210,10 @@ int main(int argc, char **argv) { list_insert(processes.end, proc); th = proc->threads.head; + if (child) { + dbg_cont(th, PTRACE_CONT); + } + cursinit(); left = newpan(0, 0, 0, 0); right = newpan(0, 0, 0, 0); -- cgit v1.2.3