#include <linux/kernel.h>
#include <linux/highmem.h>
#include <linux/pagemap.h>
#include <linux/slab.h>
#include <linux/sched.h>
#include <linux/sched/mm.h>
#include <linux/sched/coredump.h>
#include <linux/export.h>
#include <linux/rmap.h>
#include <linux/mmu_notifier.h>
#include <linux/swap.h>
#include <linux/ptrace.h>
#include <linux/kdebug.h>
#include <linux/percpu-rwsem.h>
#include <linux/task_work.h>
#include <linux/shmem_fs.h>
#include <linux/khugepaged.h>
#include <linux/uprobes.h>
#define UINSNS_PER_PAGE …
#define MAX_UPROBE_XOL_SLOTS …
static struct rb_root uprobes_tree = …;
#define no_uprobe_events() …
static DEFINE_RWLOCK(uprobes_treelock);
#define UPROBES_HASH_SZ …
static struct mutex uprobes_mmap_mutex[UPROBES_HASH_SZ];
#define uprobes_mmap_hash(v) …
DEFINE_STATIC_PERCPU_RWSEM(…);
#define UPROBE_COPY_INSN …
struct uprobe { … };
struct delayed_uprobe { … };
static DEFINE_MUTEX(delayed_uprobe_lock);
static LIST_HEAD(delayed_uprobe_list);
struct xol_area { … };
static bool valid_vma(struct vm_area_struct *vma, bool is_register)
{ … }
static unsigned long offset_to_vaddr(struct vm_area_struct *vma, loff_t offset)
{ … }
static loff_t vaddr_to_offset(struct vm_area_struct *vma, unsigned long vaddr)
{ … }
static int __replace_page(struct vm_area_struct *vma, unsigned long addr,
struct page *old_page, struct page *new_page)
{ … }
bool __weak is_swbp_insn(uprobe_opcode_t *insn)
{ … }
bool __weak is_trap_insn(uprobe_opcode_t *insn)
{ … }
static void copy_from_page(struct page *page, unsigned long vaddr, void *dst, int len)
{ … }
static void copy_to_page(struct page *page, unsigned long vaddr, const void *src, int len)
{ … }
static int verify_opcode(struct page *page, unsigned long vaddr, uprobe_opcode_t *new_opcode)
{ … }
static struct delayed_uprobe *
delayed_uprobe_check(struct uprobe *uprobe, struct mm_struct *mm)
{ … }
static int delayed_uprobe_add(struct uprobe *uprobe, struct mm_struct *mm)
{ … }
static void delayed_uprobe_delete(struct delayed_uprobe *du)
{ … }
static void delayed_uprobe_remove(struct uprobe *uprobe, struct mm_struct *mm)
{ … }
static bool valid_ref_ctr_vma(struct uprobe *uprobe,
struct vm_area_struct *vma)
{ … }
static struct vm_area_struct *
find_ref_ctr_vma(struct uprobe *uprobe, struct mm_struct *mm)
{ … }
static int
__update_ref_ctr(struct mm_struct *mm, unsigned long vaddr, short d)
{ … }
static void update_ref_ctr_warn(struct uprobe *uprobe,
struct mm_struct *mm, short d)
{ … }
static int update_ref_ctr(struct uprobe *uprobe, struct mm_struct *mm,
short d)
{ … }
int uprobe_write_opcode(struct arch_uprobe *auprobe, struct mm_struct *mm,
unsigned long vaddr, uprobe_opcode_t opcode)
{ … }
int __weak set_swbp(struct arch_uprobe *auprobe, struct mm_struct *mm, unsigned long vaddr)
{ … }
int __weak
set_orig_insn(struct arch_uprobe *auprobe, struct mm_struct *mm, unsigned long vaddr)
{ … }
static struct uprobe *get_uprobe(struct uprobe *uprobe)
{ … }
static void put_uprobe(struct uprobe *uprobe)
{ … }
static __always_inline
int uprobe_cmp(const struct inode *l_inode, const loff_t l_offset,
const struct uprobe *r)
{ … }
#define __node_2_uprobe(node) …
struct __uprobe_key { … };
static inline int __uprobe_cmp_key(const void *key, const struct rb_node *b)
{ … }
static inline int __uprobe_cmp(struct rb_node *a, const struct rb_node *b)
{ … }
static struct uprobe *__find_uprobe(struct inode *inode, loff_t offset)
{ … }
static struct uprobe *find_uprobe(struct inode *inode, loff_t offset)
{ … }
static struct uprobe *__insert_uprobe(struct uprobe *uprobe)
{ … }
static struct uprobe *insert_uprobe(struct uprobe *uprobe)
{ … }
static void
ref_ctr_mismatch_warn(struct uprobe *cur_uprobe, struct uprobe *uprobe)
{ … }
static struct uprobe *alloc_uprobe(struct inode *inode, loff_t offset,
loff_t ref_ctr_offset)
{ … }
static void consumer_add(struct uprobe *uprobe, struct uprobe_consumer *uc)
{ … }
static bool consumer_del(struct uprobe *uprobe, struct uprobe_consumer *uc)
{ … }
static int __copy_insn(struct address_space *mapping, struct file *filp,
void *insn, int nbytes, loff_t offset)
{ … }
static int copy_insn(struct uprobe *uprobe, struct file *filp)
{ … }
static int prepare_uprobe(struct uprobe *uprobe, struct file *file,
struct mm_struct *mm, unsigned long vaddr)
{ … }
static inline bool consumer_filter(struct uprobe_consumer *uc,
enum uprobe_filter_ctx ctx, struct mm_struct *mm)
{ … }
static bool filter_chain(struct uprobe *uprobe,
enum uprobe_filter_ctx ctx, struct mm_struct *mm)
{ … }
static int
install_breakpoint(struct uprobe *uprobe, struct mm_struct *mm,
struct vm_area_struct *vma, unsigned long vaddr)
{ … }
static int
remove_breakpoint(struct uprobe *uprobe, struct mm_struct *mm, unsigned long vaddr)
{ … }
static inline bool uprobe_is_active(struct uprobe *uprobe)
{ … }
static void delete_uprobe(struct uprobe *uprobe)
{ … }
struct map_info { … };
static inline struct map_info *free_map_info(struct map_info *info)
{ … }
static struct map_info *
build_map_info(struct address_space *mapping, loff_t offset, bool is_register)
{ … }
static int
register_for_each_vma(struct uprobe *uprobe, struct uprobe_consumer *new)
{ … }
static void
__uprobe_unregister(struct uprobe *uprobe, struct uprobe_consumer *uc)
{ … }
void uprobe_unregister(struct inode *inode, loff_t offset, struct uprobe_consumer *uc)
{ … }
EXPORT_SYMBOL_GPL(…);
static int __uprobe_register(struct inode *inode, loff_t offset,
loff_t ref_ctr_offset, struct uprobe_consumer *uc)
{ … }
int uprobe_register(struct inode *inode, loff_t offset,
struct uprobe_consumer *uc)
{ … }
EXPORT_SYMBOL_GPL(…);
int uprobe_register_refctr(struct inode *inode, loff_t offset,
loff_t ref_ctr_offset, struct uprobe_consumer *uc)
{ … }
EXPORT_SYMBOL_GPL(…);
int uprobe_apply(struct inode *inode, loff_t offset,
struct uprobe_consumer *uc, bool add)
{ … }
static int unapply_uprobe(struct uprobe *uprobe, struct mm_struct *mm)
{ … }
static struct rb_node *
find_node_in_range(struct inode *inode, loff_t min, loff_t max)
{ … }
static void build_probe_list(struct inode *inode,
struct vm_area_struct *vma,
unsigned long start, unsigned long end,
struct list_head *head)
{ … }
static int delayed_ref_ctr_inc(struct vm_area_struct *vma)
{ … }
int uprobe_mmap(struct vm_area_struct *vma)
{ … }
static bool
vma_has_uprobes(struct vm_area_struct *vma, unsigned long start, unsigned long end)
{ … }
void uprobe_munmap(struct vm_area_struct *vma, unsigned long start, unsigned long end)
{ … }
static int xol_add_vma(struct mm_struct *mm, struct xol_area *area)
{ … }
void * __weak arch_uprobe_trampoline(unsigned long *psize)
{ … }
static struct xol_area *__create_xol_area(unsigned long vaddr)
{ … }
static struct xol_area *get_xol_area(void)
{ … }
void uprobe_clear_state(struct mm_struct *mm)
{ … }
void uprobe_start_dup_mmap(void)
{ … }
void uprobe_end_dup_mmap(void)
{ … }
void uprobe_dup_mmap(struct mm_struct *oldmm, struct mm_struct *newmm)
{ … }
static unsigned long xol_take_insn_slot(struct xol_area *area)
{ … }
static unsigned long xol_get_insn_slot(struct uprobe *uprobe)
{ … }
static void xol_free_insn_slot(struct task_struct *tsk)
{ … }
void __weak arch_uprobe_copy_ixol(struct page *page, unsigned long vaddr,
void *src, unsigned long len)
{ … }
unsigned long __weak uprobe_get_swbp_addr(struct pt_regs *regs)
{ … }
unsigned long uprobe_get_trap_addr(struct pt_regs *regs)
{ … }
static struct return_instance *free_ret_instance(struct return_instance *ri)
{ … }
void uprobe_free_utask(struct task_struct *t)
{ … }
static struct uprobe_task *get_utask(void)
{ … }
static int dup_utask(struct task_struct *t, struct uprobe_task *o_utask)
{ … }
static void uprobe_warn(struct task_struct *t, const char *msg)
{ … }
static void dup_xol_work(struct callback_head *work)
{ … }
void uprobe_copy_process(struct task_struct *t, unsigned long flags)
{ … }
unsigned long uprobe_get_trampoline_vaddr(void)
{ … }
static void cleanup_return_instances(struct uprobe_task *utask, bool chained,
struct pt_regs *regs)
{ … }
static void prepare_uretprobe(struct uprobe *uprobe, struct pt_regs *regs)
{ … }
static int
pre_ssout(struct uprobe *uprobe, struct pt_regs *regs, unsigned long bp_vaddr)
{ … }
bool uprobe_deny_signal(void)
{ … }
static void mmf_recalc_uprobes(struct mm_struct *mm)
{ … }
static int is_trap_at_addr(struct mm_struct *mm, unsigned long vaddr)
{ … }
static struct uprobe *find_active_uprobe(unsigned long bp_vaddr, int *is_swbp)
{ … }
static void handler_chain(struct uprobe *uprobe, struct pt_regs *regs)
{ … }
static void
handle_uretprobe_chain(struct return_instance *ri, struct pt_regs *regs)
{ … }
static struct return_instance *find_next_ret_chain(struct return_instance *ri)
{ … }
void uprobe_handle_trampoline(struct pt_regs *regs)
{ … }
bool __weak arch_uprobe_ignore(struct arch_uprobe *aup, struct pt_regs *regs)
{ … }
bool __weak arch_uretprobe_is_alive(struct return_instance *ret, enum rp_check ctx,
struct pt_regs *regs)
{ … }
static void handle_swbp(struct pt_regs *regs)
{ … }
static void handle_singlestep(struct uprobe_task *utask, struct pt_regs *regs)
{ … }
void uprobe_notify_resume(struct pt_regs *regs)
{ … }
int uprobe_pre_sstep_notifier(struct pt_regs *regs)
{ … }
int uprobe_post_sstep_notifier(struct pt_regs *regs)
{ … }
static struct notifier_block uprobe_exception_nb = …;
void __init uprobes_init(void)
{ … }