[RFC PATCH] powerpc/uprobes: Fixup si_addr if we took an exception while single stepping
Christophe Leroy
christophe.leroy at csgroup.eu
Sat Mar 12 03:49:19 AEDT 2022
Le 13/09/2017 à 22:03, Naveen N. Rao a écrit :
> If the single-stepped instruction causes an exception, we may end up
> setting siginfo.si_addr to the address of the uprobe xol area. This is
> not desirable since the address won't make sense for the process if it
> wants to handle the exception. Fixup the si_addr field in such cases.
>
> Reported-by: Anton Blanchard <anton at samba.org>
> Signed-off-by: Naveen N. Rao <naveen.n.rao at linux.vnet.ibm.com>
Nowadays _exception() calls force_sig_fault_to_task() so if the change
is still required I guess it must be done there ?
Christophe
> ---
> arch/powerpc/include/asm/uprobes.h | 7 +++++++
> arch/powerpc/kernel/traps.c | 4 ++++
> arch/powerpc/kernel/uprobes.c | 17 +++++++++++++++++
> 3 files changed, 28 insertions(+)
>
> diff --git a/arch/powerpc/include/asm/uprobes.h b/arch/powerpc/include/asm/uprobes.h
> index 7422a999a39a..13fc6af3c1fd 100644
> --- a/arch/powerpc/include/asm/uprobes.h
> +++ b/arch/powerpc/include/asm/uprobes.h
> @@ -23,6 +23,7 @@
> */
>
> #include <linux/notifier.h>
> +#include <asm/siginfo.h>
> #include <asm/probes.h>
>
> typedef ppc_opcode_t uprobe_opcode_t;
> @@ -45,4 +46,10 @@ struct arch_uprobe_task {
> unsigned long saved_trap_nr;
> };
>
> +#ifdef CONFIG_UPROBES
> +extern void uprobe_fixup_exception(struct pt_regs *regs, siginfo_t *info);
> +#else
> +static inline void uprobe_fixup_exception(struct pt_regs *regs, siginfo_t *info) { }
> +#endif
> +
> #endif /* _ASM_UPROBES_H */
> diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
> index ec74e203ee04..1bb858a37029 100644
> --- a/arch/powerpc/kernel/traps.c
> +++ b/arch/powerpc/kernel/traps.c
> @@ -66,6 +66,7 @@
> #include <asm/hmi.h>
> #include <sysdev/fsl_pci.h>
> #include <asm/kprobes.h>
> +#include <asm/uprobes.h>
>
> #if defined(CONFIG_DEBUGGER) || defined(CONFIG_KEXEC_CORE)
> int (*__debugger)(struct pt_regs *regs) __read_mostly;
> @@ -292,6 +293,9 @@ void _exception(int signr, struct pt_regs *regs, int code, unsigned long addr)
> info.si_signo = signr;
> info.si_code = code;
> info.si_addr = (void __user *) addr;
> +
> + uprobe_fixup_exception(regs, &info);
> +
> force_sig_info(signr, &info, current);
> }
>
> diff --git a/arch/powerpc/kernel/uprobes.c b/arch/powerpc/kernel/uprobes.c
> index 5d105b8eeece..a361a56e6210 100644
> --- a/arch/powerpc/kernel/uprobes.c
> +++ b/arch/powerpc/kernel/uprobes.c
> @@ -25,6 +25,7 @@
> #include <linux/uprobes.h>
> #include <linux/uaccess.h>
> #include <linux/kdebug.h>
> +#include <linux/signal.h>
>
> #include <asm/sstep.h>
>
> @@ -214,3 +215,19 @@ bool arch_uretprobe_is_alive(struct return_instance *ret, enum rp_check ctx,
> else
> return regs->gpr[1] < ret->stack;
> }
> +
> +void uprobe_fixup_exception(struct pt_regs *regs, siginfo_t *info)
> +{
> + struct task_struct *t = current;
> + struct uprobe_task *utask = t->utask;
> +
> + if (likely(!utask || !utask->active_uprobe))
> + return;
> +
> + /*
> + * We reset si_addr here.
> + * regs->nip is reset during our way back through uprobe_deny_signal()
> + */
> + if (info->si_addr == (void __user *) utask->xol_vaddr)
> + info->si_addr = (void __user *) utask->vaddr;
> +}
More information about the Linuxppc-dev
mailing list