xref: /linux/include/linux/uprobes.h (revision 1a59d1b8)
1*1a59d1b8SThomas Gleixner /* SPDX-License-Identifier: GPL-2.0-or-later */
22b144498SSrikar Dronamraju #ifndef _LINUX_UPROBES_H
32b144498SSrikar Dronamraju #define _LINUX_UPROBES_H
42b144498SSrikar Dronamraju /*
57b2d81d4SIngo Molnar  * User-space Probes (UProbes)
62b144498SSrikar Dronamraju  *
735aa621bSIngo Molnar  * Copyright (C) IBM Corporation, 2008-2012
82b144498SSrikar Dronamraju  * Authors:
92b144498SSrikar Dronamraju  *	Srikar Dronamraju
102b144498SSrikar Dronamraju  *	Jim Keniston
1190eec103SPeter Zijlstra  * Copyright (C) 2011-2012 Red Hat, Inc., Peter Zijlstra
122b144498SSrikar Dronamraju  */
132b144498SSrikar Dronamraju 
142b144498SSrikar Dronamraju #include <linux/errno.h>
152b144498SSrikar Dronamraju #include <linux/rbtree.h>
1632473431SOleg Nesterov #include <linux/types.h>
17e8f4aa60SAllen Pais #include <linux/wait.h>
182b144498SSrikar Dronamraju 
192b144498SSrikar Dronamraju struct vm_area_struct;
20d4b3b638SSrikar Dronamraju struct mm_struct;
21d4b3b638SSrikar Dronamraju struct inode;
223820b4d2SDavid A. Long struct notifier_block;
2372e6ae28SVictor Kamensky struct page;
240326f5a9SSrikar Dronamraju 
25da1816b1SOleg Nesterov #define UPROBE_HANDLER_REMOVE		1
26da1816b1SOleg Nesterov #define UPROBE_HANDLER_MASK		1
27da1816b1SOleg Nesterov 
28ded49c55SAnton Arapov #define MAX_URETPROBE_DEPTH		64
29ded49c55SAnton Arapov 
308a7f2fa0SOleg Nesterov enum uprobe_filter_ctx {
318a7f2fa0SOleg Nesterov 	UPROBE_FILTER_REGISTER,
328a7f2fa0SOleg Nesterov 	UPROBE_FILTER_UNREGISTER,
338a7f2fa0SOleg Nesterov 	UPROBE_FILTER_MMAP,
348a7f2fa0SOleg Nesterov };
358a7f2fa0SOleg Nesterov 
362b144498SSrikar Dronamraju struct uprobe_consumer {
372b144498SSrikar Dronamraju 	int (*handler)(struct uprobe_consumer *self, struct pt_regs *regs);
38ea024870SAnton Arapov 	int (*ret_handler)(struct uprobe_consumer *self,
39ea024870SAnton Arapov 				unsigned long func,
40ea024870SAnton Arapov 				struct pt_regs *regs);
418a7f2fa0SOleg Nesterov 	bool (*filter)(struct uprobe_consumer *self,
428a7f2fa0SOleg Nesterov 				enum uprobe_filter_ctx ctx,
438a7f2fa0SOleg Nesterov 				struct mm_struct *mm);
442b144498SSrikar Dronamraju 
452b144498SSrikar Dronamraju 	struct uprobe_consumer *next;
462b144498SSrikar Dronamraju };
472b144498SSrikar Dronamraju 
482b144498SSrikar Dronamraju #ifdef CONFIG_UPROBES
49c912dae6SOleg Nesterov #include <asm/uprobes.h>
50c912dae6SOleg Nesterov 
510326f5a9SSrikar Dronamraju enum uprobe_task_state {
520326f5a9SSrikar Dronamraju 	UTASK_RUNNING,
530326f5a9SSrikar Dronamraju 	UTASK_SSTEP,
540326f5a9SSrikar Dronamraju 	UTASK_SSTEP_ACK,
550326f5a9SSrikar Dronamraju 	UTASK_SSTEP_TRAPPED,
560326f5a9SSrikar Dronamraju };
570326f5a9SSrikar Dronamraju 
580326f5a9SSrikar Dronamraju /*
590326f5a9SSrikar Dronamraju  * uprobe_task: Metadata of a task while it singlesteps.
600326f5a9SSrikar Dronamraju  */
610326f5a9SSrikar Dronamraju struct uprobe_task {
620326f5a9SSrikar Dronamraju 	enum uprobe_task_state		state;
6332473431SOleg Nesterov 
6432473431SOleg Nesterov 	union {
6532473431SOleg Nesterov 		struct {
660326f5a9SSrikar Dronamraju 			struct arch_uprobe_task	autask;
6732473431SOleg Nesterov 			unsigned long		vaddr;
6832473431SOleg Nesterov 		};
6932473431SOleg Nesterov 
7032473431SOleg Nesterov 		struct {
7132473431SOleg Nesterov 			struct callback_head	dup_xol_work;
7232473431SOleg Nesterov 			unsigned long		dup_xol_addr;
7332473431SOleg Nesterov 		};
7432473431SOleg Nesterov 	};
7532473431SOleg Nesterov 
7632473431SOleg Nesterov 	struct uprobe			*active_uprobe;
7732473431SOleg Nesterov 	unsigned long			xol_vaddr;
780326f5a9SSrikar Dronamraju 
790dfd0eb8SAnton Arapov 	struct return_instance		*return_instances;
80ded49c55SAnton Arapov 	unsigned int			depth;
810326f5a9SSrikar Dronamraju };
820326f5a9SSrikar Dronamraju 
8397da8976SOleg Nesterov struct return_instance {
8497da8976SOleg Nesterov 	struct uprobe		*uprobe;
8597da8976SOleg Nesterov 	unsigned long		func;
867b868e48SOleg Nesterov 	unsigned long		stack;		/* stack pointer */
8797da8976SOleg Nesterov 	unsigned long		orig_ret_vaddr; /* original return address */
8897da8976SOleg Nesterov 	bool			chained;	/* true, if instance is nested */
8997da8976SOleg Nesterov 
9097da8976SOleg Nesterov 	struct return_instance	*next;		/* keep as stack */
9197da8976SOleg Nesterov };
9297da8976SOleg Nesterov 
9386dcb702SOleg Nesterov enum rp_check {
9486dcb702SOleg Nesterov 	RP_CHECK_CALL,
95db087ef6SOleg Nesterov 	RP_CHECK_CHAIN_CALL,
9686dcb702SOleg Nesterov 	RP_CHECK_RET,
9786dcb702SOleg Nesterov };
9886dcb702SOleg Nesterov 
99c912dae6SOleg Nesterov struct xol_area;
100d4b3b638SSrikar Dronamraju 
101d4b3b638SSrikar Dronamraju struct uprobes_state {
102d4b3b638SSrikar Dronamraju 	struct xol_area		*xol_area;
103d4b3b638SSrikar Dronamraju };
104647c42dfSOleg Nesterov 
105aad42dd4SNadav Amit extern void __init uprobes_init(void);
106271a9c35SBjorn Helgaas extern int set_swbp(struct arch_uprobe *aup, struct mm_struct *mm, unsigned long vaddr);
107271a9c35SBjorn Helgaas extern int set_orig_insn(struct arch_uprobe *aup, struct mm_struct *mm, unsigned long vaddr);
108271a9c35SBjorn Helgaas extern bool is_swbp_insn(uprobe_opcode_t *insn);
109271a9c35SBjorn Helgaas extern bool is_trap_insn(uprobe_opcode_t *insn);
110271a9c35SBjorn Helgaas extern unsigned long uprobe_get_swbp_addr(struct pt_regs *regs);
111b02ef20aSOleg Nesterov extern unsigned long uprobe_get_trap_addr(struct pt_regs *regs);
1126d43743eSRavi Bangoria extern int uprobe_write_opcode(struct arch_uprobe *auprobe, struct mm_struct *mm, unsigned long vaddr, uprobe_opcode_t);
113e3343e6aSSrikar Dronamraju extern int uprobe_register(struct inode *inode, loff_t offset, struct uprobe_consumer *uc);
1141cc33161SRavi Bangoria extern int uprobe_register_refctr(struct inode *inode, loff_t offset, loff_t ref_ctr_offset, struct uprobe_consumer *uc);
115bdf8647cSOleg Nesterov extern int uprobe_apply(struct inode *inode, loff_t offset, struct uprobe_consumer *uc, bool);
116e3343e6aSSrikar Dronamraju extern void uprobe_unregister(struct inode *inode, loff_t offset, struct uprobe_consumer *uc);
1177b2d81d4SIngo Molnar extern int uprobe_mmap(struct vm_area_struct *vma);
118cbc91f71SSrikar Dronamraju extern void uprobe_munmap(struct vm_area_struct *vma, unsigned long start, unsigned long end);
11932cdba1eSOleg Nesterov extern void uprobe_start_dup_mmap(void);
12032cdba1eSOleg Nesterov extern void uprobe_end_dup_mmap(void);
121f8ac4ec9SOleg Nesterov extern void uprobe_dup_mmap(struct mm_struct *oldmm, struct mm_struct *newmm);
1220326f5a9SSrikar Dronamraju extern void uprobe_free_utask(struct task_struct *t);
1233ab67966SOleg Nesterov extern void uprobe_copy_process(struct task_struct *t, unsigned long flags);
1240326f5a9SSrikar Dronamraju extern int uprobe_post_sstep_notifier(struct pt_regs *regs);
1250326f5a9SSrikar Dronamraju extern int uprobe_pre_sstep_notifier(struct pt_regs *regs);
1260326f5a9SSrikar Dronamraju extern void uprobe_notify_resume(struct pt_regs *regs);
1270326f5a9SSrikar Dronamraju extern bool uprobe_deny_signal(void);
128c2d3f25dSRalf Baechle extern bool arch_uprobe_skip_sstep(struct arch_uprobe *aup, struct pt_regs *regs);
129d4b3b638SSrikar Dronamraju extern void uprobe_clear_state(struct mm_struct *mm);
1303820b4d2SDavid A. Long extern int  arch_uprobe_analyze_insn(struct arch_uprobe *aup, struct mm_struct *mm, unsigned long addr);
1313820b4d2SDavid A. Long extern int  arch_uprobe_pre_xol(struct arch_uprobe *aup, struct pt_regs *regs);
1323820b4d2SDavid A. Long extern int  arch_uprobe_post_xol(struct arch_uprobe *aup, struct pt_regs *regs);
1333820b4d2SDavid A. Long extern bool arch_uprobe_xol_was_trapped(struct task_struct *tsk);
1343820b4d2SDavid A. Long extern int  arch_uprobe_exception_notify(struct notifier_block *self, unsigned long val, void *data);
1353820b4d2SDavid A. Long extern void arch_uprobe_abort_xol(struct arch_uprobe *aup, struct pt_regs *regs);
1363820b4d2SDavid A. Long extern unsigned long arch_uretprobe_hijack_return_addr(unsigned long trampoline_vaddr, struct pt_regs *regs);
13786dcb702SOleg Nesterov extern bool arch_uretprobe_is_alive(struct return_instance *ret, enum rp_check ctx, struct pt_regs *regs);
138271a9c35SBjorn Helgaas extern bool arch_uprobe_ignore(struct arch_uprobe *aup, struct pt_regs *regs);
139271a9c35SBjorn Helgaas extern void arch_uprobe_copy_ixol(struct page *page, unsigned long vaddr,
14072e6ae28SVictor Kamensky 					 void *src, unsigned long len);
1410326f5a9SSrikar Dronamraju #else /* !CONFIG_UPROBES */
142d4b3b638SSrikar Dronamraju struct uprobes_state {
143d4b3b638SSrikar Dronamraju };
144b02ef20aSOleg Nesterov 
uprobes_init(void)145aad42dd4SNadav Amit static inline void uprobes_init(void)
146aad42dd4SNadav Amit {
147aad42dd4SNadav Amit }
148aad42dd4SNadav Amit 
149b02ef20aSOleg Nesterov #define uprobe_get_trap_addr(regs)	instruction_pointer(regs)
150b02ef20aSOleg Nesterov 
1517b2d81d4SIngo Molnar static inline int
uprobe_register(struct inode * inode,loff_t offset,struct uprobe_consumer * uc)152e3343e6aSSrikar Dronamraju uprobe_register(struct inode *inode, loff_t offset, struct uprobe_consumer *uc)
1532b144498SSrikar Dronamraju {
1542b144498SSrikar Dronamraju 	return -ENOSYS;
1552b144498SSrikar Dronamraju }
uprobe_register_refctr(struct inode * inode,loff_t offset,loff_t ref_ctr_offset,struct uprobe_consumer * uc)1561cc33161SRavi Bangoria static inline int uprobe_register_refctr(struct inode *inode, loff_t offset, loff_t ref_ctr_offset, struct uprobe_consumer *uc)
1571cc33161SRavi Bangoria {
1581cc33161SRavi Bangoria 	return -ENOSYS;
1591cc33161SRavi Bangoria }
160bdf8647cSOleg Nesterov static inline int
uprobe_apply(struct inode * inode,loff_t offset,struct uprobe_consumer * uc,bool add)161bdf8647cSOleg Nesterov uprobe_apply(struct inode *inode, loff_t offset, struct uprobe_consumer *uc, bool add)
162bdf8647cSOleg Nesterov {
163bdf8647cSOleg Nesterov 	return -ENOSYS;
164bdf8647cSOleg Nesterov }
1657b2d81d4SIngo Molnar static inline void
uprobe_unregister(struct inode * inode,loff_t offset,struct uprobe_consumer * uc)166e3343e6aSSrikar Dronamraju uprobe_unregister(struct inode *inode, loff_t offset, struct uprobe_consumer *uc)
1672b144498SSrikar Dronamraju {
1682b144498SSrikar Dronamraju }
uprobe_mmap(struct vm_area_struct * vma)1697b2d81d4SIngo Molnar static inline int uprobe_mmap(struct vm_area_struct *vma)
1702b144498SSrikar Dronamraju {
1712b144498SSrikar Dronamraju 	return 0;
1722b144498SSrikar Dronamraju }
173cbc91f71SSrikar Dronamraju static inline void
uprobe_munmap(struct vm_area_struct * vma,unsigned long start,unsigned long end)174cbc91f71SSrikar Dronamraju uprobe_munmap(struct vm_area_struct *vma, unsigned long start, unsigned long end)
175682968e0SSrikar Dronamraju {
176682968e0SSrikar Dronamraju }
uprobe_start_dup_mmap(void)17732cdba1eSOleg Nesterov static inline void uprobe_start_dup_mmap(void)
17832cdba1eSOleg Nesterov {
17932cdba1eSOleg Nesterov }
uprobe_end_dup_mmap(void)18032cdba1eSOleg Nesterov static inline void uprobe_end_dup_mmap(void)
18132cdba1eSOleg Nesterov {
18232cdba1eSOleg Nesterov }
183f8ac4ec9SOleg Nesterov static inline void
uprobe_dup_mmap(struct mm_struct * oldmm,struct mm_struct * newmm)184f8ac4ec9SOleg Nesterov uprobe_dup_mmap(struct mm_struct *oldmm, struct mm_struct *newmm)
185f8ac4ec9SOleg Nesterov {
186f8ac4ec9SOleg Nesterov }
uprobe_notify_resume(struct pt_regs * regs)1870326f5a9SSrikar Dronamraju static inline void uprobe_notify_resume(struct pt_regs *regs)
1880326f5a9SSrikar Dronamraju {
1890326f5a9SSrikar Dronamraju }
uprobe_deny_signal(void)1900326f5a9SSrikar Dronamraju static inline bool uprobe_deny_signal(void)
1910326f5a9SSrikar Dronamraju {
1920326f5a9SSrikar Dronamraju 	return false;
1930326f5a9SSrikar Dronamraju }
uprobe_free_utask(struct task_struct * t)1940326f5a9SSrikar Dronamraju static inline void uprobe_free_utask(struct task_struct *t)
1950326f5a9SSrikar Dronamraju {
1960326f5a9SSrikar Dronamraju }
uprobe_copy_process(struct task_struct * t,unsigned long flags)1973ab67966SOleg Nesterov static inline void uprobe_copy_process(struct task_struct *t, unsigned long flags)
1980326f5a9SSrikar Dronamraju {
1990326f5a9SSrikar Dronamraju }
uprobe_clear_state(struct mm_struct * mm)200d4b3b638SSrikar Dronamraju static inline void uprobe_clear_state(struct mm_struct *mm)
201d4b3b638SSrikar Dronamraju {
202d4b3b638SSrikar Dronamraju }
2030326f5a9SSrikar Dronamraju #endif /* !CONFIG_UPROBES */
2042b144498SSrikar Dronamraju #endif	/* _LINUX_UPROBES_H */
205