| From 46725b17f1c6c815a41429259b3f070c01e71bc1 Mon Sep 17 00:00:00 2001 |
| From: "Naveen N. Rao" <naveen.n.rao@linux.vnet.ibm.com> |
| Date: Thu, 31 Aug 2017 21:55:57 +0530 |
| Subject: powerpc/signal: Properly handle return value from uprobe_deny_signal() |
| |
| From: Naveen N. Rao <naveen.n.rao@linux.vnet.ibm.com> |
| |
| commit 46725b17f1c6c815a41429259b3f070c01e71bc1 upstream. |
| |
| When a uprobe is installed on an instruction that we currently do not |
| emulate, we copy the instruction into a xol buffer and single step |
| that instruction. If that instruction generates a fault, we abort the |
| single stepping before invoking the signal handler. Once the signal |
| handler is done, the uprobe trap is hit again since the instruction is |
| retried and the process repeats. |
| |
| We use uprobe_deny_signal() to detect if the xol instruction triggered |
| a signal. If so, we clear TIF_SIGPENDING and set TIF_UPROBE so that the |
| signal is not handled until after the single stepping is aborted. In |
| this case, uprobe_deny_signal() returns true and get_signal() ends up |
| returning 0. However, in do_signal(), we are not looking at the return |
| value, but depending on ksig.sig for further action, all with an |
| uninitialized ksig that is not touched in this scenario. Fix the same |
| by initializing ksig.sig to 0. |
| |
| Fixes: 129b69df9c90 ("powerpc: Use get_signal() signal_setup_done()") |
| Reported-by: Anton Blanchard <anton@samba.org> |
| Signed-off-by: Naveen N. Rao <naveen.n.rao@linux.vnet.ibm.com> |
| Signed-off-by: Michael Ellerman <mpe@ellerman.id.au> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| arch/powerpc/kernel/signal.c | 2 +- |
| 1 file changed, 1 insertion(+), 1 deletion(-) |
| |
| --- a/arch/powerpc/kernel/signal.c |
| +++ b/arch/powerpc/kernel/signal.c |
| @@ -102,7 +102,7 @@ static void check_syscall_restart(struct |
| static void do_signal(struct pt_regs *regs) |
| { |
| sigset_t *oldset = sigmask_to_save(); |
| - struct ksignal ksig; |
| + struct ksignal ksig = { .sig = 0 }; |
| int ret; |
| int is32 = is_32bit_task(); |
| |