]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
ppc32-linux signal handling: don't place the sigframe return stub on
authorJulian Seward <jseward@acm.org>
Mon, 10 Sep 2007 16:28:38 +0000 (16:28 +0000)
committerJulian Seward <jseward@acm.org>
Mon, 10 Sep 2007 16:28:38 +0000 (16:28 +0000)
the stack; instead use a stub in m_trampoline.S.  This makes it
possible to deliver signals on non-executable stacks, and makes the
behaviour consistent with x86-linux and amd64-linux.

git-svn-id: svn://svn.valgrind.org/valgrind/trunk@6813

coregrind/m_sigframe/sigframe-ppc32-linux.c
coregrind/m_trampoline.S
coregrind/m_translate.c
coregrind/pub_core_trampoline.h

index 5a828f816ea280f7a5095e4eebe0e251156592b0..aa364269a50bbb7bfc67fc1f10dfe895374ff7a7 100644 (file)
@@ -133,7 +133,7 @@ struct rt_sigframe {
 static 
 void stack_mcontext ( struct vki_mcontext *mc, 
                       ThreadState* tst, 
-                      Int ret,
+                      Bool use_rt_sigreturn,
                       UInt fault_addr )
 {
    VG_TRACK( pre_mem_write, Vg_CoreSignal, tst->tid, "signal frame mcontext",
@@ -164,10 +164,18 @@ void stack_mcontext ( struct vki_mcontext *mc,
    /* XXX should do FP and vector regs */
 
    /* set up signal return trampoline */
+   /* NB.  5 Sept 07.  mc->mc_pad[0..1] used to contain a the code to
+      which the signal handler returns, and it just did sys_sigreturn
+      or sys_rt_sigreturn.  But this doesn't work if the stack is
+      non-executable, and it isn't consistent with the x86-linux and
+      amd64-linux scheme for removing the stack frame.  So instead be
+      consistent and use a stub in m_trampoline.  Then it doesn't
+      matter whether or not the (guest) stack is executable.  This
+      fixes #149519 and #145837. */
    VG_TRACK(pre_mem_write, Vg_CoreSignal, tst->tid, "signal frame mcontext",
             (Addr)&mc->mc_pad, sizeof(mc->mc_pad));
-   mc->mc_pad[0] = 0x38000000U + ret;   /* li 0,ret */
-   mc->mc_pad[1] = 0x44000002U;         /* sc */
+   mc->mc_pad[0] = 0; /* invalid */
+   mc->mc_pad[1] = 0; /* invalid */
    VG_TRACK( post_mem_write,  Vg_CoreSignal, tst->tid, 
              (Addr)&mc->mc_pad, sizeof(mc->mc_pad) );
    /* invalidate any translation of this area */
@@ -175,7 +183,10 @@ void stack_mcontext ( struct vki_mcontext *mc,
                               sizeof(mc->mc_pad), "stack_mcontext" );   
 
    /* set the signal handler to return to the trampoline */
-   SET_SIGNAL_LR(tst, (Addr) &mc->mc_pad[0]);
+   SET_SIGNAL_LR(tst, (Addr)(use_rt_sigreturn 
+                               ? (Addr)&VG_(ppc32_linux_SUBST_FOR_rt_sigreturn)
+                               : (Addr)&VG_(ppc32_linux_SUBST_FOR_sigreturn)
+                      ));
 }
 
 //:: /* Valgrind-specific parts of the signal frame */
@@ -719,7 +730,7 @@ void VG_(sigframe_create)( ThreadId tid,
                 (Addr)&ucp->uc_regs,
                 sizeof(ucp->uc_regs) + sizeof(ucp->uc_sigmask) );
 
-      stack_mcontext(&ucp->uc_mcontext, tst, __NR_rt_sigreturn, faultaddr);
+      stack_mcontext(&ucp->uc_mcontext, tst, True/*use_rt_sigreturn*/, faultaddr);
       priv = &frame->priv;
 
       SET_SIGNAL_GPR(tid, 4, (Addr) &frame->siginfo);
@@ -741,7 +752,7 @@ void VG_(sigframe_create)( ThreadId tid,
       VG_TRACK( post_mem_write, Vg_CoreSignal, tid,
                 (Addr)&scp->_unused[3], sizeof(*scp) - 3 * sizeof(UInt) );
 
-      stack_mcontext(&frame->mcontext, tst, __NR_sigreturn, faultaddr);
+      stack_mcontext(&frame->mcontext, tst, False/*!use_rt_sigreturn*/, faultaddr);
       priv = &frame->priv;
 
       SET_SIGNAL_GPR(tid, 4, (Addr) scp);
index 40a96bcc470230bf9825c4d4df4e44986cadc520..10d5ec403600744fd3e12c39a80fa0a72960ba37 100644 (file)
@@ -242,6 +242,18 @@ VG_(trampoline_stuff_end):
 .global VG_(trampoline_stuff_start)
 VG_(trampoline_stuff_start):
 
+.global VG_(ppc32_linux_SUBST_FOR_sigreturn)
+VG_(ppc32_linux_SUBST_FOR_sigreturn):
+       li 0,__NR_sigreturn
+        sc
+        .long 0        /*illegal insn*/
+
+.global VG_(ppc32_linux_SUBST_FOR_rt_sigreturn)
+VG_(ppc32_linux_SUBST_FOR_rt_sigreturn):
+       li 0,__NR_rt_sigreturn
+        sc
+        .long 0        /*illegal insn*/
+       
 /* There's no particular reason that this needs to be handwritten
    assembly, but since that's what this file contains, here's a
    simple strlen implementation (written in C and compiled by gcc.)
index 0d796a817aae9a1cd892041207edad4504949abe..eec5e8f7494d2e7d4a98a293f6233e59353282e3 100644 (file)
@@ -1164,8 +1164,8 @@ Bool VG_(translate) ( ThreadId tid,
    if ( (!translations_allowable_from_seg(seg))
         || addr == TRANSTAB_BOGUS_GUEST_ADDR ) {
       if (VG_(clo_trace_signals))
-         VG_(message)(Vg_DebugMsg, "translations not allowed here "
-                                   "- throwing SEGV");
+         VG_(message)(Vg_DebugMsg, "translations not allowed here (0x%llx)"
+                                   " - throwing SEGV", addr);
       /* U R busted, sonny.  Place your hands on your head and step
          away from the orig_addr. */
       /* Code address is bad - deliver a signal instead */
index 86a077a114d0b59cfdaba9d99773b7888501795a..da9ff416eccab5d31b69df08bce300965cba3f85 100644 (file)
@@ -69,6 +69,8 @@ extern void VG_(amd64_linux_REDIR_FOR_vtime);
 #endif
 
 #if defined(VGP_ppc32_linux)
+extern void  VG_(ppc32_linux_SUBST_FOR_sigreturn);
+extern void  VG_(ppc32_linux_SUBST_FOR_rt_sigreturn);
 extern UInt  VG_(ppc32_linux_REDIR_FOR_strlen)( void* );
 extern UInt  VG_(ppc32_linux_REDIR_FOR_strcmp)( void*, void* );
 extern void* VG_(ppc32_linux_REDIR_FOR_strchr)( void*, Int );