From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from lists.gentoo.org (pigeon.gentoo.org [208.92.234.80]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by finch.gentoo.org (Postfix) with ESMTPS id BC9BD158086 for ; Thu, 21 Oct 2021 22:30:52 +0000 (UTC) Received: from pigeon.gentoo.org (localhost [127.0.0.1]) by pigeon.gentoo.org (Postfix) with SMTP id F1767E0880; Thu, 21 Oct 2021 22:30:50 +0000 (UTC) Received: from smtp.gentoo.org (woodpecker.gentoo.org [140.211.166.183]) (using TLSv1.2 with cipher ECDHE-RSA-CHACHA20-POLY1305 (256/256 bits)) (No client certificate requested) by pigeon.gentoo.org (Postfix) with ESMTPS id C7177E0880 for ; Thu, 21 Oct 2021 22:30:50 +0000 (UTC) Received: from oystercatcher.gentoo.org (unknown [IPv6:2a01:4f8:202:4333:225:90ff:fed9:fc84]) (using TLSv1.2 with cipher ECDHE-RSA-CHACHA20-POLY1305 (256/256 bits)) (No client certificate requested) by smtp.gentoo.org (Postfix) with ESMTPS id 6B7633433B8 for ; Thu, 21 Oct 2021 22:30:49 +0000 (UTC) Received: from localhost.localdomain (localhost [IPv6:::1]) by oystercatcher.gentoo.org (Postfix) with ESMTP id 11802156 for ; Thu, 21 Oct 2021 22:30:48 +0000 (UTC) From: "Mike Frysinger" To: gentoo-commits@lists.gentoo.org Content-Transfer-Encoding: 8bit Content-type: text/plain; charset=UTF-8 Reply-To: gentoo-dev@lists.gentoo.org, "Mike Frysinger" Message-ID: <1634809868.e9946633344c34b295485130f8f0fceb10fedc96.vapier@gentoo> Subject: [gentoo-commits] proj/sandbox:master commit in: libsandbox/, tests/ X-VCS-Repository: proj/sandbox X-VCS-Files: libsandbox/trace.c tests/trace-0 X-VCS-Directories: tests/ libsandbox/ X-VCS-Committer: vapier X-VCS-Committer-Name: Mike Frysinger X-VCS-Revision: e9946633344c34b295485130f8f0fceb10fedc96 X-VCS-Branch: master Date: Thu, 21 Oct 2021 22:30:48 +0000 (UTC) Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: List-Id: Gentoo Linux mail X-BeenThere: gentoo-commits@lists.gentoo.org X-Auto-Response-Suppress: DR, RN, NRN, OOF, AutoReply X-Archives-Salt: 825448ce-1ec0-482d-bbbb-90e15830e87d X-Archives-Hash: 494c133a781c07abb133b807d07a5d59 commit: e9946633344c34b295485130f8f0fceb10fedc96 Author: Mike Frysinger gentoo org> AuthorDate: Thu Oct 21 09:51:08 2021 +0000 Commit: Mike Frysinger gentoo org> CommitDate: Thu Oct 21 09:51:08 2021 +0000 URL: https://gitweb.gentoo.org/proj/sandbox.git/commit/?id=e9946633 libsandbox: switch tracing from signal handler to waitpid Since we can get all the details we need from the existing waitpid call, there's no need for an async signal handler. We can merge that logic into the main synchronous loop. This makes the code a lot easier to reason about as we know it's fully contained here. Signed-off-by: Mike Frysinger gentoo.org> libsandbox/trace.c | 126 ++++++++++++++++++++++++----------------------------- tests/trace-0 | 2 +- 2 files changed, 59 insertions(+), 69 deletions(-) diff --git a/libsandbox/trace.c b/libsandbox/trace.c index fc700e3..8394b71 100644 --- a/libsandbox/trace.c +++ b/libsandbox/trace.c @@ -178,20 +178,6 @@ static char *do_peekstr(unsigned long lptr) } } -static const char *strcld_chld(int cld) -{ - switch (cld) { -#define C(c) case CLD_##c: return "CLD_"#c; - C(CONTINUED) - C(DUMPED) - C(EXITED) - C(KILLED) - C(TRAPPED) - C(STOPPED) -#undef C - default: return "CLD_???"; - } -} /* strsignal() translates the string when i want C define */ static const char *strsig(int sig) { @@ -214,47 +200,6 @@ static const char *strsig(int sig) } } -static void trace_child_signal(int signo, siginfo_t *info, void *context) -{ - sb_debug("got sig %s(%i): code:%s(%i) status:%s(%i)", - strsig(signo), signo, - strcld_chld(info->si_code), info->si_code, - strsig(info->si_status), info->si_status); - - switch (info->si_code) { - case CLD_DUMPED: - case CLD_KILLED: - trace_exit(128 + info->si_status); - - case CLD_EXITED: - __sb_debug(" = %i\n", info->si_status); - trace_exit(info->si_status); - - case CLD_TRAPPED: - switch (info->si_status) { - case SIGSTOP: - kill(trace_pid, SIGCONT); - case SIGTRAP: - case SIGCONT: - return; - } - - /* For whatever signal the child caught, let's ignore it and - * continue on. If it aborted, segfaulted, whatever, that's - * its problem, not ours, so don't whine about it. We just - * have to be sure to bubble it back up. #265072 - */ - do_ptrace(PTRACE_CONT, NULL, (void *)(long)info->si_status); - return; - } - - sb_eerror("ISE:trace_child_signal: child (%i) signal %s(%i), code %s(%i), status %s(%i)\n", - trace_pid, - strsig(signo), signo, - strcld_chld(info->si_code), info->si_code, - strsig(info->si_status), info->si_status); -} - static const struct syscall_entry *lookup_syscall_in_tbl(const struct syscall_entry *tbl, int nr) { while (tbl->name) @@ -441,8 +386,9 @@ static void trace_loop(void) { trace_regs regs; bool before_exec, before_syscall, fake_syscall_ret; + unsigned event; long ret; - int nr, status; + int nr, status, sig; const struct syscall_entry *se, *tbl_after_fork; before_exec = true; @@ -453,16 +399,63 @@ static void trace_loop(void) ret = do_ptrace(PTRACE_SYSCALL, NULL, NULL); waitpid(trace_pid, &status, 0); - if (before_exec) { - unsigned event = ((unsigned)status >> 16); - if (event == PTRACE_EVENT_EXEC) { - _sb_debug("hit exec!"); - before_exec = false; - } else + event = (unsigned)status >> 16; + + if (WIFSIGNALED(status)) { + int sig = WTERMSIG(status); + sb_debug("signaled %s %i", strsig(sig), sig); + kill(getpid(), sig); + trace_exit(128 + sig); + + } else if (WIFEXITED(status)) { + ret = WEXITSTATUS(status); + sb_debug("exited %li", ret); + trace_exit(ret); + + } + + sb_assert(WIFSTOPPED(status)); + sig = WSTOPSIG(status); + + switch (event) { + case 0: + if (sig != (SIGTRAP | 0x80)) { + /* For whatever signal the child caught, let's ignore it and + * continue on. If it aborted, segfaulted, whatever, that's + * its problem, not ours, so don't whine about it. We just + * have to be sure to bubble it back up. #265072 + * + * The next run of this loop should see the WIFSIGNALED status + * and we'll exit then. + */ + sb_debug("passing signal through %s (%i)", strsig(sig), sig); + do_ptrace(PTRACE_CONT, NULL, (void *)(uintptr_t)(sig)); + continue; + } + + if (before_exec) { _sb_debug("waiting for exec; status: %#x", status); + continue; + } + break; + + case PTRACE_EVENT_EXEC: + __sb_debug("hit exec!"); + before_exec = false; ret = trace_get_regs(®s); tbl_after_fork = trace_check_personality(®s); continue; + + case PTRACE_EVENT_EXIT: + /* We'll tell the process to resume, which should make it exit, + * and then we'll pick up its exit status and exit above. + */ + __sb_debug(" exit event!\n"); + continue; + + default: + sb_ebort("ISE: unhandle ptrace signal %s (%i) event %u\n", + strsig(sig), sig, event); } ret = trace_get_regs(®s); @@ -499,17 +492,14 @@ static void trace_loop(void) void trace_main(const char *filename, char *const argv[]) { - struct sigaction sa, old_sa; - - sa.sa_flags = SA_RESTART | SA_SIGINFO; - sa.sa_sigaction = trace_child_signal; - sigaction(SIGCHLD, &sa, &old_sa); + struct sigaction old_sa, sa = { .sa_handler = SIG_DFL, }; sb_debug_dyn("trace_main: tracing: %s\n", filename); if (trace_pid) sb_ebort("ISE: trace code assumes multiple threads are not forking\n"); + sigaction(SIGCHLD, &sa, &old_sa); trace_pid = fork(); if (unlikely(trace_pid == -1)) { sb_ebort("ISE: vfork() failed: %s\n", strerror(errno)); @@ -517,7 +507,7 @@ void trace_main(const char *filename, char *const argv[]) sb_debug("parent waiting for child (pid=%i) to signal", trace_pid); waitpid(trace_pid, NULL, 0); do_ptrace(PTRACE_SETOPTIONS, NULL, - (void *)(PTRACE_O_TRACESYSGOOD | PTRACE_O_TRACEEXEC)); + (void *)(PTRACE_O_TRACESYSGOOD | PTRACE_O_TRACEEXEC | PTRACE_O_TRACEEXIT)); sb_close_all_fds(); trace_loop(); sb_ebort("ISE: child should have quit, as should we\n"); diff --git a/tests/trace-0 b/tests/trace-0 index 5a91c7a..99f3037 100755 --- a/tests/trace-0 +++ b/tests/trace-0 @@ -1,6 +1,6 @@ #!/bin/sh # make sure trace support exists -if grep -q trace_child_signal "$abs_top_builddir"/libsandbox/.libs/libsandbox.so ; then +if grep -q trace_loop "$abs_top_builddir"/libsandbox/.libs/libsandbox.so ; then # see comment at top of script-0 -- same issue applies here because # the ld.so isn't around to load the correct sandbox lib for us exec script-0