Uprobes patches.
Subsystems (9)
cover Uprobes patches.
This patchset implements Uprobes which enables you to dynamically break into any routine in a user space application and collect information non-disruptively.
This patchset is a rework based on suggestions from discussions on lkml in January this year (http://lkml.org/lkml/2010/1/11/92 and
http://lkml.org/lkml/2010/1/27/19). This implementation of uprobes doesnt depend on utrace.
When a uprobe is registered, Uprobes makes a copy of the probed instruction, replaces the first byte(s) of the probed instruction with a breakpoint instruction. (Uprobes uses background page replacement mechanism and ensures that the breakpoint affects only that process.)
When a CPU hits the breakpoint instruction, Uprobes gets notified of trap and finds the associated uprobe. It then executes the associated handler. Uprobes single-steps its copy of the probed instruction and resumes execution of the probed process at the instruction following the probepoint. Instruction copies to be single-stepped are stored in a per-process "execution out of line (XOL) area". Currently XOL area is allocated as one page vma.
Advantages of uprobes over conventional debugging include:
1. Non-disruptive.
2. Much better handling of multithreaded programs because of XOL.
3. No context switch between tracer, tracee.
4. Allows multiple processes to trace same tracee.
Here is the list of TODO Items.
- Provide a perf interface to uprobes. (coming in next version)
- Allowing probes across fork/exec.
- Allowing probes on per-executable/per dso.
- Allow multiple probes to share a probepoint.
- Support for other architectures.
- Return probes.
- Uprobes booster.
This patchset is based on 2.6.34-rc2.
Please do provide your valuable comments.
Thanks in advance.
Srikar
Srikar Dronamraju (10):
1. X86 instruction analysis: Move Macro W to insn.h 2. mm: Move replace_page() to mm/memory.c 3. mm: Enhance replace_page() to support pagecache 4. user_bkpt: User Space Breakpoint Assistance Layer 5. user_bkpt: X86 details for User space breakpoint assistance 6. user_bkpt: Slot allocation for Execution out of line 7. uprobes: Uprobes Implementation 8. uprobes: X86 details for Uprobes 9. uprobes: Uprobes Documentation patch
10. samples: Uprobes samples
Documentation/uprobes.txt | 244 ++++++++++++ arch/Kconfig | 31 ++ arch/x86/Kconfig | 2 + arch/x86/include/asm/insn.h | 7 + arch/x86/include/asm/user_bkpt.h | 43 ++ arch/x86/kernel/Makefile | 3 + arch/x86/kernel/kprobes.c | 7 - arch/x86/kernel/uprobes.c | 87 ++++ arch/x86/kernel/user_bkpt.c | 574 +++++++++++++++++++++++++++ include/linux/mm.h | 2 + include/linux/sched.h | 3 + include/linux/tracehook.h | 18 + include/linux/uprobes.h | 178 +++++++++ include/linux/user_bkpt.h | 296 ++++++++++++++ include/linux/user_bkpt_xol.h | 61 +++ kernel/Makefile | 3 + kernel/fork.c | 3 + kernel/uprobes.c | 798 ++++++++++++++++++++++++++++++++++++++ kernel/user_bkpt.c | 572 +++++++++++++++++++++++++++ kernel/user_bkpt_xol.c | 290 ++++++++++++++ mm/ksm.c | 59 --- mm/memory.c | 62 +++ samples/Kconfig | 7 + samples/uprobes/Makefile | 17 + samples/uprobes/uprobe_example.c | 83 ++++ 25 files changed, 3384 insertions(+), 66 deletions(-)
---
0 files changed, 0 insertions(+), 0 deletions(-)
PATCH 1/10 Move Macro W to insn.h
Move Macro W to asm/insn.h
Macro W used to know if the instructions are valid for user-space/kernel space. This macro is used by kprobes and user_bkpt. (i.e user space breakpoint assistance layer.) So moving it to a common header file asm/insn.h.
---
arch/x86/include/asm/insn.h | 7 +++++++ arch/x86/kernel/kprobes.c | 7 ------- 2 files changed, 7 insertions(+), 7 deletions(-)
arch/x86/include/asm/insn.h +7 -0
@@ -23,6 +23,13 @@/* insn_attr_t is defined in inat.h */ #include <asm/inat.h> +#define W (row, b0, b1, b2, b3, b4, b5, b6, b7, b8, b9, ba, bb, bc, bd, be, bf)\ + (((b0##UL << 0x0)|(b1##UL << 0x1)|(b2##UL << 0x2)|(b3##UL << 0x3) | \ + (b4##UL << 0x4)|(b5##UL << 0x5)|(b6##UL << 0x6)|(b7##UL << 0x7) | \ + (b8##UL << 0x8)|(b9##UL << 0x9)|(ba##UL << 0xa)|(bb##UL << 0xb) | \ + (bc##UL << 0xc)|(bd##UL << 0xd)|(be##UL << 0xe)|(bf##UL << 0xf)) \ + << (row % 32)) + struct insn_field { union { insn_value_t value;
arch/x86/kernel/kprobes.c +0 -7
@@ -66,12 +66,6 @@ DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk);#define stack_addr (regs) ((unsigned long *)kernel_stack_pointer(regs)) -#define W (row, b0, b1, b2, b3, b4, b5, b6, b7, b8, b9, ba, bb, bc, bd, be, bf)\ - (((b0##UL << 0x0)|(b1##UL << 0x1)|(b2##UL << 0x2)|(b3##UL << 0x3) | \ - (b4##UL << 0x4)|(b5##UL << 0x5)|(b6##UL << 0x6)|(b7##UL << 0x7) | \ - (b8##UL << 0x8)|(b9##UL << 0x9)|(ba##UL << 0xa)|(bb##UL << 0xb) | \ - (bc##UL << 0xc)|(bd##UL << 0xd)|(be##UL << 0xe)|(bf##UL << 0xf)) \ - << (row % 32))/* * Undefined/reserved opcodes, conditional jump, Opcode Extension * Groups, and some special opcodes can not boost.
@@ -98,7 +92,6 @@ static const u32 twobyte_is_boostable[256 / 32] = {/* ----------------------------------------------- */ /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ }; -#undef Wstruct kretprobe_blackpoint kretprobe_blacklist[] = { {"__switch_to" , },/* This function switches only current task, but
Re: [PATCH v1 1/10] Move Macro W to insn.h
Quoted 6 lines · Srikar Dronamraju
Move Macro W to
asm/insn.hMacro W used to know if the instructions are valid for user-space/kernel space. This macro is used by kprobes and
user_bkpt. (i.e user space breakpoint assistance layer.) So moving it to a common header fileasm/insn.h.
Hmm, I don't think this shortest macro name is good to expose commonly... And also, since we already have inat (instruction attribute) table, we'd better expand an inat bit to indicate which instruction can be probed/boosted.
Thank you,
Signature · 2 lines
Masami Hiramatsu e-mail: [email protected]
Re: [PATCH v1 1/10] Move Macro W to insn.h
Quoted 8 lines · Masami Hiramatsu
Quoted 6 lines · Srikar Dronamraju
Move Macro W to
asm/insn.hMacro W used to know if the instructions are valid for user-space/kernel space. This macro is used by kprobes and
user_bkpt. (i.e user space breakpoint assistance layer.) So moving it to a common header fileasm/insn.h.
Quoted 5 lines
Hmm, I don't think this shortest macro name is good to expose commonly... And also, since we already have inat (instruction attribute) table, we'd better expand an inat bit to indicate which instruction can be probed/boosted.
Guess we would need three bits,
- Instruction can be probed in kernel.
- Instruction can be probed in user space.
- Instruction can be boosted.
Or do you have other ideas?
--
Thanks and Regards
Srikar
Re: [PATCH v1 1/10] Move Macro W to insn.h
Quoted 10 lines · Srikar Dronamraju
Quoted 8 lines · Masami Hiramatsu
Quoted 6 lines · Srikar Dronamraju
Move Macro W to
asm/insn.hMacro W used to know if the instructions are valid for user-space/kernel space. This macro is used by kprobes and
user_bkpt. (i.e user space breakpoint assistance layer.) So moving it to a common header fileasm/insn.h.
Quoted 8 lines
Quoted 5 lines
Hmm, I don't think this shortest macro name is good to expose commonly... And also, since we already have inat (instruction attribute) table, we'd better expand an inat bit to indicate which instruction can be probed/boosted.
Guess we would need three bits,
- Instruction can be probed in kernel.
Currently, we don't have any maps for this bit.
Quoted 2 lines
- Instruction can be probed in user space.
- Instruction can be boosted.
Other two bits are ok for me :)
Thank you,
Quoted 6 lines
Or do you have other ideas?
--
Thanks and Regards
Srikar
Signature · 2 lines
Masami Hiramatsu e-mail: [email protected]
PATCH 2/10 Move replace_page() to mm/memory.c
In reply to Srikar DronamrajuMove replace_page() to mm/memory.c
Move replace_page from mm/ksm.c to mm/memory.c.
User bkpt will use background page replacement approach to insert/delete breakpoints. Background page replacement approach will be based on replace_page. Now replace_page() loses its static attribute.
---
include/linux/mm.h | 2 ++ mm/ksm.c | 59 ---------------------------------------------------- mm/memory.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 61 insertions(+), 59 deletions(-)
include/linux/mm.h +2 -0
@@ -854,6 +854,8 @@ void account_page_dirtied(struct page *page, struct address_space *mapping);int set_page_dirty (struct page *page);int set_page_dirty_lock (struct page *page);int clear_page_dirty_for_io (struct page *page); +int replace_page (struct vm_area_struct *vma,struct page *page, +struct page *kpage,pte_t orig_pte); extern unsigned long move_page_tables(struct vm_area_struct *vma, unsigned long old_addr, struct vm_area_struct *new_vma,
mm/ksm.c +0 -59
65 lines not on this page · raw message
mm/memory.c +59 -0
65 lines not on this page · raw message
PATCH 3/10 Enhance replace_page() to support pagecache
In reply to Srikar DronamrajuEnhance replace_page() to support pagecache
Currently replace_page would work only for anonymous pages. This patch enhances replace_page() to work for pagecache pages
This enhancement is useful for user_bkpt's replace_page based background page replacement for insertion and removal of breakpoints.
---
mm/memory.c | 5 ++++- 1 files changed, 4 insertions(+), 1 deletions(-)
mm/memory.c +4 -1
@@ -2616,7 +2616,10 @@ int replace_page(struct vm_area_struct *vma, struct page *page, }get_page (kpage); -page_add_anon_rmap (kpage, vma, addr); +if (PageAnon (kpage)) +page_add_anon_rmap (kpage, vma, addr); +else +page_add_file_rmap (kpage);flush_cache_page (vma, addr,pte_pfn (*ptep));ptep_clear_flush (vma, addr, ptep);
PATCH 4/10 User Space Breakpoint Assistance Layer
In reply to Srikar DronamrajuUser Space Breakpoint Assistance Layer (USER_BKPT)
Currently there is no mechanism in kernel to insert/remove breakpoints.
This patch implements user space breakpoint assistance layer provides kernel subsystems with architecture independent interface to establish breakpoints in user applications. This patch provides core implementation of user_bkpt and also wrappers for architecture dependent methods.
USER_BKPT currently supports both single stepping inline and execution out of line strategies. Two different probepoints in the same process can have two different strategies. It handles pre-processing and post-processing of singlestep after a breakpoint hit.
Single stepping inline strategy is the traditional method where original instructions replace the breakpointed instructions on a breakpoint hit. This method works well with single threaded applications. However its racy with multithreaded applications.
Execution out of line strategy single steps on a copy of the instruction. This method works well for both single-threaded and multithreaded applications.
There could be other strategies like emulating an instruction. However they are currently not implemented.
Insertion and removal of breakpoints is by "Background page replacement". i.e make a copy of the page, modify its the contents, set the pagetable and flush the tlbs. This page uses enhanced replace_page to cow the page. Modified page is only reflected for the interested process. Others sharing the page will still see the old copy.
You need to follow this up with the USER_BKPT patch for your architecture.
Uprobes uses this facility to insert/remove breakpoint.
---
arch/Kconfig | 14 + include/linux/user_bkpt.h | 296 +++++++++++++++++++++++ kernel/Makefile | 1 kernel/user_bkpt.c | 572 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 883 insertions(+), 0 deletions(-) create mode 100644 include/linux/user_bkpt.h create mode 100644 kernel/user_bkpt.c
arch/Kconfig +14 -0
@@ -52,6 +52,17 @@ config OPTPROBES This option will allow kprobes to optimize breakpoint to a jump for reducing its overhead. +config USER_BKPT + bool "User-space breakpoint assistance (EXPERIMENTAL)" + depends on MODULES + depends on HAVE_USER_BKPT + depends on !HIGHPTE + help + User_bkpt (User-space breakpoint assistance layer) enables + kernel subsystems to establish breakpoints in user applications. + This service is used by components such as uprobes. + If in doubt, say "N". + config HAVE_EFFICIENT_UNALIGNED_ACCESS bool help
@@ -85,6 +96,9 @@ config USER_RETURN_NOTIFIER Provide a kernel-internal notification when a cpu is about to switch to user mode. +config HAVE_USER_BKPT + def_bool n + config HAVE_IOREMAP_PROT bool
include/linux/user_bkpt.h new file +296 -0
296 lines not on this page · raw message
kernel/Makefile +1 -0
@@ -105,6 +105,7 @@ obj-$(CONFIG_PERF_EVENTS) += perf_event.o obj-$(CONFIG_HAVE_HW_BREAKPOINT) += hw_breakpoint.o obj-$(CONFIG_USER_RETURN_NOTIFIER) += user-return-notifier.o obj-$(CONFIG_PADATA) += padata.o +obj-$(CONFIG_USER_BKPT) += user_bkpt.o ifneq ($(CONFIG_SCHED_OMIT_FRAME_POINTER),y) # According to Alan Modra <[email protected]>, the -fno-omit-frame-pointer is
kernel/user_bkpt.c new file +572 -0
572 lines not on this page · raw message
Andrew Morton
maintainerRe: [PATCH v1 4/10] User Space Breakpoint Assistance Layer
Quoted 2 lines · On Sat, 20 Mar 2010 19:55:41 +0530 Srikar Dronamraju…
User Space Breakpoint Assistance Layer (
USER_BKPT)
A quick scan, just to show I was paying attention ;)
Quoted 7 lines
...
+/*
+ * Read @nbytes at @vaddr from @tsk into @kbuf. Return number of bytes read.
+ * Not exported, but available for use by arch-specificuser_bkptcode.
+ */
You may as well finish off the kerneldoc on some of these functions.
kernel/user_bkpt.c line 101
Quoted 10 lines
kernel/user_bkpt.c new file +10
-0+int user_bkpt_read_vm (struct task_struct *tsk,unsigned long vaddr, +void *kbuf,int nbytes) +{ +if (tsk == current) { +int nleft =copy_from_user (kbuf, (void __user *) vaddr, + nbytes); +return nbytes - nleft; + }else +return access_process_vm (tsk, vaddr, kbuf, nbytes,0 ); +}
copy_from_user() takes and returns an unsigned long arg but this function is converting these to and from ints. That's OK if we're 100% sure that we'll never get or return an arg >2G. Otherwise things could get ghastly. Please have a think. (Dittoes for some other functionss around here).
Quoted 7 lines
kernel/user_bkpt.c new file +7
-0+ +* Write @nbytes from @kbuf at @vaddr in @tsk. Return number of bytes written. +* Can be used to write to stack or data VM areas, but not instructions. +* Not exported, but available for use by arch-specific user_bkpt code. +*/ +int user_bkpt_write_data (struct task_struct *tsk,unsigned long vaddr, +const void *kbuf,int nbytes)
kernel/user_bkpt.c line 119
Quoted 10 lines
kernel/user_bkpt.c new file +10
-0+{ +int nleft; + +if (tsk == current) { + nleft =copy_to_user ((void __user *) vaddr, kbuf, nbytes); +return nbytes - nleft; + }else +return access_process_vm (tsk, vaddr, (void *) kbuf, + nbytes,1 ); +}
This looks like it has the wrong interface. It should take a `void __user *vaddr'. If any casting is to be done, it should be done at the highest level so that sparse can check that the thing is used correctly in as many places as possible.
kernel/user_bkpt.c line 125
Quoted 5 lines
kernel/user_bkpt.c new file +5
-0+/* +* Given an address, get its pte. Very similar to get_locked_pte except +* there is no spinlock involved. +*/ +static inline pte_t *get_pte (struct mm_struct *mm,unsigned long vaddr)
The inline is either unneeded or undesirable, I suspect.
Quoted 36 lines
kernel/user_bkpt.c new file +36
-0+{ +pgd_t *pgd; +pud_t *pud; +pmd_t *pmd; +pte_t *pte; + + pgd =pgd_offset (mm, vaddr); + pud =pud_alloc (mm, pgd, vaddr); +if (!pud) +return NULL ; + pmd =pmd_alloc (mm, pud, vaddr); +if (!pmd) +return NULL ; + pte =pte_alloc_map (mm, pmd, vaddr); +return pte; +} + +static int write_opcode (struct task_struct *tsk,unsigned long vaddr, +user_bkpt_opcode_t opcode) +{ +struct mm_struct *mm; +struct vm_area_struct *vma; +struct page *old_page, *new_page; +void *maddr; +pte_t *old_pte; +int offset; +int ret = -EINVAL ; + +if (!tsk) +return ret; + + mm =get_task_mm (tsk); +if (!mm) +return ret; + +down_read (&mm->mmap_sem);
kernel/user_bkpt.c line 171
Quoted 10 lines
kernel/user_bkpt.c new file +10
-0+ +/* Read the page with vaddr into memory */ + ret =get_user_pages (tsk, mm, vaddr,1 ,0 ,1 , &old_page, &vma); +if (ret <=0 ) { +up_read (&mm->mmap_sem); + goto mmput_out; + } + +/* Allocate a page and copy contents over from the old page */ + new_page =alloc_page_vma (GFP_HIGHUSER_MOVABLE , vma, vaddr);
It might be smarter to allocate this page outside the mmap_sem region. More scalable, less opportunity for weird deadlocks.
Quoted 10 lines
kernel/user_bkpt.c new file +10
-0+if (!new_page) { + ret = -ENOMEM ; + goto unlock_out; + } + +/* +* check if the page we are interested is read-only mapped +* Since we are interested in text pages, Our pages of interest +* should be mapped read-only. +*/
kernel/user_bkpt.c line 191
Quoted 10 lines
kernel/user_bkpt.c new file +10
-0+if ((vma->vm_flags && (VM_READ |VM_WRITE )) !=VM_READ ) { + ret = -EINVAL ; + goto unlock_out; + } + +copy_user_highpage (new_page, old_page, vaddr, vma); + maddr =kmap (new_page); + offset = vaddr & (PAGE_SIZE -1 ); +memcpy (maddr + offset, &opcode, user_bkpt_opcode_sz); +kunmap (new_page);
kmap_atomic() is preferred - it's faster. kmap() is still deadlockable I guess if a process ever kmaps two pages at the same time. This code doesn't do that, but kmap is still a bit sucky.
Quoted 20 lines
kernel/user_bkpt.c new file +20
-0+ old_pte =get_pte (mm, vaddr); +if (!old_pte) { + ret = -EINVAL ; + goto unlock_out; + } + +/* +* Now replace the page in vma with the new page. +* This is a text page; so, setup mapping and index. +*/ + new_page->mapping = old_page->mapping; + new_page->index = old_page->index; + ret =replace_page (vma, old_page, new_page, *old_pte); + +unlock_out: +if (ret !=0 ) +page_cache_release (new_page); +put_page (old_page);/* we did a get_page in the beginning */ +up_read (&mm->mmap_sem); +mmput_out:
kernel/user_bkpt.c line 271
Quoted 10 lines
kernel/user_bkpt.c new file +7
-0+mmput (mm); +return ret; +} + +/** +* user_bkpt_validate_insn_addr - Validate if the instruction is an +* executable vma.
It used to be the case that the above linebreak is "wrong". (Nobody ever tests their kerneldoc output!) I have a vague feeling that this might have been fixed lately. Randy?
Quoted 17 lines
+ * Returns 0 if the vaddr is a valid instruction address.
+ * @tsk: the probed task
+ * @vaddr: virtual address of the instruction to be verified.
+ *
+ * Possible errors:
+ * -%EINVAL: Instruction passed is not a valid instruction address.
+ */kernel/user_bkpt.c new file +10
-0+int user_bkpt_validate_insn_addr (struct task_struct *tsk,unsigned long vaddr) +{ +int result; + + result =check_vma (tsk, vaddr); +if (result !=0 ) +return result; +if (arch->validate_address) + result = arch->validate_address (tsk, vaddr); +return result;
kernel/user_bkpt.c line 334
Quoted 10 lines
kernel/user_bkpt.c new file +7
-0+} + +int user_bkpt_insert_bkpt (struct task_struct *tsk,struct user_bkpt *user_bkpt) +{ +int result, len; + +BUG_ON (!tsk || !user_bkpt);
If this BUG_ON triggers, we won't know which of these pointers was NULL, which makes us sad.
kernel/user_bkpt.c line 410
Quoted 12 lines
kernel/user_bkpt.c new file +9
-0+if (!validate_strategy (user_bkpt->strategy,USER_BKPT_HNT_MASK )) +return -EINVAL ; + +int user_bkpt_pre_sstep (struct task_struct *tsk,struct user_bkpt *user_bkpt, +struct user_bkpt_task_arch_info *tskinfo,struct pt_regs *regs) +{ +int result; + +BUG_ON (!tsk || !user_bkpt || !regs);
ditto.
Really, there's never much point in
BUG_ON(!some_pointer);
Just go ahead and dereference the pointer. If it's NULL then we'll get an oops which gives all the information which the BUG_ON would have given.
Quoted 22 lines
kernel/user_bkpt.c new file +22
-0+if (uses_xol_strategy (user_bkpt->strategy)) { +BUG_ON (!user_bkpt->xol_vaddr); +return arch->pre_xol (tsk, user_bkpt, tskinfo, regs); + } + +/* +* Single-step this instruction inline. Replace the breakpoint +* with the original opcode. +*/ + result = arch->set_orig_insn (tsk, user_bkpt, false); +if (result ==0 ) + arch->set_ip (regs, user_bkpt->vaddr); +return result; +} + +/** +* user_bkpt_post_sstep - prepare to resume execution after single-step +* @tsk: the probed task +* @user_bkpt: the probepoint information, as with @user_bkpt_pre_sstep() +* @tskinfo: the @user_bkpt_task_arch_info object, if any, passed to +* @user_bkpt_pre_sstep() +* @regs: reflects the saved state of @tsk after the single-step
kernel/user_bkpt.c line 442
Quoted 10 lines
kernel/user_bkpt.c new file +10
-0+* operation. @user_bkpt_post_sstep() adjusts @tsk's state as needed, +* including pointing the instruction pointer at the instruction +* following the probed instruction. +* Possible errors: +* -%EFAULT: Failed to read or write @tsk's address space as needed. +*/ +int user_bkpt_post_sstep (struct task_struct *tsk,struct user_bkpt *user_bkpt, +struct user_bkpt_task_arch_info *tskinfo,struct pt_regs *regs) +{ +BUG_ON (!tsk || !user_bkpt || !regs);
More dittoes. It's just bloat.
Quoted 13 lines
kernel/user_bkpt.c new file +10
-0+if (uses_xol_strategy (user_bkpt->strategy)) +return arch->post_xol (tsk, user_bkpt, tskinfo, regs); + +/* +* Single-stepped this instruction inline. Put the breakpoint +* instruction back. +*/ +return arch->set_bkpt (tsk, user_bkpt); +} +
Re: [PATCH v1 4/10] User Space Breakpoint Assistance Layer
Quoted 5 lines · Andrew Morton
Quoted 3 lines · On Sat, 20 Mar 2010 19:55:41 +0530 Srikar Dronamraju…
...
Quoted 7 lines
Quoted 3 lines
+/**
+ *user_bkpt_validate_insn_addr- Validate if the instruction is an
+ * executable vma.It used to be the case that the above linebreak is "wrong". (Nobody ever tests their kerneldoc output!) I have a vague feeling that this might have been fixed lately. Randy?
Yes, that's OK now. Not a problem.
Signature · 1 line
~Randy
Re: [PATCH v1 4/10] User Space Breakpoint Assistance Layer
In reply to Andrew MortonQuoted 5 lines
Quoted 3 lines
User Space Breakpoint Assistance Layer (
USER_BKPT)A quick scan, just to show I was paying attention ;)
Thanks for taking a look and commenting on the code.
Quoted 18 lines
kernel/user_bkpt.c line 101
Quoted 11 lines
kernel/user_bkpt.c new file +10
-0+int user_bkpt_read_vm (struct task_struct *tsk,unsigned long vaddr, +void *kbuf,int nbytes) +{ +if (tsk == current) { +int nleft =copy_from_user (kbuf, (void __user *) vaddr, + nbytes); +return nbytes - nleft; + }else +return access_process_vm (tsk, vaddr, kbuf, nbytes,0 ); +}
copy_from_user()takes and returns an unsigned long arg but this function is converting these to and from ints. That's OK if we're 100% sure that we'll never get or return an arg >2G. Otherwise things could get ghastly. Please have a think. (Dittoes for some other functionss around here).
nbytes would not be greater than the maximum size of a instruction for that architecture. Hence I dont see it going above 2G. However I will take a relook.
I will rework the rest of the comments as suggested by you. It would be part of the next version.
--
Thanks and Regards
Srikar
PATCH 5/10 X86 details for user space breakpoint assistance.
In reply to Srikar Dronamrajux86 support for user breakpoint Infrastructure
This patch provides x86 specific userspace breakpoint assistance implementation details. It uses the "x86: instruction decoder API" patch to do validate and analyze the instructions. This analysis is used at the time of post-processing of breakpoint hit to do the necessary fix-ups.
Almost all instructions are handled for traditional strategy and execution out of line strategy. Instruction handled include the RIP relative instructions.
This patch requires "x86: instruction decoder API" patch.
http://lkml.org/lkml/2009/6/1/459
---
arch/x86/Kconfig | 1 arch/x86/include/asm/user_bkpt.h | 43 +++ arch/x86/kernel/Makefile | 2 arch/x86/kernel/user_bkpt.c | 574 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 620 insertions(+), 0 deletions(-) create mode 100644 arch/x86/include/asm/user_bkpt.h create mode 100644 arch/x86/kernel/user_bkpt.c
arch/x86/Kconfig +1 -0
@@ -53,6 +53,7 @@ config X86 select HAVE_KERNEL_LZMA select HAVE_KERNEL_LZO select HAVE_HW_BREAKPOINT + select HAVE_USER_BKPT select PERF_EVENTS select ANON_INODES select HAVE_ARCH_KMEMCHECK
arch/x86/include/asm/user_bkpt.h new file +43 -0
43 lines not on this page · raw message
arch/x86/kernel/Makefile +2 -0
@@ -117,6 +117,8 @@ obj-$(CONFIG_X86_CHECK_BIOS_CORRUPTION) += check.o obj-$(CONFIG_SWIOTLB) += pci-swiotlb.o +obj-$(CONFIG_USER_BKPT) += user_bkpt.o + ### # 64 bit specific files ifeq ($(CONFIG_X86_64),y)
arch/x86/kernel/user_bkpt.c new file +574 -0
574 lines not on this page · raw message
PATCH 6/10 Slot allocation for Execution out of line
In reply to Srikar DronamrajuSlot allocation for Execution out of line strategy(XOL)
This patch provides slot allocation mechanism for execution out of line strategy for use with user space breakpoint infrastructure.
Traditional method of replacing the original instructions on breakpoint hit are racy when used on multithreaded applications.
Alternatives for the traditional method include:
- Emulating the breakpointed instruction.
- Execution out of line.
Emulating the instruction:
This approach would use a in-kernel instruction emulator to
emulate the breakpointed instruction. This approach could be looked in at a later point of time.
Execution out of line:
In execution out of line strategy, a new vma is injected into
the target process, a copy of the instructions which are breakpointed is stored in one of the slots. On breakpoint hit, the copy of the instruction is single-stepped leaving the breakpoint instruction as is. This method is architecture independent.
This method is useful while handling multithreaded processes.
This patch allocates one page per process for slots to be used to copy the breakpointed instructions.
Current slot allocation mechanism:
1. Allocate one dedicated slot per user breakpoint. Each slot is big enuf to accomodate the biggest instruction for that architecture. (16 bytes for x86).
2. We currently allocate only one page for slots. Hence the number of slots is limited to active breakpoint hits on that process.
3. Bitmap to track used slots.
---
arch/Kconfig | 4 + include/linux/user_bkpt_xol.h | 61 +++++++++ kernel/Makefile | 1 kernel/user_bkpt_xol.c | 290 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 356 insertions(+), 0 deletions(-) create mode 100644 include/linux/user_bkpt_xol.h create mode 100644 kernel/user_bkpt_xol.c
arch/Kconfig +4 -0
@@ -99,6 +99,10 @@ config USER_RETURN_NOTIFIER config HAVE_USER_BKPT def_bool n +config USER_BKPT_XOL + def_bool y + depends on USER_BKPT + config HAVE_IOREMAP_PROT bool
include/linux/user_bkpt_xol.h new file +61 -0
61 lines not on this page · raw message
kernel/Makefile +1 -0
@@ -106,6 +106,7 @@ obj-$(CONFIG_HAVE_HW_BREAKPOINT) += hw_breakpoint.o obj-$(CONFIG_USER_RETURN_NOTIFIER) += user-return-notifier.o obj-$(CONFIG_PADATA) += padata.o obj-$(CONFIG_USER_BKPT) += user_bkpt.o +obj-$(CONFIG_USER_BKPT_XOL) += user_bkpt_xol.o ifneq ($(CONFIG_SCHED_OMIT_FRAME_POINTER),y) # According to Alan Modra <[email protected]>, the -fno-omit-frame-pointer is
kernel/user_bkpt_xol.c new file +290 -0
290 lines not on this page · raw message
PATCH 7/10 Uprobes Implementation
In reply to Srikar DronamrajuUprobes Implementation
The uprobes infrastructure enables a user to dynamically establish probepoints in user applications and collect information by executing a handler function when a probepoint is hit.
The user specifies the virtual address and the pid of the process of interest along with the action to be performed (handler). The handle Uprobes is implemented on the user-space breakpoint assistance layer and uses the execution out of line strategy. Uprobes follows lazy slot allocation. I.e, on the first probe hit for that process, a new vma (to hold the probed instructions for execution out of line) is allocated. Once allocated, this vma remains for the life of the process, and is reused as needed for subsequent probes. A slot in the vma is allocated for a probepoint when it is first hit.
A slot is marked for reuse when the probe gets unregistered and no threads are using that slot.
In a multithreaded process, a probepoint once registered is active for all threads of a process. If a thread specific action for a probepoint is required then the handler should be implemented to do the same.
If a breakpoint already exists at a particular address (irrespective of who inserted the breakpoint including uprobes), uprobes will refuse to register any more probes at that address.
You need to follow this up with the uprobes patch for your architecture.
For more information: please refer to Documentation/uprobes.txt
TODO:
1. Perf/trace events interface for uprobes.
2. Allow multiple probes at a probepoint.
3. Booster probes.
4. Allow probes to be inherited across fork.
5. probing function returns.
---
arch/Kconfig | 13 + include/linux/sched.h | 3 include/linux/tracehook.h | 18 + include/linux/uprobes.h | 178 ++++++++++ kernel/Makefile | 1 kernel/fork.c | 3 kernel/uprobes.c | 798 +++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 1014 insertions(+), 0 deletions(-) create mode 100644 include/linux/uprobes.h create mode 100644 kernel/uprobes.c
arch/Kconfig +13 -0
@@ -63,6 +63,16 @@ config USER_BKPT This service is used by components such as uprobes. If in doubt, say "N". +config UPROBES + bool "User-space probes (EXPERIMENTAL)" + depends on MODULES && USER_BKPT_XOL + depends on HAVE_UPROBES + help + Uprobes enables kernel modules to establish probepoints + in user applications and execute handler functions when + the probepoints are hit. For more information, refer to + Documentation/uprobes.txt. If in doubt, say "N". + config HAVE_EFFICIENT_UNALIGNED_ACCESS bool help
@@ -114,6 +124,9 @@ config HAVE_KRETPROBES config HAVE_OPTPROBES bool + +config HAVE_UPROBES + def_bool n # # An arch should select this if it provides all these things: #
include/linux/sched.h +3 -0
@@ -1506,6 +1506,9 @@ struct task_struct { unsigned long memsw_bytes; /* uncharged mem+swap usage */ } memcg_batch;#endif +#ifdef CONFIG_UPROBES +struct uprobe_task *utask; +#endif };/* Future-safe accessor for struct task_struct's cpus_allowed. */
include/linux/tracehook.h +18 -0
@@ -49,6 +49,7 @@#include <linux/sched.h> #include <linux/ptrace.h> #include <linux/security.h> +#include <linux/uprobes.h> struct linux_binprm ;/**
@@ -204,6 +205,11 @@ static inline void tracehook_report_exec(struct linux_binfmt *fmt,if (!ptrace_event (PT_TRACE_EXEC ,PTRACE_EVENT_EXEC ,0 ) &&unlikely (task_ptrace (current) &PT_PTRACED ))send_sig (SIGTRAP , current,0 ); + +#ifdef CONFIG_UPROBES +if (unlikely (current->utask)) +uprobe_free_utask (); +#endif }/**
@@ -219,6 +225,10 @@ static inline void tracehook_report_exec(struct linux_binfmt *fmt,static inline void tracehook_report_exit (long *exit_code) {ptrace_event (PT_TRACE_EXIT ,PTRACE_EVENT_EXIT , *exit_code); +#ifdef CONFIG_UPROBES +if (unlikely (current->utask)) +uprobe_free_utask (); +#endif }/**
@@ -293,6 +303,10 @@ static inline void tracehook_report_clone(struct pt_regs *regs,sigaddset (&child->pending.signal,SIGSTOP );set_tsk_thread_flag (child,TIF_SIGPENDING ); } +#ifdef CONFIG_UPROBES +if (unlikely (current->utask)) +uprobe_handle_clone (clone_flags, child); +#endif }/**
@@ -593,6 +607,10 @@ static inline void set_notify_resume(struct task_struct *task)*/ static inline void tracehook_notify_resume (struct pt_regs *regs) { +#ifdef CONFIG_UPROBES +if (current->utask && current->utask->active_ppt) +uprobe_notify_resume (regs); +#endif }#endif /* TIF_NOTIFY_RESUME */
include/linux/uprobes.h new file +178 -0
178 lines not on this page · raw message
kernel/Makefile +1 -0
@@ -107,6 +107,7 @@ obj-$(CONFIG_USER_RETURN_NOTIFIER) += user-return-notifier.o obj-$(CONFIG_PADATA) += padata.o obj-$(CONFIG_USER_BKPT) += user_bkpt.o obj-$(CONFIG_USER_BKPT_XOL) += user_bkpt_xol.o +obj-$(CONFIG_UPROBES) += uprobes.o ifneq ($(CONFIG_SCHED_OMIT_FRAME_POINTER),y) # According to Alan Modra <[email protected]>, the -fno-omit-frame-pointer is
kernel/fork.c +3 -0
@@ -1180,6 +1180,9 @@ static struct task_struct *copy_process(unsigned long clone_flags,INIT_LIST_HEAD (&p->pi_state_list); p->pi_state_cache =NULL ;#endif +#ifdef CONFIG_UPROBES + p->utask =NULL ; +#endif /* * sigaltstack should be cleared when sharing the same VM */
kernel/uprobes.c new file +798 -0
798 lines not on this page · raw message
Peter Zijlstra
maintainerRe: [PATCH v1 7/10] Uprobes Implementation
Quoted 6 lines · Srikar Dronamraju
include/linux/uprobes.h new file +6
-0+struct uprobe { +/* +* The pid of the probed process. Currently, this can be the +* thread ID (task->pid) of any active thread in the process. +*/ +pid_t pid;
include/linux/uprobes.h line 55
Quoted 10 lines
include/linux/uprobes.h new file +10
-0+ +/* Location of the probepoint */ +unsigned long vaddr; + +/* Handler to run when the probepoint is hit */ +void (*handler)(struct uprobe *,struct pt_regs *); + +/* true if handler runs in interrupt context*/ +bool handler_in_interrupt; +};
I would still prefer to see something like:
vma:offset, instead of tid:vaddr
You want to probe a symbol in a DSO, filtering per-task comes after that if desired.
Also, like we discussed in person, I think we can do away with the handler_in_interrupt thing by letting the handler have an error return value and doing something like:
do_int3:
uprobe = find_probe_point(addr);
pagefault_disable();
err = uprobe->handler(uprobe, regs);
pagefault_enable();
if (err == -EFAULT) {
/* set TIF flag and call the handler again from
task context */
}This should allow the handler to optimistically access memory from the trap handler, but in case it does need to fault pages in we'll call it from task context.
Quoted 61 lines
include/linux/sched.h +3
-0@@ -1506,6 +1506,9 @@ struct task_struct { unsigned long memsw_bytes; /* uncharged mem+swap usage */ } memcg_batch;#endif +#ifdef CONFIG_UPROBES +struct uprobe_task *utask; +#endif };/* Future-safe accessor for struct task_struct's cpus_allowed. */ include/linux/tracehook.h +14
-0@@ -49,6 +49,7 @@#include <linux/sched.h> #include <linux/ptrace.h> #include <linux/security.h> +#include <linux/uprobes.h> struct linux_binprm ;/** @@ -204,6 +205,11 @@ static inline void tracehook_report_exec(struct linux_binfmt *fmt,if (!ptrace_event (PT_TRACE_EXEC ,PTRACE_EVENT_EXEC ,0 ) &&unlikely (task_ptrace (current) &PT_PTRACED ))send_sig (SIGTRAP , current,0 ); + +#ifdef CONFIG_UPROBES +if (unlikely (current->utask)) +uprobe_free_utask (); +#endif }/** @@ -219,6 +225,10 @@ static inline void tracehook_report_exec(struct linux_binfmt *fmt,static inline void tracehook_report_exit (long *exit_code) {ptrace_event (PT_TRACE_EXIT ,PTRACE_EVENT_EXIT , *exit_code); +#ifdef CONFIG_UPROBES +if (unlikely (current->utask)) +uprobe_free_utask (); +#endif }/** @@ -293,6 +303,10 @@ static inline void tracehook_report_clone(struct pt_regs *regs,sigaddset (&child->pending.signal,SIGSTOP );set_tsk_thread_flag (child,TIF_SIGPENDING ); } +#ifdef CONFIG_UPROBES +if (unlikely (current->utask)) +uprobe_handle_clone (clone_flags, child); +#endif }/**
include/linux/tracehook.h static inline void set_notify_resume(struct task_struct *task) · line 615
Quoted 9 lines
include/linux/tracehook.h +4
-0@@ -593,6 +607,10 @@ static inline void set_notify_resume(struct task_struct *task)*/ static inline void tracehook_notify_resume (struct pt_regs *regs) { +#ifdef CONFIG_UPROBES +if (current->utask && current->utask->active_ppt) +uprobe_notify_resume (regs); +#endif }#endif /* TIF_NOTIFY_RESUME */
Everybody else simply places callbacks in kernel/fork.c and kernel/exit.c, but as it is I don't think you want per-task state like this.
One thing I would like to see is a slot per task, that has a number of advantages over the current patch-set in that it doesn't have one page limit in number of probe sites, nor do you need to insert vmas into each and every address space that happens to have your DSO mapped.
Also, I would simply kill the user_bkpt stuff and merge it into uprobes, we don't have a kernel_bkpt thing either, only kprobes.
Peter Zijlstra
maintainerRe: [PATCH v1 7/10] Uprobes Implementation
Quoted 1 line · Peter Zijlstra
Also, like we discussed in person,
To clarify: like I discussed with Jim in person.
Re: [PATCH v1 7/10] Uprobes Implementation
In reply to Peter ZijlstraHi Peter,
Quoted 20 lines · Srikar Dronamraju
Quoted 6 lines
include/linux/uprobes.h new file +6
-0+struct uprobe { +/* +* The pid of the probed process. Currently, this can be the +* thread ID (task->pid) of any active thread in the process. +*/ +pid_t pid;include/linux/uprobes.h line 55
Quoted 10 lines
include/linux/uprobes.h new file +10
-0+ +/* Location of the probepoint */ +unsigned long vaddr; + +/* Handler to run when the probepoint is hit */ +void (*handler)(struct uprobe *,struct pt_regs *); + +/* true if handler runs in interrupt context*/ +bool handler_in_interrupt; +};I would still prefer to see something like:
Quoted 5 lines
vma:offset, instead of tid:vaddr
You want to probe a symbol in a DSO, filtering per-task comes after that if desired.
If I would want to trace malloc in a process
$ objdump -T /lib64/libc.so.6 | grep malloc 000000357c274b80 g DF .text 0000000000000224 GLIBC_2.2.5 __libc_malloc 000000357c271000 w DF .text 0000000000000273 GLIBC_2.2.5 malloc_stats 000000357c275570 w DF .text 00000000000001fb GLIBC_2.2.5 malloc_get_state 000000357c5514f8 w DO .data 0000000000000008 GLIBC_2.2.5 __malloc_hook 000000357c274b80 g DF .text 0000000000000224 GLIBC_2.2.5 malloc 000000357c26f570 w DF .text 0000000000000033 GLIBC_2.2.5 malloc_usable_size 000000357c271420 w DF .text 000000000000024e GLIBC_2.2.5 malloc_trim 000000357c5529a0 w DO .bss 0000000000000008 GLIBC_2.2.5 __malloc_initialize_hook 000000357c271670 w DF .text 00000000000003c2 GLIBC_2.2.5 malloc_set_state $ $ cat /proc/9069/maps ............... 357c200000-357c34d000 r-xp 00000000 08:03 6115979 /lib64/libc-2.5.so 357c34d000-357c54d000 ---p 0014d000 08:03 6115979 /lib64/libc-2.5.so 357c54d000-357c551000 r--p 0014d000 08:03 6115979 /lib64/libc-2.5.so 357c551000-357c552000 rw-p 00151000 08:03 6115979 /lib64/libc-2.5.so ............... $
do you mean the user should be specifying 357c200000:74b80 to denote 000000357c274b80? or /lib64/libc.so.6:74b80
And we trace all the process which have mapped this address?
Quoted 17 lines
Also, like we discussed in person, I think we can do away with the
handler_in_interruptthing by letting the handler have an error return value and doing something like:
do_int3:uprobe = find_probe_point(addr); pagefault_disable(); err = uprobe->handler(uprobe, regs); pagefault_enable(); if (err == -EFAULT) { /* set TIF flag and call the handler again from task context */ }
Quoted 3 lines
This should allow the handler to optimistically access memory from the trap handler, but in case it does need to fault pages in we'll call it from task context.
Okay but what if the handler is coded to sleep.
Quoted 10 lines
Everybody else simply places callbacks in
kernel/fork.candkernel/exit.c, but as it is I don't think you want per-task state like this.One thing I would like to see is a slot per task, that has a number of advantages over the current patch-set in that it doesn't have one page limit in number of probe sites, nor do you need to insert vmas into each and every address space that happens to have your DSO mapped.
where are the per task slots stored?
or Are you looking at a XOL vma area per DSO?
Quoted 3 lines
Also, I would simply kill the
user_bkptstuff and merge it into uprobes, we don't have akernel_bkptthing either, only kprobes.
We had uprobes as one single layer. However it was suggested that breaking it up into two layers was useful because it would help code reuse. Esp it was felt that a generic user_bkpt layer would be far more useful than being used for just uprobes.
Here are links where these discussion happened.
http://sourceware.org/ml/systemtap/2007-q1/msg00570.html
http://sourceware.org/ml/systemtap/2007-q1/msg00571.html
--
Thanks and Regards
Srikar
Peter Zijlstra
maintainerRe: [PATCH v1 7/10] Uprobes Implementation
Quoted 24 lines · Srikar Dronamraju
Hi Peter,
Quoted 22 lines · Srikar Dronamraju
Quoted 6 lines
include/linux/uprobes.h new file +6
-0+struct uprobe { +/* +* The pid of the probed process. Currently, this can be the +* thread ID (task->pid) of any active thread in the process. +*/ +pid_t pid;include/linux/uprobes.h line 55
Quoted 10 lines
include/linux/uprobes.h new file +10
-0+ +/* Location of the probepoint */ +unsigned long vaddr; + +/* Handler to run when the probepoint is hit */ +void (*handler)(struct uprobe *,struct pt_regs *); + +/* true if handler runs in interrupt context*/ +bool handler_in_interrupt; +};I would still prefer to see something like:
vma:offset, instead of tid:vaddr
Quoted 7 lines
Quoted 3 lines
You want to probe a symbol in a DSO, filtering per-task comes after that if desired.
do you mean the user should be specifying 357c200000:74b80 to denote
000000357c274b80? or /lib64/libc.so.6:74b80
And we trace all the process which have mapped this address?
Well userspace would simply specify something like: /lib/libc.so:malloc, we'd probably communicate that to the kernel using a filedesc and offset.
And yes, all processes that share that DSO, consumers can install filters.
Quoted 17 lines
Quoted 17 lines
Also, like we discussed in person, I think we can do away with the
handler_in_interruptthing by letting the handler have an error return value and doing something like:
do_int3:uprobe = find_probe_point(addr); pagefault_disable(); err = uprobe->handler(uprobe, regs); pagefault_enable(); if (err == -EFAULT) { /* set TIF flag and call the handler again from task context */ }
Quoted 5 lines
Quoted 3 lines
This should allow the handler to optimistically access memory from the trap handler, but in case it does need to fault pages in we'll call it from task context.
Okay but what if the handler is coded to sleep.
Don't do that ;-)
What reason would you have to sleep from a int3 anyway? You want to log bits and get on with life, right? The only interesting case is faulting when some memory references you want are not currently available, and that can be done as suggested.
Quoted 4 lines
Quoted 4 lines
Everybody else simply places callbacks in
kernel/fork.candkernel/exit.c, but as it is I don't think you want per-task state like this.
Quoted 8 lines
Quoted 5 lines
One thing I would like to see is a slot per task, that has a number of advantages over the current patch-set in that it doesn't have one page limit in number of probe sites, nor do you need to insert vmas into each and every address space that happens to have your DSO mapped.
where are the per task slots stored?
or Are you looking at a XOL vma area per DSO?
The per task slot (note the singular, each task needs only ever have a single slot since a task can only ever hit one trap at a time) would live in the task TLS or task stack.
Quoted 9 lines
Quoted 3 lines
Also, I would simply kill the
user_bkptstuff and merge it into uprobes, we don't have akernel_bkptthing either, only kprobes.We had uprobes as one single layer. However it was suggested that breaking it up into two layers was useful because it would help code reuse. Esp it was felt that a generic
user_bkptlayer would be far more useful than being used for just uprobes.
Here are links where these discussion happened.
I'm so not going to read ancient emails on a funky list. What re-use? uprobe should be the only interface to this, there's no second interface to kprobes either is there?
Re: [PATCH v1 7/10] Uprobes Implementation
Quoted 33 lines · Peter Zijlstra
Quoted 24 lines · Srikar Dronamraju
Hi Peter,
Quoted 22 lines · Srikar Dronamraju
Quoted 6 lines
include/linux/uprobes.h new file +6
-0+struct uprobe { +/* +* The pid of the probed process. Currently, this can be the +* thread ID (task->pid) of any active thread in the process. +*/ +pid_t pid;include/linux/uprobes.h line 55
Quoted 10 lines
include/linux/uprobes.h new file +10
-0+ +/* Location of the probepoint */ +unsigned long vaddr; + +/* Handler to run when the probepoint is hit */ +void (*handler)(struct uprobe *,struct pt_regs *); + +/* true if handler runs in interrupt context*/ +bool handler_in_interrupt; +};I would still prefer to see something like:
vma:offset, instead of tid:vaddr
Quoted 7 lines
Quoted 3 lines
You want to probe a symbol in a DSO, filtering per-task comes after that if desired.
do you mean the user should be specifying 357c200000:74b80 to denote
000000357c274b80? or /lib64/libc.so.6:74b80
And we trace all the process which have mapped this address?
Quoted 6 lines
Well userspace would simply specify something like: /lib/libc.so:malloc, we'd probably communicate that to the kernel using a filedesc and offset.
And yes, all processes that share that DSO, consumers can install filters.
Hmm, for low-level interface, it will be good. If we provide a user interface(trace_uprobe.c), we'd better add pid filter for it.
Quoted 21 lines
Quoted 21 lines
Quoted 20 lines
Also, like we discussed in person, I think we can do away with the
handler_in_interruptthing by letting the handler have an error return value and doing something like:
do_int3:uprobe = find_probe_point(addr); pagefault_disable(); err = uprobe->handler(uprobe, regs); pagefault_enable(); if (err == -EFAULT) { /* set TIF flag and call the handler again from task context */ }This should allow the handler to optimistically access memory from the trap handler, but in case it does need to fault pages in we'll call it from task context.
Quoted 8 lines
Quoted 1 line
Okay but what if the handler is coded to sleep.
Don't do that ;-)
What reason would you have to sleep from a int3 anyway? You want to log bits and get on with life, right? The only interesting case is faulting when some memory references you want are not currently available, and that can be done as suggested.
Out of curiously, what does the task-context mean? ('current' is probed task in int3, isn't it?). I think, uprobe handler can cause page fault (and should sleep) if the page is swapped out.
Quoted 10 lines
Quoted 10 lines
Quoted 9 lines
Everybody else simply places callbacks in
kernel/fork.candkernel/exit.c, but as it is I don't think you want per-task state like this.One thing I would like to see is a slot per task, that has a number of advantages over the current patch-set in that it doesn't have one page limit in number of probe sites, nor do you need to insert vmas into each and every address space that happens to have your DSO mapped.
Quoted 6 lines
Quoted 2 lines
where are the per task slots stored?
or Are you looking at a XOL vma area per DSO?The per task slot (note the singular, each task needs only ever have a single slot since a task can only ever hit one trap at a time) would live in the task TLS or task stack.
Hmm, I just worried about whether TLS/task stack can be executable (no one set NX bit).
Quoted 10 lines
Quoted 9 lines
Quoted 3 lines
Also, I would simply kill the
user_bkptstuff and merge it into uprobes, we don't have akernel_bkptthing either, only kprobes.We had uprobes as one single layer. However it was suggested that breaking it up into two layers was useful because it would help code reuse. Esp it was felt that a generic
user_bkptlayer would be far more useful than being used for just uprobes.
Here are links where these discussion happened.
Quoted 3 lines
I'm so not going to read ancient emails on a funky list. What re-use? uprobe should be the only interface to this, there's no second interface to kprobes either is there?
It will be good when we start working on 'ptrace2' :) Anyway, the patch order looks a bit odd, because user_bkpt uses XOL but XOL patch is introduced after user_bkpt patch...
Thank you,
Signature · 2 lines
Masami Hiramatsu e-mail: [email protected]
Peter Zijlstra
maintainerRe: [PATCH v1 7/10] Uprobes Implementation
Quoted 6 lines · Masami Hiramatsu
Quoted 2 lines
And yes, all processes that share that DSO, consumers can install filters.
Hmm, for low-level interface, it will be good. If we provide a user
interface(trace_uprobe.c), we'd better add pid filter for it.
ftrace already has pid filters.
Quoted 25 lines
Quoted 25 lines
Quoted 17 lines
Quoted 17 lines
Also, like we discussed in person, I think we can do away with the
handler_in_interruptthing by letting the handler have an error return value and doing something like:
do_int3:uprobe = find_probe_point(addr); pagefault_disable(); err = uprobe->handler(uprobe, regs); pagefault_enable(); if (err == -EFAULT) { /* set TIF flag and call the handler again from task context */ }Quoted 5 lines
Quoted 3 lines
This should allow the handler to optimistically access memory from the trap handler, but in case it does need to fault pages in we'll call it from task context.
Okay but what if the handler is coded to sleep.
Don't do that ;-)
Quoted 8 lines
Quoted 4 lines
What reason would you have to sleep from a int3 anyway? You want to log bits and get on with life, right? The only interesting case is faulting when some memory references you want are not currently available, and that can be done as suggested.
Out of curiously, what does the task-context mean? ('current' is probed task in int3, isn't it?). I think, uprobe handler can cause page fault (and should sleep) if the page is swapped out.
Task context means the regular kernel task stack where we can schedule, int3 has its own exception stack and we cannot schedule from that.
And yes, the fault thing is the one case where sleeping makes sense and is dealt with in my proposal, you don't need two handlers for that, just call it from trap context with pagefault_disable() and when it fails with -EFAULT set a TIF flag to deal with it later when we're back in task context.
There is a very good probability that the memory you want to reference is mapped (because typically the program itself will want to access it as well) so doing the optimistic access with pagefault_disabled() will work most of the times and you only end up taking the slow path when it does indeed fault.
Quoted 13 lines
Quoted 13 lines
Quoted 12 lines
Quoted 9 lines
Everybody else simply places callbacks in
kernel/fork.candkernel/exit.c, but as it is I don't think you want per-task state like this.One thing I would like to see is a slot per task, that has a number of advantages over the current patch-set in that it doesn't have one page limit in number of probe sites, nor do you need to insert vmas into each and every address space that happens to have your DSO mapped.
where are the per task slots stored?
or Are you looking at a XOL vma area per DSO?
Quoted 6 lines
Quoted 3 lines
The per task slot (note the singular, each task needs only ever have a single slot since a task can only ever hit one trap at a time) would live in the task TLS or task stack.
Hmm, I just worried about whether TLS/task stack can be executable (no one set NX bit).
You can remove the NX bit from that one page I guess.
Quoted 10 lines
Quoted 10 lines
Quoted 9 lines
Quoted 3 lines
Also, I would simply kill the
user_bkptstuff and merge it into uprobes, we don't have akernel_bkptthing either, only kprobes.We had uprobes as one single layer. However it was suggested that breaking it up into two layers was useful because it would help code reuse. Esp it was felt that a generic
user_bkptlayer would be far more useful than being used for just uprobes.
Here are links where these discussion happened.
Quoted 7 lines
Quoted 3 lines
I'm so not going to read ancient emails on a funky list. What re-use? uprobe should be the only interface to this, there's no second interface to kprobes either is there?
It will be good when we start working on 'ptrace2' :) Anyway, the patch order looks a bit odd, because
user_bkptuses XOL but XOL patch is introduced afteruser_bkptpatch...
But why would ptrace2 use a different interface? Also, why introduce some abstraction layer now without having a user for it, you could always restructure things and or add interfaces later when you have a clear idea what it is you need.
Re: [PATCH v1 7/10] Uprobes Implementation
Quoted 10 lines · Peter Zijlstra
Quoted 6 lines · Masami Hiramatsu
Quoted 2 lines
And yes, all processes that share that DSO, consumers can install filters.
Hmm, for low-level interface, it will be good. If we provide a user
interface(trace_uprobe.c), we'd better add pid filter for it.ftrace already has pid filters.
Indeed.
Quoted 35 lines
Quoted 26 lines
Quoted 26 lines
Quoted 18 lines
Quoted 18 lines
Also, like we discussed in person, I think we can do away with the
handler_in_interruptthing by letting the handler have an error return value and doing something like:
do_int3:uprobe = find_probe_point(addr); pagefault_disable(); err = uprobe->handler(uprobe, regs); pagefault_enable(); if (err == -EFAULT) { /* set TIF flag and call the handler again from task context */ }Quoted 5 lines
Quoted 3 lines
This should allow the handler to optimistically access memory from the trap handler, but in case it does need to fault pages in we'll call it from task context.
Okay but what if the handler is coded to sleep.
Don't do that ;-)
Quoted 8 lines
Quoted 4 lines
What reason would you have to sleep from a int3 anyway? You want to log bits and get on with life, right? The only interesting case is faulting when some memory references you want are not currently available, and that can be done as suggested.
Out of curiously, what does the task-context mean? ('current' is probed task in int3, isn't it?). I think, uprobe handler can cause page fault (and should sleep) if the page is swapped out.
Quoted 8 lines
Task context means the regular kernel task stack where we can schedule, int3 has its own exception stack and we cannot schedule from that.
And yes, the fault thing is the one case where sleeping makes sense and is dealt with in my proposal, you don't need two handlers for that, just call it from trap context with
pagefault_disable()and when it fails with-EFAULTset a TIF flag to deal with it later when we're back in task context.
Ah, I see. so it will be done later. Actually, since int3 handler will disable irq, it is reasonable.
Quoted 5 lines
There is a very good probability that the memory you want to reference is mapped (because typically the program itself will want to access it as well) so doing the optimistic access with
pagefault_disabled()will work most of the times and you only end up taking the slow path when it does indeed fault.
hm, similar technique can be applied to kprobe-tracer too (for getting __user arguments). :)
Quoted 13 lines
Quoted 13 lines
Quoted 13 lines
Quoted 12 lines
Quoted 9 lines
Everybody else simply places callbacks in
kernel/fork.candkernel/exit.c, but as it is I don't think you want per-task state like this.One thing I would like to see is a slot per task, that has a number of advantages over the current patch-set in that it doesn't have one page limit in number of probe sites, nor do you need to insert vmas into each and every address space that happens to have your DSO mapped.
where are the per task slots stored?
or Are you looking at a XOL vma area per DSO?
Quoted 8 lines
Quoted 6 lines
Quoted 3 lines
The per task slot (note the singular, each task needs only ever have a single slot since a task can only ever hit one trap at a time) would live in the task TLS or task stack.
Hmm, I just worried about whether TLS/task stack can be executable (no one set NX bit).
You can remove the NX bit from that one page I guess.
OK.
Quoted 14 lines
Quoted 14 lines
Quoted 13 lines
Quoted 9 lines
Quoted 3 lines
Also, I would simply kill the
user_bkptstuff and merge it into uprobes, we don't have akernel_bkptthing either, only kprobes.We had uprobes as one single layer. However it was suggested that breaking it up into two layers was useful because it would help code reuse. Esp it was felt that a generic
user_bkptlayer would be far more useful than being used for just uprobes.
Here are links where these discussion happened.I'm so not going to read ancient emails on a funky list. What re-use? uprobe should be the only interface to this, there's no second interface to kprobes either is there?
Quoted 8 lines
Quoted 3 lines
It will be good when we start working on 'ptrace2' :) Anyway, the patch order looks a bit odd, because
user_bkptuses XOL but XOL patch is introduced afteruser_bkptpatch...But why would ptrace2 use a different interface? Also, why introduce some abstraction layer now without having a user for it, you could always restructure things and or add interfaces later when you have a clear idea what it is you need.
Because 'ptrace' doesn't have any breakpoint insertion helper. Programs which uses ptrace must setup single-stepping buffer and modify target code by themselves. This causes problems when multiple debuggers/tracers attach to the same process and try to modify same address. First program can see the original instruction, but next one will see int3! I think we'd better provide some abstraction interface for breakpoint setting in next generation ptrace (of course, we also need to provide memory peek interface which returns original instructions).
But anyway, I agree with you, we don't need it *now*, but someday.
Thank you,
Signature · 2 lines
Masami Hiramatsu e-mail: [email protected]
Re: [PATCH v1 7/10] Uprobes Implementation
In reply to Masami HiramatsuQuoted 3 lines
Anyway, the patch order looks a bit odd, because
user_bkptuses XOL but XOL patch is introduced afteruser_bkptpatch...
user_bkpt provides xol strategy.
user_bkpt_xol patch only provides slot allocation for Execution out of line strategy. It doesnt implement execution out of line strategy. The current implementation assumes that we pass the user_bkpt structure as an argument while allocating/freeing a slot.
user_bkpt knows how to handle execution out of line. Its working is independent of how and where the slot is allocated. The field xol_vaddr points to a location which holds the copy of the instruction to be single-stepped/executed.
Hence user_bkpt patch was followed by user_bkpt_xol patch.
--
Thanks and Regards
Srikar
Quoted 6 lines
Thank you,
Signature · 2 lines
Masami Hiramatsu e-mail: [email protected]
Re: [PATCH v1 7/10] Uprobes Implementation
In reply to Peter ZijlstraQuoted 14 lines · Peter Zijlstra
Quoted 11 lines · Srikar Dronamraju
Quoted 7 lines
I would still prefer to see something like:
vma:offset, instead of tid:vaddr
You want to probe a symbol in a DSO, filtering per-task comes after that if desired.
do you mean the user should be specifying 357c200000:74b80 to denote
000000357c274b80? or /lib64/libc.so.6:74b80
And we trace all the process which have mapped this address?
Quoted 6 lines
Well userspace would simply specify something like: /lib/libc.so:malloc, we'd probably communicate that to the kernel using a filedesc and offset.
And yes, all processes that share that DSO, consumers can install filters.
Well, rewind back to 2006 to the first edition of uprobes; it had the 'global' tracing feature like what you indicate here, although Andrew wouldn't want to be reminded of *how* that was done (hooking readpages()) :-)
At the time, global tracing was vehemently vetoed in favour of a per-process approach.
Now the question is, where the complexity needs to be.
Quoted 21 lines
Quoted 21 lines
Quoted 20 lines
Also, like we discussed in person, I think we can do away with the
handler_in_interruptthing by letting the handler have an error return value and doing something like:
do_int3:uprobe = find_probe_point(addr); pagefault_disable(); err = uprobe->handler(uprobe, regs); pagefault_enable(); if (err == -EFAULT) { /* set TIF flag and call the handler again from task context */ }This should allow the handler to optimistically access memory from the trap handler, but in case it does need to fault pages in we'll call it from task context.
Quoted 8 lines
Quoted 1 line
Okay but what if the handler is coded to sleep.
Don't do that ;-)
What reason would you have to sleep from a int3 anyway? You want to log bits and get on with life, right? The only interesting case is faulting when some memory references you want are not currently available, and that can be done as suggested.
With the TIF method, you get to the probed process' task context in do_notify_resume(), and have sufficient flexibility for non-perf users, like gdb, 'cos what uprobes provides now, is close to what Tom Tromey asked for gdb's usage.
Ananth
Peter Zijlstra
maintainerRe: [PATCH v1 7/10] Uprobes Implementation
Quoted 1 line · Ananth N Mavinakayanahalli
Now the question is, where the complexity needs to be.
Both in-tree consumers of uprobes (ftrace and perf) are capable of task filters.
But the thing is, dso:sym is very much not a task property, adding task filters afterwards sure makes sense in some cases but it should not be the primary mode.
If people really want to optimize this we can easily add a few bits of task state which could tell the trap handler to not even bother looking up things but restart as fast as possible.
Re: [PATCH v1 7/10] Uprobes Implementation
Hi -
Quoted 4 lines
Quoted 1 line
Now the question is, where the complexity needs to be.
Both in-tree consumers of uprobes (ftrace and perf) are capable of task filters. [...]
If you wish this new uprobes to be useful to tools such as gdb, remember the value of preserving the property that processes not being debugged are not to be interfered with. You don't want a DoS due to some guy setting ten thousand breakpoints on glibc. Such considerations should overrule perf/ftrace's simplifying assumptions that after-the-fact event filtering is surely always sufficient.
- FChE
Re: [PATCH v1 7/10] Uprobes Implementation
In reply to Peter ZijlstraQuoted 9 lines · Peter Zijlstra
Quoted 1 line · Ananth N Mavinakayanahalli
Now the question is, where the complexity needs to be.
Both in-tree consumers of uprobes (ftrace and perf) are capable of task filters.
But the thing is, dso:sym is very much not a task property, adding task filters afterwards sure makes sense in some cases but it should not be the primary mode.
Not sure if I am following you correctly...
Quoted 3 lines
If people really want to optimize this we can easily add a few bits of task state which could tell the trap handler to not even bother looking up things but restart as fast as possible.
Are you suggesting we have the global tracing as default and then have task filters. I've already alluded to this being vetoed earlier, by people including Andrew Morton, Hugh Dickins, Arjan, Christoph Hellwig, Nick Piggin, etc. It's a route we'd prefer not to go down again...
Aside, what are the mechanisms to do this?
The current breakpoint insertion and removal, even for shared libraries, is process local since the only page tables of the process being traced is modified.
In order to have a global visibility of dso probes, one obvious method is to put in the probes before the text hits pagecache. This approach works for 'yet-to-start' processes that would map the dso too. This was prototyped in the series at http://lkml.org/lkml/2006/5/9/25 did that and was suitably junked, for very valid reasons. Even Hugh Dickins thumbed down the pagecache approach (http://lkml.org/lkml/2006/5/9/209)
Given the current design has enough flexibility to accommodate non perf users like gdb, a simple pid based approach for the lowest layer makes the most sense. I'd rather prefer a higher level entity (say, perf) do the difficult job of filtering down individual requests only for processes of interest, then the lower layer can iteratively do the probe insertions for all processes of interest.
I am not sure if there is a better method to do probes with 'global' visibility. Did you have an easier approach in mind?
Ananth
Re: [PATCH v1 7/10] Uprobes Implementation
In reply to Peter ZijlstraHi Peter,
Quoted 12 lines
Quoted 11 lines
Quoted 7 lines
I would still prefer to see something like:
vma:offset, instead of tid:vaddr
You want to probe a symbol in a DSO, filtering per-task comes after that if desired.
do you mean the user should be specifying 357c200000:74b80 to denote
000000357c274b80? or /lib64/libc.so.6:74b80
And we trace all the process which have mapped this address?
Quoted 7 lines
Well userspace would simply specify something like: /lib/libc.so:malloc, we'd probably communicate that to the kernel using a filedesc and offset.
And yes, all processes that share that DSO, consumers can install filters.
I think perf would be using uprobes in one of the four ways.
- Trace a particular process.
- Trace a particular session.
- Trace all instances of an executable.
- Trace all programs in the system.
If we use global approach, filtering would still be part of the handler. So even if we want to probe just one process, we would still take hit for all processes that map the DSO and hit that vaddr.
Other process could be hitting the probepoint more often while the probed process could rarely be hitting the probepoint. This could place significant overhead on the system.
Also with KSM, the page we are probing could be part of the stable tree and mapped by different virtual machines. Can this lead to interruptting work on an unrelated virtual machine? If yes, Is it okay to interrupt an unrelated VM? If not, what measures need to be taken?
Currently perf can be used by priviledged users. However when perf gets to trace user space programs, would it still be limited to priviledged users. Do we have plans to allow users to trace their owned applications thro perf?
Quoted 5 lines
Quoted 5 lines
Quoted 4 lines
This should allow the handler to optimistically access memory from the trap handler, but in case it does need to fault pages in we'll call it from task context.
Quoted 9 lines
Quoted 1 line
Okay but what if the handler is coded to sleep.
Don't do that ;-)
What reason would you have to sleep from a int3 anyway? You want to log bits and get on with life, right? The only interesting case is faulting when some memory references you want are not currently available, and that can be done as suggested.
Though one of the usp of uprobes is non disruptive tracing, applications like debuggers who do disruptive tracing can benefit from uprobes.
Debuggers could use uprobes as a feature to implement inserting/removing breakpoints and get the out of line single-stepping. In an earlier discussion http://lkml.org/lkml/2010/1/26/344 Tom Tromey did say that if a facility was given, it could be used in gdb.
What I expect is the tracee to inform the tracer that it has hit the breakpoint and "wait" for the tracer to give indication to continue.
Benefits could be
- Debuggers can benefit from execution out of line and can debug multithread processes much better.
- Two debbugers/tracers could trace the same process. One of the tracer could be strace, while the other one could be gdb.
- perf and debugger could be interested in the same vaddr for that process and still continue to work.
Lets say debugger and perf are interested in a particular function for example malloc.
If perf uses uprobes and debuggers uses existing methods, then perf measures of malloc may not be accurate as it misses those mallocs of the process that's being debugged. However I agree that its a very very very minute case.
Quoted 10 lines
Quoted 10 lines
Quoted 9 lines
Everybody else simply places callbacks in
kernel/fork.candkernel/exit.c, but as it is I don't think you want per-task state like this.One thing I would like to see is a slot per task, that has a number of advantages over the current patch-set in that it doesn't have one page limit in number of probe sites, nor do you need to insert vmas into each and every address space that happens to have your DSO mapped.
Quoted 7 lines
Quoted 2 lines
where are the per task slots stored?
or Are you looking at a XOL vma area per DSO?The per task slot (note the singular, each task needs only ever have a single slot since a task can only ever hit one trap at a time) would live in the task TLS or task stack.
Do we need a buy-in from glibc folks to do this?
Also here is what Roland had once said about TLS.
"Next we come to the problem of where to store copied instructions for stepping. The idea of stealing a stack page for this is a non-starter. For both security and robustness, it's never acceptable to introduce a user mapping that is both writable and executable, even temporarily. We need to use an otherwise unused page in the address space, that will be read/execute only for the user, we can write to it only from kernel mode."
--
Thanks and Regards
Srikar
Peter Zijlstra
maintainerRe: [PATCH v1 7/10] Uprobes Implementation
Quoted 40 lines · Srikar Dronamraju
Hi Peter,
Quoted 12 lines
Quoted 11 lines
Quoted 7 lines
I would still prefer to see something like:
vma:offset, instead of tid:vaddr
You want to probe a symbol in a DSO, filtering per-task comes after that if desired.
do you mean the user should be specifying 357c200000:74b80 to denote
000000357c274b80? or /lib64/libc.so.6:74b80
And we trace all the process which have mapped this address?Quoted 7 lines
Well userspace would simply specify something like: /lib/libc.so:malloc, we'd probably communicate that to the kernel using a filedesc and offset.
And yes, all processes that share that DSO, consumers can install filters.
I think perf would be using uprobes in one of the four ways.
- Trace a particular process.
- Trace a particular session.
- Trace all instances of an executable.
- Trace all programs in the system.If we use global approach, filtering would still be part of the handler. So even if we want to probe just one process, we would still take hit for all processes that map the DSO and hit that vaddr.
Other process could be hitting the probepoint more often while the probed process could rarely be hitting the probepoint. This could place significant overhead on the system.Also with KSM, the page we are probing could be part of the stable tree and mapped by different virtual machines. Can this lead to interruptting work on an unrelated virtual machine? If yes, Is it okay to interrupt an unrelated VM? If not, what measures need to be taken?
Quoted 4 lines
Currently perf can be used by priviledged users. However when perf gets to trace user space programs, would it still be limited to priviledged users. Do we have plans to allow users to trace their owned applications thro perf?
I'm not sure, currently all the tracing bits require root. One of the complications is that dynamic trace events (kprobes and uprobes) share a global namespace, so making that accessible to users might be interesting.
So one thing we can do to avoid some of the trap overhead is to de-couple the trace event creation from trace event enable (pretty much already so for existing implementations), so while you define a dynamic trace event as dso:sym, you provide ways to enable it globally and per task.
We'd basically need a global and per-task refcount on enable and make sure the breakpoint is installed properly for (global || task).
That way a perf per-cpu event will do the global enable, and a perf per-task event will do the task enable.
Quoted 32 lines
Quoted 4 lines
Quoted 4 lines
Quoted 3 lines
This should allow the handler to optimistically access memory from the trap handler, but in case it does need to fault pages in we'll call it from task context.
Quoted 9 lines
Quoted 1 line
Okay but what if the handler is coded to sleep.
Don't do that ;-)
What reason would you have to sleep from a int3 anyway? You want to log bits and get on with life, right? The only interesting case is faulting when some memory references you want are not currently available, and that can be done as suggested.
Though one of the usp of uprobes is non disruptive tracing, applications like debuggers who do disruptive tracing can benefit from uprobes.
Debuggers could use uprobes as a feature to implement inserting/removing breakpoints and get the out of line single-stepping. In an earlier discussion http://lkml.org/lkml/2010/1/26/344 Tom Tromey did say that if a facility was given, it could be used in gdb.
What I expect is the tracee to inform the tracer that it has hit the breakpoint and "wait" for the tracer to give indication to continue.
Benefits could be
- Debuggers can benefit from execution out of line and can debug multithread processes much better.- Two debbugers/tracers could trace the same process. One of the tracer could be strace, while the other one could be gdb.
Quoted 8 lines
- perf and debugger could be interested in the same vaddr for that process and still continue to work.
Lets say debugger and perf are interested in a particular function for example malloc.
If perf uses uprobes and debuggers uses existing methods, then perf measures of malloc may not be accurate as it misses those mallocs of the process that's being debugged. However I agree that its a very very very minute case.
A double scribble will be an issue for the current generation of debuggers anyway, right?
But yes, I suppose if you want to use uprobes for debuggers then yes it makes sense to allow to put the task to sleep. One way would be to provide means for the handler to detect the context and simply always return -EFAULT from the trap context.
Quoted 21 lines
Quoted 10 lines
Quoted 10 lines
Quoted 9 lines
Everybody else simply places callbacks in
kernel/fork.candkernel/exit.c, but as it is I don't think you want per-task state like this.One thing I would like to see is a slot per task, that has a number of advantages over the current patch-set in that it doesn't have one page limit in number of probe sites, nor do you need to insert vmas into each and every address space that happens to have your DSO mapped.
Quoted 7 lines
Quoted 2 lines
where are the per task slots stored?
or Are you looking at a XOL vma area per DSO?The per task slot (note the singular, each task needs only ever have a single slot since a task can only ever hit one trap at a time) would live in the task TLS or task stack.
Do we need a buy-in from glibc folks to do this?
Also here is what Roland had once said about TLS.
Quoted 7 lines
"Next we come to the problem of where to store copied instructions for stepping. The idea of stealing a stack page for this is a non-starter. For both security and robustness, it's never acceptable to introduce a user mapping that is both writable and executable, even temporarily. We need to use an otherwise unused page in the address space, that will be read/execute only for the user, we can write to it only from kernel mode."
Before NX there simply was no option, anyway, I guess the writable requirement comes from being stack, and I'm not sure how TLS is done, but I guess that has similar constraints on being writable, right?
I've heard from people that some other OS does indeed have the trampoline in TLS.
Re: [PATCH v1 7/10] Uprobes Implementation
Quoted 26 lines
Quoted 18 lines
Quoted 7 lines
Quoted 7 lines
Quoted 6 lines
One thing I would like to see is a slot per task, that has a number of advantages over the current patch-set in that it doesn't have one page limit in number of probe sites, nor do you need to insert vmas into each and every address space that happens to have your DSO mapped.
Quoted 7 lines
Quoted 2 lines
where are the per task slots stored?
or Are you looking at a XOL vma area per DSO?The per task slot (note the singular, each task needs only ever have a single slot since a task can only ever hit one trap at a time) would live in the task TLS or task stack.
Do we need a buy-in from glibc folks to do this?
Also here is what Roland had once said about TLS.Quoted 7 lines
"Next we come to the problem of where to store copied instructions for stepping. The idea of stealing a stack page for this is a non-starter. For both security and robustness, it's never acceptable to introduce a user mapping that is both writable and executable, even temporarily. We need to use an otherwise unused page in the address space, that will be read/execute only for the user, we can write to it only from kernel mode."
Quoted 6 lines
Before NX there simply was no option, anyway, I guess the writable requirement comes from being stack, and I'm not sure how TLS is done, but I guess that has similar constraints on being writable, right?
I've heard from people that some other OS does indeed have the trampoline in TLS.
Ulrich,
Can you please comment if a slot in TLS can be used for storing and executing an instruction? Are there any additional issues that we need to take care of? Are there architectures that dont support TLS?
--
Thanks and Regards
Srikar
Re: [PATCH v1 7/10] Uprobes Implementation
In reply to Peter ZijlstraQuoted 6 lines
I'm not sure, currently all the tracing bits require root. One of the complications is that dynamic trace events (kprobes and uprobes) share a global namespace, so making that accessible to users might be interesting.
Quoted 8 lines
So one thing we can do to avoid some of the trap overhead is to de-couple the trace event creation from trace event enable (pretty much already so for existing implementations), so while you define a dynamic trace event as dso:sym, you provide ways to enable it globally and per task.
We'd basically need a global and per-task refcount on enable and make sure the breakpoint is installed properly for (global || task).
Yes, when we allow two or more probes to co-exist at a probepoint, we will be able to do this.
Quoted 9 lines
That way a perf per-cpu event will do the global enable, and a perf per-task event will do the task enable.
A double scribble will be an issue for the current generation of debuggers anyway, right?
double scribble as in two apps writing to the same address? Uprobes handles this by failing into insert probes at location where there is a breakpoint already inserted. So if both apps were to use the uprobes interface, then they could co-operate and co-exist. (This would need the feature in uprobes to have multiple probes per probepoint which is excluded in this RFC).
Quoted 5 lines
But yes, I suppose if you want to use uprobes for debuggers then yes it makes sense to allow to put the task to sleep. One way would be to provide means for the handler to detect the context and simply always return
-EFAULTfrom the trap context.
Yes, thats certainly possible. However lets consider the case when we allow multiple probes per probepoint and one handler faults (handler detects it could be sleeping) while the other handler may or may not fault (handler could be doing a copy_from_user).
When the thread switches to task context and runs the first handler but it has no state information about the second handler having run in the interrupt context. So here we may be unable to decide if we should run the second handler or not.
--
Thanks and Regards
Srikar
PATCH 8/10 X86 details for uprobes.
In reply to Srikar DronamrajuX86 support for Uprobes
This patch provides x86 specific details for uprobes. This includes interrupt notifier for uprobes, enabling/disabling singlestep.
---
arch/x86/Kconfig | 1 + arch/x86/kernel/Makefile | 1 + arch/x86/kernel/uprobes.c | 87 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 89 insertions(+), 0 deletions(-) create mode 100644 arch/x86/kernel/uprobes.c
arch/x86/Kconfig +1 -0
@@ -54,6 +54,7 @@ config X86 select HAVE_KERNEL_LZO select HAVE_HW_BREAKPOINT select HAVE_USER_BKPT + select HAVE_UPROBES select PERF_EVENTS select ANON_INODES select HAVE_ARCH_KMEMCHECK
arch/x86/kernel/Makefile +1 -0
@@ -118,6 +118,7 @@ obj-$(CONFIG_X86_CHECK_BIOS_CORRUPTION) += check.o obj-$(CONFIG_SWIOTLB) += pci-swiotlb.o obj-$(CONFIG_USER_BKPT) += user_bkpt.o +obj-$(CONFIG_UPROBES) += uprobes.o ### # 64 bit specific files
arch/x86/kernel/uprobes.c new file +87 -0
87 lines not on this page · raw message
PATCH 9/10 Uprobes Documentation patch
In reply to Srikar DronamrajuUprobes documentation.
---
Documentation/uprobes.txt | 244 +++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 244 insertions(+), 0 deletions(-) create mode 100644 Documentation/uprobes.txt
Documentation/uprobes.txt new file +244 -0
@@ -0,0 +1,244 @@ +Title : User-Space Probes (Uprobes) +Authors : Jim Keniston <[email protected]> + : Srikar Dronamraju <[email protected]> + +CONTENTS + +1. Concepts: Uprobes +2. Architectures Supported +3. Configuring Uprobes +4. API Reference +5. Uprobes Features and Limitations +6. Probe Overhead +7. TODO +8. Uprobes Team +9. Uprobes Example + +1. Concepts: Uprobes + +Uprobes enables you to dynamically break into any routine in a +user application and collect debugging and performance information +non-disruptively. You can trap at any code address, specifying a +kernel handler routine to be invoked when the breakpoint is hit. + +A uprobe can be inserted on any instruction in the application's +virtual address space. The registration function register_uprobe() +specifies which process is to be probed, where the probe is to be +inserted, and what handler is to be called when the probe is hit. + +Uprobes-based instrumentation can be packaged as a kernel +module. In the simplest case, the module's init function installs +("registers") one or more probes, and the exit function unregisters +them. + +1.1 How Does a Uprobe Work? + +When a uprobe is registered, Uprobes makes a copy of the probed +instruction, stops the probed application, replaces the first byte(s) +of the probed instruction with a breakpoint instruction (e.g., int3 +on i386 and x86_64), and allows the probed application to continue. +(When inserting the breakpoint, Uprobes uses background page +replacement mechanism, so that the breakpoint affects only that +process, and not any other process running that program. This is +true even if the probed instruction is in a shared library.) + +When a CPU hits the breakpoint instruction, a trap occurs, the CPU's +user-mode registers are saved, and uprobes notifier code finds the +associated uprobe. It then executes the handler associated with the +uprobe, passing the handler the addresses of the uprobe struct and the +saved registers. The handler can run either in interrupt context or in +task context; this specified by the user at the time of registration. +When run in task context, the handler may block, but keep in mind that +the probed thread remains stopped while your handler runs. + +Next, Uprobes single-steps its copy of the probed instruction and +resumes execution of the probed process at the instruction following +the probepoint. (It would be simpler to single-step the actual +instruction in place, but then Uprobes would have to temporarily +remove the breakpoint instruction. This would create problems in a +multithreaded application. For example, it would open a time window +when another thread could sail right past the probepoint.) + +Instruction copies to be single-stepped are stored in a per-process +"execution out of line (XOL) area," which is a little VM area +created by Uprobes in each probed process's address space. + +Uprobes handles interesting events in the lifetime of the probed +process, such as fork, clone, exec, and exit. + +1.2 Multithreaded Applications + +Uprobes supports the probing of multithreaded applications. Uprobes +imposes no limit on the number of threads in a probed application. +All threads in a process use the same text pages, so every probe +in a process affects all threads; of course, each thread hits the +probepoint (and runs the handler) independently. Multiple threads +may run the same handler simultaneously. If you want a particular +thread or set of threads to run a particular handler, your handler +should check current or current->pid to determine which thread has +hit the probepoint. + +When a process clones a new thread, that thread automatically shares +all current and future probes established for that process. + +2. Architectures Supported + +This user-bkpt based version of Uprobes is implemented on the following +architectures: + +- x86 + +3. Configuring Uprobes + +When configuring the kernel using make menuconfig/xconfig/oldconfig, +ensure that CONFIG_UPROBES is set to "y". Under "General setup" select +"User-space breakpoint assistance" then select "User-space probes". + +So that you can load and unload Uprobes-based instrumentation modules, +make sure "Loadable module support" (CONFIG_MODULES) and "Module +unloading" (CONFIG_MODULE_UNLOAD) are set to "y". + +4. API Reference + +The Uprobes API includes a "register" function and an "unregister" +function for uprobes. Here are terse, mini-man-page specifications for +these functions and the associated probe handlers that you'll write. +See the latter half of this document for examples. + +4.1 register_uprobe + +#include <linux/uprobes.h> +int register_uprobe(struct uprobe *u); + +Sets a breakpoint at virtual address u->vaddr in the process whose +pid is u->pid. When the breakpoint is hit, Uprobes calls u->handler. +If u->handler_in_interrupt is set, the handler runs in interrupt +context. Otherwise it runs in task context. + +register_uprobe() returns 0 on success, or a negative errno +otherwise. + +User's handler (u->handler): +#include <linux/uprobes.h> +#include <linux/ptrace.h> +void handler(struct uprobe *u, struct pt_regs *regs); + +Called with u pointing to the uprobe associated with the breakpoint, +and regs pointing to the struct containing the registers saved when +the breakpoint was hit. + +4.2 unregister_uprobe + +#include <linux/uprobes.h> +void unregister_uprobe(struct uprobe *u); + +Removes the specified probe. The unregister function can be called +at any time after the probe has been registered, and can be called +from a uprobe handler. + +5. Uprobes Features and Limitations + +The user is expected to assign values to the following members +of struct uprobe: pid, vaddr, handler, and handler_in_interrupt. +Uprobes may produce unexpected results if you: +- change the contents of a uprobe object while it is registered; or +- attempt to register a uprobe that is already registered. + +In this implementation, Uprobes allows only one uprobe at a particular +address. + +Any number of kernel modules may probe a particular process +simultaneously, and a particular module may probe any number of +processes simultaneously. + +Probes are shared by all threads in a process (including newly +created threads). + +If a probed process exits or execs, Uprobes automatically +unregisters all uprobes associated with that process. Subsequent +attempts to unregister these probes will be treated as no-ops. + +On the other hand, if a probed memory area is removed from the +process's virtual memory map (e.g., via dlclose(3) or munmap(2)), +it's currently up to you to unregister the probes first. + +There is no way to specify that probes should be inherited across fork; +Uprobes removes all probepoints in the newly created child process. + +To avoid interfering with interactive debuggers, Uprobes will refuse +to insert a probepoint where a breakpoint instruction already exists, +Some architectures may refuse to insert probes on other types of +instructions. + +If you install a probe in an inline-able function, Uprobes makes +no attempt to chase down all inline instances of the function and +install probes there. gcc may inline a function without being asked, +so keep this in mind if you're not seeing the probe hits you expect. + +A probe handler can modify the environment of the probed function +-- e.g., by modifying data structures, or by modifying the +contents of the pt_regs struct (which are restored to the registers +upon return from the breakpoint). So Uprobes can be used, for example, +to install a bug fix or to inject faults for testing. Uprobes, of +course, has no way to distinguish the deliberately injected faults +from the accidental ones. Don't drink and probe. + +When Uprobes establishes a probepoint on a previous unprobed page +of text, Linux creates a new copy of the page via its copy-on-write +mechanism. When probepoints are removed, Uprobes makes no attempt +to consolidate identical copies of the same page. This could affect +memory availability if you probe many, many pages in many, many +long-running processes. + +6. Probe Overhead + +Probe overhead is measured on a benchmark that hits the same probepoint +repeatedly, firing a simple handler each time. Probe overhead +changes with different cpus/archs/ probe handlers and the number of +iterations. + +Here are sample overhead figures (in usec) for x86 architecture. + +i686: Intel(R) Xeon(TM) CPU 2.40GHz +Without probe module. +100000 interations in 0.000650 sec i.e 0.006500 usec per iteration + +With probes and handler run in interrupt context. +100000 interations in 0.340774 sec i.e 3.407740 usec per iteration +probe overhead is 3.401240 usec per probe hit. + +With probes and handler run in task context. +100000 interations in 0.365589 sec i.e 3.655890 usec per iteration +probe overhead is 3.649390 usec per probe hit. + +x86_64: Intel(R) Xeon(R) CPU X7350 @ 2.93GHz +Without probe module. +100000 interations in 0.000468 sec i.e 0.004680 usec per iteration + +With probes and handler run in interrupt context. +100000 interations in 0.120369 sec i.e 1.203690 usec per iteration +Probe overhead is 1.199010 usec per probe hit. + +With probes and handler run in task context. +100000 interations in 0.130685 sec i.e 1.306850 usec per iteration +Probe overhead is 1.302170 usec per probe hit. + +7. TODO + +a. Support for other architectures. +b. Support for multiple probes at the same address. +c. Support for boosted probes. +d. Support return probes. + +8. Uprobes Team + +The following people have made major contributions to Uprobes: +Jim Keniston - [email protected] +Srikar Dronamraju - [email protected] +Ananth Mavinakayanahalli - [email protected] +Prasanna Panchamukhi - [email protected] +Dave Wilder - [email protected] + +9. Uprobes Example + +samples/uprobes/uprobe_example.c
Re: [PATCH v1 9/10] Uprobes Documentation patch
Quoted 57 lines · Srikar Dronamraju
Uprobes documentation.
Signed-off-by Jim Keniston <[email protected]>Signed-off-by Srikar Dronamraju <[email protected]>---
Documentation/uprobes.txt | 244 +++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 244 insertions(+), 0 deletions(-) create mode 100644 Documentation/uprobes.txtDocumentation/uprobes.txt new file +40
-0@@ -0,0 +1,244 @@ +Title : User-Space Probes (Uprobes) +Authors : Jim Keniston <[email protected]> + : Srikar Dronamraju <[email protected]> + +CONTENTS + +1. Concepts: Uprobes +2. Architectures Supported +3. Configuring Uprobes +4. API Reference +5. Uprobes Features and Limitations +6. Probe Overhead +7. TODO +8. Uprobes Team +9. Uprobes Example + +1. Concepts: Uprobes + +Uprobes enables you to dynamically break into any routine in a +user application and collect debugging and performance information +non-disruptively. You can trap at any code address, specifying a +kernel handler routine to be invoked when the breakpoint is hit. + +A uprobe can be inserted on any instruction in the application's +virtual address space. The registration function register_uprobe() +specifies which process is to be probed, where the probe is to be +inserted, and what handler is to be called when the probe is hit. + +Uprobes-based instrumentation can be packaged as a kernel +module. In the simplest case, the module's init function installs +("registers") one or more probes, and the exit function unregisters +them. + +1.1 How Does a Uprobe Work? + +When a uprobe is registered, Uprobes makes a copy of the probed +instruction, stops the probed application, replaces the first byte(s) +of the probed instruction with a breakpoint instruction (e.g., int3 +on i386 and x86_64), and allows the probed application to continue. +(When inserting the breakpoint, Uprobes uses background page
Documentation/uprobes.txt line 50
Quoted 10 lines
Documentation/uprobes.txt new file +10
-0+replacement mechanism, so that the breakpoint affects only that +process, and not any other process running that program. This is +true even if the probed instruction is in a shared library.) + +When a CPU hits the breakpoint instruction, a trap occurs, the CPU's +user-mode registers are saved, and uprobes notifier code finds the +associated uprobe. It then executes the handler associated with the +uprobe, passing the handler the addresses of the uprobe struct and the +saved registers. The handler can run either in interrupt context or in +task context; this specified by the user at the time of registration.
this is specified
Quoted 26 lines
Documentation/uprobes.txt new file +26
-0+When run in task context, the handler may block, but keep in mind that +the probed thread remains stopped while your handler runs. + +Next, Uprobes single-steps its copy of the probed instruction and +resumes execution of the probed process at the instruction following +the probepoint. (It would be simpler to single-step the actual +instruction in place, but then Uprobes would have to temporarily +remove the breakpoint instruction. This would create problems in a +multithreaded application. For example, it would open a time window +when another thread could sail right past the probepoint.) + +Instruction copies to be single-stepped are stored in a per-process +"execution out of line (XOL) area," which is a little VM area +created by Uprobes in each probed process's address space. + +Uprobes handles interesting events in the lifetime of the probed +process, such as fork, clone, exec, and exit. + +1.2 Multithreaded Applications + +Uprobes supports the probing of multithreaded applications. Uprobes +imposes no limit on the number of threads in a probed application. +All threads in a process use the same text pages, so every probe +in a process affects all threads; of course, each thread hits the +probepoint (and runs the handler) independently. Multiple threads +may run the same handler simultaneously. If you want a particular
Documentation/uprobes.txt line 86
Quoted 10 lines
Documentation/uprobes.txt new file +10
-0+thread or set of threads to run a particular handler, your handler +should check current or current->pid to determine which thread has +hit the probepoint. + +When a process clones a new thread, that thread automatically shares +all current and future probes established for that process. + +2. Architectures Supported + +This user-bkpt based version of Uprobes is implemented on the following
s/bkpt/breakpoint/
Quoted 73 lines
Documentation/uprobes.txt new file +73
-0+architectures: + +- x86 + +3. Configuring Uprobes + +When configuring the kernel using make menuconfig/xconfig/oldconfig, +ensure that CONFIG_UPROBES is set to "y". Under "General setup" select +"User-space breakpoint assistance" then select "User-space probes". + +So that you can load and unload Uprobes-based instrumentation modules, +make sure "Loadable module support" (CONFIG_MODULES) and "Module +unloading" (CONFIG_MODULE_UNLOAD) are set to "y". + +4. API Reference + +The Uprobes API includes a "register" function and an "unregister" +function for uprobes. Here are terse, mini-man-page specifications for +these functions and the associated probe handlers that you'll write. +See the latter half of this document for examples. + +4.1 register_uprobe + +#include <linux/uprobes.h> +int register_uprobe(struct uprobe *u); + +Sets a breakpoint at virtual address u->vaddr in the process whose +pid is u->pid. When the breakpoint is hit, Uprobes calls u->handler. +If u->handler_in_interrupt is set, the handler runs in interrupt +context. Otherwise it runs in task context. + +register_uprobe() returns 0 on success, or a negative errno +otherwise. + +User's handler (u->handler): +#include <linux/uprobes.h> +#include <linux/ptrace.h> +void handler(struct uprobe *u, struct pt_regs *regs); + +Called with u pointing to the uprobe associated with the breakpoint, +and regs pointing to the struct containing the registers saved when +the breakpoint was hit. + +4.2 unregister_uprobe + +#include <linux/uprobes.h> +void unregister_uprobe(struct uprobe *u); + +Removes the specified probe. The unregister function can be called +at any time after the probe has been registered, and can be called +from a uprobe handler. + +5. Uprobes Features and Limitations + +The user is expected to assign values to the following members +of struct uprobe: pid, vaddr, handler, and handler_in_interrupt. +Uprobes may produce unexpected results if you: +- change the contents of a uprobe object while it is registered; or +- attempt to register a uprobe that is already registered. + +In this implementation, Uprobes allows only one uprobe at a particular +address. + +Any number of kernel modules may probe a particular process +simultaneously, and a particular module may probe any number of +processes simultaneously. + +Probes are shared by all threads in a process (including newly +created threads). + +If a probed process exits or execs, Uprobes automatically +unregisters all uprobes associated with that process. Subsequent +attempts to unregister these probes will be treated as no-ops.
Documentation/uprobes.txt line 169
Quoted 10 lines
Documentation/uprobes.txt new file +10
-0+ +On the other hand, if a probed memory area is removed from the +process's virtual memory map (e.g., via dlclose(3) or munmap(2)), +it's currently up to you to unregister the probes first. + +There is no way to specify that probes should be inherited across fork; +Uprobes removes all probepoints in the newly created child process. + +To avoid interfering with interactive debuggers, Uprobes will refuse +to insert a probepoint where a breakpoint instruction already exists,
exists.
Quoted 18 lines
Documentation/uprobes.txt new file +18
-0+Some architectures may refuse to insert probes on other types of +instructions. + +If you install a probe in an inline-able function, Uprobes makes +no attempt to chase down all inline instances of the function and +install probes there. gcc may inline a function without being asked, +so keep this in mind if you're not seeing the probe hits you expect. + +A probe handler can modify the environment of the probed function +-- e.g., by modifying data structures, or by modifying the +contents of the pt_regs struct (which are restored to the registers +upon return from the breakpoint). So Uprobes can be used, for example, +to install a bug fix or to inject faults for testing. Uprobes, of +course, has no way to distinguish the deliberately injected faults +from the accidental ones. Don't drink and probe. + +When Uprobes establishes a probepoint on a previous unprobed page +of text, Linux creates a new copy of the page via its copy-on-write
Documentation/uprobes.txt line 197
Quoted 10 lines
Documentation/uprobes.txt new file +10
-0+mechanism. When probepoints are removed, Uprobes makes no attempt +to consolidate identical copies of the same page. This could affect +memory availability if you probe many, many pages in many, many +long-running processes. + +6. Probe Overhead + +Probe overhead is measured on a benchmark that hits the same probepoint +repeatedly, firing a simple handler each time. Probe overhead +changes with different cpus/archs/ probe handlers and the number of
no space after "archs/", just:
CPUs/archs/probe handlers
Quoted 48 lines
Documentation/uprobes.txt new file +47
-1+iterations. + +Here are sample overhead figures (in usec) for x86 architecture. + +i686: Intel(R) Xeon(TM) CPU 2.40GHz +Without probe module. +100000 interations in 0.000650 sec i.e 0.006500 usec per iteration + +With probes and handler run in interrupt context. +100000 interations in 0.340774 sec i.e 3.407740 usec per iteration +probe overhead is 3.401240 usec per probe hit. + +With probes and handler run in task context. +100000 interations in 0.365589 sec i.e 3.655890 usec per iteration +probe overhead is 3.649390 usec per probe hit. + +x86_64: Intel(R) Xeon(R) CPU X7350 @ 2.93GHz +Without probe module. +100000 interations in 0.000468 sec i.e 0.004680 usec per iteration + +With probes and handler run in interrupt context. +100000 interations in 0.120369 sec i.e 1.203690 usec per iteration +Probe overhead is 1.199010 usec per probe hit. + +With probes and handler run in task context. +100000 interations in 0.130685 sec i.e 1.306850 usec per iteration +Probe overhead is 1.302170 usec per probe hit. + +7. TODO + +a. Support for other architectures. +b. Support for multiple probes at the same address. +c. Support for boosted probes. +d. Support return probes. + +8. Uprobes Team + +The following people have made major contributions to Uprobes: +Jim Keniston - [email protected] +Srikar Dronamraju - [email protected] +Ananth Mavinakayanahalli - [email protected] +Prasanna Panchamukhi - [email protected] +Dave Wilder - [email protected] + +9. Uprobes Example + +samples/uprobes/uprobe_example.c --
Signature · 1 line
~Randy
Re: [PATCH v1 9/10] Uprobes Documentation patch
Thanks for the review,
The next version of the patchset will address your comments.
Quoted 5 lines
Review
Quoted 2 lines
(quoted diff) +2
-0+ +This user-bkpt based version of Uprobes is implemented on the followings/bkpt/breakpoint/
Your comment however made me realize that I had used user-bkpt here rather than user_bkpt.
user_bkpt is a layer that provides breakpoint insertion and removal. I wanted to mention that uprobes depends on user_bkpt layer. I think "This user_bkpt based version" is probably better than "This user-breakpoint based version"
--
Thanks and Regards
Srikar
Re: [PATCH v1 9/10] Uprobes Documentation patch
Quoted 9 lines · Srikar Dronamraju
Thanks for the review,
The next version of the patchset will address your comments.Quoted 5 lines
Review
Quoted 2 lines
(quoted diff) +2
-0+ +This user-bkpt based version of Uprobes is implemented on the followings/bkpt/breakpoint/
Quoted 7 lines
Your comment however made me realize that I had used user-bkpt here rather than
user_bkpt.
user_bkptis a layer that provides breakpoint insertion and removal. I wanted to mention that uprobes depends onuser_bkptlayer. I think "Thisuser_bkptbased version" is probably better than "This user-breakpoint based version"
I see. Sure, that's fine.
Signature · 1 line
~Randy
PATCH 10/10 Uprobes samples.
In reply to Srikar DronamrajuUprobes Samples
This provides an example uprobes module in the samples directory.
To run this module run (as root)
insmod uprobe_example.ko vaddr=<vaddr> pid=<pid>
Where <vaddr> is the address where we want to place the probe.
<pid> is the pid of the process we are interested to probe.
example: -
# cd samples/uprobes
[get the virtual address to place the probe.]
# vaddr=0x$(objdump -T /bin/bash |awk '/echo_builtin/ {print $1}')
[Run a bash shell in the background; have it echo 4 lines.] # (sleep 10; echo 1; echo 2; echo 3; echo 4) & [Probe calls echo_builtin() in the background bash process.]
# insmod uprobe_example.ko vaddr=$vaddr pid=$! # sleep 10 # rmmod uprobe_example # dmesg | tail -n 3 Registering uprobe on pid 10875, vaddr 0x45aa30 Unregistering uprobe on pid 10875, vaddr 0x45aa30 Probepoint was hit 4 times # [ Output shows that echo_builtin function was hit 4 times. ]
---
samples/Kconfig | 7 +++ samples/uprobes/Makefile | 17 ++++++++ samples/uprobes/uprobe_example.c | 83 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 107 insertions(+), 0 deletions(-) create mode 100644 samples/uprobes/Makefile create mode 100644 samples/uprobes/uprobe_example.c
samples/Kconfig +7 -0
@@ -44,4 +44,11 @@ config SAMPLE_HW_BREAKPOINT help This builds kernel hardware breakpoint example modules. +config SAMPLE_UPROBES + tristate "Build uprobes example -- loadable module only" + depends on UPROBES && m + help + This builds uprobes example module. + + endif # SAMPLES
samples/uprobes/Makefile new file +17 -0
@@ -0,0 +1,17 @@ +# builds the uprobes example kernel modules; +# then to use one (as root): +# insmod <module_name.ko> vaddr=<vaddr> pid=<pid> +# +# +# example: - +# vaddr=0x$(objdump -T /bin/bash |awk '/echo_builtin/ print $1}') +# (sleep 10; echo 1; echo 2; echo 3; echo 4) & +# insmod uprobe_example.ko vaddr=$vaddr pid=$! +# sleep 10 +# rmmod uprobe_example +# dmesg | tail -n 3 +# Registering uprobe on pid 3920, vaddr 0x45aa30 +# Unregistering uprobe on pid 3920, vaddr 0x45aa30 +# Probepoint was hit 4 times + +obj-$(CONFIG_SAMPLE_UPROBES) += uprobe_example.o
samples/uprobes/uprobe_example.c new file +83 -0
83 lines not on this page · raw message
Andrew Morton
maintainerQuoted 3 lines · On Sat, 20 Mar 2010 19:54:55 +0530 Srikar Dronamraju…
This patchset implements Uprobes which enables you to dynamically break into any routine in a user space application and collect information non-disruptively.
What's missing here is a description of why all this is useful. Presumably much of the functionality which this feature offers can be done wholly in userspace. So I think it would be useful if you were to carefully explain the thinking here - what the value is, how people will use it, why it needs to be done in-kernel, etc. Right now if I was asked "why did you merge that", I'd say "gee, I dunno". I say that a lot. Knowing all of this would perhaps help me to understand your thinking regarding ftrace integration.
The code itself is positioned as non-x86-specific, but the implementation is x86-only. It would be nice to get some confirmation that other architectures can successfully use the core code. But that will be hard to arrange, so probably crossing our fingers is the best approach here.
The code scares me a bit from the "how can malicious people exploit it" point of view. Breaking into other users programs/memory, causing the kernel to scribble on itself, causing unbound memory consumption, etc. No specific issues that I can point at, just vague fear.
Do we know that exiting userspace will never ever already be using int3?
What happens if I run this code in 2016 on a CPU which has new opcodes which this code didn't know about?
When uprobes was being pushed five-odd years ago, it did all sorts of hair-raising things to avoid COWing shared pages. Lots of reasons were given why it *had* to avoid COW. But now it COWs. What were those reasons why COW was unacceptable, and what changed?
Hi Andrew,
Quoted 5 lines
Quoted 4 lines
This patchset implements Uprobes which enables you to dynamically break into any routine in a user space application and collect information non-disruptively.
Quoted 8 lines
What's missing here is a description of why all this is useful. Presumably much of the functionality which this feature offers can be done wholly in userspace. So I think it would be useful if you were to carefully explain the thinking here - what the value is, how people will use it, why it needs to be done in-kernel, etc. Right now if I was asked "why did you merge that", I'd say "gee, I dunno". I say that a lot. Knowing all of this would perhaps help me to understand your thinking regarding ftrace integration.
Main motivations for uprobes
- non-disruptive tracing.
Current ptrace based mechanisms generally involve signals and stopped threads. Also it involves context switching between the tracer and tracee. The delay and involvement of signals can result in problems seen in production systems not seen while tracing. Uprobes tracing wouldnt involve signals, context switches between tracer and tracee.
- Multithreaded support.
Current ptrace based mechanisms for tracing apps use single stepping inline, i.e they copy back the original instruction on hitting a breakpoint. In such mechanisms tracers have to stop all the threads on a breakpoint hit or tracers will not be able to handle all hits to the location of interest. Uprobes uses execution out of line, where the instruction to be traced is analysed at the time of breakpoint insertion and a copy of instruction is stored at a different location. On breakpoint hit, uprobes jumps to that copied location and singlesteps the same instruction and does the necessary fixups post singlestepping.
- Tracing multiple applications:
A uprobe based tracer would be able to trace multiple (similar or different) applications. This could be very useful in understanding how different applications are interacting with each other.
- Multiple tracers for an application:
Multiple uprobes based tracer could work in unison to trace an application. There could one tracer that could be interested in generic events for a particular set of process. While there could be another tracer that is just interested in one specific event of a particular process thats part of the previous set of process.
- Corelating events from kernels and userspace.
Uprobes could be used with other tools like kprobes, tracepoints or as part of higher level tools like perf to give a consolidated set of events from kernel and userspace.
In future we could look at a single backtrace showing application, library and kernel calls.
We are looking at providing a perf interface for uprobes. Last year based on inputs from Christoph and Roland, Frank and I had developed a prototype gdbstub which used uprobes to insert/remove breakpoints.
Uprobes has been used to make use of dtrace style application markers already present in applications
If community is favourable, we could have a syscall to insert/remove breakpoints so that gdb or other debuggers could benefit. Here is some discussion on this idea (http://lkml.org/lkml/2010/1/26/344)
Quoted 5 lines
The code itself is positioned as non-x86-specific, but the implementation is x86-only. It would be nice to get some confirmation that other architectures can successfully use the core code. But that will be hard to arrange, so probably crossing our fingers is the best approach here.
We do have some bits for Powerpc and S390 though they are not updated to the current bits. So I know core code can work with other architectures. Once the core code gets merged, I will work to get these other architectures to use core code.
Quoted 5 lines
The code scares me a bit from the "how can malicious people exploit it" point of view. Breaking into other users programs/memory, causing the kernel to scribble on itself, causing unbound memory consumption, etc. No specific issues that I can point at, just vague fear.
Users of uprobes could use capabilities to restrict who can trace a process. Currently we restrict the area allocated for the slots to be one page. We could also look at restricting the number of processes that could be uprobed at a time.
Do you have ideas on what other measures we could take?
Quoted 2 lines
Do we know that exiting userspace will never ever already be using int3?
User_bkpt layer (and hence uprobes) will not insert breakpoints if a breakpoint already exists at that address. If the user program traps on a int3 that is not inserted by user_bkpt/uprobes, then user_bkpt/uprobes will allow not handle such int3. uprobes only handles breakpoints that it has inserted.
Quoted 3 lines
What happens if I run this code in 2016 on a CPU which has new opcodes which this code didn't know about?
user_bkpt is based on x86 instruction decoder. Based on how the x86 instruction decoder handles the opcodes, we would have to update the good set of instructions for userspace. This good set of instructions is currently maintained in user_bkpt layer. However Masami was proposing using bits in inat instruction table to know if the instructions are valid and boostable. Once that gets implemented, uprobes maintainance for newcodes would mostly be moved to x86 instruction decoder.
However this might vary for other architectures.
Quoted 6 lines
When uprobes was being pushed five-odd years ago, it did all sorts of hair-raising things to avoid COWing shared pages. Lots of reasons were given why it *had* to avoid COW. But now it COWs. What were those reasons why COW was unacceptable, and what changed?
Some of the ideas put forth by the community including you made us rethink that COW was probably better. This also influenced us from moving from a file/executable based approach to a process based approach. I am hopeful of implementing a file based tracing on a process based uprobes. The details are still to be hashed out.
http://lkml.indiana.edu/hypermail/linux/kernel/0603.2/1821.html
lists your mail where you suggested a process based tracing over a file/executable based tracing.
Reasons listed then for not doing a COW
- Tracing instructions in a page thats not yet loaded will result in a new page being loaded into memory immediately.
- Tracing same code in shared libraries could result in multiple copies of the same page being loaded into memory.
So not using COW probably means we will have more pages loaded into memory but as pointed out by you and others in community, its probably simpler and cleaner.
Infact what we are doing is not COW but a background page replacement as was suggested by Linus, Peter and Mel. I.e, we explicitly make a copy of the page, modify it and then update the page tables to reflect the new page. (http://lkml.org/lkml/2010/1/27/89)
Please let me know if there is anything that I can clarify.
--
Thanks and Regards
Srikar