[ltrace-commits] 01/01: Detect return from rt_sigreturn syscalls

Petr Machata pmachata-guest at moszumanska.debian.org
Fri Feb 20 10:08:47 UTC 2015


This is an automated email from the git hooks/post-receive script.

pmachata-guest pushed a commit to branch master
in repository ltrace.

commit c18a46eff706e956c4dc755144d752dc163a1145
Author: Faraz Shahbazker <faraz.shahbazker at imgtec.com>
Date:   Thu Feb 19 10:13:11 2015 -0800

    Detect return from rt_sigreturn syscalls
    
    On MIPS, sigreturn/rt_sigreturn does not return control to the instruction
    after the syscall instruction. Instead, it transfers control directly to
    the point where the signal occurred. If this transfer is not correctly
    marked as a SYSRET event, it gets mis-categorized as a breakpoint event
    and generates "unexpected breakpoint" messages. The sigreturn
    frame remains on the callstack until the next sigreturn, which is then
    misinterpreted as as a return from the previous 'unfinished' syscall.
    
    If the top of the callstack is a sigreturn or rt_sigreturn syscall, we
    must force the current event to be treated as a SYSRET without checking
    for a preceding SYSCALL instruction.
    
    Verify by invoking:
    $ ltrace [-S] openssl speed
---
 sysdeps/linux-gnu/mips/trace.c | 20 +++++++++++++++++++-
 1 file changed, 19 insertions(+), 1 deletion(-)

diff --git a/sysdeps/linux-gnu/mips/trace.c b/sysdeps/linux-gnu/mips/trace.c
index 88e13ac..f3198c6 100644
--- a/sysdeps/linux-gnu/mips/trace.c
+++ b/sysdeps/linux-gnu/mips/trace.c
@@ -30,6 +30,7 @@
 #include <sys/ptrace.h>
 #include <asm/ptrace.h>
 #include <assert.h>
+#include <asm/unistd.h>
 
 #include "backend.h"
 #include "common.h"
@@ -103,7 +104,24 @@ syscall_p(struct process *proc, int status, int *sysnum)
 		   0000000c    syscall
 		 */
 		if(insn!=0x0000000c){
-			return 0;
+			/* sigreturn returns control to the point
+			   where the signal was received; skip check 
+			   for preceeding syscall instruction */
+			int depth = proc->callstack_depth;
+			struct callstack_element *top = NULL;
+			if (depth > 0)
+				top = &proc->callstack[depth - 1];
+
+			if (top != NULL &&  top->is_syscall &&
+			    (top->c_un.syscall == (__NR_rt_sigreturn -
+						   __NR_Linux) ||
+			     top->c_un.syscall == (__NR_sigreturn -
+						   __NR_Linux))) {
+				*sysnum = top->c_un.syscall;
+				return 2;
+			}
+			else
+				return 0;
 		}
 
 		*sysnum = (num & 0xFFFF) - 4000;

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/collab-maint/ltrace.git



More information about the ltrace-commits mailing list