From 2ce12ed31c2b46260b8fd140bfe8d6c30bc0eb29 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 24 Aug 2011 17:25:32 +0200 Subject: [PATCH] Unify per-architecture post-execve SIGTRAP check. Move post-execve SIGTRAP check from get_scno_on_sysenter (multitude of places on many architectures) to a single location in trace_syscall_entering. This loosens the logic for some arches, since many of them had additional checks such as scno == 0. However, on non-ancient Linux kernels we should never have post-execve SIGTRAP in the first place, by virtue of using PTRACE_O_TRACEEXEC. * syscall.c (get_scno_on_sysenter): Remove tcp->flags & TCB_WAITEXECVE checks. (trace_syscall_entering): Do tcp->flags & TCB_WAITEXECVE check here. (get_scno_on_sysexit): Tweak comment. (syscall_fixup): Likewise. (trace_syscall_exiting): Likewise. Signed-off-by: Denys Vlasenko --- syscall.c | 113 +++++++----------------------------------------------- 1 file changed, 13 insertions(+), 100 deletions(-) diff --git a/syscall.c b/syscall.c index fc502bf2..8ffa4a6a 100644 --- a/syscall.c +++ b/syscall.c @@ -754,12 +754,6 @@ get_scno_on_sysenter(struct tcb *tcp) #ifdef LINUX # if defined(S390) || defined(S390X) - if (tcp->flags & TCB_WAITEXECVE) { - /* This is the post-execve SIGTRAP. */ - tcp->flags &= ~TCB_WAITEXECVE; - return 0; - } - if (upeek(tcp, PT_GPR2, &syscall_mode) < 0) return -1; @@ -843,11 +837,6 @@ get_scno_on_sysenter(struct tcb *tcp) # elif defined (POWERPC) if (upeek(tcp, sizeof(unsigned long)*PT_R0, &scno) < 0) return -1; - /* Check if this is the post-execve SIGTRAP. */ - if (scno == 0 && (tcp->flags & TCB_WAITEXECVE)) { - tcp->flags &= ~TCB_WAITEXECVE; - return 0; - } # ifdef POWERPC64 /* TODO: speed up strace by not doing this at every syscall. * We only need to do it after execve. @@ -872,19 +861,10 @@ get_scno_on_sysenter(struct tcb *tcp) } # endif # elif defined(AVR32) - /* - * Read complete register set in one go. - */ + /* Read complete register set in one go. */ if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, ®s) < 0) return -1; - scno = regs.r8; - - /* Check if this is the post-execve SIGTRAP. */ - if (tcp->flags & TCB_WAITEXECVE) { - tcp->flags &= ~TCB_WAITEXECVE; - return 0; - } # elif defined(BFIN) if (upeek(tcp, PT_ORIG_P0, &scno)) return -1; @@ -969,15 +949,8 @@ get_scno_on_sysenter(struct tcb *tcp) if (upeek(tcp, PT_R15, &scno) < 0) return -1; } - /* Check if this is the post-execve SIGTRAP. */ - if (tcp->flags & TCB_WAITEXECVE) { - tcp->flags &= ~TCB_WAITEXECVE; - return 0; - } # elif defined (ARM) - /* - * Read complete register set in one go. - */ + /* Read complete register set in one go. */ if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (void *)®s) == -1) return -1; @@ -985,12 +958,6 @@ get_scno_on_sysenter(struct tcb *tcp) * We only need to grab the syscall number on syscall entry. */ if (regs.ARM_ip == 0) { - /* Check if this is the post-execve SIGTRAP. */ - if (tcp->flags & TCB_WAITEXECVE) { - tcp->flags &= ~TCB_WAITEXECVE; - return 0; - } - /* * Note: we only deal with only 32-bit CPUs here. */ @@ -1008,14 +975,6 @@ get_scno_on_sysenter(struct tcb *tcp) if (errno) return -1; - /* FIXME: bogus check? it is already done before, - * so we never can see it here? - */ - if (scno == 0 && (tcp->flags & TCB_WAITEXECVE)) { - tcp->flags &= ~TCB_WAITEXECVE; - return 0; - } - /* Handle the EABI syscall convention. We do not bother converting structures between the two ABIs, but basic functionality should work even @@ -1061,13 +1020,6 @@ get_scno_on_sysenter(struct tcb *tcp) r2 = regs[REG_V0]; scno = r2; - - /* Check if this is the post-execve SIGTRAP. */ - if (scno == 0 && tcp->flags & TCB_WAITEXECVE) { - tcp->flags &= ~TCB_WAITEXECVE; - return 0; - } - if (scno < 0 || scno > nsyscalls) { if (a3 == 0 || a3 == -1) { if (debug) @@ -1081,12 +1033,6 @@ get_scno_on_sysenter(struct tcb *tcp) if (upeek(tcp, REG_V0, &scno) < 0) return -1; - /* Check if this is the post-execve SIGTRAP. */ - if (scno == 0 && tcp->flags & TCB_WAITEXECVE) { - tcp->flags &= ~TCB_WAITEXECVE; - return 0; - } - if (scno < 0 || scno > nsyscalls) { if (a3 == 0 || a3 == -1) { if (debug) @@ -1097,16 +1043,9 @@ get_scno_on_sysenter(struct tcb *tcp) # elif defined (ALPHA) if (upeek(tcp, REG_A3, &a3) < 0) return -1; - if (upeek(tcp, REG_R0, &scno) < 0) return -1; - /* Check if this is the post-execve SIGTRAP. */ - if (scno == 0 && tcp->flags & TCB_WAITEXECVE) { - tcp->flags &= ~TCB_WAITEXECVE; - return 0; - } - /* * Do some sanity checks to figure out if it's * really a syscall entry @@ -1162,11 +1101,6 @@ get_scno_on_sysenter(struct tcb *tcp) set_personality(1); break; default: - /* Check if this is the post-execve SIGTRAP. */ - if (tcp->flags & TCB_WAITEXECVE) { - tcp->flags &= ~TCB_WAITEXECVE; - return 0; - } # if defined (SPARC64) fprintf(stderr, "syscall: unknown syscall trap %08lx %016lx\n", trap, regs.tpc); # else @@ -1187,11 +1121,6 @@ get_scno_on_sysenter(struct tcb *tcp) # elif defined(HPPA) if (upeek(tcp, PT_GR20, &scno) < 0) return -1; - /* Check if this is the post-execve SIGTRAP. */ - if (tcp->flags & TCB_WAITEXECVE) { - tcp->flags &= ~TCB_WAITEXECVE; - return 0; - } # elif defined(SH) /* * In the new syscall ABI, the system call number is in R3. @@ -1212,34 +1141,16 @@ get_scno_on_sysenter(struct tcb *tcp) correct_scno); scno = correct_scno; } - - /* Check if this is the post-execve SIGTRAP. */ - if (scno == 0 && tcp->flags & TCB_WAITEXECVE) { - tcp->flags &= ~TCB_WAITEXECVE; - return 0; - } # elif defined(SH64) if (upeek(tcp, REG_SYSCALL, &scno) < 0) return -1; scno &= 0xFFFF; - - /* Check if this is the post-execve SIGTRAP. */ - if (tcp->flags & TCB_WAITEXECVE) { - tcp->flags &= ~TCB_WAITEXECVE; - return 0; - } # elif defined(CRISV10) || defined(CRISV32) if (upeek(tcp, 4*PT_R9, &scno) < 0) return -1; # elif defined(TILE) if (upeek(tcp, PTREGS_OFFSET_REG(10), &scno) < 0) return -1; - - /* Check if this is the post-execve SIGTRAP. */ - if (tcp->flags & TCB_WAITEXECVE) { - tcp->flags &= ~TCB_WAITEXECVE; - return 0; - } # elif defined(MICROBLAZE) if (upeek(tcp, 0, &scno) < 0) return -1; @@ -1300,9 +1211,7 @@ get_scno_on_sysexit(struct tcb *tcp) # if defined(S390) || defined(S390X) # elif defined (POWERPC) # elif defined(AVR32) - /* - * Read complete register set in one go. - */ + /* Read complete register set in one go. */ if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, ®s) < 0) return -1; # elif defined(BFIN) @@ -1321,9 +1230,7 @@ get_scno_on_sysexit(struct tcb *tcp) if (upeek(tcp, PT_R10, &r10) < 0) return -1; # elif defined (ARM) - /* - * Read complete register set in one go. - */ + /* Read complete register set in one go. */ if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (void *)®s) == -1) return -1; # elif defined (M68K) @@ -1511,6 +1418,7 @@ syscall_fixup(struct tcb *tcp) == (TCB_INSYSCALL|TCB_WAITEXECVE)) && (gpr2 == -ENOSYS || gpr2 == tcp->scno)) { /* + * Return from execve. * Fake a return value of zero. We leave the TCB_WAITEXECVE * flag set for the post-execve SIGTRAP to see and reset. */ @@ -2308,6 +2216,14 @@ trace_syscall_entering(struct tcb *tcp) { int res, scno_good; +#if defined TCB_WAITEXECVE + if (tcp->flags & TCB_WAITEXECVE) { + /* This is the post-execve SIGTRAP. */ + tcp->flags &= ~TCB_WAITEXECVE; + return 0; + } +#endif + scno_good = res = get_scno_on_sysenter(tcp); if (res == 0) return res; @@ -2477,9 +2393,6 @@ trace_syscall_exiting(struct tcb *tcp) if (dtime || cflag) gettimeofday(&tv, NULL); - /* BTW, why we don't just memorize syscall no. on entry - * in tcp->something? - */ scno_good = res = get_scno_on_sysexit(tcp); if (res == 0) return res; -- 2.40.0