ARM64: Uprobe support added
Subsystems (5)
cover ARM64: Uprobe support added
These patches have been prepared on top of ARM64 kprobe v3 patches [1] under review.
Unit test for following has been done so far and they have been found working
1. Normal instruction, which can be probed like sub, ldr, add etc.
2. Instructions which can be simulated like ret.
3. uretprobe
[1]https://lkml.org/lkml/2014/11/18/33
Pratyush Anand (8):
ARM64: Move BRK opcodes defines from kprobes.h to insn.h
ARM64: Refactor kprobes-arm64
Kernel/uprobe: Define arch_uprobe_exception_notify as __weak
ARM64: Add instruction_pointer_set function
ARM64: Re-factor flush_ptrace_access
ARM64: Handle TRAP_HWBRKPT for user mode as well
ARM64: Handle TRAP_BRKPT for user mode as well
ARM64: Add uprobe support
arch/arm/kernel/uprobes.c | 6 -
arch/arm64/Kconfig | 3 +
arch/arm64/include/asm/insn.h | 8 +
arch/arm64/include/asm/probes.h | 26 ++-
arch/arm64/include/asm/ptrace.h | 7 +
arch/arm64/include/asm/thread_info.h | 5 +-
arch/arm64/include/asm/uprobes.h | 43 ++++
arch/arm64/kernel/Makefile | 5 +-
arch/arm64/kernel/debug-monitors.c | 14 +-
arch/arm64/kernel/kprobes.c | 11 +-
arch/arm64/kernel/kprobes.h | 7 +-
.../kernel/{kprobes-arm64.c => probes-arm64.c} | 84 +++----
.../kernel/{kprobes-arm64.h => probes-arm64.h} | 17 +-
arch/arm64/kernel/probes-condn-check.c | 2 +-
arch/arm64/kernel/probes-decode.h | 4 +-
arch/arm64/kernel/signal.c | 4 +-
arch/arm64/kernel/uprobes.c | 255 +++++++++++++++++++++
arch/arm64/mm/flush.c | 30 ++-
kernel/events/uprobes.c | 18 ++
19 files changed, 445 insertions(+), 104 deletions(-)
create mode 100644 arch/arm64/include/asm/uprobes.h
rename arch/arm64/kernel/{kprobes-arm64.c => probes-arm64.c} (79%)
rename arch/arm64/kernel/{kprobes-arm64.h => probes-arm64.h} (60%)
create mode 100644 arch/arm64/kernel/uprobes.cSignature · 1 line
2.1.0
RFC 3/8 Kernel/uprobe: Define arch_uprobe_exception_notify as __weak
Both ARM and ARM64 handle uprobe exceptions through their own hooks.So nothing to be done in arch_uprobe_exception_notify except to return NOTIFY_DONE. Implement this as weak default function and remove definition from arm arch code.
--- arch/arm/kernel/uprobes.c | 6 ------ kernel/events/uprobes.c | 18 ++++++++++++++++++ 2 files changed, 18 insertions(+), 6 deletions(-)
arch/arm/kernel/uprobes.c +0 -6
@@ -178,12 +178,6 @@ void arch_uprobe_abort_xol(struct arch_uprobe *auprobe, struct pt_regs *regs)instruction_pointer_set (regs, utask->vaddr); } -int arch_uprobe_exception_notify (struct notifier_block *self, -unsigned long val,void *data) -{ -return NOTIFY_DONE ; -} -static int uprobe_trap_handler (struct pt_regs *regs,unsigned int instr) {unsigned long flags;
kernel/events/uprobes.c +18 -0
@@ -1973,6 +1973,24 @@ int uprobe_post_sstep_notifier(struct pt_regs *regs)return 1 ; } +/** +* arch_uprobe_exception_notify - Pass uprobe exception notigfication to +* architecture +* @self: Pointer to notifier_block +* @val: Type of exception +* @data: Exception specific data +* Default implementation of arch_uprobe_exception_notify +* Returns NOTIFY_DONE. +* +* Few architectures like arm and arm64 handle uprobe exceptions through +* their own hooks.So nothing to be done here. +*/ +int __weak arch_uprobe_exception_notify (struct notifier_block *self, +unsigned long val,void *data) +{ +return NOTIFY_DONE ; +} +static struct notifier_block uprobe_exception_nb = { .notifier_call = arch_uprobe_exception_notify, .priority =INT_MAX -1 ,/* notified after kprobes, kgdb */
Signature · 1 line
2.1.0
RFC 1/8 ARM64: Move BRK opcodes defines from kprobes.h to insn.h
In reply to Pratyush AnandIts better to keep all BRK opcodes used by kprobes and uprobes at one place. Therefore move these defines to asm/insn.h.
--- arch/arm64/include/asm/insn.h | 6 ++++++ arch/arm64/kernel/kprobes.h | 7 +------ 2 files changed, 7 insertions(+), 6 deletions(-)
arch/arm64/include/asm/insn.h +6 -0
@@ -23,6 +23,12 @@/* A64 instructions are always 32 bits. */ #define AARCH64_INSN_SIZE 4 +/* BRK opcodes with ESR encoding */ +#define BRK64_ESR_MASK 0xFFFF +#define BRK64_ESR_KPROBES 0x0004 +#define BRK64_OPCODE_KPROBES 0xD4200080/* "brk 0x4" */ +#define ARCH64_NOP_OPCODE 0xD503201F +#ifndef __ASSEMBLY__/* * ARM Architecture Reference Manual for ARMv8 Profile-A, Issue A.a
arch/arm64/kernel/kprobes.h +1 -6
@@ -15,12 +15,7 @@#ifndef _ARM_KERNEL_KPROBES_H#define _ARM_KERNEL_KPROBES_H - -/* BRK opcodes with ESR encoding */ -#define BRK64_ESR_MASK 0xFFFF -#define BRK64_ESR_KPROBES 0x0004 -#define BRK64_OPCODE_KPROBES 0xD4200080/* "brk 0x4" */ -#define ARCH64_NOP_OPCODE 0xD503201F +#include <asm/insn.h> #define JPROBES_MAGIC_NUM 0xa5a5a5a5a5a5a5a5
Signature · 1 line
2.1.0
RFC 4/8 ARM64: Add instruction_pointer_set function
In reply to Pratyush Anandinstruction_pointer_set is needed for uprobe implementation. Hence define it for ARM64.
--- arch/arm64/include/asm/ptrace.h | 6 ++++++ 1 file changed, 6 insertions(+)
arch/arm64/include/asm/ptrace.h +6 -0
@@ -206,6 +206,12 @@ static inline int valid_user_regs(struct user_pt_regs *regs)#define instruction_pointer (regs) ((regs)->pc)#define stack_pointer (regs) ((regs)->sp) +static inline void instruction_pointer_set (struct pt_regs *regs, +unsigned long val) +{ +instruction_pointer (regs) = val; +} +#ifdef CONFIG_SMP extern unsigned long profile_pc (struct pt_regs *regs);#else
Signature · 1 line
2.1.0
RFC 6/8 ARM64: Handle TRAP_HWBRKPT for user mode as well
In reply to Pratyush Ananduprobe registers a handler at step_hook. So, single_step_handler now checks for user mode as well if there is a valid hook.
--- arch/arm64/kernel/debug-monitors.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
arch/arm64/kernel/debug-monitors.c +3 -3
@@ -236,6 +236,9 @@ static int single_step_handler(unsigned long addr, unsigned int esr,if (!reinstall_suspended_bps (regs))return 0 ; +if (call_step_hook (regs, esr) ==DBG_HOOK_HANDLED ) +return 0 ; +if (user_mode (regs)) { info.si_signo =SIGTRAP ; info.si_errno =0 ;
@@ -251,9 +254,6 @@ static int single_step_handler(unsigned long addr, unsigned int esr,*/ user_rewind_single_step (current); }else { -if (call_step_hook (regs, esr) ==DBG_HOOK_HANDLED ) -return 0 ; -pr_warning ("Unexpected kernel single-step exception at EL1\n" );/* * Re-enable stepping since we know that we will be
Signature · 1 line
2.1.0
RFC 5/8 ARM64: Re-factor flush_ptrace_access
In reply to Pratyush AnandRe-factor flush_ptrace_access to reuse vma independent part.
--- arch/arm64/mm/flush.c | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-)
arch/arm64/mm/flush.c +15 -9
@@ -34,19 +34,25 @@ void flush_cache_range(struct vm_area_struct *vma, unsigned long start,__flush_icache_all (); } +static void __flush_ptrace_access (struct page *page,unsigned long uaddr, +void *kaddr,unsigned long len) +{ +unsigned long addr = (unsigned long )kaddr; + +if (icache_is_aliasing ()) { +__flush_dcache_area (kaddr, len); +__flush_icache_all (); + }else { +flush_icache_range (addr, addr + len); + } +} +static void flush_ptrace_access (struct vm_area_struct *vma,struct page *page,unsigned long uaddr,void *kaddr,unsigned long len) { -if (vma->vm_flags &VM_EXEC ) { -unsigned long addr = (unsigned long )kaddr; -if (icache_is_aliasing ()) { -__flush_dcache_area (kaddr, len); -__flush_icache_all (); - }else { -flush_icache_range (addr, addr + len); - } - } +if (vma->vm_flags &VM_EXEC ) +__flush_ptrace_access (page, uaddr, kaddr, len); }/*
Signature · 1 line
2.1.0
RFC 7/8 ARM64: Handle TRAP_BRKPT for user mode as well
In reply to Pratyush Ananduprobe is registered at break_hook with a unique ESR code. So, when a TRAP_BRKPT occurs, call_break_hook checks if it was for uprobe. If not, then send a SIGTRAP to user.
--- arch/arm64/kernel/debug-monitors.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)
arch/arm64/kernel/debug-monitors.c +5 -3
@@ -306,6 +306,9 @@ static int brk_handler(unsigned long addr, unsigned int esr, {siginfo_t info; +if (call_break_hook (regs, esr) ==DBG_HOOK_HANDLED ) +return 0 ; +if (user_mode (regs)) { info = (siginfo_t ) { .si_signo = SIGTRAP,
@@ -315,12 +318,11 @@ static int brk_handler(unsigned long addr, unsigned int esr, };force_sig_info (SIGTRAP , &info, current); - }else if (call_break_hook (regs, esr) !=DBG_HOOK_HANDLED ) { +return 0 ; + }else {pr_warning ("Unexpected kernel BRK exception at EL1\n" );return -EFAULT ; } - -return 0 ; }int aarch32_break_handler (struct pt_regs *regs)
Signature · 1 line
2.1.0
RFC 8/8 ARM64: Add uprobe support
In reply to Pratyush AnandThis patch adds support for uprobe on ARM64 architecture.
Unit test for following has been done so far and they have been found working
1. Normal instruction, which can be probed like sub, ldr, add etc.
2. Instructions which can be simulated like ret.
3. uretprobe
--- arch/arm64/Kconfig | 3 + arch/arm64/include/asm/insn.h | 2 + arch/arm64/include/asm/probes.h | 1 + arch/arm64/include/asm/ptrace.h | 1 + arch/arm64/include/asm/thread_info.h | 5 +- arch/arm64/include/asm/uprobes.h | 43 ++++++ arch/arm64/kernel/Makefile | 3 + arch/arm64/kernel/signal.c | 4 +- arch/arm64/kernel/uprobes.c | 255 +++++++++++++++++++++++++++++++++++ arch/arm64/mm/flush.c | 6 + 10 files changed, 321 insertions(+), 2 deletions(-) create mode 100644 arch/arm64/include/asm/uprobes.h create mode 100644 arch/arm64/kernel/uprobes.c
arch/arm64/Kconfig +3 -0
@@ -145,6 +145,9 @@ config KERNEL_MODE_NEON config FIX_EARLYCON_MEM def_bool y +config ARCH_SUPPORTS_UPROBES + def_bool y + source "init/Kconfig" source "kernel/Kconfig.freezer"
arch/arm64/include/asm/insn.h +2 -0
@@ -27,6 +27,8 @@#define BRK64_ESR_MASK 0xFFFF#define BRK64_ESR_KPROBES 0x0004#define BRK64_OPCODE_KPROBES 0xD4200080/* "brk 0x4" */ +#define BRK64_ESR_UPROBES 0x0008 +#define BRK64_OPCODE_UPROBES 0xD4200100/* "brk 0x8" */ #define ARCH64_NOP_OPCODE 0xD503201F#ifndef __ASSEMBLY__
arch/arm64/include/asm/probes.h +1 -0
@@ -18,6 +18,7 @@struct arch_specific_insn ;typedef u32 kprobe_opcode_t ; +typedef u32 uprobe_opcode_t ;typedef u32 probe_opcode_t ;typedef unsigned long (probes_pstate_check_t )(unsigned long );typedef unsigned long
arch/arm64/include/asm/ptrace.h +1 -0
@@ -205,6 +205,7 @@ static inline int valid_user_regs(struct user_pt_regs *regs)#define instruction_pointer (regs) ((regs)->pc)#define stack_pointer (regs) ((regs)->sp) +#define procedure_link_pointer (regs) ((regs)->regs[30])static inline void instruction_pointer_set (struct pt_regs *regs,unsigned long val)
arch/arm64/include/asm/thread_info.h +4 -1
@@ -108,6 +108,7 @@ static inline struct thread_info *current_thread_info(void)#define TIF_NEED_RESCHED 1#define TIF_NOTIFY_RESUME 2/* callback before returning to user */ #define TIF_FOREIGN_FPSTATE 3/* CPU's FP state is not current's */ +#define TIF_UPROBE 4/* uprobe breakpoint or singlestep */ #define TIF_NOHZ 7#define TIF_SYSCALL_TRACE 8#define TIF_SYSCALL_AUDIT 9
@@ -129,10 +130,12 @@ static inline struct thread_info *current_thread_info(void)#define _TIF_SYSCALL_AUDIT (1 << TIF_SYSCALL_AUDIT)#define _TIF_SYSCALL_TRACEPOINT (1 << TIF_SYSCALL_TRACEPOINT)#define _TIF_SECCOMP (1 << TIF_SECCOMP) +#define _TIF_UPROBE (1 << TIF_UPROBE)#define _TIF_32BIT (1 << TIF_32BIT)#define _TIF_WORK_MASK (_TIF_NEED_RESCHED | _TIF_SIGPENDING | \ - _TIF_NOTIFY_RESUME | _TIF_FOREIGN_FPSTATE) + _TIF_NOTIFY_RESUME | _TIF_FOREIGN_FPSTATE | \ + _TIF_UPROBE)#define _TIF_SYSCALL_WORK (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | \ _TIF_SYSCALL_TRACEPOINT | _TIF_SECCOMP | \
arch/arm64/include/asm/uprobes.h new file +43 -0
43 lines not on this page · raw message
arch/arm64/kernel/Makefile +3 -0
@@ -31,6 +31,9 @@ arm64-obj-$(CONFIG_ARM64_CPU_SUSPEND) += sleep.o suspend.o arm64-obj-$(CONFIG_CPU_IDLE) += cpuidle.o arm64-obj-$(CONFIG_JUMP_LABEL) += jump_label.o arm64-obj-$(CONFIG_KGDB) += kgdb.o +arm64-obj-$(CONFIG_UPROBES) += uprobes.o probes-arm64.o \ + probes-simulate-insn.o \ + probes-condn-check.o arm64-obj-$(CONFIG_KPROBES) += kprobes.o probes-arm64.o \ probes-simulate-insn.o \ probes-condn-check.o
arch/arm64/kernel/signal.c +3 -1
@@ -409,6 +409,9 @@ static void do_signal(struct pt_regs *regs) asmlinkage void do_notify_resume(struct pt_regs *regs,unsigned int thread_flags) { +if (thread_flags & _TIF_UPROBE) +uprobe_notify_resume (regs); +if (thread_flags & _TIF_SIGPENDING)do_signal (regs);
@@ -419,5 +422,4 @@ asmlinkage void do_notify_resume(struct pt_regs *regs,if (thread_flags & _TIF_FOREIGN_FPSTATE)fpsimd_restore_current_state (); - }
arch/arm64/kernel/uprobes.c new file +255 -0
255 lines not on this page · raw message
arch/arm64/mm/flush.c +6 -0
@@ -55,6 +55,12 @@ static void flush_ptrace_access(struct vm_area_struct *vma, struct page *page,__flush_ptrace_access (page, uaddr, kaddr, len); } +void flush_uprobe_xol_access (struct page *page,unsigned long uaddr, +void *kaddr,unsigned long len) +{ +__flush_ptrace_access (page, uaddr, kaddr, len); +} +/* * Copy user data from/to a page which is mapped into a different processes * address space. Really, we want to allow our "user space" model to handle
Signature · 1 line
2.1.0
RFC 2/8 ARM64: Refactor kprobes-arm64
In reply to Pratyush AnandMost of the stuff of kprobes-arm64.c can also be used by uprobes.c. So move all those part to common code area. In the process rename kprobe to probe whereever possible.
No functional change.
---
arch/arm64/include/asm/probes.h | 25 +++----
arch/arm64/kernel/Makefile | 2 +-
arch/arm64/kernel/kprobes.c | 11 +--
.../kernel/{kprobes-arm64.c => probes-arm64.c} | 84 ++++++++++------------
.../kernel/{kprobes-arm64.h => probes-arm64.h} | 17 ++---
arch/arm64/kernel/probes-condn-check.c | 2 +-
arch/arm64/kernel/probes-decode.h | 4 +-
7 files changed, 70 insertions(+), 75 deletions(-)
rename arch/arm64/kernel/{kprobes-arm64.c => probes-arm64.c} (79%)
rename arch/arm64/kernel/{kprobes-arm64.h => probes-arm64.h} (60%)arch/arm64/include/asm/probes.h +13 -12
@@ -15,36 +15,37 @@#ifndef _ARM_PROBES_H#define _ARM_PROBES_H -struct kprobe ;struct arch_specific_insn ;typedef u32 kprobe_opcode_t ; -typedef unsigned long (kprobes_pstate_check_t )(unsigned long ); +typedef u32 probe_opcode_t ; +typedef unsigned long (probes_pstate_check_t )(unsigned long );typedef unsigned long -(kprobes_condition_check_t )(struct kprobe *p,struct pt_regs *); +(probes_condition_check_t )(u32 opcode,struct arch_specific_insn *, +struct pt_regs *);typedef void -(kprobes_prepare_t )(struct kprobe *,struct arch_specific_insn *); -typedef void (kprobes_handler_t ) (u32 opcode,long addr,struct pt_regs *); +(probes_prepare_t )(u32 opcode,struct arch_specific_insn *); +typedef void (probes_handler_t ) (u32 opcode,long addr,struct pt_regs *);enum pc_restore_type {NO_RESTORE ,RESTORE_PC , }; -struct kprobe_pc_restore { +struct probe_pc_restore {enum pc_restore_type type;unsigned long addr; };/* architecture specific copy of original instruction */ struct arch_specific_insn { -kprobe_opcode_t *insn; -kprobes_pstate_check_t *pstate_cc; -kprobes_condition_check_t *check_condn; -kprobes_prepare_t *prepare; -kprobes_handler_t *handler; +probe_opcode_t *insn; +probes_pstate_check_t *pstate_cc; +probes_condition_check_t *check_condn; +probes_prepare_t *prepare; +probes_handler_t *handler;/* restore address after step xol */ -struct kprobe_pc_restore restore; +struct probe_pc_restore restore; };#endif
arch/arm64/kernel/Makefile +1 -1
@@ -31,7 +31,7 @@ arm64-obj-$(CONFIG_ARM64_CPU_SUSPEND) += sleep.o suspend.o arm64-obj-$(CONFIG_CPU_IDLE) += cpuidle.o arm64-obj-$(CONFIG_JUMP_LABEL) += jump_label.o arm64-obj-$(CONFIG_KGDB) += kgdb.o -arm64-obj-$(CONFIG_KPROBES) += kprobes.o kprobes-arm64.o \ +arm64-obj-$(CONFIG_KPROBES) += kprobes.o probes-arm64.o \ probes-simulate-insn.o \ probes-condn-check.o arm64-obj-$(CONFIG_EFI) += efi.o efi-stub.o efi-entry.o
arch/arm64/kernel/kprobes.c +6 -5
@@ -30,7 +30,7 @@#include <asm/insn.h> #include "kprobes.h" -#include "kprobes-arm64.h" +#include "probes-arm64.h" #define MIN_STACK_SIZE (addr) min((unsigned long)MAX_STACK_SIZE, \ (unsigned long)current_thread_info() + THREAD_START_SP - (addr))
@@ -60,7 +60,7 @@ static void __kprobes arch_prepare_ss_slot(struct kprobe *p)static void __kprobes arch_prepare_simulate (struct kprobe *p) {if (p->ainsn.prepare) - p->ainsn.prepare (p, &p->ainsn); + p->ainsn.prepare (p->opcode, &p->ainsn);/* This instructions is not executed xol. No need to adjust the PC */ p->ainsn.restore.addr =0 ;
@@ -91,7 +91,7 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p)return -EINVAL ;/* decode instruction */ -switch (arm_kprobe_decode_insn (insn, &p->ainsn)) { +switch (arm_probe_decode_insn (insn, &p->ainsn)) {case INSN_REJECTED :/* insn not supported */ return -EINVAL ;
@@ -275,7 +275,8 @@ static int __kprobes reenter_kprobe(struct kprobe *p,switch (kcb->kprobe_status) {case KPROBE_HIT_SSDONE :case KPROBE_HIT_ACTIVE : -if (!p->ainsn.check_condn || p->ainsn.check_condn (p, regs)) { +if (!p->ainsn.check_condn || p->ainsn.check_condn (p->opcode, + &p->ainsn, regs)) {kprobes_inc_nmissed_count (p);setup_singlestep (p, regs, kcb,1 ); }else {
@@ -408,7 +409,7 @@ void __kprobes kprobe_handler(struct pt_regs *regs)if (reenter_kprobe (p, regs, kcb))return ; }else if (!p->ainsn.check_condn || - p->ainsn.check_condn (p, regs)) { + p->ainsn.check_condn (p->opcode, &p->ainsn, regs)) {/* Probe hit and conditional execution check ok. */ set_current_kprobe (p); kcb->kprobe_status =KPROBE_HIT_ACTIVE ;
arch/arm64/kernel/probes-arm64.c renamed from arch/arm64/kernel/kprobes-arm64.c +38 -46
165 lines not on this page · raw message
arch/arm64/kernel/probes-arm64.h renamed from arch/arm64/kernel/kprobes-arm64.h +9 -8
@@ -1,5 +1,5 @@/* -* arch/arm64/kernel/kprobes-arm64.h +* arch/arm64/kernel/probes-arm64.h * * Copyright (C) 2013 Linaro Limited. *
@@ -13,18 +13,19 @@* General Public License for more details. */ -#ifndef _ARM_KERNEL_KPROBES_ARM64_H -#define _ARM_KERNEL_KPROBES_ARM64_H +#ifndef _ARM_KERNEL_PROBES_ARM64_H +#define _ARM_KERNEL_PROBES_ARM64_H -enum kprobe_insn { +enum probe_insn {INSN_REJECTED ,INSN_GOOD_NO_SLOT ,INSN_GOOD , }; -extern kprobes_pstate_check_t *const kprobe_condition_checks[16 ]; +typedef u32 probe_opcode_t ; +extern probes_pstate_check_t *const probe_condition_checks[16 ]; -enum kprobe_insn __kprobes -arm_kprobe_decode_insn (kprobe_opcode_t insn,struct arch_specific_insn *asi); +enum probe_insn +arm_probe_decode_insn (probe_opcode_t insn,struct arch_specific_insn *asi); -#endif /* _ARM_KERNEL_KPROBES_ARM64_H */ +#endif /* _ARM_KERNEL_PROBES_ARM64_H */
arch/arm64/kernel/probes-condn-check.c +1 -1
@@ -114,7 +114,7 @@ static unsigned long __kprobes __check_al(unsigned long pstate)return true; } -kprobes_pstate_check_t *const kprobe_condition_checks[16 ] = { +probes_pstate_check_t *const probe_condition_checks[16 ] = { &__check_eq, &__check_ne, &__check_cs, &__check_cc, &__check_mi, &__check_pl, &__check_vs, &__check_vc, &__check_hi, &__check_ls, &__check_ge, &__check_lt,
arch/arm64/kernel/probes-decode.h +2 -2
@@ -37,8 +37,8 @@ struct aarch64_decode_header { };struct aarch64_decode_actions { -kprobes_prepare_t *prepare; -kprobes_handler_t *handler; +probes_prepare_t *prepare; +probes_handler_t *handler; };struct aarch64_decode_table {
Signature · 1 line
2.1.0
+Dave
Sorry, I took all cc list from your kprobe patches and forgot to add you. :(
Please review.
Quoted 48 lines · Pratyush Anand
These patches have been prepared on top of ARM64 kprobe v3 patches [1] under review.
Unit test for following has been done so far and they have been found working
1. Normal instruction, which can be probed like sub, ldr, add etc.
2. Instructions which can be simulated like ret.
3. uretprobe[1]https://lkml.org/lkml/2014/11/18/33
Pratyush Anand (8):
ARM64: Move BRK opcodes defines fromkprobes.htoinsn.h
ARM64: Refactor kprobes-arm64
Kernel/uprobe: Definearch_uprobe_exception_notifyas__weak
ARM64: Addinstruction_pointer_setfunction
ARM64: Re-factorflush_ptrace_access
ARM64: HandleTRAP_HWBRKPTfor user mode as well
ARM64: HandleTRAP_BRKPTfor user mode as well
ARM64: Add uprobe supportarch/arm/kernel/uprobes.c | 6 - arch/arm64/Kconfig | 3 + arch/arm64/include/asm/insn.h | 8 + arch/arm64/include/asm/probes.h | 26 ++- arch/arm64/include/asm/ptrace.h | 7 + arch/arm64/include/asm/thread_info.h | 5 +- arch/arm64/include/asm/uprobes.h | 43 ++++ arch/arm64/kernel/Makefile | 5 +- arch/arm64/kernel/debug-monitors.c | 14 +- arch/arm64/kernel/kprobes.c | 11 +- arch/arm64/kernel/kprobes.h | 7 +- .../kernel/{kprobes-arm64.c => probes-arm64.c} | 84 +++---- .../kernel/{kprobes-arm64.h => probes-arm64.h} | 17 +- arch/arm64/kernel/probes-condn-check.c | 2 +- arch/arm64/kernel/probes-decode.h | 4 +- arch/arm64/kernel/signal.c | 4 +- arch/arm64/kernel/uprobes.c | 255 +++++++++++++++++++++ arch/arm64/mm/flush.c | 30 ++- kernel/events/uprobes.c | 18 ++ 19 files changed, 445 insertions(+), 104 deletions(-)create mode 100644
arch/arm64/include/asm/uprobes.hrenamearch/arm64/kernel/{kprobes-arm64.c=>probes-arm64.c} (79%) renamearch/arm64/kernel/{kprobes-arm64.h=>probes-arm64.h} (60%) create mode 100644arch/arm64/kernel/uprobes.c
Oleg Nesterov
maintainerRe: [RFC 8/8] ARM64: Add uprobe support
In reply to Pratyush AnandHi Pratyush,
I'll try to actually read this patch (and the whole series) later, just a couple of quick questions for now.
arch/arm64/include/asm/ptrace.h static inline int valid_user_regs(struct user_pt_regs *regs) · line 208
Quoted 8 lines · Pratyush Anand
arch/arm64/include/asm/ptrace.h +1
-0@@ -205,6 +205,7 @@ static inline int valid_user_regs(struct user_pt_regs *regs)#define instruction_pointer (regs) ((regs)->pc)#define stack_pointer (regs) ((regs)->sp) +#define procedure_link_pointer (regs) ((regs)->regs[30])
perhaps it makes sense to change (at least) arch_prepare_kretprobe() to use the new helper? OK, we can do this later.
arch/arm64/include/asm/ptrace.h static inline int valid_user_regs(struct user_pt_regs *regs)
Quoted 5 lines
arch/arm64/include/asm/ptrace.h +5
-0+/* Single step context for uprobe */ +struct uprobe_step_ctx { +struct list_head node; +unsigned long match_addr; +};
I don't understand this... please see below.
arch/arm64/include/asm/ptrace.h
Quoted 5 lines
arch/arm64/include/asm/ptrace.h +5
-0+struct arch_uprobe_task { +unsigned long saved_fault_code; +u64 saved_user_pc; +struct uprobe_step_ctx ss_ctx; +};
saved_user_pc looks unneeded, you can rely on uprobe_task->vaddr ?
Quoted 37 lines
+++
b/arch/arm64/kernel/uprobes.carch/arm64/include/asm/ptrace.h +35
-0@@ -0,0 +1,255 @@ +/* +* Copyright (C) 2014 Pratyush Anand <[email protected]> +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +*/ +#include <linux/highmem.h> +#include <linux/ptrace.h> +#include <linux/uprobes.h> +#include <asm/debug-monitors.h> +#include <asm/probes.h> + +#include "probes-arm64.h" + +#define UPROBE_INV_FAULT_CODE UINT_MAX + +static LIST_HEAD (step_ctx); +static DEFINE_RWLOCK (step_ctx_lock); + +static void add_ss_context (struct uprobe_task *utask) +{ +struct uprobe_step_ctx *ss_ctx = &utask->autask.ss_ctx; + + ss_ctx->match_addr = utask->xol_vaddr; +write_lock (&step_ctx_lock); +list_add (&ss_ctx->node, &step_ctx); +write_unlock (&step_ctx_lock); +} + +static struct uprobe_step_ctx *find_ss_context (unsigned long vaddr) +{ +struct uprobe_step_ctx *ss_ctx; + +read_lock (&step_ctx_lock);
arch/arm64/include/asm/ptrace.h line 45
Quoted 10 lines
arch/arm64/include/asm/ptrace.h +10
-0+list_for_each_entry (ss_ctx, &step_ctx, node) { +if (ss_ctx->match_addr == vaddr) { +read_unlock (&step_ctx_lock); +return ss_ctx; + } + } +read_unlock (&step_ctx_lock); + +return NULL ; +}
This looks very wrong to me, but perhaps because I do not understand why do we need these *_ss_context() helpers.
arch/arm64/include/asm/ptrace.h line 57
Quoted 12 lines
arch/arm64/include/asm/ptrace.h +12
-0+static void del_ss_context (struct uprobe_task *utask) +{ +struct uprobe_step_ctx *ss_ctx =find_ss_context (utask->xol_vaddr); + +if (ss_ctx) { +write_lock (&step_ctx_lock); +list_del (&ss_ctx->node); +write_unlock (&step_ctx_lock); + }else { +WARN_ON (1 ); + } +}
Don't we need del_ss_context() in arch_uprobe_abort_xol() ? But this is minor.
Why we can trust find_ss_context() ? What if another thread also called add_ss_context() with the same (virtual) ->xol_vaddr ?
But the main question is: why do we need add/find_ss_context ?? Please explain.
Quoted 34 lines
arch/arm64/include/asm/ptrace.h +34
-0+int arch_uprobe_pre_xol (struct arch_uprobe *auprobe,struct pt_regs *regs) +{ +struct uprobe_task *utask = current->utask; + +/* saved fault code is restored in post_xol */ + utask->autask.saved_fault_code = current->thread.fault_code; + +/* An invalid fault code between pre/post xol event */ + current->thread.fault_code =UPROBE_INV_FAULT_CODE ; + +/* Save user pc */ + utask->autask.saved_user_pc =task_pt_regs (current)->user_regs.pc; + +/* Instruction point to execute ol */ +instruction_pointer_set (regs, utask->xol_vaddr); + +add_ss_context (utask); + +user_enable_single_step (current); + +return 0 ; +} + +int arch_uprobe_post_xol (struct arch_uprobe *auprobe,struct pt_regs *regs) +{ +struct uprobe_task *utask = current->utask; + +WARN_ON_ONCE (current->thread.fault_code !=UPROBE_INV_FAULT_CODE ); + +/* restore fault code */ + current->thread.fault_code = utask->autask.saved_fault_code; + +/* restore user pc */ +task_pt_regs (current)->user_regs.pc = utask->autask.saved_user_pc;
arch/arm64/include/asm/ptrace.h line 101
Quoted 10 lines
arch/arm64/include/asm/ptrace.h +10
-0+ +/* Instruction point to execute next to breakpoint address */ +instruction_pointer_set (regs, utask->vaddr +4 ); + +del_ss_context (utask); + +user_disable_single_step (current); + +return 0 ; +}
task_pt_regs() above looks strange. We we can't use "struct pt_regs *regs" passed as an argument?
See also the note about .saved_user_pc above. I think you can use utask->vaddr instead.
And why do you need to play with ->user_regs.pc?? instruction_pointer_set() after that modifies the same word?
Or it is possible that regs != task_pt_regs(current) ? (to remind, I do not know arm ;)
Could you also explain
instruction_pointer_set(regs, utask->vaddr + 4);
?
I mean, I do not understand why this is always correct. What if the probed insn is "jmp" (I do not know arm64's name for jump) ?
Probably this is correct because in this case arm_probe_decode_insn() should return INSN_GOOD_NO_SLOT and this insn will be emulated? If yes, this needs a comment, imo.
arch/arm64/include/asm/ptrace.h line 111
Quoted 10 lines
arch/arm64/include/asm/ptrace.h +10
-0+static int uprobe_breakpoint_handler (struct pt_regs *regs,unsigned int esr) +{ +unsigned long flags; + +local_irq_save (flags); +uprobe_pre_sstep_notifier (regs); +local_irq_restore (flags); + +return 0 ; +}
Again, you do not need to disable irqs around uprobe_pre_sstep_notifier().
And I am not sure I understand the logic... "return 0" actually means "return DBG_HOOK_HANDLED", right?
I do not understand this register_break_hook() interface and the usage of .esr_mask/esr_val. But given that this patch adds BRK64_ESR_UPROBES and uses BRK64_OPCODE_UPROBES, I will assume that uprobe_breakpoint_handler() will be called if this exception was triggered by UPROBE_SWBP_INSN.
In this case, why the unconditional DBG_HOOK_HANDLED is correct? For example, what if the application itself or debugger use UPROBE_SWBP_INSN for (self) debugging and this task has no uprobes? In this case uprobe_pre_sstep_notifier() will do nothing, it won't set TIF_UPROBES and handle_swbp() won't be called.
IOW, shouldn't it do
if (user_mode(regs) && uprobe_pre_sstep_notifier(regs)) return DBG_HOOK_HANDLED; return DBG_HOOK_ERROR;
?
arch/arm64/include/asm/ptrace.h line 124
Quoted 13 lines
arch/arm64/include/asm/ptrace.h +13
-0+static int uprobe_single_step_handler (struct pt_regs *regs,unsigned int esr) +{ +unsigned long flags; + +if (!find_ss_context (regs->pc -4 )) +return DBG_HOOK_ERROR ; + +local_irq_save (flags); +uprobe_post_sstep_notifier (regs); +local_irq_restore (flags); + +return 0 ; +}
The same. No need to clear irqs, and please explain why we can't rely on user_mode() && uprobe_post_sstep_notifier(), and why do we need find_ss_context().
arch/arm64/include/asm/ptrace.h line 129
Quoted 5 lines
arch/arm64/include/asm/ptrace.h +5
-0+void flush_uprobe_xol_access (struct page *page,unsigned long uaddr, +void *kaddr,unsigned long len) +{ +__flush_ptrace_access (page, uaddr, kaddr, len); +}
I have some concerns... I'll reply to 5/8 which adds __flush_ptrace_access.
Oleg.
Oleg Nesterov
maintainerRe: [RFC 3/8] Kernel/uprobe: Define arch_uprobe_exception_notify as __weak
In reply to Pratyush AnandQuoted 17 lines · Pratyush Anand
Both ARM and ARM64 handle uprobe exceptions through their own hooks.So nothing to be done in
arch_uprobe_exception_notifyexcept to returnNOTIFY_DONE. Implement this as weak default function and remove definition from arm arch code.Signed-off-by Pratyush Anand <[email protected]>--- arch/arm/kernel/uprobes.c | 6 ------ kernel/events/uprobes.c | 18 ++++++++++++++++++ 2 files changed, 18 insertions(+), 6 deletions(-)arch/arm/kernel/uprobes.c +0
-0
arch/arm/kernel/uprobes.c void arch_uprobe_abort_xol(struct arch_uprobe *auprobe, struct pt_regs *regs) · line 185
Quoted 8 lines
arch/arm/kernel/uprobes.c +0
-5@@ -178,12 +178,6 @@ void arch_uprobe_abort_xol(struct arch_uprobe *auprobe, struct pt_regs *regs)instruction_pointer_set (regs, utask->vaddr); } -int arch_uprobe_exception_notify (struct notifier_block *self, -unsigned long val,void *data) -{ -return NOTIFY_DONE ; -}
I agree, this is ugly. But I disagree with this change.
I think we should simply kill uprobe_exception_nb and unexport arch_uprobe_exception_notify on x86/powerpc, and in fact I was going to do this a long ago.
I'll send the patch later. Until then please add the dummy arch_uprobe_exception_notify() like arch/arm does, to make the generic code happy.
Oleg.
Oleg Nesterov
maintainerRe: [RFC 5/8] ARM64: Re-factor flush_ptrace_access
In reply to Pratyush AnandQuoted 2 lines · Pratyush Anand
Re-factor
flush_ptrace_accessto reuse vma independent part.
But for what? The changelog should explain this.
Quoted 32 lines
Signed-off-by Pratyush Anand <[email protected]>--- arch/arm64/mm/flush.c | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-)arch/arm64/mm/flush.c +13
-2@@ -34,19 +34,25 @@ void flush_cache_range(struct vm_area_struct *vma, unsigned long start,__flush_icache_all (); } +static void __flush_ptrace_access (struct page *page,unsigned long uaddr, +void *kaddr,unsigned long len) +{ +unsigned long addr = (unsigned long )kaddr; + +if (icache_is_aliasing ()) { +__flush_dcache_area (kaddr, len); +__flush_icache_all (); + }else { +flush_icache_range (addr, addr + len); + } +} +static void flush_ptrace_access (struct vm_area_struct *vma,struct page *page,unsigned long uaddr,void *kaddr,unsigned long len) { -if (vma->vm_flags &VM_EXEC ) { -unsigned long addr = (unsigned long )kaddr;
arch/arm64/mm/flush.c void flush_cache_range(struct vm_area_struct *vma, unsigned long start, · line 56
Quoted 10 lines
arch/arm64/mm/flush.c +2
-7-if (icache_is_aliasing ()) { -__flush_dcache_area (kaddr, len); -__flush_icache_all (); - }else { -flush_icache_range (addr, addr + len); - } - } +if (vma->vm_flags &VM_EXEC ) +__flush_ptrace_access (page, uaddr, kaddr, len); }
So why uprobes can't use flush_ptrace_access() ? flush_uprobe_xol_access() is called by arch_uprobe_copy_ixol(), and xol vma has VM_EXEC bit set.
Oleg.
Oleg Nesterov
maintainerRe: [RFC 6/8] ARM64: Handle TRAP_HWBRKPT for user mode as well
In reply to Pratyush AnandLet me repeat once again that I know absolutely nothing about arm* ;)
Quoted 24 lines · Pratyush Anand
uprobe registers a handler at
step_hook. So,single_step_handlernow checks for user mode as well if there is a valid hook.Signed-off-by Pratyush Anand <[email protected]>--- arch/arm64/kernel/debug-monitors.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)arch/arm64/kernel/debug-monitors.c +3
-0@@ -236,6 +236,9 @@ static int single_step_handler(unsigned long addr, unsigned int esr,if (!reinstall_suspended_bps (regs))return 0 ; +if (call_step_hook (regs, esr) ==DBG_HOOK_HANDLED ) +return 0 ; +if (user_mode (regs)) { info.si_signo =SIGTRAP ; info.si_errno =0 ;
arch/arm64/kernel/debug-monitors.c static int single_step_handler(unsigned long addr, unsigned int esr, · line 256
Quoted 6 lines
arch/arm64/kernel/debug-monitors.c +0
-3@@ -251,9 +254,6 @@ static int single_step_handler(unsigned long addr, unsigned int esr,*/ user_rewind_single_step (current); }else { -if (call_step_hook (regs, esr) ==DBG_HOOK_HANDLED ) -return 0 ; -
Agreed, we need something like this change...
But did you verify that it can't break other users of register_step_hook() ? The current handlers do not check user_mode() == F, they assume that they can't be called otherwise.
If this all is correct, please explain why in the changelog.
The same for the next patch.
Oleg.
Oleg Nesterov
maintainerRe: [RFC 5/8] ARM64: Re-factor flush_ptrace_access
In reply to Oleg NesterovQuoted 44 lines · Oleg Nesterov
Quoted 2 lines · Pratyush Anand
Re-factor
flush_ptrace_accessto reuse vma independent part.But for what? The changelog should explain this.
Quoted 37 lines
Signed-off-by Pratyush Anand <[email protected]>--- arch/arm64/mm/flush.c | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-)arch/arm64/mm/flush.c +13
-7@@ -34,19 +34,25 @@ void flush_cache_range(struct vm_area_struct *vma, unsigned long start,__flush_icache_all (); } +static void __flush_ptrace_access (struct page *page,unsigned long uaddr, +void *kaddr,unsigned long len) +{ +unsigned long addr = (unsigned long )kaddr; + +if (icache_is_aliasing ()) { +__flush_dcache_area (kaddr, len); +__flush_icache_all (); + }else { +flush_icache_range (addr, addr + len); + } +} +static void flush_ptrace_access (struct vm_area_struct *vma,struct page *page,unsigned long uaddr,void *kaddr,unsigned long len) { -if (vma->vm_flags &VM_EXEC ) { -unsigned long addr = (unsigned long )kaddr; -if (icache_is_aliasing ()) { -__flush_dcache_area (kaddr, len); -__flush_icache_all (); - }else { -flush_icache_range (addr, addr + len);
Quoted 8 lines
arch/arm64/mm/flush.c void flush_cache_range(struct vm_area_struct *vma, unsigned long start, · line 56
Quoted 5 lines
arch/arm64/mm/flush.c +2
-2- } - } +if (vma->vm_flags &VM_EXEC ) +__flush_ptrace_access (page, uaddr, kaddr, len); }So why uprobes can't use
flush_ptrace_access()?flush_uprobe_xol_access()is called byarch_uprobe_copy_ixol(), and xol vma hasVM_EXECbit set.
Ah, sorry, I forgot that arch_uprobe_copy_ixol() doesn't have "vma" so it can't use flush_ptrace_access()... perhaps you can update the changelog.
Oleg.
Re: [RFC 8/8] ARM64: Add uprobe support
In reply to Oleg NesterovQuoted 11 lines · Oleg Nesterov
Hi Pratyush,
I'll try to actually read this patch (and the whole series) later, just a couple of quick questions for now.
Quoted 5 lines · Pratyush Anand
arch/arm64/include/asm/ptrace.h +0
-0@@ -205,6 +205,7 @@ static inline int valid_user_regs(struct user_pt_regs *regs)
Quoted 6 lines
arch/arm64/include/asm/ptrace.h static inline int valid_user_regs(struct user_pt_regs *regs) · line 208
Quoted 3 lines
arch/arm64/include/asm/ptrace.h +1
-0#define instruction_pointer (regs) ((regs)->pc)#define stack_pointer (regs) ((regs)->sp) +#define procedure_link_pointer (regs) ((regs)->regs[30])perhaps it makes sense to change (at least)
arch_prepare_kretprobe()to use the new helper? OK, we can do this later.
Yes.
Quoted 9 lines
arch/arm64/include/asm/ptrace.h static inline int valid_user_regs(struct user_pt_regs *regs)
Quoted 6 lines
arch/arm64/include/asm/ptrace.h +5
-0+/* Single step context for uprobe */ +struct uprobe_step_ctx { +struct list_head node; +unsigned long match_addr; +};I don't understand this... please see below.
Quoted 7 lines
arch/arm64/include/asm/ptrace.h
Quoted 5 lines
arch/arm64/include/asm/ptrace.h +5
-0+struct arch_uprobe_task { +unsigned long saved_fault_code; +u64 saved_user_pc; +struct uprobe_step_ctx ss_ctx; +};
saved_user_pclooks unneeded, you can rely onuprobe_task->vaddr?
Probably yes. Will change.
Quoted 52 lines
Quoted 38 lines
+++
b/arch/arm64/kernel/uprobes.carch/arm64/include/asm/ptrace.h +35
-0@@ -0,0 +1,255 @@ +/* +* Copyright (C) 2014 Pratyush Anand <[email protected]> +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +*/ +#include <linux/highmem.h> +#include <linux/ptrace.h> +#include <linux/uprobes.h> +#include <asm/debug-monitors.h> +#include <asm/probes.h> + +#include "probes-arm64.h" + +#define UPROBE_INV_FAULT_CODE UINT_MAX + +static LIST_HEAD (step_ctx); +static DEFINE_RWLOCK (step_ctx_lock); + +static void add_ss_context (struct uprobe_task *utask) +{ +struct uprobe_step_ctx *ss_ctx = &utask->autask.ss_ctx; + + ss_ctx->match_addr = utask->xol_vaddr; +write_lock (&step_ctx_lock); +list_add (&ss_ctx->node, &step_ctx); +write_unlock (&step_ctx_lock); +} + +static struct uprobe_step_ctx *find_ss_context (unsigned long vaddr) +{ +struct uprobe_step_ctx *ss_ctx; + +read_lock (&step_ctx_lock);arch/arm64/include/asm/ptrace.h line 45
Quoted 10 lines
arch/arm64/include/asm/ptrace.h +10
-0+list_for_each_entry (ss_ctx, &step_ctx, node) { +if (ss_ctx->match_addr == vaddr) { +read_unlock (&step_ctx_lock); +return ss_ctx; + } + } +read_unlock (&step_ctx_lock); + +return NULL ; +}This looks very wrong to me, but perhaps because I do not understand why do we need these
*_ss_context()helpers.
Quoted 15 lines
arch/arm64/include/asm/ptrace.h line 57
Quoted 12 lines
arch/arm64/include/asm/ptrace.h +12
-0+static void del_ss_context (struct uprobe_task *utask) +{ +struct uprobe_step_ctx *ss_ctx =find_ss_context (utask->xol_vaddr); + +if (ss_ctx) { +write_lock (&step_ctx_lock); +list_del (&ss_ctx->node); +write_unlock (&step_ctx_lock); + }else { +WARN_ON (1 ); + } +}Don't we need
del_ss_context()inarch_uprobe_abort_xol()? But this is minor.
Thanks. Yes, we need del_ss_context() in arch_uprobe_abort_xol().
Quoted 3 lines
Why we can trust
find_ss_context()? What if another thread also calledadd_ss_context()with the same (virtual) ->xol_vaddr ?
OK..So xol_vaddr is not unique, then need to look for something else which could be unique for each probe.
Quoted 4 lines
But the main question is: why do we need add/find_ss_context ?? Please explain.
See arch/arm64/kernel/debug-monitors.c: call_step_hook
Unlike breakpoint exception, there is no ESR info check for step exception. So, it is the responsibility of step handler (uprobe_single_step_handler) to make sure that exception was generated for it.
Quoted 54 lines
Quoted 34 lines
arch/arm64/include/asm/ptrace.h +34
-0+int arch_uprobe_pre_xol (struct arch_uprobe *auprobe,struct pt_regs *regs) +{ +struct uprobe_task *utask = current->utask; + +/* saved fault code is restored in post_xol */ + utask->autask.saved_fault_code = current->thread.fault_code; + +/* An invalid fault code between pre/post xol event */ + current->thread.fault_code =UPROBE_INV_FAULT_CODE ; + +/* Save user pc */ + utask->autask.saved_user_pc =task_pt_regs (current)->user_regs.pc; + +/* Instruction point to execute ol */ +instruction_pointer_set (regs, utask->xol_vaddr); + +add_ss_context (utask); + +user_enable_single_step (current); + +return 0 ; +} + +int arch_uprobe_post_xol (struct arch_uprobe *auprobe,struct pt_regs *regs) +{ +struct uprobe_task *utask = current->utask; + +WARN_ON_ONCE (current->thread.fault_code !=UPROBE_INV_FAULT_CODE ); + +/* restore fault code */ + current->thread.fault_code = utask->autask.saved_fault_code; + +/* restore user pc */ +task_pt_regs (current)->user_regs.pc = utask->autask.saved_user_pc;arch/arm64/include/asm/ptrace.h line 101
Quoted 10 lines
arch/arm64/include/asm/ptrace.h +10
-0+ +/* Instruction point to execute next to breakpoint address */ +instruction_pointer_set (regs, utask->vaddr +4 ); + +del_ss_context (utask); + +user_disable_single_step (current); + +return 0 ; +}
task_pt_regs()above looks strange. We we can't use "structpt_regs*regs" passed as an argument?See also the note about .saved_user_pc above. I think you can use
utask->vaddrinstead.And why do you need to play with ->user_regs.pc??
instruction_pointer_set()after that modifies the same word?
Quoted 9 lines
Or it is possible that regs !=
task_pt_regs(current)? (to remind, I do not know arm ;)Could you also explain
instruction_pointer_set(regs, utask->vaddr + 4);?
Correct, saved_user_pc is not needed and also no need to play with ->user_regs.pc. instruction_pointer_set should be sufficient.
Quoted 7 lines
I mean, I do not understand why this is always correct. What if the probed insn is "jmp" (I do not know arm64's name for jump) ?
Probably this is correct because in this case
arm_probe_decode_insn()should returnINSN_GOOD_NO_SLOTand this insn will be emulated? If yes, this needs a comment, imo.
Yes, a branch instruction like b or bl or ret will be simulated.
Quoted 4 lines
Quoted 4 lines
arch/arm64/include/asm/ptrace.h +4
-0+static int uprobe_breakpoint_handler (struct pt_regs *regs,unsigned int esr) +{ +unsigned long flags; +
Quoted 8 lines
arch/arm64/include/asm/ptrace.h line 111
Quoted 6 lines
arch/arm64/include/asm/ptrace.h +6
-0+local_irq_save (flags); +uprobe_pre_sstep_notifier (regs); +local_irq_restore (flags); + +return 0 ; +}Again, you do not need to disable irqs around
uprobe_pre_sstep_notifier().
OK. (Actually took it from arch/arm/kernel/uprobe.c)
Quoted 3 lines
And I am not sure I understand the logic... "return 0" actually means "return
DBG_HOOK_HANDLED", right?
Yes. So better I will put return DBG_HOOK_HANDLED;
Quoted 5 lines
I do not understand this
register_break_hook()interface and the usage of .esr_mask/esr_val. But given that this patch addsBRK64_ESR_UPROBESand usesBRK64_OPCODE_UPROBES, I will assume thatuprobe_breakpoint_handler()will be called if this exception was triggered byUPROBE_SWBP_INSN.
Correct.
Quoted 6 lines
In this case, why the unconditional
DBG_HOOK_HANDLEDis correct? For example, what if the application itself or debugger useUPROBE_SWBP_INSNfor (self) debugging and this task has no uprobes? In this caseuprobe_pre_sstep_notifier()will do nothing, it won't setTIF_UPROBESandhandle_swbp()won't be called.
Quoted 7 lines
IOW, shouldn't it do
if (user_mode(regs) && uprobe_pre_sstep_notifier(regs)) return DBG_HOOK_HANDLED; return DBG_HOOK_ERROR;?
Thanks for pointing out this bug with the code.
Your point seems pretty valid.
Quoted 10 lines
Quoted 10 lines
arch/arm64/include/asm/ptrace.h +9
-0+static int uprobe_single_step_handler (struct pt_regs *regs,unsigned int esr) +{ +unsigned long flags; + +if (!find_ss_context (regs->pc -4 )) +return DBG_HOOK_ERROR ; + +local_irq_save (flags); +uprobe_post_sstep_notifier (regs);
Quoted 9 lines
arch/arm64/include/asm/ptrace.h line 124
Quoted 4 lines
arch/arm64/include/asm/ptrace.h +4
-0+local_irq_restore (flags); + +return 0 ; +}The same. No need to clear irqs, and please explain why we can't rely on
user_mode()&&uprobe_post_sstep_notifier(), and why do we needfind_ss_context().
I had not looked into uprobe_post_sstep_notifier implementtaion.I think, you are right.
Thanks for all these valuable comments.
~Pratyush
Quoted 10 lines
arch/arm64/include/asm/ptrace.h line 129
Quoted 5 lines
arch/arm64/include/asm/ptrace.h +5
-0+void flush_uprobe_xol_access (struct page *page,unsigned long uaddr, +void *kaddr,unsigned long len) +{ +__flush_ptrace_access (page, uaddr, kaddr, len); +}I have some concerns... I'll reply to 5/8 which adds
__flush_ptrace_access.Oleg.
Re: [RFC 3/8] Kernel/uprobe: Define arch_uprobe_exception_notify as __weak
In reply to Oleg NesterovQuoted 29 lines · Oleg Nesterov
Quoted 17 lines · Pratyush Anand
Both ARM and ARM64 handle uprobe exceptions through their own hooks.So nothing to be done in
arch_uprobe_exception_notifyexcept to returnNOTIFY_DONE. Implement this as weak default function and remove definition from arm arch code.Signed-off-by Pratyush Anand <[email protected]>--- arch/arm/kernel/uprobes.c | 6 ------ kernel/events/uprobes.c | 18 ++++++++++++++++++ 2 files changed, 18 insertions(+), 6 deletions(-)arch/arm/kernel/uprobes.c +0
-0arch/arm/kernel/uprobes.c void arch_uprobe_abort_xol(struct arch_uprobe *auprobe, struct pt_regs *regs) · line 185
Quoted 8 lines
arch/arm/kernel/uprobes.c +0
-5@@ -178,12 +178,6 @@ void arch_uprobe_abort_xol(struct arch_uprobe *auprobe, struct pt_regs *regs)instruction_pointer_set (regs, utask->vaddr); } -int arch_uprobe_exception_notify (struct notifier_block *self, -unsigned long val,void *data) -{ -return NOTIFY_DONE ; -}I agree, this is ugly. But I disagree with this change.
Quoted 6 lines
I think we should simply kill
uprobe_exception_nband unexportarch_uprobe_exception_notifyon x86/powerpc, and in fact I was going to do this a long ago.I'll send the patch later. Until then please add the dummy
arch_uprobe_exception_notify()likearch/armdoes, to make the generic code happy.
OK.
~Pratyush
Quoted 3 lines
Oleg.
Re: [RFC 5/8] ARM64: Re-factor flush_ptrace_access
In reply to Oleg NesterovQuoted 54 lines · Oleg Nesterov
Quoted 44 lines · Oleg Nesterov
Quoted 2 lines · Pratyush Anand
Re-factor
flush_ptrace_accessto reuse vma independent part.But for what? The changelog should explain this.
Quoted 37 lines
Signed-off-by Pratyush Anand <[email protected]>--- arch/arm64/mm/flush.c | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-)arch/arm64/mm/flush.c +13
-7@@ -34,19 +34,25 @@ void flush_cache_range(struct vm_area_struct *vma, unsigned long start,__flush_icache_all (); } +static void __flush_ptrace_access (struct page *page,unsigned long uaddr, +void *kaddr,unsigned long len) +{ +unsigned long addr = (unsigned long )kaddr; + +if (icache_is_aliasing ()) { +__flush_dcache_area (kaddr, len); +__flush_icache_all (); + }else { +flush_icache_range (addr, addr + len); + } +} +static void flush_ptrace_access (struct vm_area_struct *vma,struct page *page,unsigned long uaddr,void *kaddr,unsigned long len) { -if (vma->vm_flags &VM_EXEC ) { -unsigned long addr = (unsigned long )kaddr; -if (icache_is_aliasing ()) { -__flush_dcache_area (kaddr, len); -__flush_icache_all (); - }else { -flush_icache_range (addr, addr + len);Quoted 8 lines
arch/arm64/mm/flush.c void flush_cache_range(struct vm_area_struct *vma, unsigned long start, · line 56
Quoted 5 lines
arch/arm64/mm/flush.c +2
-2- } - } +if (vma->vm_flags &VM_EXEC ) +__flush_ptrace_access (page, uaddr, kaddr, len); }So why uprobes can't use
flush_ptrace_access()?flush_uprobe_xol_access()is called byarch_uprobe_copy_ixol(), and xol vma hasVM_EXECbit set.
Quoted 3 lines
Ah, sorry, I forgot that
arch_uprobe_copy_ixol()doesn't have "vma" so it can't useflush_ptrace_access()... perhaps you can update the changelog.
OK.. Will improve commit log.
~Pratyush
Quoted 2 lines
Oleg.
Oleg Nesterov
maintainerRe: [RFC 8/8] ARM64: Add uprobe support
In reply to Pratyush AnandQuoted 6 lines · Pratyush Anand
Quoted 3 lines · Oleg Nesterov
But the main question is: why do we need add/find_ss_context ?? Please explain.
Quoted 6 lines
See
arch/arm64/kernel/debug-monitors.c:call_step_hookUnlike breakpoint exception, there is no ESR info check for step exception. So, it is the responsibility of step handler (
uprobe_single_step_handler) to make sure that exception was generated for it.
Yes, yes, this is clear. My point was, we can (I think) rely on uprobe_post_sstep_notifier() which checks ->active_uprobe != NULL.
And I guess you understood what I meant, but since I wasn't clear let me repeat to ensure we really understand each other.
Can't
uprobe_single_step_handler(regs, esr)
{
if (user_mode(regs) && uprobe_post_sstep_notifier(regs))
return HANDLED;
return ERROR;
}work without this step_ctx logic?
If everything is correct, the probed task can execute a single (xol) insn in user-mode before the trap. If ->active_uprobe is set we know that we expect the ss trap in user-mode, and nothing else except this xol insn can generate it?
Perhaps arm64 needs additional checks, I dunno... If you think that the ->active_uprobe check is not enough you can probably also verify that "utask->state = UTASK_SSTEP" and/or "regs->pc - 4 == utask->xol_vaddr", but so far it seems to me that these additional checks can only make sense under WARN_ON().
Oleg.
Re: [RFC 8/8] ARM64: Add uprobe support
Quoted 22 lines · Oleg Nesterov
Quoted 6 lines · Pratyush Anand
Quoted 3 lines · Oleg Nesterov
But the main question is: why do we need add/find_ss_context ?? Please explain.
Quoted 6 lines
See
arch/arm64/kernel/debug-monitors.c:call_step_hookUnlike breakpoint exception, there is no ESR info check for step exception. So, it is the responsibility of step handler (
uprobe_single_step_handler) to make sure that exception was generated for it.Yes, yes, this is clear. My point was, we can (I think) rely on
uprobe_post_sstep_notifier()which checks ->active_uprobe != NULL.And I guess you understood what I meant, but since I wasn't clear let me repeat to ensure we really understand each other.
Can't
Quoted 9 lines
uprobe_single_step_handler(regs, esr) { if (user_mode(regs) && uprobe_post_sstep_notifier(regs)) return HANDLED; return ERROR; }work without this
step_ctxlogic?
Yes,yes, no need of step_ctx logic.
Quoted 4 lines
If everything is correct, the probed task can execute a single (xol) insn in user-mode before the trap. If ->active_uprobe is set we know that we expect the ss trap in user-mode, and nothing else except this xol insn can generate it?
Yes, I do see any value addition in saving xol_vaddr in ss_ctx->match_addr.
Quoted 6 lines
Perhaps arm64 needs additional checks, I dunno... If you think that the ->active_uprobe check is not enough you can probably also verify that "
utask->state=UTASK_SSTEP" and/or "regs->pc- 4 ==utask->xol_vaddr", but so far it seems to me that these additional checks can only make sense underWARN_ON().
Yes.
~Pratyush
Re: [RFC 1/8] ARM64: Move BRK opcodes defines from kprobes.h to insn.h
In reply to Pratyush AnandQuoted 14 lines · Pratyush Anand
Its better to keep all BRK opcodes used by kprobes and uprobes at one place. Therefore move these defines to
asm/insn.h.Signed-off-by Pratyush Anand <[email protected]>--- arch/arm64/include/asm/insn.h | 6 ++++++ arch/arm64/kernel/kprobes.h | 7 +------ 2 files changed, 7 insertions(+), 6 deletions(-)arch/arm64/include/asm/insn.h +0
-0
arch/arm64/include/asm/insn.h line 29
Quoted 7 lines
arch/arm64/include/asm/insn.h +4
-0@@ -23,6 +23,12 @@/* A64 instructions are always 32 bits. */ #define AARCH64_INSN_SIZE 4 +/* BRK opcodes with ESR encoding */ +#define BRK64_ESR_MASK 0xFFFF +#define BRK64_ESR_KPROBES 0x0004 +#define BRK64_OPCODE_KPROBES 0xD4200080/* "brk 0x4" */
These might be better off in debug-monitors.h, but I guess that's for the kprobes series to sort out.
arch/arm64/include/asm/insn.h line 30
Quoted 1 line
arch/arm64/include/asm/insn.h +1
-0+#define ARCH64_NOP_OPCODE 0xD503201F
We have aarch64_insn_gen_nop for this.
Will
Re: [RFC 2/8] ARM64: Refactor kprobes-arm64
In reply to Pratyush AnandQuoted 5 lines · Pratyush Anand
Most of the stuff of
kprobes-arm64.ccan also be used byuprobes.c. So move all those part to common code area. In the process rename kprobe to probe whereever possible.No functional change.
In which case, can you merge this into the kprobes series (which we haven't merged yet)?
Will
Re: [RFC 4/8] ARM64: Add instruction_pointer_set function
In reply to Pratyush AnandQuoted 13 lines · Pratyush Anand
instruction_pointer_setis needed for uprobe implementation. Hence define it for ARM64.Signed-off-by Pratyush Anand <[email protected]>--- arch/arm64/include/asm/ptrace.h | 6 ++++++ 1 file changed, 6 insertions(+)arch/arm64/include/asm/ptrace.h +0
-0
arch/arm64/include/asm/ptrace.h static inline int valid_user_regs(struct user_pt_regs *regs) · line 213
Quoted 8 lines
arch/arm64/include/asm/ptrace.h +5
-0@@ -206,6 +206,12 @@ static inline int valid_user_regs(struct user_pt_regs *regs)#define instruction_pointer (regs) ((regs)->pc)#define stack_pointer (regs) ((regs)->sp) +static inline void instruction_pointer_set (struct pt_regs *regs, +unsigned long val) +{ +instruction_pointer (regs) = val; +}
Do you think we could make use of the asm-generic ptrace header to get this for free? afaict, we just need to implement GET_USP and possibly GET_FP for the compat case (although it may well be that we still handle the compat case entirely separately).
Will
Re: [RFC 6/8] ARM64: Handle TRAP_HWBRKPT for user mode as well
In reply to Oleg NesterovQuoted 36 lines · Oleg Nesterov
Let me repeat once again that I know absolutely nothing about arm* ;)
Quoted 24 lines · Pratyush Anand
uprobe registers a handler at
step_hook. So,single_step_handlernow checks for user mode as well if there is a valid hook.Signed-off-by Pratyush Anand <[email protected]>--- arch/arm64/kernel/debug-monitors.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)arch/arm64/kernel/debug-monitors.c +3
-0@@ -236,6 +236,9 @@ static int single_step_handler(unsigned long addr, unsigned int esr,if (!reinstall_suspended_bps (regs))return 0 ; +if (call_step_hook (regs, esr) ==DBG_HOOK_HANDLED ) +return 0 ; +if (user_mode (regs)) { info.si_signo =SIGTRAP ; info.si_errno =0 ;arch/arm64/kernel/debug-monitors.c static int single_step_handler(unsigned long addr, unsigned int esr, · line 256
Quoted 6 lines
arch/arm64/kernel/debug-monitors.c +0
-3@@ -251,9 +254,6 @@ static int single_step_handler(unsigned long addr, unsigned int esr,*/ user_rewind_single_step (current); }else { -if (call_step_hook (regs, esr) ==DBG_HOOK_HANDLED ) -return 0 ; -Agreed, we need something like this change...
Quoted 5 lines
But did you verify that it can't break other users of
register_step_hook()? The current handlers do not checkuser_mode()== F, they assume that they can't be called otherwise.If this all is correct, please explain why in the changelog.
I think you're right, and kgdb will need fixing with this change.
Will
Re: [RFC 8/8] ARM64: Add uprobe support
In reply to Pratyush AnandQuoted 7 lines · Pratyush Anand
This patch adds support for uprobe on ARM64 architecture.
Unit test for following has been done so far and they have been found working
1. Normal instruction, which can be probed like sub, ldr, add etc.
2. Instructions which can be simulated like ret.
3. uretprobe
I'm assuming that means you don't support compat (AArch32) tasks with this? How do you enforce that?
Will
Re: [RFC 1/8] ARM64: Move BRK opcodes defines from kprobes.h to insn.h
In reply to Will DeaconQuoted 18 lines · Will Deacon
Quoted 17 lines · Pratyush Anand
Its better to keep all BRK opcodes used by kprobes and uprobes at one place. Therefore move these defines to
asm/insn.h.Signed-off-by Pratyush Anand <[email protected]>--- arch/arm64/include/asm/insn.h | 6 ++++++ arch/arm64/kernel/kprobes.h | 7 +------ 2 files changed, 7 insertions(+), 6 deletions(-)arch/arm64/include/asm/insn.h +0
-0@@ -23,6 +23,12 @@/* A64 instructions are always 32 bits. */ #define AARCH64_INSN_SIZE 4
Quoted 8 lines
arch/arm64/include/asm/insn.h line 29
Quoted 4 lines
arch/arm64/include/asm/insn.h +4
-0+/* BRK opcodes with ESR encoding */ +#define BRK64_ESR_MASK 0xFFFF +#define BRK64_ESR_KPROBES 0x0004 +#define BRK64_OPCODE_KPROBES 0xD4200080/* "brk 0x4" */ These might be better off in
debug-monitors.h, but I guess that's for the kprobes series to sort out.
Agreed.
~Pratyush
Quoted 6 lines
arch/arm64/include/asm/insn.h line 30
Quoted 1 line
arch/arm64/include/asm/insn.h +1
-0+#define ARCH64_NOP_OPCODE 0xD503201FWe have
aarch64_insn_gen_nopfor this.Will
Re: [RFC 2/8] ARM64: Refactor kprobes-arm64
In reply to Will DeaconQuoted 10 lines · Will Deacon
Quoted 5 lines · Pratyush Anand
Most of the stuff of
kprobes-arm64.ccan also be used byuprobes.c. So move all those part to common code area. In the process rename kprobe to probe whereever possible.No functional change.
In which case, can you merge this into the kprobes series (which we haven't merged yet)?
Yes, thats why these are just RFCs. I will send next version of uprobe only after kprobe patches are accepted into maintainer's tree.
~Pratyush
Quoted 7 lines
Will
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo at vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Re: [RFC 2/8] ARM64: Refactor kprobes-arm64
Quoted 6 lines · Pratyush Anand
Quoted 5 lines · Will Deacon
Quoted 4 lines · Pratyush Anand
Most of the stuff of
kprobes-arm64.ccan also be used byuprobes.c. So move all those part to common code area. In the process rename kprobe to probe whereever possible.
Quoted 8 lines
Quoted 5 lines
Quoted 1 line
No functional change.
In which case, can you merge this into the kprobes series (which we haven't merged yet)?
Yes, thats why these are just RFCs. I will send next version of uprobe only after kprobe patches are accepted into maintainer's tree.
Ok, but it also makes sense to make kprobes refactoring changes *before* the patches are merged, as that reduces churn in mainline whilst you don't have any other dependencies.
Will
Re: [RFC 2/8] ARM64: Refactor kprobes-arm64
Quoted 13 lines · Will Deacon
Quoted 12 lines · Pratyush Anand
Quoted 10 lines · Will Deacon
Quoted 5 lines · Pratyush Anand
Most of the stuff of
kprobes-arm64.ccan also be used byuprobes.c. So move all those part to common code area. In the process rename kprobe to probe whereever possible.No functional change.
In which case, can you merge this into the kprobes series (which we haven't merged yet)?
Quoted 7 lines
Quoted 2 lines
Yes, thats why these are just RFCs. I will send next version of uprobe only after kprobe patches are accepted into maintainer's tree.
Ok, but it also makes sense to make kprobes refactoring changes *before* the patches are merged, as that reduces churn in mainline whilst you don't have any other dependencies.
Sure, Sure.. I too expect first two patches to be merged with kprobe series. I just did that to develop my uprobe code.
~Pratyush
Quoted 2 lines
Will
Re: [RFC 6/8] ARM64: Handle TRAP_HWBRKPT for user mode as well
In reply to Will DeaconQuoted 37 lines · Will Deacon
Quoted 36 lines · Oleg Nesterov
Let me repeat once again that I know absolutely nothing about arm* ;)
Quoted 24 lines · Pratyush Anand
uprobe registers a handler at
step_hook. So,single_step_handlernow checks for user mode as well if there is a valid hook.Signed-off-by Pratyush Anand <[email protected]>--- arch/arm64/kernel/debug-monitors.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)arch/arm64/kernel/debug-monitors.c +3
-0@@ -236,6 +236,9 @@ static int single_step_handler(unsigned long addr, unsigned int esr,if (!reinstall_suspended_bps (regs))return 0 ; +if (call_step_hook (regs, esr) ==DBG_HOOK_HANDLED ) +return 0 ; +if (user_mode (regs)) { info.si_signo =SIGTRAP ; info.si_errno =0 ;arch/arm64/kernel/debug-monitors.c static int single_step_handler(unsigned long addr, unsigned int esr, · line 256
Quoted 6 lines
arch/arm64/kernel/debug-monitors.c +0
-3@@ -251,9 +254,6 @@ static int single_step_handler(unsigned long addr, unsigned int esr,*/ user_rewind_single_step (current); }else { -if (call_step_hook (regs, esr) ==DBG_HOOK_HANDLED ) -return 0 ; -Agreed, we need something like this change...
Quoted 7 lines
Quoted 5 lines
But did you verify that it can't break other users of
register_step_hook()? The current handlers do not checkuser_mode()== F, they assume that they can't be called otherwise.If this all is correct, please explain why in the changelog.
I think you're right, and kgdb will need fixing with this change.
OK, I will fix kgdb too when I will send next revision.
~Pratyush
Quoted 8 lines
Will
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo at vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Re: [RFC 8/8] ARM64: Add uprobe support
In reply to Will DeaconQuoted 10 lines · Will Deacon
Quoted 7 lines · Pratyush Anand
This patch adds support for uprobe on ARM64 architecture.
Unit test for following has been done so far and they have been found working
1. Normal instruction, which can be probed like sub, ldr, add etc.
2. Instructions which can be simulated like ret.
3. uretprobeI'm assuming that means you don't support compat (AArch32) tasks with this?
Hummm.. Yes, compat not yet supported.
I will come back on this.
~Pratyush
Quoted 9 lines
How do you enforce that?
Will
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel at lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
Re: [RFC 4/8] ARM64: Add instruction_pointer_set function
In reply to Will DeaconQuoted 17 lines · Will Deacon
Quoted 16 lines · Pratyush Anand
instruction_pointer_setis needed for uprobe implementation. Hence define it for ARM64.Signed-off-by Pratyush Anand <[email protected]>--- arch/arm64/include/asm/ptrace.h | 6 ++++++ 1 file changed, 6 insertions(+)arch/arm64/include/asm/ptrace.h +0
-0@@ -206,6 +206,12 @@ static inline int valid_user_regs(struct user_pt_regs *regs)#define instruction_pointer (regs) ((regs)->pc)#define stack_pointer (regs) ((regs)->sp)
Quoted 11 lines
arch/arm64/include/asm/ptrace.h static inline int valid_user_regs(struct user_pt_regs *regs) · line 213
Quoted 5 lines
arch/arm64/include/asm/ptrace.h +5
-0+static inline void instruction_pointer_set (struct pt_regs *regs, +unsigned long val) +{ +instruction_pointer (regs) = val; +}Do you think we could make use of the asm-generic ptrace header to get this for free? afaict, we just need to implement
GET_USPand possiblyGET_FPfor the compat case (although it may well be that we still handle the compat case entirely separately).
Yes, We can use asm-generic for it.
I think , we can also add link_pointer and link_pointer_set in asm-generic/ptrace.h to help with all retprobes.
~Pratyush
Quoted 7 lines
Will
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo at vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Oleg Nesterov
maintainerRe: [RFC 8/8] ARM64: Add uprobe support
In reply to Pratyush AnandQuoted 8 lines · Pratyush Anand
Quoted 2 lines · Will Deacon
I'm assuming that means you don't support compat (AArch32) tasks with this?
Hummm.. Yes, compat not yet supported.
I will come back on this.
I obviously do not know how difficult is to support the compat tasks, and in any case I leave this to you and Will.
But if this is not simple, perhaps the initial implementation could simply nack the probe in arch_uprobe_analyze_insn() if this mm is not 64-bit. Although I do not see something like is_64bit_mm() in arch/arm64... So may be the first version can even ignore this problem and just document the fact that AArch32 tasks are not supported.
Oleg.
Oleg Nesterov
maintainerRe: [RFC 8/8] ARM64: Add uprobe support
In reply to Pratyush AnandQuoted 15 lines · Pratyush Anand
arch/arm64/kernel/uprobes.c new file +14
-0+int arch_uprobe_analyze_insn (struct arch_uprobe *auprobe,struct mm_struct *mm, +unsigned long addr) +{ +probe_opcode_t insn; + + insn = *(probe_opcode_t *)(&auprobe->insn[0 ]); + +switch (arm_probe_decode_insn (insn, &auprobe->ainsn)) { +case INSN_REJECTED : +return -EINVAL ; + +case INSN_GOOD_NO_SLOT : + auprobe->simulate = true; +if (auprobe->ainsn.prepare)
arch/arm64/kernel/uprobes.c line 107
Quoted 10 lines
arch/arm64/kernel/uprobes.c new file +10
-0+ auprobe->ainsn.prepare (insn, &auprobe->ainsn); +break ; + +case INSN_GOOD : +default : +break ; + } + +return 0 ; +}
forgot to mention... shouldn't it also check IS_ALIGNED(addr, AARCH64_INSN_SIZE) ?
I do not know if unaligned insn address is valid on arm64 or not, but please note that at least it should not cross the page boundary, set_swbp() needs to write AARCH64_INSN_SIZE == UPROBE_SWBP_INSN bytes and it assumes that this should fit the single page.
Oleg.
Re: [RFC 8/8] ARM64: Add uprobe support
In reply to Oleg NesterovQuoted 4 lines · Oleg Nesterov
Quoted 3 lines · Pratyush Anand
Quoted 1 line · Will Deacon
Quoted 9 lines
Quoted 5 lines
Quoted 1 line
I'm assuming that means you don't support compat (AArch32) tasks with this?
Hummm.. Yes, compat not yet supported.
I will come back on this.
I obviously do not know how difficult is to support the compat tasks, and in any case I leave this to you and Will.
I think most of the stuff can be picked from arch/arm. But I do not have a platform to test this feature.So, I will not be taking up as of now.
~Pratyush
Re: [RFC 8/8] ARM64: Add uprobe support
In reply to Oleg NesterovQuoted 29 lines · Oleg Nesterov
Quoted 15 lines · Pratyush Anand
arch/arm64/kernel/uprobes.c new file +14
-0+int arch_uprobe_analyze_insn (struct arch_uprobe *auprobe,struct mm_struct *mm, +unsigned long addr) +{ +probe_opcode_t insn; + + insn = *(probe_opcode_t *)(&auprobe->insn[0 ]); + +switch (arm_probe_decode_insn (insn, &auprobe->ainsn)) { +case INSN_REJECTED : +return -EINVAL ; + +case INSN_GOOD_NO_SLOT : + auprobe->simulate = true; +if (auprobe->ainsn.prepare)arch/arm64/kernel/uprobes.c line 107
Quoted 10 lines
arch/arm64/kernel/uprobes.c new file +10
-0+ auprobe->ainsn.prepare (insn, &auprobe->ainsn); +break ; + +case INSN_GOOD : +default : +break ; + } + +return 0 ; +}forgot to mention... shouldn't it also check
IS_ALIGNED(addr, AARCH64_INSN_SIZE)?
Quoted 1 line
I do not know if unaligned insn address is valid on arm64 or not, but please
AARCH64 instructions are always of fixed lenght ie 4 bytes. I do not see possibility of addr being unaligned. Please let me know, if I am missing something.
Quoted 3 lines
note that at least it should not cross the page boundary,
set_swbp()needs to writeAARCH64_INSN_SIZE==UPROBE_SWBP_INSNbytes and it assumes that this should fit the single page.
So, again I do not see the possibility of crossing of page boundary for any instruction address.
~Pratyush
Re: [RFC 8/8] ARM64: Add uprobe support
Hi Oleg,
How can I generate a scenario to test:
a) arch_uprobe_xol_was_trapped
b) arch_uprobe_abort_xol
~Pratyush
Quoted 51 lines · Pratyush Anand
Quoted 31 lines · Oleg Nesterov
Quoted 16 lines · Pratyush Anand
+int arch_uprobe_analyze_insn(struct
arch_uprobe*auprobe, structmm_struct*mm,arch/arm64/kernel/uprobes.c new file +13
-0+ unsigned long addr) +{ +probe_opcode_t insn; + + insn = *(probe_opcode_t *)(&auprobe->insn[0 ]); + +switch (arm_probe_decode_insn (insn, &auprobe->ainsn)) { +case INSN_REJECTED : +return -EINVAL ; + +case INSN_GOOD_NO_SLOT : + auprobe->simulate = true; +if (auprobe->ainsn.prepare)arch/arm64/kernel/uprobes.c line 107
Quoted 10 lines
arch/arm64/kernel/uprobes.c new file +10
-0+ auprobe->ainsn.prepare (insn, &auprobe->ainsn); +break ; + +case INSN_GOOD : +default : +break ; + } + +return 0 ; +}forgot to mention... shouldn't it also check
IS_ALIGNED(addr, AARCH64_INSN_SIZE)?Quoted 2 lines
I do not know if unaligned insn address is valid on arm64 or not, but please
AARCH64 instructions are always of fixed lenght ie 4 bytes. I do not see possibility of addr being unaligned. Please let me know, if I am missing something.
Quoted 5 lines
note that at least it should not cross the page boundary,
set_swbp()needs to
writeAARCH64_INSN_SIZE==UPROBE_SWBP_INSNbytes and it assumes that this
should fit the single page.So, again I do not see the possibility of crossing of page boundary for any instruction address.
~Pratyush
Oleg Nesterov
maintainerRe: [RFC 8/8] ARM64: Add uprobe support
In reply to Pratyush AnandQuoted 32 lines · Pratyush Anand
Quoted 29 lines · Oleg Nesterov
Quoted 15 lines · Pratyush Anand
arch/arm64/kernel/uprobes.c new file +14
-0+int arch_uprobe_analyze_insn (struct arch_uprobe *auprobe,struct mm_struct *mm, +unsigned long addr) +{ +probe_opcode_t insn; + + insn = *(probe_opcode_t *)(&auprobe->insn[0 ]); + +switch (arm_probe_decode_insn (insn, &auprobe->ainsn)) { +case INSN_REJECTED : +return -EINVAL ; + +case INSN_GOOD_NO_SLOT : + auprobe->simulate = true; +if (auprobe->ainsn.prepare)arch/arm64/kernel/uprobes.c line 107
Quoted 10 lines
arch/arm64/kernel/uprobes.c new file +10
-0+ auprobe->ainsn.prepare (insn, &auprobe->ainsn); +break ; + +case INSN_GOOD : +default : +break ; + } + +return 0 ; +}forgot to mention... shouldn't it also check
IS_ALIGNED(addr, AARCH64_INSN_SIZE)?
Quoted 5 lines
Quoted 1 line
I do not know if unaligned insn address is valid on arm64 or not, but please
AARCH64 instructions are always of fixed lenght ie 4 bytes. I do not see possibility of addr being unaligned. Please let me know, if I am missing something.
A user can write any offset into uprobe_events, and the generic code doesn't check it is aligned.
Quoted 6 lines
Quoted 3 lines
note that at least it should not cross the page boundary,
set_swbp()needs to writeAARCH64_INSN_SIZE==UPROBE_SWBP_INSNbytes and it assumes that this should fit the single page.So, again I do not see the possibility of crossing of page boundary for any instruction address.
See above. So yes, it should really check IS_ALIGNED(AARCH64_INSN_SIZE).
Oleg.
Oleg Nesterov
maintainerRe: [RFC 8/8] ARM64: Add uprobe support
In reply to Pratyush AnandQuoted 7 lines · Pratyush Anand
Hi Oleg,
How can I generate a scenario to test:
a)
arch_uprobe_xol_was_trapped
b)arch_uprobe_abort_xol
For example, you can probe something like
*(int *)NULL = 0;
See also the x86 test-case in https://lkml.org/lkml/2011/10/21/148
and the whole thread.
Oleg.