* powerpc/tm: Fix 32bit non-rt signal return
@ 2013-06-03 10:56 Michael Neuling
2013-06-05 7:25 ` Michael Neuling
0 siblings, 1 reply; 2+ messages in thread
From: Michael Neuling @ 2013-06-03 10:56 UTC (permalink / raw)
To: benh; +Cc: Linux PPC dev, matt
Currently sys_sigreturn() is transactional memory unaware, hence if we take a
32 bit signal without SIGINFO (non RT) inside a transaction, we don't restore
the signal frame correctly on return.
This checks if the signal frame being restoring is an active transaction, and
if so, it copies the additional state to the ptregs so it can be restored.
Signed-off-by: Michael Neuling <mikey@neuling.org>
cc: <stable@vger.kernel.org> # 3.9 only
diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c
index 201385c..0bc961b 100644
--- a/arch/powerpc/kernel/signal_32.c
+++ b/arch/powerpc/kernel/signal_32.c
@@ -1481,16 +1481,22 @@ badframe:
long sys_sigreturn(int r3, int r4, int r5, int r6, int r7, int r8,
struct pt_regs *regs)
{
+ struct sigframe __user *sf;
struct sigcontext __user *sc;
struct sigcontext sigctx;
struct mcontext __user *sr;
void __user *addr;
sigset_t set;
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+ struct mcontext __user *mcp, *tm_mcp;
+ unsigned long msr_hi;
+#endif
/* Always make any pending restarted system calls return -EINTR */
current_thread_info()->restart_block.fn = do_no_restart_syscall;
- sc = (struct sigcontext __user *)(regs->gpr[1] + __SIGNAL_FRAMESIZE);
+ sf = (struct sigframe __user *)(regs->gpr[1] + __SIGNAL_FRAMESIZE);
+ sc = &sf->sctx;
addr = sc;
if (copy_from_user(&sigctx, sc, sizeof(sigctx)))
goto badframe;
@@ -1507,12 +1513,23 @@ long sys_sigreturn(int r3, int r4, int r5, int r6, int r7, int r8,
#endif
set_current_blocked(&set);
- sr = (struct mcontext __user *)from_user_ptr(sigctx.regs);
- addr = sr;
- if (!access_ok(VERIFY_READ, sr, sizeof(*sr))
- || restore_user_regs(regs, sr, 1))
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+ mcp = (struct mcontext __user *)&sf->mctx;
+ tm_mcp = (struct mcontext __user *)&sf->mctx_transact;
+ if (__get_user(msr_hi, &mcp->mc_gregs[PT_MSR]))
goto badframe;
-
+ if MSR_TM_ACTIVE(msr_hi<<32) {
+ if (restore_tm_user_regs(regs, mcp, tm_mcp))
+ goto badframe;
+ } else
+#endif
+ {
+ sr = (struct mcontext __user *)from_user_ptr(sigctx.regs);
+ addr = sr;
+ if (!access_ok(VERIFY_READ, sr, sizeof(*sr))
+ || restore_user_regs(regs, sr, 1))
+ goto badframe;
+ }
set_thread_flag(TIF_RESTOREALL);
return 0;
^ permalink raw reply related [flat|nested] 2+ messages in thread
* Re: powerpc/tm: Fix 32bit non-rt signal return
2013-06-03 10:56 powerpc/tm: Fix 32bit non-rt signal return Michael Neuling
@ 2013-06-05 7:25 ` Michael Neuling
0 siblings, 0 replies; 2+ messages in thread
From: Michael Neuling @ 2013-06-05 7:25 UTC (permalink / raw)
To: benh, Linux PPC dev, matt
benh,
Hold off on taking this for now... I'm seeing a crash with it on power7.
Mikey
Michael Neuling <mikey@neuling.org> wrote:
> Currently sys_sigreturn() is transactional memory unaware, hence if we take a
> 32 bit signal without SIGINFO (non RT) inside a transaction, we don't restore
> the signal frame correctly on return.
>
> This checks if the signal frame being restoring is an active transaction, and
> if so, it copies the additional state to the ptregs so it can be restored.
>
> Signed-off-by: Michael Neuling <mikey@neuling.org>
> cc: <stable@vger.kernel.org> # 3.9 only
>
> diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c
> index 201385c..0bc961b 100644
> --- a/arch/powerpc/kernel/signal_32.c
> +++ b/arch/powerpc/kernel/signal_32.c
> @@ -1481,16 +1481,22 @@ badframe:
> long sys_sigreturn(int r3, int r4, int r5, int r6, int r7, int r8,
> struct pt_regs *regs)
> {
> + struct sigframe __user *sf;
> struct sigcontext __user *sc;
> struct sigcontext sigctx;
> struct mcontext __user *sr;
> void __user *addr;
> sigset_t set;
> +#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
> + struct mcontext __user *mcp, *tm_mcp;
> + unsigned long msr_hi;
> +#endif
>
> /* Always make any pending restarted system calls return -EINTR */
> current_thread_info()->restart_block.fn = do_no_restart_syscall;
>
> - sc = (struct sigcontext __user *)(regs->gpr[1] + __SIGNAL_FRAMESIZE);
> + sf = (struct sigframe __user *)(regs->gpr[1] + __SIGNAL_FRAMESIZE);
> + sc = &sf->sctx;
> addr = sc;
> if (copy_from_user(&sigctx, sc, sizeof(sigctx)))
> goto badframe;
> @@ -1507,12 +1513,23 @@ long sys_sigreturn(int r3, int r4, int r5, int r6, int r7, int r8,
> #endif
> set_current_blocked(&set);
>
> - sr = (struct mcontext __user *)from_user_ptr(sigctx.regs);
> - addr = sr;
> - if (!access_ok(VERIFY_READ, sr, sizeof(*sr))
> - || restore_user_regs(regs, sr, 1))
> +#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
> + mcp = (struct mcontext __user *)&sf->mctx;
> + tm_mcp = (struct mcontext __user *)&sf->mctx_transact;
> + if (__get_user(msr_hi, &mcp->mc_gregs[PT_MSR]))
> goto badframe;
> -
> + if MSR_TM_ACTIVE(msr_hi<<32) {
> + if (restore_tm_user_regs(regs, mcp, tm_mcp))
> + goto badframe;
> + } else
> +#endif
> + {
> + sr = (struct mcontext __user *)from_user_ptr(sigctx.regs);
> + addr = sr;
> + if (!access_ok(VERIFY_READ, sr, sizeof(*sr))
> + || restore_user_regs(regs, sr, 1))
> + goto badframe;
> + }
> set_thread_flag(TIF_RESTOREALL);
> return 0;
>
>
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2013-06-05 7:25 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-06-03 10:56 powerpc/tm: Fix 32bit non-rt signal return Michael Neuling
2013-06-05 7:25 ` Michael Neuling
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).