NOMMU bogus syscall return values
Rich Felker
dalias at libc.org
Mon Feb 29 20:56:54 UTC 2016
I've been trying to use strace on a NOMMU system (sh2) and have been
experiencing an issue where the return value (read from r0) and args
5/6 (r0,r1) are bogus, making the output much less useful than it
otherwise would be. The problem seems to be that the tracer is
desynced with the child's STOP parity and is confusing syscall
entry/exit, probably due to exec_or_die not stopping itself before
exec to sync with the parent. Even if not for the bug I'm
experiencing, this seems to be problematic in that early syscalls in
the child can be lost (I've actually hit that problem too).
The attached (very hackish at the moment) patch makes it work for me
by eliminating the need to define NOMMU_SYSTEM to 1 and using clone()
with CLONE_VM and a new stack for the child, instead of vfork. I see
some potential issues that need to be addressed before this could be
made into a proper solution, though:
1. I'm not sure if all NOMMU systems strace supports have clone. If
so, I think vfork could be dropped completely and this used
instead.
2. The feature checks which were bypassed on NOMMU, and which I
hard-bypassed, could also be changed to use clone.
3. My approach is not directly applicable to daemonized tracer mode
without some significant refactoring; either the entire remainder
of init() and main() would need to be moved into a function that
runs in the child, or longjmp back to the parent's call frame would
need to be performed with some synchronization to make it safe.
An alternate approach would be to keep vfork but have strace self-exec
itself with a special argument to make it STOP itself then exec. For
what it's worth this could be significantly slower on NOMMU especially
if not using a binary format that's capable of sharing text.
Any thoughts on whether changes like this would be acceptable
upstream?
Rich
-------------- next part --------------
--- strace.c.orig 2016-02-29 03:53:49.113264699 +0000
+++ strace.c 2016-02-29 19:00:03.704101962 +0000
@@ -28,8 +28,10 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#define _GNU_SOURCE
#include "defs.h"
#include <stdarg.h>
+#include <sched.h>
#include <sys/param.h>
#include <fcntl.h>
#include <sys/resource.h>
@@ -1155,6 +1157,14 @@ exec_or_die(void)
perror_msg_and_die("exec");
}
+static char child_stack[16384];
+
+static int exec_or_die_wrapper(void *arg)
+{
+ exec_or_die();
+ return 0; /* unreachable */
+}
+
static void
startup_child(char **argv)
{
@@ -1228,24 +1238,21 @@ startup_child(char **argv)
* On NOMMU, can be safely freed only after execve in tracee.
* It's hard to know when that happens, so we just leak it.
*/
- params_for_tracee.pathname = NOMMU_SYSTEM ? strdup(pathname) : pathname;
+ //params_for_tracee.pathname = NOMMU_SYSTEM ? strdup(pathname) : pathname;
+ params_for_tracee.pathname = strdup(pathname);
#if defined HAVE_PRCTL && defined PR_SET_PTRACER && defined PR_SET_PTRACER_ANY
if (daemonized_tracer)
prctl(PR_SET_PTRACER, PR_SET_PTRACER_ANY);
#endif
- pid = fork();
+ pid = daemonized_tracer ? fork() :
+ clone(exec_or_die_wrapper, child_stack + sizeof child_stack / 2,
+ CLONE_VM|SIGCHLD, 0);
if (pid < 0) {
perror_msg_and_die("fork");
}
- if ((pid != 0 && daemonized_tracer)
- || (pid == 0 && !daemonized_tracer)
- ) {
- /* We are to become the tracee. Two cases:
- * -D: we are parent
- * not -D: we are child
- */
+ if (pid && daemonized_tracer) {
exec_or_die();
}
@@ -1334,7 +1341,7 @@ test_ptrace_setoptions_followfork(void)
PTRACE_O_TRACEVFORK;
/* Need fork for test. NOMMU has no forks */
- if (NOMMU_SYSTEM)
+ if (1 || NOMMU_SYSTEM)
goto worked; /* be bold, and pretend that test succeeded */
pid = fork();
@@ -1454,7 +1461,7 @@ test_ptrace_setoptions_for_all(void)
int it_worked = 0;
/* Need fork for test. NOMMU has no forks */
- if (NOMMU_SYSTEM)
+ if (1 || NOMMU_SYSTEM)
goto worked; /* be bold, and pretend that test succeeded */
pid = fork();
@@ -1540,7 +1547,7 @@ test_ptrace_seize(void)
int pid;
/* Need fork for test. NOMMU has no forks */
- if (NOMMU_SYSTEM) {
+ if (1 || NOMMU_SYSTEM) {
post_attach_sigstop = 0; /* this sets use_seize to 1 */
return;
}
More information about the Strace-devel
mailing list