11da177e4SLinus Torvalds /* 21da177e4SLinus Torvalds * Kernel Probes (KProbes) 31da177e4SLinus Torvalds * kernel/kprobes.c 41da177e4SLinus Torvalds * 51da177e4SLinus Torvalds * This program is free software; you can redistribute it and/or modify 61da177e4SLinus Torvalds * it under the terms of the GNU General Public License as published by 71da177e4SLinus Torvalds * the Free Software Foundation; either version 2 of the License, or 81da177e4SLinus Torvalds * (at your option) any later version. 91da177e4SLinus Torvalds * 101da177e4SLinus Torvalds * This program is distributed in the hope that it will be useful, 111da177e4SLinus Torvalds * but WITHOUT ANY WARRANTY; without even the implied warranty of 121da177e4SLinus Torvalds * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 131da177e4SLinus Torvalds * GNU General Public License for more details. 141da177e4SLinus Torvalds * 151da177e4SLinus Torvalds * You should have received a copy of the GNU General Public License 161da177e4SLinus Torvalds * along with this program; if not, write to the Free Software 171da177e4SLinus Torvalds * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 181da177e4SLinus Torvalds * 191da177e4SLinus Torvalds * Copyright (C) IBM Corporation, 2002, 2004 201da177e4SLinus Torvalds * 211da177e4SLinus Torvalds * 2002-Oct Created by Vamsi Krishna S <vamsi_krishna@in.ibm.com> Kernel 221da177e4SLinus Torvalds * Probes initial implementation (includes suggestions from 231da177e4SLinus Torvalds * Rusty Russell). 241da177e4SLinus Torvalds * 2004-Aug Updated by Prasanna S Panchamukhi <prasanna@in.ibm.com> with 251da177e4SLinus Torvalds * hlists and exceptions notifier as suggested by Andi Kleen. 261da177e4SLinus Torvalds * 2004-July Suparna Bhattacharya <suparna@in.ibm.com> added jumper probes 271da177e4SLinus Torvalds * interface to access function arguments. 281da177e4SLinus Torvalds * 2004-Sep Prasanna S Panchamukhi <prasanna@in.ibm.com> Changed Kprobes 291da177e4SLinus Torvalds * exceptions notifier to be first on the priority list. 30b94cce92SHien Nguyen * 2005-May Hien Nguyen <hien@us.ibm.com>, Jim Keniston 31b94cce92SHien Nguyen * <jkenisto@us.ibm.com> and Prasanna S Panchamukhi 32b94cce92SHien Nguyen * <prasanna@in.ibm.com> added function-return probes. 331da177e4SLinus Torvalds */ 341da177e4SLinus Torvalds #include <linux/kprobes.h> 351da177e4SLinus Torvalds #include <linux/hash.h> 361da177e4SLinus Torvalds #include <linux/init.h> 374e57b681STim Schmielau #include <linux/slab.h> 38e3869792SRandy Dunlap #include <linux/stddef.h> 391da177e4SLinus Torvalds #include <linux/module.h> 409ec4b1f3SAnanth N Mavinakayanahalli #include <linux/moduleloader.h> 413a872d89SAnanth N Mavinakayanahalli #include <linux/kallsyms.h> 42b4c6c34aSMasami Hiramatsu #include <linux/freezer.h> 43346fd59bSSrinivasa Ds #include <linux/seq_file.h> 44346fd59bSSrinivasa Ds #include <linux/debugfs.h> 451eeb66a1SChristoph Hellwig #include <linux/kdebug.h> 46bf8f6e5bSAnanth N Mavinakayanahalli 47d0aaff97SPrasanna S Panchamukhi #include <asm-generic/sections.h> 481da177e4SLinus Torvalds #include <asm/cacheflush.h> 491da177e4SLinus Torvalds #include <asm/errno.h> 50bf8f6e5bSAnanth N Mavinakayanahalli #include <asm/uaccess.h> 511da177e4SLinus Torvalds 521da177e4SLinus Torvalds #define KPROBE_HASH_BITS 6 531da177e4SLinus Torvalds #define KPROBE_TABLE_SIZE (1 << KPROBE_HASH_BITS) 541da177e4SLinus Torvalds 553a872d89SAnanth N Mavinakayanahalli 563a872d89SAnanth N Mavinakayanahalli /* 573a872d89SAnanth N Mavinakayanahalli * Some oddball architectures like 64bit powerpc have function descriptors 583a872d89SAnanth N Mavinakayanahalli * so this must be overridable. 593a872d89SAnanth N Mavinakayanahalli */ 603a872d89SAnanth N Mavinakayanahalli #ifndef kprobe_lookup_name 613a872d89SAnanth N Mavinakayanahalli #define kprobe_lookup_name(name, addr) \ 623a872d89SAnanth N Mavinakayanahalli addr = ((kprobe_opcode_t *)(kallsyms_lookup_name(name))) 633a872d89SAnanth N Mavinakayanahalli #endif 643a872d89SAnanth N Mavinakayanahalli 651da177e4SLinus Torvalds static struct hlist_head kprobe_table[KPROBE_TABLE_SIZE]; 66b94cce92SHien Nguyen static struct hlist_head kretprobe_inst_table[KPROBE_TABLE_SIZE]; 671da177e4SLinus Torvalds 68bf8f6e5bSAnanth N Mavinakayanahalli /* NOTE: change this value only with kprobe_mutex held */ 69bf8f6e5bSAnanth N Mavinakayanahalli static bool kprobe_enabled; 70bf8f6e5bSAnanth N Mavinakayanahalli 717a7d1cf9SIngo Molnar DEFINE_MUTEX(kprobe_mutex); /* Protects kprobe_table */ 723516a460SAnanth N Mavinakayanahalli DEFINE_SPINLOCK(kretprobe_lock); /* Protects kretprobe_inst_table */ 73e6584523SAnanth N Mavinakayanahalli static DEFINE_PER_CPU(struct kprobe *, kprobe_instance) = NULL; 741da177e4SLinus Torvalds 753d8d996eSSrinivasa Ds /* 763d8d996eSSrinivasa Ds * Normally, functions that we'd want to prohibit kprobes in, are marked 773d8d996eSSrinivasa Ds * __kprobes. But, there are cases where such functions already belong to 783d8d996eSSrinivasa Ds * a different section (__sched for preempt_schedule) 793d8d996eSSrinivasa Ds * 803d8d996eSSrinivasa Ds * For such cases, we now have a blacklist 813d8d996eSSrinivasa Ds */ 823d8d996eSSrinivasa Ds struct kprobe_blackpoint kprobe_blacklist[] = { 833d8d996eSSrinivasa Ds {"preempt_schedule",}, 843d8d996eSSrinivasa Ds {NULL} /* Terminator */ 853d8d996eSSrinivasa Ds }; 863d8d996eSSrinivasa Ds 872d14e39dSAnil S Keshavamurthy #ifdef __ARCH_WANT_KPROBES_INSN_SLOT 889ec4b1f3SAnanth N Mavinakayanahalli /* 899ec4b1f3SAnanth N Mavinakayanahalli * kprobe->ainsn.insn points to the copy of the instruction to be 909ec4b1f3SAnanth N Mavinakayanahalli * single-stepped. x86_64, POWER4 and above have no-exec support and 919ec4b1f3SAnanth N Mavinakayanahalli * stepping on the instruction on a vmalloced/kmalloced/data page 929ec4b1f3SAnanth N Mavinakayanahalli * is a recipe for disaster 939ec4b1f3SAnanth N Mavinakayanahalli */ 949ec4b1f3SAnanth N Mavinakayanahalli #define INSNS_PER_PAGE (PAGE_SIZE/(MAX_INSN_SIZE * sizeof(kprobe_opcode_t))) 959ec4b1f3SAnanth N Mavinakayanahalli 969ec4b1f3SAnanth N Mavinakayanahalli struct kprobe_insn_page { 979ec4b1f3SAnanth N Mavinakayanahalli struct hlist_node hlist; 989ec4b1f3SAnanth N Mavinakayanahalli kprobe_opcode_t *insns; /* Page of instruction slots */ 999ec4b1f3SAnanth N Mavinakayanahalli char slot_used[INSNS_PER_PAGE]; 1009ec4b1f3SAnanth N Mavinakayanahalli int nused; 101b4c6c34aSMasami Hiramatsu int ngarbage; 1029ec4b1f3SAnanth N Mavinakayanahalli }; 1039ec4b1f3SAnanth N Mavinakayanahalli 104ab40c5c6SMasami Hiramatsu enum kprobe_slot_state { 105ab40c5c6SMasami Hiramatsu SLOT_CLEAN = 0, 106ab40c5c6SMasami Hiramatsu SLOT_DIRTY = 1, 107ab40c5c6SMasami Hiramatsu SLOT_USED = 2, 108ab40c5c6SMasami Hiramatsu }; 109ab40c5c6SMasami Hiramatsu 1109ec4b1f3SAnanth N Mavinakayanahalli static struct hlist_head kprobe_insn_pages; 111b4c6c34aSMasami Hiramatsu static int kprobe_garbage_slots; 112b4c6c34aSMasami Hiramatsu static int collect_garbage_slots(void); 113b4c6c34aSMasami Hiramatsu 114b4c6c34aSMasami Hiramatsu static int __kprobes check_safety(void) 115b4c6c34aSMasami Hiramatsu { 116b4c6c34aSMasami Hiramatsu int ret = 0; 117b4c6c34aSMasami Hiramatsu #if defined(CONFIG_PREEMPT) && defined(CONFIG_PM) 118b4c6c34aSMasami Hiramatsu ret = freeze_processes(); 119b4c6c34aSMasami Hiramatsu if (ret == 0) { 120b4c6c34aSMasami Hiramatsu struct task_struct *p, *q; 121b4c6c34aSMasami Hiramatsu do_each_thread(p, q) { 122b4c6c34aSMasami Hiramatsu if (p != current && p->state == TASK_RUNNING && 123b4c6c34aSMasami Hiramatsu p->pid != 0) { 124b4c6c34aSMasami Hiramatsu printk("Check failed: %s is running\n",p->comm); 125b4c6c34aSMasami Hiramatsu ret = -1; 126b4c6c34aSMasami Hiramatsu goto loop_end; 127b4c6c34aSMasami Hiramatsu } 128b4c6c34aSMasami Hiramatsu } while_each_thread(p, q); 129b4c6c34aSMasami Hiramatsu } 130b4c6c34aSMasami Hiramatsu loop_end: 131b4c6c34aSMasami Hiramatsu thaw_processes(); 132b4c6c34aSMasami Hiramatsu #else 133b4c6c34aSMasami Hiramatsu synchronize_sched(); 134b4c6c34aSMasami Hiramatsu #endif 135b4c6c34aSMasami Hiramatsu return ret; 136b4c6c34aSMasami Hiramatsu } 1379ec4b1f3SAnanth N Mavinakayanahalli 1389ec4b1f3SAnanth N Mavinakayanahalli /** 1399ec4b1f3SAnanth N Mavinakayanahalli * get_insn_slot() - Find a slot on an executable page for an instruction. 1409ec4b1f3SAnanth N Mavinakayanahalli * We allocate an executable page if there's no room on existing ones. 1419ec4b1f3SAnanth N Mavinakayanahalli */ 142d0aaff97SPrasanna S Panchamukhi kprobe_opcode_t __kprobes *get_insn_slot(void) 1439ec4b1f3SAnanth N Mavinakayanahalli { 1449ec4b1f3SAnanth N Mavinakayanahalli struct kprobe_insn_page *kip; 1459ec4b1f3SAnanth N Mavinakayanahalli struct hlist_node *pos; 1469ec4b1f3SAnanth N Mavinakayanahalli 147b4c6c34aSMasami Hiramatsu retry: 148b0bb5016SChristoph Hellwig hlist_for_each_entry(kip, pos, &kprobe_insn_pages, hlist) { 1499ec4b1f3SAnanth N Mavinakayanahalli if (kip->nused < INSNS_PER_PAGE) { 1509ec4b1f3SAnanth N Mavinakayanahalli int i; 1519ec4b1f3SAnanth N Mavinakayanahalli for (i = 0; i < INSNS_PER_PAGE; i++) { 152ab40c5c6SMasami Hiramatsu if (kip->slot_used[i] == SLOT_CLEAN) { 153ab40c5c6SMasami Hiramatsu kip->slot_used[i] = SLOT_USED; 1549ec4b1f3SAnanth N Mavinakayanahalli kip->nused++; 1559ec4b1f3SAnanth N Mavinakayanahalli return kip->insns + (i * MAX_INSN_SIZE); 1569ec4b1f3SAnanth N Mavinakayanahalli } 1579ec4b1f3SAnanth N Mavinakayanahalli } 1589ec4b1f3SAnanth N Mavinakayanahalli /* Surprise! No unused slots. Fix kip->nused. */ 1599ec4b1f3SAnanth N Mavinakayanahalli kip->nused = INSNS_PER_PAGE; 1609ec4b1f3SAnanth N Mavinakayanahalli } 1619ec4b1f3SAnanth N Mavinakayanahalli } 1629ec4b1f3SAnanth N Mavinakayanahalli 163b4c6c34aSMasami Hiramatsu /* If there are any garbage slots, collect it and try again. */ 164b4c6c34aSMasami Hiramatsu if (kprobe_garbage_slots && collect_garbage_slots() == 0) { 165b4c6c34aSMasami Hiramatsu goto retry; 166b4c6c34aSMasami Hiramatsu } 1679ec4b1f3SAnanth N Mavinakayanahalli /* All out of space. Need to allocate a new page. Use slot 0. */ 1689ec4b1f3SAnanth N Mavinakayanahalli kip = kmalloc(sizeof(struct kprobe_insn_page), GFP_KERNEL); 1696f716acdSChristoph Hellwig if (!kip) 1709ec4b1f3SAnanth N Mavinakayanahalli return NULL; 1719ec4b1f3SAnanth N Mavinakayanahalli 1729ec4b1f3SAnanth N Mavinakayanahalli /* 1739ec4b1f3SAnanth N Mavinakayanahalli * Use module_alloc so this page is within +/- 2GB of where the 1749ec4b1f3SAnanth N Mavinakayanahalli * kernel image and loaded module images reside. This is required 1759ec4b1f3SAnanth N Mavinakayanahalli * so x86_64 can correctly handle the %rip-relative fixups. 1769ec4b1f3SAnanth N Mavinakayanahalli */ 1779ec4b1f3SAnanth N Mavinakayanahalli kip->insns = module_alloc(PAGE_SIZE); 1789ec4b1f3SAnanth N Mavinakayanahalli if (!kip->insns) { 1799ec4b1f3SAnanth N Mavinakayanahalli kfree(kip); 1809ec4b1f3SAnanth N Mavinakayanahalli return NULL; 1819ec4b1f3SAnanth N Mavinakayanahalli } 1829ec4b1f3SAnanth N Mavinakayanahalli INIT_HLIST_NODE(&kip->hlist); 1839ec4b1f3SAnanth N Mavinakayanahalli hlist_add_head(&kip->hlist, &kprobe_insn_pages); 184ab40c5c6SMasami Hiramatsu memset(kip->slot_used, SLOT_CLEAN, INSNS_PER_PAGE); 185ab40c5c6SMasami Hiramatsu kip->slot_used[0] = SLOT_USED; 1869ec4b1f3SAnanth N Mavinakayanahalli kip->nused = 1; 187b4c6c34aSMasami Hiramatsu kip->ngarbage = 0; 1889ec4b1f3SAnanth N Mavinakayanahalli return kip->insns; 1899ec4b1f3SAnanth N Mavinakayanahalli } 1909ec4b1f3SAnanth N Mavinakayanahalli 191b4c6c34aSMasami Hiramatsu /* Return 1 if all garbages are collected, otherwise 0. */ 192b4c6c34aSMasami Hiramatsu static int __kprobes collect_one_slot(struct kprobe_insn_page *kip, int idx) 1939ec4b1f3SAnanth N Mavinakayanahalli { 194ab40c5c6SMasami Hiramatsu kip->slot_used[idx] = SLOT_CLEAN; 1959ec4b1f3SAnanth N Mavinakayanahalli kip->nused--; 1969ec4b1f3SAnanth N Mavinakayanahalli if (kip->nused == 0) { 1979ec4b1f3SAnanth N Mavinakayanahalli /* 1989ec4b1f3SAnanth N Mavinakayanahalli * Page is no longer in use. Free it unless 1999ec4b1f3SAnanth N Mavinakayanahalli * it's the last one. We keep the last one 2009ec4b1f3SAnanth N Mavinakayanahalli * so as not to have to set it up again the 2019ec4b1f3SAnanth N Mavinakayanahalli * next time somebody inserts a probe. 2029ec4b1f3SAnanth N Mavinakayanahalli */ 2039ec4b1f3SAnanth N Mavinakayanahalli hlist_del(&kip->hlist); 2049ec4b1f3SAnanth N Mavinakayanahalli if (hlist_empty(&kprobe_insn_pages)) { 2059ec4b1f3SAnanth N Mavinakayanahalli INIT_HLIST_NODE(&kip->hlist); 2069ec4b1f3SAnanth N Mavinakayanahalli hlist_add_head(&kip->hlist, 2079ec4b1f3SAnanth N Mavinakayanahalli &kprobe_insn_pages); 2089ec4b1f3SAnanth N Mavinakayanahalli } else { 2099ec4b1f3SAnanth N Mavinakayanahalli module_free(NULL, kip->insns); 2109ec4b1f3SAnanth N Mavinakayanahalli kfree(kip); 2119ec4b1f3SAnanth N Mavinakayanahalli } 212b4c6c34aSMasami Hiramatsu return 1; 2139ec4b1f3SAnanth N Mavinakayanahalli } 214b4c6c34aSMasami Hiramatsu return 0; 2159ec4b1f3SAnanth N Mavinakayanahalli } 216b4c6c34aSMasami Hiramatsu 217b4c6c34aSMasami Hiramatsu static int __kprobes collect_garbage_slots(void) 218b4c6c34aSMasami Hiramatsu { 219b4c6c34aSMasami Hiramatsu struct kprobe_insn_page *kip; 220b4c6c34aSMasami Hiramatsu struct hlist_node *pos, *next; 221b4c6c34aSMasami Hiramatsu 222b4c6c34aSMasami Hiramatsu /* Ensure no-one is preepmted on the garbages */ 223b4c6c34aSMasami Hiramatsu if (check_safety() != 0) 224b4c6c34aSMasami Hiramatsu return -EAGAIN; 225b4c6c34aSMasami Hiramatsu 226b0bb5016SChristoph Hellwig hlist_for_each_entry_safe(kip, pos, next, &kprobe_insn_pages, hlist) { 227b4c6c34aSMasami Hiramatsu int i; 228b4c6c34aSMasami Hiramatsu if (kip->ngarbage == 0) 229b4c6c34aSMasami Hiramatsu continue; 230b4c6c34aSMasami Hiramatsu kip->ngarbage = 0; /* we will collect all garbages */ 231b4c6c34aSMasami Hiramatsu for (i = 0; i < INSNS_PER_PAGE; i++) { 232ab40c5c6SMasami Hiramatsu if (kip->slot_used[i] == SLOT_DIRTY && 233b4c6c34aSMasami Hiramatsu collect_one_slot(kip, i)) 234b4c6c34aSMasami Hiramatsu break; 235b4c6c34aSMasami Hiramatsu } 236b4c6c34aSMasami Hiramatsu } 237b4c6c34aSMasami Hiramatsu kprobe_garbage_slots = 0; 238b4c6c34aSMasami Hiramatsu return 0; 239b4c6c34aSMasami Hiramatsu } 240b4c6c34aSMasami Hiramatsu 241b4c6c34aSMasami Hiramatsu void __kprobes free_insn_slot(kprobe_opcode_t * slot, int dirty) 242b4c6c34aSMasami Hiramatsu { 243b4c6c34aSMasami Hiramatsu struct kprobe_insn_page *kip; 244b4c6c34aSMasami Hiramatsu struct hlist_node *pos; 245b4c6c34aSMasami Hiramatsu 246b0bb5016SChristoph Hellwig hlist_for_each_entry(kip, pos, &kprobe_insn_pages, hlist) { 247b4c6c34aSMasami Hiramatsu if (kip->insns <= slot && 248b4c6c34aSMasami Hiramatsu slot < kip->insns + (INSNS_PER_PAGE * MAX_INSN_SIZE)) { 249b4c6c34aSMasami Hiramatsu int i = (slot - kip->insns) / MAX_INSN_SIZE; 250b4c6c34aSMasami Hiramatsu if (dirty) { 251ab40c5c6SMasami Hiramatsu kip->slot_used[i] = SLOT_DIRTY; 252b4c6c34aSMasami Hiramatsu kip->ngarbage++; 253b4c6c34aSMasami Hiramatsu } else { 254b4c6c34aSMasami Hiramatsu collect_one_slot(kip, i); 255b4c6c34aSMasami Hiramatsu } 256b4c6c34aSMasami Hiramatsu break; 257b4c6c34aSMasami Hiramatsu } 258b4c6c34aSMasami Hiramatsu } 2596f716acdSChristoph Hellwig 2606f716acdSChristoph Hellwig if (dirty && ++kprobe_garbage_slots > INSNS_PER_PAGE) 261b4c6c34aSMasami Hiramatsu collect_garbage_slots(); 2629ec4b1f3SAnanth N Mavinakayanahalli } 2632d14e39dSAnil S Keshavamurthy #endif 2649ec4b1f3SAnanth N Mavinakayanahalli 265e6584523SAnanth N Mavinakayanahalli /* We have preemption disabled.. so it is safe to use __ versions */ 266e6584523SAnanth N Mavinakayanahalli static inline void set_kprobe_instance(struct kprobe *kp) 267e6584523SAnanth N Mavinakayanahalli { 268e6584523SAnanth N Mavinakayanahalli __get_cpu_var(kprobe_instance) = kp; 269e6584523SAnanth N Mavinakayanahalli } 270e6584523SAnanth N Mavinakayanahalli 271e6584523SAnanth N Mavinakayanahalli static inline void reset_kprobe_instance(void) 272e6584523SAnanth N Mavinakayanahalli { 273e6584523SAnanth N Mavinakayanahalli __get_cpu_var(kprobe_instance) = NULL; 274e6584523SAnanth N Mavinakayanahalli } 275e6584523SAnanth N Mavinakayanahalli 2763516a460SAnanth N Mavinakayanahalli /* 2773516a460SAnanth N Mavinakayanahalli * This routine is called either: 27849a2a1b8SAnil S Keshavamurthy * - under the kprobe_mutex - during kprobe_[un]register() 2793516a460SAnanth N Mavinakayanahalli * OR 280d217d545SAnanth N Mavinakayanahalli * - with preemption disabled - from arch/xxx/kernel/kprobes.c 2813516a460SAnanth N Mavinakayanahalli */ 282d0aaff97SPrasanna S Panchamukhi struct kprobe __kprobes *get_kprobe(void *addr) 2831da177e4SLinus Torvalds { 2841da177e4SLinus Torvalds struct hlist_head *head; 2851da177e4SLinus Torvalds struct hlist_node *node; 2863516a460SAnanth N Mavinakayanahalli struct kprobe *p; 2871da177e4SLinus Torvalds 2881da177e4SLinus Torvalds head = &kprobe_table[hash_ptr(addr, KPROBE_HASH_BITS)]; 2893516a460SAnanth N Mavinakayanahalli hlist_for_each_entry_rcu(p, node, head, hlist) { 2901da177e4SLinus Torvalds if (p->addr == addr) 2911da177e4SLinus Torvalds return p; 2921da177e4SLinus Torvalds } 2931da177e4SLinus Torvalds return NULL; 2941da177e4SLinus Torvalds } 2951da177e4SLinus Torvalds 29664f562c6SAnanth N Mavinakayanahalli /* 29764f562c6SAnanth N Mavinakayanahalli * Aggregate handlers for multiple kprobes support - these handlers 29864f562c6SAnanth N Mavinakayanahalli * take care of invoking the individual kprobe handlers on p->list 29964f562c6SAnanth N Mavinakayanahalli */ 300d0aaff97SPrasanna S Panchamukhi static int __kprobes aggr_pre_handler(struct kprobe *p, struct pt_regs *regs) 30164f562c6SAnanth N Mavinakayanahalli { 30264f562c6SAnanth N Mavinakayanahalli struct kprobe *kp; 30364f562c6SAnanth N Mavinakayanahalli 3043516a460SAnanth N Mavinakayanahalli list_for_each_entry_rcu(kp, &p->list, list) { 30564f562c6SAnanth N Mavinakayanahalli if (kp->pre_handler) { 306e6584523SAnanth N Mavinakayanahalli set_kprobe_instance(kp); 3078b0914eaSPrasanna S Panchamukhi if (kp->pre_handler(kp, regs)) 3088b0914eaSPrasanna S Panchamukhi return 1; 30964f562c6SAnanth N Mavinakayanahalli } 310e6584523SAnanth N Mavinakayanahalli reset_kprobe_instance(); 31164f562c6SAnanth N Mavinakayanahalli } 31264f562c6SAnanth N Mavinakayanahalli return 0; 31364f562c6SAnanth N Mavinakayanahalli } 31464f562c6SAnanth N Mavinakayanahalli 315d0aaff97SPrasanna S Panchamukhi static void __kprobes aggr_post_handler(struct kprobe *p, struct pt_regs *regs, 31664f562c6SAnanth N Mavinakayanahalli unsigned long flags) 31764f562c6SAnanth N Mavinakayanahalli { 31864f562c6SAnanth N Mavinakayanahalli struct kprobe *kp; 31964f562c6SAnanth N Mavinakayanahalli 3203516a460SAnanth N Mavinakayanahalli list_for_each_entry_rcu(kp, &p->list, list) { 32164f562c6SAnanth N Mavinakayanahalli if (kp->post_handler) { 322e6584523SAnanth N Mavinakayanahalli set_kprobe_instance(kp); 32364f562c6SAnanth N Mavinakayanahalli kp->post_handler(kp, regs, flags); 324e6584523SAnanth N Mavinakayanahalli reset_kprobe_instance(); 32564f562c6SAnanth N Mavinakayanahalli } 32664f562c6SAnanth N Mavinakayanahalli } 32764f562c6SAnanth N Mavinakayanahalli } 32864f562c6SAnanth N Mavinakayanahalli 329d0aaff97SPrasanna S Panchamukhi static int __kprobes aggr_fault_handler(struct kprobe *p, struct pt_regs *regs, 330b94cce92SHien Nguyen int trapnr) 33164f562c6SAnanth N Mavinakayanahalli { 332e6584523SAnanth N Mavinakayanahalli struct kprobe *cur = __get_cpu_var(kprobe_instance); 333e6584523SAnanth N Mavinakayanahalli 33464f562c6SAnanth N Mavinakayanahalli /* 33564f562c6SAnanth N Mavinakayanahalli * if we faulted "during" the execution of a user specified 33664f562c6SAnanth N Mavinakayanahalli * probe handler, invoke just that probe's fault handler 33764f562c6SAnanth N Mavinakayanahalli */ 338e6584523SAnanth N Mavinakayanahalli if (cur && cur->fault_handler) { 339e6584523SAnanth N Mavinakayanahalli if (cur->fault_handler(cur, regs, trapnr)) 34064f562c6SAnanth N Mavinakayanahalli return 1; 34164f562c6SAnanth N Mavinakayanahalli } 34264f562c6SAnanth N Mavinakayanahalli return 0; 34364f562c6SAnanth N Mavinakayanahalli } 34464f562c6SAnanth N Mavinakayanahalli 345d0aaff97SPrasanna S Panchamukhi static int __kprobes aggr_break_handler(struct kprobe *p, struct pt_regs *regs) 3468b0914eaSPrasanna S Panchamukhi { 347e6584523SAnanth N Mavinakayanahalli struct kprobe *cur = __get_cpu_var(kprobe_instance); 348e6584523SAnanth N Mavinakayanahalli int ret = 0; 349e6584523SAnanth N Mavinakayanahalli 350e6584523SAnanth N Mavinakayanahalli if (cur && cur->break_handler) { 351e6584523SAnanth N Mavinakayanahalli if (cur->break_handler(cur, regs)) 352e6584523SAnanth N Mavinakayanahalli ret = 1; 3538b0914eaSPrasanna S Panchamukhi } 354e6584523SAnanth N Mavinakayanahalli reset_kprobe_instance(); 355e6584523SAnanth N Mavinakayanahalli return ret; 3568b0914eaSPrasanna S Panchamukhi } 3578b0914eaSPrasanna S Panchamukhi 358bf8d5c52SKeshavamurthy Anil S /* Walks the list and increments nmissed count for multiprobe case */ 359bf8d5c52SKeshavamurthy Anil S void __kprobes kprobes_inc_nmissed_count(struct kprobe *p) 360bf8d5c52SKeshavamurthy Anil S { 361bf8d5c52SKeshavamurthy Anil S struct kprobe *kp; 362bf8d5c52SKeshavamurthy Anil S if (p->pre_handler != aggr_pre_handler) { 363bf8d5c52SKeshavamurthy Anil S p->nmissed++; 364bf8d5c52SKeshavamurthy Anil S } else { 365bf8d5c52SKeshavamurthy Anil S list_for_each_entry_rcu(kp, &p->list, list) 366bf8d5c52SKeshavamurthy Anil S kp->nmissed++; 367bf8d5c52SKeshavamurthy Anil S } 368bf8d5c52SKeshavamurthy Anil S return; 369bf8d5c52SKeshavamurthy Anil S } 370bf8d5c52SKeshavamurthy Anil S 3713516a460SAnanth N Mavinakayanahalli /* Called with kretprobe_lock held */ 37299219a3fSbibo,mao void __kprobes recycle_rp_inst(struct kretprobe_instance *ri, 37399219a3fSbibo,mao struct hlist_head *head) 374b94cce92SHien Nguyen { 375b94cce92SHien Nguyen /* remove rp inst off the rprobe_inst_table */ 376b94cce92SHien Nguyen hlist_del(&ri->hlist); 377b94cce92SHien Nguyen if (ri->rp) { 378b94cce92SHien Nguyen /* remove rp inst off the used list */ 379b94cce92SHien Nguyen hlist_del(&ri->uflist); 380b94cce92SHien Nguyen /* put rp inst back onto the free list */ 381b94cce92SHien Nguyen INIT_HLIST_NODE(&ri->uflist); 382b94cce92SHien Nguyen hlist_add_head(&ri->uflist, &ri->rp->free_instances); 383b94cce92SHien Nguyen } else 384b94cce92SHien Nguyen /* Unregistering */ 38599219a3fSbibo,mao hlist_add_head(&ri->hlist, head); 386b94cce92SHien Nguyen } 387b94cce92SHien Nguyen 388d0aaff97SPrasanna S Panchamukhi struct hlist_head __kprobes *kretprobe_inst_table_head(struct task_struct *tsk) 389b94cce92SHien Nguyen { 390b94cce92SHien Nguyen return &kretprobe_inst_table[hash_ptr(tsk, KPROBE_HASH_BITS)]; 391b94cce92SHien Nguyen } 392b94cce92SHien Nguyen 393b94cce92SHien Nguyen /* 394c6fd91f0Sbibo mao * This function is called from finish_task_switch when task tk becomes dead, 395c6fd91f0Sbibo mao * so that we can recycle any function-return probe instances associated 396c6fd91f0Sbibo mao * with this task. These left over instances represent probed functions 397c6fd91f0Sbibo mao * that have been called but will never return. 398b94cce92SHien Nguyen */ 399d0aaff97SPrasanna S Panchamukhi void __kprobes kprobe_flush_task(struct task_struct *tk) 400b94cce92SHien Nguyen { 401802eae7cSRusty Lynch struct kretprobe_instance *ri; 40299219a3fSbibo,mao struct hlist_head *head, empty_rp; 403802eae7cSRusty Lynch struct hlist_node *node, *tmp; 4040aa55e4dSHien Nguyen unsigned long flags = 0; 405802eae7cSRusty Lynch 40699219a3fSbibo,mao INIT_HLIST_HEAD(&empty_rp); 4073516a460SAnanth N Mavinakayanahalli spin_lock_irqsave(&kretprobe_lock, flags); 408c6fd91f0Sbibo mao head = kretprobe_inst_table_head(tk); 409802eae7cSRusty Lynch hlist_for_each_entry_safe(ri, node, tmp, head, hlist) { 410802eae7cSRusty Lynch if (ri->task == tk) 41199219a3fSbibo,mao recycle_rp_inst(ri, &empty_rp); 412802eae7cSRusty Lynch } 4133516a460SAnanth N Mavinakayanahalli spin_unlock_irqrestore(&kretprobe_lock, flags); 41499219a3fSbibo,mao 41599219a3fSbibo,mao hlist_for_each_entry_safe(ri, node, tmp, &empty_rp, hlist) { 41699219a3fSbibo,mao hlist_del(&ri->hlist); 41799219a3fSbibo,mao kfree(ri); 41899219a3fSbibo,mao } 419b94cce92SHien Nguyen } 420b94cce92SHien Nguyen 421b94cce92SHien Nguyen static inline void free_rp_inst(struct kretprobe *rp) 422b94cce92SHien Nguyen { 423b94cce92SHien Nguyen struct kretprobe_instance *ri; 4244c4308cbSChristoph Hellwig struct hlist_node *pos, *next; 4254c4308cbSChristoph Hellwig 4264c4308cbSChristoph Hellwig hlist_for_each_entry_safe(ri, pos, next, &rp->free_instances, uflist) { 427b94cce92SHien Nguyen hlist_del(&ri->uflist); 428b94cce92SHien Nguyen kfree(ri); 429b94cce92SHien Nguyen } 430b94cce92SHien Nguyen } 431b94cce92SHien Nguyen 432*4a296e07SMasami Hiramatsu static void __kprobes cleanup_rp_inst(struct kretprobe *rp) 433*4a296e07SMasami Hiramatsu { 434*4a296e07SMasami Hiramatsu unsigned long flags; 435*4a296e07SMasami Hiramatsu struct kretprobe_instance *ri; 436*4a296e07SMasami Hiramatsu struct hlist_node *pos, *next; 437*4a296e07SMasami Hiramatsu /* No race here */ 438*4a296e07SMasami Hiramatsu spin_lock_irqsave(&kretprobe_lock, flags); 439*4a296e07SMasami Hiramatsu hlist_for_each_entry_safe(ri, pos, next, &rp->used_instances, uflist) { 440*4a296e07SMasami Hiramatsu ri->rp = NULL; 441*4a296e07SMasami Hiramatsu hlist_del(&ri->uflist); 442*4a296e07SMasami Hiramatsu } 443*4a296e07SMasami Hiramatsu spin_unlock_irqrestore(&kretprobe_lock, flags); 444*4a296e07SMasami Hiramatsu free_rp_inst(rp); 445*4a296e07SMasami Hiramatsu } 446*4a296e07SMasami Hiramatsu 44764f562c6SAnanth N Mavinakayanahalli /* 4488b0914eaSPrasanna S Panchamukhi * Keep all fields in the kprobe consistent 4498b0914eaSPrasanna S Panchamukhi */ 4508b0914eaSPrasanna S Panchamukhi static inline void copy_kprobe(struct kprobe *old_p, struct kprobe *p) 4518b0914eaSPrasanna S Panchamukhi { 4528b0914eaSPrasanna S Panchamukhi memcpy(&p->opcode, &old_p->opcode, sizeof(kprobe_opcode_t)); 4538b0914eaSPrasanna S Panchamukhi memcpy(&p->ainsn, &old_p->ainsn, sizeof(struct arch_specific_insn)); 4548b0914eaSPrasanna S Panchamukhi } 4558b0914eaSPrasanna S Panchamukhi 4568b0914eaSPrasanna S Panchamukhi /* 4578b0914eaSPrasanna S Panchamukhi * Add the new probe to old_p->list. Fail if this is the 4588b0914eaSPrasanna S Panchamukhi * second jprobe at the address - two jprobes can't coexist 4598b0914eaSPrasanna S Panchamukhi */ 460d0aaff97SPrasanna S Panchamukhi static int __kprobes add_new_kprobe(struct kprobe *old_p, struct kprobe *p) 4618b0914eaSPrasanna S Panchamukhi { 4628b0914eaSPrasanna S Panchamukhi if (p->break_handler) { 46336721656Smao, bibo if (old_p->break_handler) 4648b0914eaSPrasanna S Panchamukhi return -EEXIST; 4653516a460SAnanth N Mavinakayanahalli list_add_tail_rcu(&p->list, &old_p->list); 46636721656Smao, bibo old_p->break_handler = aggr_break_handler; 4678b0914eaSPrasanna S Panchamukhi } else 4683516a460SAnanth N Mavinakayanahalli list_add_rcu(&p->list, &old_p->list); 46936721656Smao, bibo if (p->post_handler && !old_p->post_handler) 47036721656Smao, bibo old_p->post_handler = aggr_post_handler; 4718b0914eaSPrasanna S Panchamukhi return 0; 4728b0914eaSPrasanna S Panchamukhi } 4738b0914eaSPrasanna S Panchamukhi 4748b0914eaSPrasanna S Panchamukhi /* 47564f562c6SAnanth N Mavinakayanahalli * Fill in the required fields of the "manager kprobe". Replace the 47664f562c6SAnanth N Mavinakayanahalli * earlier kprobe in the hlist with the manager kprobe 47764f562c6SAnanth N Mavinakayanahalli */ 47864f562c6SAnanth N Mavinakayanahalli static inline void add_aggr_kprobe(struct kprobe *ap, struct kprobe *p) 47964f562c6SAnanth N Mavinakayanahalli { 4808b0914eaSPrasanna S Panchamukhi copy_kprobe(p, ap); 481a9ad965eSbibo, mao flush_insn_slot(ap); 48264f562c6SAnanth N Mavinakayanahalli ap->addr = p->addr; 48364f562c6SAnanth N Mavinakayanahalli ap->pre_handler = aggr_pre_handler; 48464f562c6SAnanth N Mavinakayanahalli ap->fault_handler = aggr_fault_handler; 48536721656Smao, bibo if (p->post_handler) 48636721656Smao, bibo ap->post_handler = aggr_post_handler; 48736721656Smao, bibo if (p->break_handler) 4888b0914eaSPrasanna S Panchamukhi ap->break_handler = aggr_break_handler; 48964f562c6SAnanth N Mavinakayanahalli 49064f562c6SAnanth N Mavinakayanahalli INIT_LIST_HEAD(&ap->list); 4913516a460SAnanth N Mavinakayanahalli list_add_rcu(&p->list, &ap->list); 49264f562c6SAnanth N Mavinakayanahalli 493adad0f33SKeshavamurthy Anil S hlist_replace_rcu(&p->hlist, &ap->hlist); 49464f562c6SAnanth N Mavinakayanahalli } 49564f562c6SAnanth N Mavinakayanahalli 49664f562c6SAnanth N Mavinakayanahalli /* 49764f562c6SAnanth N Mavinakayanahalli * This is the second or subsequent kprobe at the address - handle 49864f562c6SAnanth N Mavinakayanahalli * the intricacies 49964f562c6SAnanth N Mavinakayanahalli */ 500d0aaff97SPrasanna S Panchamukhi static int __kprobes register_aggr_kprobe(struct kprobe *old_p, 501d0aaff97SPrasanna S Panchamukhi struct kprobe *p) 50264f562c6SAnanth N Mavinakayanahalli { 50364f562c6SAnanth N Mavinakayanahalli int ret = 0; 50464f562c6SAnanth N Mavinakayanahalli struct kprobe *ap; 50564f562c6SAnanth N Mavinakayanahalli 5068b0914eaSPrasanna S Panchamukhi if (old_p->pre_handler == aggr_pre_handler) { 5078b0914eaSPrasanna S Panchamukhi copy_kprobe(old_p, p); 5088b0914eaSPrasanna S Panchamukhi ret = add_new_kprobe(old_p, p); 50964f562c6SAnanth N Mavinakayanahalli } else { 510a0d50069SKeshavamurthy Anil S ap = kzalloc(sizeof(struct kprobe), GFP_KERNEL); 51164f562c6SAnanth N Mavinakayanahalli if (!ap) 51264f562c6SAnanth N Mavinakayanahalli return -ENOMEM; 51364f562c6SAnanth N Mavinakayanahalli add_aggr_kprobe(ap, old_p); 5148b0914eaSPrasanna S Panchamukhi copy_kprobe(ap, p); 5158b0914eaSPrasanna S Panchamukhi ret = add_new_kprobe(ap, p); 51664f562c6SAnanth N Mavinakayanahalli } 51764f562c6SAnanth N Mavinakayanahalli return ret; 51864f562c6SAnanth N Mavinakayanahalli } 51964f562c6SAnanth N Mavinakayanahalli 520d0aaff97SPrasanna S Panchamukhi static int __kprobes in_kprobes_functions(unsigned long addr) 521d0aaff97SPrasanna S Panchamukhi { 5223d8d996eSSrinivasa Ds struct kprobe_blackpoint *kb; 5233d8d996eSSrinivasa Ds 5246f716acdSChristoph Hellwig if (addr >= (unsigned long)__kprobes_text_start && 5256f716acdSChristoph Hellwig addr < (unsigned long)__kprobes_text_end) 526d0aaff97SPrasanna S Panchamukhi return -EINVAL; 5273d8d996eSSrinivasa Ds /* 5283d8d996eSSrinivasa Ds * If there exists a kprobe_blacklist, verify and 5293d8d996eSSrinivasa Ds * fail any probe registration in the prohibited area 5303d8d996eSSrinivasa Ds */ 5313d8d996eSSrinivasa Ds for (kb = kprobe_blacklist; kb->name != NULL; kb++) { 5323d8d996eSSrinivasa Ds if (kb->start_addr) { 5333d8d996eSSrinivasa Ds if (addr >= kb->start_addr && 5343d8d996eSSrinivasa Ds addr < (kb->start_addr + kb->range)) 5353d8d996eSSrinivasa Ds return -EINVAL; 5363d8d996eSSrinivasa Ds } 5373d8d996eSSrinivasa Ds } 538d0aaff97SPrasanna S Panchamukhi return 0; 539d0aaff97SPrasanna S Panchamukhi } 540d0aaff97SPrasanna S Panchamukhi 541b2a5cd69SMasami Hiramatsu /* 542b2a5cd69SMasami Hiramatsu * If we have a symbol_name argument, look it up and add the offset field 543b2a5cd69SMasami Hiramatsu * to it. This way, we can specify a relative address to a symbol. 544b2a5cd69SMasami Hiramatsu */ 545b2a5cd69SMasami Hiramatsu static kprobe_opcode_t __kprobes *kprobe_addr(struct kprobe *p) 546b2a5cd69SMasami Hiramatsu { 547b2a5cd69SMasami Hiramatsu kprobe_opcode_t *addr = p->addr; 548b2a5cd69SMasami Hiramatsu if (p->symbol_name) { 549b2a5cd69SMasami Hiramatsu if (addr) 550b2a5cd69SMasami Hiramatsu return NULL; 551b2a5cd69SMasami Hiramatsu kprobe_lookup_name(p->symbol_name, addr); 552b2a5cd69SMasami Hiramatsu } 553b2a5cd69SMasami Hiramatsu 554b2a5cd69SMasami Hiramatsu if (!addr) 555b2a5cd69SMasami Hiramatsu return NULL; 556b2a5cd69SMasami Hiramatsu return (kprobe_opcode_t *)(((char *)addr) + p->offset); 557b2a5cd69SMasami Hiramatsu } 558b2a5cd69SMasami Hiramatsu 559df019b1dSKeshavamurthy Anil S static int __kprobes __register_kprobe(struct kprobe *p, 560df019b1dSKeshavamurthy Anil S unsigned long called_from) 5611da177e4SLinus Torvalds { 5621da177e4SLinus Torvalds int ret = 0; 56364f562c6SAnanth N Mavinakayanahalli struct kprobe *old_p; 564df019b1dSKeshavamurthy Anil S struct module *probed_mod; 565b2a5cd69SMasami Hiramatsu kprobe_opcode_t *addr; 5661da177e4SLinus Torvalds 567b2a5cd69SMasami Hiramatsu addr = kprobe_addr(p); 568b2a5cd69SMasami Hiramatsu if (!addr) 5693a872d89SAnanth N Mavinakayanahalli return -EINVAL; 570b2a5cd69SMasami Hiramatsu p->addr = addr; 5713a872d89SAnanth N Mavinakayanahalli 5726f716acdSChristoph Hellwig if (!kernel_text_address((unsigned long) p->addr) || 573b3e55c72SMao, Bibo in_kprobes_functions((unsigned long) p->addr)) 574b3e55c72SMao, Bibo return -EINVAL; 575b3e55c72SMao, Bibo 576df019b1dSKeshavamurthy Anil S p->mod_refcounted = 0; 5776f716acdSChristoph Hellwig 5786f716acdSChristoph Hellwig /* 5796f716acdSChristoph Hellwig * Check if are we probing a module. 580df019b1dSKeshavamurthy Anil S */ 5816f716acdSChristoph Hellwig probed_mod = module_text_address((unsigned long) p->addr); 5826f716acdSChristoph Hellwig if (probed_mod) { 5836f716acdSChristoph Hellwig struct module *calling_mod = module_text_address(called_from); 5846f716acdSChristoph Hellwig /* 5856f716acdSChristoph Hellwig * We must allow modules to probe themself and in this case 5866f716acdSChristoph Hellwig * avoid incrementing the module refcount, so as to allow 5876f716acdSChristoph Hellwig * unloading of self probing modules. 5886f716acdSChristoph Hellwig */ 5896f716acdSChristoph Hellwig if (calling_mod && calling_mod != probed_mod) { 590df019b1dSKeshavamurthy Anil S if (unlikely(!try_module_get(probed_mod))) 591b3e55c72SMao, Bibo return -EINVAL; 592df019b1dSKeshavamurthy Anil S p->mod_refcounted = 1; 593df019b1dSKeshavamurthy Anil S } else 594df019b1dSKeshavamurthy Anil S probed_mod = NULL; 595df019b1dSKeshavamurthy Anil S } 596b3e55c72SMao, Bibo 5973516a460SAnanth N Mavinakayanahalli p->nmissed = 0; 5989861668fSMasami Hiramatsu INIT_LIST_HEAD(&p->list); 5997a7d1cf9SIngo Molnar mutex_lock(&kprobe_mutex); 60064f562c6SAnanth N Mavinakayanahalli old_p = get_kprobe(p->addr); 60164f562c6SAnanth N Mavinakayanahalli if (old_p) { 60264f562c6SAnanth N Mavinakayanahalli ret = register_aggr_kprobe(old_p, p); 6031da177e4SLinus Torvalds goto out; 6041da177e4SLinus Torvalds } 6051da177e4SLinus Torvalds 6066f716acdSChristoph Hellwig ret = arch_prepare_kprobe(p); 6076f716acdSChristoph Hellwig if (ret) 60849a2a1b8SAnil S Keshavamurthy goto out; 60949a2a1b8SAnil S Keshavamurthy 61064f562c6SAnanth N Mavinakayanahalli INIT_HLIST_NODE(&p->hlist); 6113516a460SAnanth N Mavinakayanahalli hlist_add_head_rcu(&p->hlist, 6121da177e4SLinus Torvalds &kprobe_table[hash_ptr(p->addr, KPROBE_HASH_BITS)]); 6131da177e4SLinus Torvalds 61474a0b576SChristoph Hellwig if (kprobe_enabled) 6157e1048b1SRusty Lynch arch_arm_kprobe(p); 61674a0b576SChristoph Hellwig 6171da177e4SLinus Torvalds out: 6187a7d1cf9SIngo Molnar mutex_unlock(&kprobe_mutex); 61949a2a1b8SAnil S Keshavamurthy 620df019b1dSKeshavamurthy Anil S if (ret && probed_mod) 621df019b1dSKeshavamurthy Anil S module_put(probed_mod); 6221da177e4SLinus Torvalds return ret; 6231da177e4SLinus Torvalds } 6241da177e4SLinus Torvalds 6259861668fSMasami Hiramatsu /* 6269861668fSMasami Hiramatsu * Unregister a kprobe without a scheduler synchronization. 6279861668fSMasami Hiramatsu */ 6289861668fSMasami Hiramatsu static int __kprobes __unregister_kprobe_top(struct kprobe *p) 629df019b1dSKeshavamurthy Anil S { 630f709b122SKeshavamurthy Anil S struct kprobe *old_p, *list_p; 63164f562c6SAnanth N Mavinakayanahalli 63264f562c6SAnanth N Mavinakayanahalli old_p = get_kprobe(p->addr); 6339861668fSMasami Hiramatsu if (unlikely(!old_p)) 6349861668fSMasami Hiramatsu return -EINVAL; 6359861668fSMasami Hiramatsu 636f709b122SKeshavamurthy Anil S if (p != old_p) { 637f709b122SKeshavamurthy Anil S list_for_each_entry_rcu(list_p, &old_p->list, list) 638f709b122SKeshavamurthy Anil S if (list_p == p) 639f709b122SKeshavamurthy Anil S /* kprobe p is a valid probe */ 640f709b122SKeshavamurthy Anil S goto valid_p; 6419861668fSMasami Hiramatsu return -EINVAL; 642f709b122SKeshavamurthy Anil S } 643f709b122SKeshavamurthy Anil S valid_p: 6446f716acdSChristoph Hellwig if (old_p == p || 6456f716acdSChristoph Hellwig (old_p->pre_handler == aggr_pre_handler && 6469861668fSMasami Hiramatsu list_is_singular(&old_p->list))) { 647bf8f6e5bSAnanth N Mavinakayanahalli /* 648bf8f6e5bSAnanth N Mavinakayanahalli * Only probe on the hash list. Disarm only if kprobes are 649bf8f6e5bSAnanth N Mavinakayanahalli * enabled - otherwise, the breakpoint would already have 650bf8f6e5bSAnanth N Mavinakayanahalli * been removed. We save on flushing icache. 651bf8f6e5bSAnanth N Mavinakayanahalli */ 652bf8f6e5bSAnanth N Mavinakayanahalli if (kprobe_enabled) 65349a2a1b8SAnil S Keshavamurthy arch_disarm_kprobe(p); 65449a2a1b8SAnil S Keshavamurthy hlist_del_rcu(&old_p->hlist); 65549a2a1b8SAnil S Keshavamurthy } else { 6569861668fSMasami Hiramatsu if (p->break_handler) 6579861668fSMasami Hiramatsu old_p->break_handler = NULL; 6589861668fSMasami Hiramatsu if (p->post_handler) { 6599861668fSMasami Hiramatsu list_for_each_entry_rcu(list_p, &old_p->list, list) { 6609861668fSMasami Hiramatsu if ((list_p != p) && (list_p->post_handler)) 6619861668fSMasami Hiramatsu goto noclean; 6629861668fSMasami Hiramatsu } 6639861668fSMasami Hiramatsu old_p->post_handler = NULL; 6649861668fSMasami Hiramatsu } 6659861668fSMasami Hiramatsu noclean: 66649a2a1b8SAnil S Keshavamurthy list_del_rcu(&p->list); 6679861668fSMasami Hiramatsu } 6689861668fSMasami Hiramatsu return 0; 66949a2a1b8SAnil S Keshavamurthy } 67049a2a1b8SAnil S Keshavamurthy 6719861668fSMasami Hiramatsu static void __kprobes __unregister_kprobe_bottom(struct kprobe *p) 6729861668fSMasami Hiramatsu { 6739861668fSMasami Hiramatsu struct module *mod; 6749861668fSMasami Hiramatsu struct kprobe *old_p; 6753516a460SAnanth N Mavinakayanahalli 6766f716acdSChristoph Hellwig if (p->mod_refcounted) { 6776f716acdSChristoph Hellwig mod = module_text_address((unsigned long)p->addr); 6786f716acdSChristoph Hellwig if (mod) 679b3e55c72SMao, Bibo module_put(mod); 6806f716acdSChristoph Hellwig } 681b3e55c72SMao, Bibo 6829861668fSMasami Hiramatsu if (list_empty(&p->list) || list_is_singular(&p->list)) { 6839861668fSMasami Hiramatsu if (!list_empty(&p->list)) { 6849861668fSMasami Hiramatsu /* "p" is the last child of an aggr_kprobe */ 6859861668fSMasami Hiramatsu old_p = list_entry(p->list.next, struct kprobe, list); 6869861668fSMasami Hiramatsu list_del(&p->list); 6873516a460SAnanth N Mavinakayanahalli kfree(old_p); 68849a2a1b8SAnil S Keshavamurthy } 6890498b635SAnanth N Mavinakayanahalli arch_remove_kprobe(p); 6909861668fSMasami Hiramatsu } 6919861668fSMasami Hiramatsu } 6929861668fSMasami Hiramatsu 6939861668fSMasami Hiramatsu static int __register_kprobes(struct kprobe **kps, int num, 6949861668fSMasami Hiramatsu unsigned long called_from) 6959861668fSMasami Hiramatsu { 6969861668fSMasami Hiramatsu int i, ret = 0; 6979861668fSMasami Hiramatsu 6989861668fSMasami Hiramatsu if (num <= 0) 6999861668fSMasami Hiramatsu return -EINVAL; 7009861668fSMasami Hiramatsu for (i = 0; i < num; i++) { 7019861668fSMasami Hiramatsu ret = __register_kprobe(kps[i], called_from); 7029861668fSMasami Hiramatsu if (ret < 0 && i > 0) { 7039861668fSMasami Hiramatsu unregister_kprobes(kps, i); 70436721656Smao, bibo break; 70536721656Smao, bibo } 70636721656Smao, bibo } 7079861668fSMasami Hiramatsu return ret; 70836721656Smao, bibo } 7099861668fSMasami Hiramatsu 7109861668fSMasami Hiramatsu /* 7119861668fSMasami Hiramatsu * Registration and unregistration functions for kprobe. 7129861668fSMasami Hiramatsu */ 7139861668fSMasami Hiramatsu int __kprobes register_kprobe(struct kprobe *p) 7149861668fSMasami Hiramatsu { 7159861668fSMasami Hiramatsu return __register_kprobes(&p, 1, 7169861668fSMasami Hiramatsu (unsigned long)__builtin_return_address(0)); 7179861668fSMasami Hiramatsu } 7189861668fSMasami Hiramatsu 7199861668fSMasami Hiramatsu void __kprobes unregister_kprobe(struct kprobe *p) 7209861668fSMasami Hiramatsu { 7219861668fSMasami Hiramatsu unregister_kprobes(&p, 1); 7229861668fSMasami Hiramatsu } 7239861668fSMasami Hiramatsu 7249861668fSMasami Hiramatsu int __kprobes register_kprobes(struct kprobe **kps, int num) 7259861668fSMasami Hiramatsu { 7269861668fSMasami Hiramatsu return __register_kprobes(kps, num, 7279861668fSMasami Hiramatsu (unsigned long)__builtin_return_address(0)); 7289861668fSMasami Hiramatsu } 7299861668fSMasami Hiramatsu 7309861668fSMasami Hiramatsu void __kprobes unregister_kprobes(struct kprobe **kps, int num) 7319861668fSMasami Hiramatsu { 7329861668fSMasami Hiramatsu int i; 7339861668fSMasami Hiramatsu 7349861668fSMasami Hiramatsu if (num <= 0) 7359861668fSMasami Hiramatsu return; 7369861668fSMasami Hiramatsu mutex_lock(&kprobe_mutex); 7379861668fSMasami Hiramatsu for (i = 0; i < num; i++) 7389861668fSMasami Hiramatsu if (__unregister_kprobe_top(kps[i]) < 0) 7399861668fSMasami Hiramatsu kps[i]->addr = NULL; 74036721656Smao, bibo mutex_unlock(&kprobe_mutex); 7419861668fSMasami Hiramatsu 7429861668fSMasami Hiramatsu synchronize_sched(); 7439861668fSMasami Hiramatsu for (i = 0; i < num; i++) 7449861668fSMasami Hiramatsu if (kps[i]->addr) 7459861668fSMasami Hiramatsu __unregister_kprobe_bottom(kps[i]); 7461da177e4SLinus Torvalds } 7471da177e4SLinus Torvalds 7481da177e4SLinus Torvalds static struct notifier_block kprobe_exceptions_nb = { 7491da177e4SLinus Torvalds .notifier_call = kprobe_exceptions_notify, 7503d5631e0SAnil S Keshavamurthy .priority = 0x7fffffff /* we need to be notified first */ 7513d5631e0SAnil S Keshavamurthy }; 7523d5631e0SAnil S Keshavamurthy 7533d7e3382SMichael Ellerman unsigned long __weak arch_deref_entry_point(void *entry) 7543d7e3382SMichael Ellerman { 7553d7e3382SMichael Ellerman return (unsigned long)entry; 7563d7e3382SMichael Ellerman } 7571da177e4SLinus Torvalds 758d0aaff97SPrasanna S Panchamukhi int __kprobes register_jprobe(struct jprobe *jp) 7591da177e4SLinus Torvalds { 7603d7e3382SMichael Ellerman unsigned long addr = arch_deref_entry_point(jp->entry); 7613d7e3382SMichael Ellerman 7623d7e3382SMichael Ellerman if (!kernel_text_address(addr)) 7633d7e3382SMichael Ellerman return -EINVAL; 7643d7e3382SMichael Ellerman 7651da177e4SLinus Torvalds /* Todo: Verify probepoint is a function entry point */ 7661da177e4SLinus Torvalds jp->kp.pre_handler = setjmp_pre_handler; 7671da177e4SLinus Torvalds jp->kp.break_handler = longjmp_break_handler; 7681da177e4SLinus Torvalds 769df019b1dSKeshavamurthy Anil S return __register_kprobe(&jp->kp, 770df019b1dSKeshavamurthy Anil S (unsigned long)__builtin_return_address(0)); 7711da177e4SLinus Torvalds } 7721da177e4SLinus Torvalds 773d0aaff97SPrasanna S Panchamukhi void __kprobes unregister_jprobe(struct jprobe *jp) 7741da177e4SLinus Torvalds { 7751da177e4SLinus Torvalds unregister_kprobe(&jp->kp); 7761da177e4SLinus Torvalds } 7771da177e4SLinus Torvalds 7789edddaa2SAnanth N Mavinakayanahalli #ifdef CONFIG_KRETPROBES 779e65cefe8SAdrian Bunk /* 780e65cefe8SAdrian Bunk * This kprobe pre_handler is registered with every kretprobe. When probe 781e65cefe8SAdrian Bunk * hits it will set up the return probe. 782e65cefe8SAdrian Bunk */ 783e65cefe8SAdrian Bunk static int __kprobes pre_handler_kretprobe(struct kprobe *p, 784e65cefe8SAdrian Bunk struct pt_regs *regs) 785e65cefe8SAdrian Bunk { 786e65cefe8SAdrian Bunk struct kretprobe *rp = container_of(p, struct kretprobe, kp); 787e65cefe8SAdrian Bunk unsigned long flags = 0; 788e65cefe8SAdrian Bunk 789e65cefe8SAdrian Bunk /*TODO: consider to only swap the RA after the last pre_handler fired */ 790e65cefe8SAdrian Bunk spin_lock_irqsave(&kretprobe_lock, flags); 7914c4308cbSChristoph Hellwig if (!hlist_empty(&rp->free_instances)) { 7924c4308cbSChristoph Hellwig struct kretprobe_instance *ri; 7934c4308cbSChristoph Hellwig 7944c4308cbSChristoph Hellwig ri = hlist_entry(rp->free_instances.first, 7954c4308cbSChristoph Hellwig struct kretprobe_instance, uflist); 7964c4308cbSChristoph Hellwig ri->rp = rp; 7974c4308cbSChristoph Hellwig ri->task = current; 798f47cd9b5SAbhishek Sagar 799f47cd9b5SAbhishek Sagar if (rp->entry_handler && rp->entry_handler(ri, regs)) { 800f47cd9b5SAbhishek Sagar spin_unlock_irqrestore(&kretprobe_lock, flags); 801f47cd9b5SAbhishek Sagar return 0; 802f47cd9b5SAbhishek Sagar } 803f47cd9b5SAbhishek Sagar 8044c4308cbSChristoph Hellwig arch_prepare_kretprobe(ri, regs); 8054c4308cbSChristoph Hellwig 8064c4308cbSChristoph Hellwig /* XXX(hch): why is there no hlist_move_head? */ 8074c4308cbSChristoph Hellwig hlist_del(&ri->uflist); 8084c4308cbSChristoph Hellwig hlist_add_head(&ri->uflist, &ri->rp->used_instances); 8094c4308cbSChristoph Hellwig hlist_add_head(&ri->hlist, kretprobe_inst_table_head(ri->task)); 8104c4308cbSChristoph Hellwig } else 8114c4308cbSChristoph Hellwig rp->nmissed++; 812e65cefe8SAdrian Bunk spin_unlock_irqrestore(&kretprobe_lock, flags); 813e65cefe8SAdrian Bunk return 0; 814e65cefe8SAdrian Bunk } 815e65cefe8SAdrian Bunk 816*4a296e07SMasami Hiramatsu static int __kprobes __register_kretprobe(struct kretprobe *rp, 817*4a296e07SMasami Hiramatsu unsigned long called_from) 818b94cce92SHien Nguyen { 819b94cce92SHien Nguyen int ret = 0; 820b94cce92SHien Nguyen struct kretprobe_instance *inst; 821b94cce92SHien Nguyen int i; 822b2a5cd69SMasami Hiramatsu void *addr; 823f438d914SMasami Hiramatsu 824f438d914SMasami Hiramatsu if (kretprobe_blacklist_size) { 825b2a5cd69SMasami Hiramatsu addr = kprobe_addr(&rp->kp); 826b2a5cd69SMasami Hiramatsu if (!addr) 827b2a5cd69SMasami Hiramatsu return -EINVAL; 828f438d914SMasami Hiramatsu 829f438d914SMasami Hiramatsu for (i = 0; kretprobe_blacklist[i].name != NULL; i++) { 830f438d914SMasami Hiramatsu if (kretprobe_blacklist[i].addr == addr) 831f438d914SMasami Hiramatsu return -EINVAL; 832f438d914SMasami Hiramatsu } 833f438d914SMasami Hiramatsu } 834b94cce92SHien Nguyen 835b94cce92SHien Nguyen rp->kp.pre_handler = pre_handler_kretprobe; 8367522a842SAnanth N Mavinakayanahalli rp->kp.post_handler = NULL; 8377522a842SAnanth N Mavinakayanahalli rp->kp.fault_handler = NULL; 8387522a842SAnanth N Mavinakayanahalli rp->kp.break_handler = NULL; 839b94cce92SHien Nguyen 840b94cce92SHien Nguyen /* Pre-allocate memory for max kretprobe instances */ 841b94cce92SHien Nguyen if (rp->maxactive <= 0) { 842b94cce92SHien Nguyen #ifdef CONFIG_PREEMPT 843b94cce92SHien Nguyen rp->maxactive = max(10, 2 * NR_CPUS); 844b94cce92SHien Nguyen #else 845b94cce92SHien Nguyen rp->maxactive = NR_CPUS; 846b94cce92SHien Nguyen #endif 847b94cce92SHien Nguyen } 848b94cce92SHien Nguyen INIT_HLIST_HEAD(&rp->used_instances); 849b94cce92SHien Nguyen INIT_HLIST_HEAD(&rp->free_instances); 850b94cce92SHien Nguyen for (i = 0; i < rp->maxactive; i++) { 851f47cd9b5SAbhishek Sagar inst = kmalloc(sizeof(struct kretprobe_instance) + 852f47cd9b5SAbhishek Sagar rp->data_size, GFP_KERNEL); 853b94cce92SHien Nguyen if (inst == NULL) { 854b94cce92SHien Nguyen free_rp_inst(rp); 855b94cce92SHien Nguyen return -ENOMEM; 856b94cce92SHien Nguyen } 857b94cce92SHien Nguyen INIT_HLIST_NODE(&inst->uflist); 858b94cce92SHien Nguyen hlist_add_head(&inst->uflist, &rp->free_instances); 859b94cce92SHien Nguyen } 860b94cce92SHien Nguyen 861b94cce92SHien Nguyen rp->nmissed = 0; 862b94cce92SHien Nguyen /* Establish function entry probe point */ 863*4a296e07SMasami Hiramatsu ret = __register_kprobe(&rp->kp, called_from); 864*4a296e07SMasami Hiramatsu if (ret != 0) 865b94cce92SHien Nguyen free_rp_inst(rp); 866b94cce92SHien Nguyen return ret; 867b94cce92SHien Nguyen } 868b94cce92SHien Nguyen 869*4a296e07SMasami Hiramatsu static int __register_kretprobes(struct kretprobe **rps, int num, 870*4a296e07SMasami Hiramatsu unsigned long called_from) 871*4a296e07SMasami Hiramatsu { 872*4a296e07SMasami Hiramatsu int ret = 0, i; 873*4a296e07SMasami Hiramatsu 874*4a296e07SMasami Hiramatsu if (num <= 0) 875*4a296e07SMasami Hiramatsu return -EINVAL; 876*4a296e07SMasami Hiramatsu for (i = 0; i < num; i++) { 877*4a296e07SMasami Hiramatsu ret = __register_kretprobe(rps[i], called_from); 878*4a296e07SMasami Hiramatsu if (ret < 0 && i > 0) { 879*4a296e07SMasami Hiramatsu unregister_kretprobes(rps, i); 880*4a296e07SMasami Hiramatsu break; 881*4a296e07SMasami Hiramatsu } 882*4a296e07SMasami Hiramatsu } 883*4a296e07SMasami Hiramatsu return ret; 884*4a296e07SMasami Hiramatsu } 885*4a296e07SMasami Hiramatsu 886*4a296e07SMasami Hiramatsu int __kprobes register_kretprobe(struct kretprobe *rp) 887*4a296e07SMasami Hiramatsu { 888*4a296e07SMasami Hiramatsu return __register_kretprobes(&rp, 1, 889*4a296e07SMasami Hiramatsu (unsigned long)__builtin_return_address(0)); 890*4a296e07SMasami Hiramatsu } 891*4a296e07SMasami Hiramatsu 892*4a296e07SMasami Hiramatsu void __kprobes unregister_kretprobe(struct kretprobe *rp) 893*4a296e07SMasami Hiramatsu { 894*4a296e07SMasami Hiramatsu unregister_kretprobes(&rp, 1); 895*4a296e07SMasami Hiramatsu } 896*4a296e07SMasami Hiramatsu 897*4a296e07SMasami Hiramatsu int __kprobes register_kretprobes(struct kretprobe **rps, int num) 898*4a296e07SMasami Hiramatsu { 899*4a296e07SMasami Hiramatsu return __register_kretprobes(rps, num, 900*4a296e07SMasami Hiramatsu (unsigned long)__builtin_return_address(0)); 901*4a296e07SMasami Hiramatsu } 902*4a296e07SMasami Hiramatsu 903*4a296e07SMasami Hiramatsu void __kprobes unregister_kretprobes(struct kretprobe **rps, int num) 904*4a296e07SMasami Hiramatsu { 905*4a296e07SMasami Hiramatsu int i; 906*4a296e07SMasami Hiramatsu 907*4a296e07SMasami Hiramatsu if (num <= 0) 908*4a296e07SMasami Hiramatsu return; 909*4a296e07SMasami Hiramatsu mutex_lock(&kprobe_mutex); 910*4a296e07SMasami Hiramatsu for (i = 0; i < num; i++) 911*4a296e07SMasami Hiramatsu if (__unregister_kprobe_top(&rps[i]->kp) < 0) 912*4a296e07SMasami Hiramatsu rps[i]->kp.addr = NULL; 913*4a296e07SMasami Hiramatsu mutex_unlock(&kprobe_mutex); 914*4a296e07SMasami Hiramatsu 915*4a296e07SMasami Hiramatsu synchronize_sched(); 916*4a296e07SMasami Hiramatsu for (i = 0; i < num; i++) { 917*4a296e07SMasami Hiramatsu if (rps[i]->kp.addr) { 918*4a296e07SMasami Hiramatsu __unregister_kprobe_bottom(&rps[i]->kp); 919*4a296e07SMasami Hiramatsu cleanup_rp_inst(rps[i]); 920*4a296e07SMasami Hiramatsu } 921*4a296e07SMasami Hiramatsu } 922*4a296e07SMasami Hiramatsu } 923*4a296e07SMasami Hiramatsu 9249edddaa2SAnanth N Mavinakayanahalli #else /* CONFIG_KRETPROBES */ 925d0aaff97SPrasanna S Panchamukhi int __kprobes register_kretprobe(struct kretprobe *rp) 926b94cce92SHien Nguyen { 927b94cce92SHien Nguyen return -ENOSYS; 928b94cce92SHien Nguyen } 929b94cce92SHien Nguyen 930*4a296e07SMasami Hiramatsu int __kprobes register_kretprobes(struct kretprobe **rps, int num) 931*4a296e07SMasami Hiramatsu { 932*4a296e07SMasami Hiramatsu return -ENOSYS; 933*4a296e07SMasami Hiramatsu } 934*4a296e07SMasami Hiramatsu void __kprobes unregister_kretprobe(struct kretprobe *rp) 935*4a296e07SMasami Hiramatsu { 936*4a296e07SMasami Hiramatsu } 937*4a296e07SMasami Hiramatsu 938*4a296e07SMasami Hiramatsu void __kprobes unregister_kretprobes(struct kretprobe **rps, int num) 939*4a296e07SMasami Hiramatsu { 940*4a296e07SMasami Hiramatsu } 941*4a296e07SMasami Hiramatsu 942346fd59bSSrinivasa Ds static int __kprobes pre_handler_kretprobe(struct kprobe *p, 943346fd59bSSrinivasa Ds struct pt_regs *regs) 944346fd59bSSrinivasa Ds { 945346fd59bSSrinivasa Ds return 0; 946346fd59bSSrinivasa Ds } 947*4a296e07SMasami Hiramatsu 9489edddaa2SAnanth N Mavinakayanahalli #endif /* CONFIG_KRETPROBES */ 949b94cce92SHien Nguyen 9501da177e4SLinus Torvalds static int __init init_kprobes(void) 9511da177e4SLinus Torvalds { 9521da177e4SLinus Torvalds int i, err = 0; 9533d8d996eSSrinivasa Ds unsigned long offset = 0, size = 0; 9543d8d996eSSrinivasa Ds char *modname, namebuf[128]; 9553d8d996eSSrinivasa Ds const char *symbol_name; 9563d8d996eSSrinivasa Ds void *addr; 9573d8d996eSSrinivasa Ds struct kprobe_blackpoint *kb; 9581da177e4SLinus Torvalds 9591da177e4SLinus Torvalds /* FIXME allocate the probe table, currently defined statically */ 9601da177e4SLinus Torvalds /* initialize all list heads */ 961b94cce92SHien Nguyen for (i = 0; i < KPROBE_TABLE_SIZE; i++) { 9621da177e4SLinus Torvalds INIT_HLIST_HEAD(&kprobe_table[i]); 963b94cce92SHien Nguyen INIT_HLIST_HEAD(&kretprobe_inst_table[i]); 964b94cce92SHien Nguyen } 9651da177e4SLinus Torvalds 9663d8d996eSSrinivasa Ds /* 9673d8d996eSSrinivasa Ds * Lookup and populate the kprobe_blacklist. 9683d8d996eSSrinivasa Ds * 9693d8d996eSSrinivasa Ds * Unlike the kretprobe blacklist, we'll need to determine 9703d8d996eSSrinivasa Ds * the range of addresses that belong to the said functions, 9713d8d996eSSrinivasa Ds * since a kprobe need not necessarily be at the beginning 9723d8d996eSSrinivasa Ds * of a function. 9733d8d996eSSrinivasa Ds */ 9743d8d996eSSrinivasa Ds for (kb = kprobe_blacklist; kb->name != NULL; kb++) { 9753d8d996eSSrinivasa Ds kprobe_lookup_name(kb->name, addr); 9763d8d996eSSrinivasa Ds if (!addr) 9773d8d996eSSrinivasa Ds continue; 9783d8d996eSSrinivasa Ds 9793d8d996eSSrinivasa Ds kb->start_addr = (unsigned long)addr; 9803d8d996eSSrinivasa Ds symbol_name = kallsyms_lookup(kb->start_addr, 9813d8d996eSSrinivasa Ds &size, &offset, &modname, namebuf); 9823d8d996eSSrinivasa Ds if (!symbol_name) 9833d8d996eSSrinivasa Ds kb->range = 0; 9843d8d996eSSrinivasa Ds else 9853d8d996eSSrinivasa Ds kb->range = size; 9863d8d996eSSrinivasa Ds } 9873d8d996eSSrinivasa Ds 988f438d914SMasami Hiramatsu if (kretprobe_blacklist_size) { 989f438d914SMasami Hiramatsu /* lookup the function address from its name */ 990f438d914SMasami Hiramatsu for (i = 0; kretprobe_blacklist[i].name != NULL; i++) { 991f438d914SMasami Hiramatsu kprobe_lookup_name(kretprobe_blacklist[i].name, 992f438d914SMasami Hiramatsu kretprobe_blacklist[i].addr); 993f438d914SMasami Hiramatsu if (!kretprobe_blacklist[i].addr) 994f438d914SMasami Hiramatsu printk("kretprobe: lookup failed: %s\n", 995f438d914SMasami Hiramatsu kretprobe_blacklist[i].name); 996f438d914SMasami Hiramatsu } 997f438d914SMasami Hiramatsu } 998f438d914SMasami Hiramatsu 999bf8f6e5bSAnanth N Mavinakayanahalli /* By default, kprobes are enabled */ 1000bf8f6e5bSAnanth N Mavinakayanahalli kprobe_enabled = true; 1001bf8f6e5bSAnanth N Mavinakayanahalli 10026772926bSRusty Lynch err = arch_init_kprobes(); 1003802eae7cSRusty Lynch if (!err) 10041da177e4SLinus Torvalds err = register_die_notifier(&kprobe_exceptions_nb); 1005802eae7cSRusty Lynch 10068c1c9356SAnanth N Mavinakayanahalli if (!err) 10078c1c9356SAnanth N Mavinakayanahalli init_test_probes(); 10081da177e4SLinus Torvalds return err; 10091da177e4SLinus Torvalds } 10101da177e4SLinus Torvalds 1011346fd59bSSrinivasa Ds #ifdef CONFIG_DEBUG_FS 1012346fd59bSSrinivasa Ds static void __kprobes report_probe(struct seq_file *pi, struct kprobe *p, 1013346fd59bSSrinivasa Ds const char *sym, int offset,char *modname) 1014346fd59bSSrinivasa Ds { 1015346fd59bSSrinivasa Ds char *kprobe_type; 1016346fd59bSSrinivasa Ds 1017346fd59bSSrinivasa Ds if (p->pre_handler == pre_handler_kretprobe) 1018346fd59bSSrinivasa Ds kprobe_type = "r"; 1019346fd59bSSrinivasa Ds else if (p->pre_handler == setjmp_pre_handler) 1020346fd59bSSrinivasa Ds kprobe_type = "j"; 1021346fd59bSSrinivasa Ds else 1022346fd59bSSrinivasa Ds kprobe_type = "k"; 1023346fd59bSSrinivasa Ds if (sym) 1024346fd59bSSrinivasa Ds seq_printf(pi, "%p %s %s+0x%x %s\n", p->addr, kprobe_type, 1025346fd59bSSrinivasa Ds sym, offset, (modname ? modname : " ")); 1026346fd59bSSrinivasa Ds else 1027346fd59bSSrinivasa Ds seq_printf(pi, "%p %s %p\n", p->addr, kprobe_type, p->addr); 1028346fd59bSSrinivasa Ds } 1029346fd59bSSrinivasa Ds 1030346fd59bSSrinivasa Ds static void __kprobes *kprobe_seq_start(struct seq_file *f, loff_t *pos) 1031346fd59bSSrinivasa Ds { 1032346fd59bSSrinivasa Ds return (*pos < KPROBE_TABLE_SIZE) ? pos : NULL; 1033346fd59bSSrinivasa Ds } 1034346fd59bSSrinivasa Ds 1035346fd59bSSrinivasa Ds static void __kprobes *kprobe_seq_next(struct seq_file *f, void *v, loff_t *pos) 1036346fd59bSSrinivasa Ds { 1037346fd59bSSrinivasa Ds (*pos)++; 1038346fd59bSSrinivasa Ds if (*pos >= KPROBE_TABLE_SIZE) 1039346fd59bSSrinivasa Ds return NULL; 1040346fd59bSSrinivasa Ds return pos; 1041346fd59bSSrinivasa Ds } 1042346fd59bSSrinivasa Ds 1043346fd59bSSrinivasa Ds static void __kprobes kprobe_seq_stop(struct seq_file *f, void *v) 1044346fd59bSSrinivasa Ds { 1045346fd59bSSrinivasa Ds /* Nothing to do */ 1046346fd59bSSrinivasa Ds } 1047346fd59bSSrinivasa Ds 1048346fd59bSSrinivasa Ds static int __kprobes show_kprobe_addr(struct seq_file *pi, void *v) 1049346fd59bSSrinivasa Ds { 1050346fd59bSSrinivasa Ds struct hlist_head *head; 1051346fd59bSSrinivasa Ds struct hlist_node *node; 1052346fd59bSSrinivasa Ds struct kprobe *p, *kp; 1053346fd59bSSrinivasa Ds const char *sym = NULL; 1054346fd59bSSrinivasa Ds unsigned int i = *(loff_t *) v; 1055ffb45122SAlexey Dobriyan unsigned long offset = 0; 1056346fd59bSSrinivasa Ds char *modname, namebuf[128]; 1057346fd59bSSrinivasa Ds 1058346fd59bSSrinivasa Ds head = &kprobe_table[i]; 1059346fd59bSSrinivasa Ds preempt_disable(); 1060346fd59bSSrinivasa Ds hlist_for_each_entry_rcu(p, node, head, hlist) { 1061ffb45122SAlexey Dobriyan sym = kallsyms_lookup((unsigned long)p->addr, NULL, 1062346fd59bSSrinivasa Ds &offset, &modname, namebuf); 1063346fd59bSSrinivasa Ds if (p->pre_handler == aggr_pre_handler) { 1064346fd59bSSrinivasa Ds list_for_each_entry_rcu(kp, &p->list, list) 1065346fd59bSSrinivasa Ds report_probe(pi, kp, sym, offset, modname); 1066346fd59bSSrinivasa Ds } else 1067346fd59bSSrinivasa Ds report_probe(pi, p, sym, offset, modname); 1068346fd59bSSrinivasa Ds } 1069346fd59bSSrinivasa Ds preempt_enable(); 1070346fd59bSSrinivasa Ds return 0; 1071346fd59bSSrinivasa Ds } 1072346fd59bSSrinivasa Ds 1073346fd59bSSrinivasa Ds static struct seq_operations kprobes_seq_ops = { 1074346fd59bSSrinivasa Ds .start = kprobe_seq_start, 1075346fd59bSSrinivasa Ds .next = kprobe_seq_next, 1076346fd59bSSrinivasa Ds .stop = kprobe_seq_stop, 1077346fd59bSSrinivasa Ds .show = show_kprobe_addr 1078346fd59bSSrinivasa Ds }; 1079346fd59bSSrinivasa Ds 1080346fd59bSSrinivasa Ds static int __kprobes kprobes_open(struct inode *inode, struct file *filp) 1081346fd59bSSrinivasa Ds { 1082346fd59bSSrinivasa Ds return seq_open(filp, &kprobes_seq_ops); 1083346fd59bSSrinivasa Ds } 1084346fd59bSSrinivasa Ds 1085346fd59bSSrinivasa Ds static struct file_operations debugfs_kprobes_operations = { 1086346fd59bSSrinivasa Ds .open = kprobes_open, 1087346fd59bSSrinivasa Ds .read = seq_read, 1088346fd59bSSrinivasa Ds .llseek = seq_lseek, 1089346fd59bSSrinivasa Ds .release = seq_release, 1090346fd59bSSrinivasa Ds }; 1091346fd59bSSrinivasa Ds 1092bf8f6e5bSAnanth N Mavinakayanahalli static void __kprobes enable_all_kprobes(void) 1093bf8f6e5bSAnanth N Mavinakayanahalli { 1094bf8f6e5bSAnanth N Mavinakayanahalli struct hlist_head *head; 1095bf8f6e5bSAnanth N Mavinakayanahalli struct hlist_node *node; 1096bf8f6e5bSAnanth N Mavinakayanahalli struct kprobe *p; 1097bf8f6e5bSAnanth N Mavinakayanahalli unsigned int i; 1098bf8f6e5bSAnanth N Mavinakayanahalli 1099bf8f6e5bSAnanth N Mavinakayanahalli mutex_lock(&kprobe_mutex); 1100bf8f6e5bSAnanth N Mavinakayanahalli 1101bf8f6e5bSAnanth N Mavinakayanahalli /* If kprobes are already enabled, just return */ 1102bf8f6e5bSAnanth N Mavinakayanahalli if (kprobe_enabled) 1103bf8f6e5bSAnanth N Mavinakayanahalli goto already_enabled; 1104bf8f6e5bSAnanth N Mavinakayanahalli 1105bf8f6e5bSAnanth N Mavinakayanahalli for (i = 0; i < KPROBE_TABLE_SIZE; i++) { 1106bf8f6e5bSAnanth N Mavinakayanahalli head = &kprobe_table[i]; 1107bf8f6e5bSAnanth N Mavinakayanahalli hlist_for_each_entry_rcu(p, node, head, hlist) 1108bf8f6e5bSAnanth N Mavinakayanahalli arch_arm_kprobe(p); 1109bf8f6e5bSAnanth N Mavinakayanahalli } 1110bf8f6e5bSAnanth N Mavinakayanahalli 1111bf8f6e5bSAnanth N Mavinakayanahalli kprobe_enabled = true; 1112bf8f6e5bSAnanth N Mavinakayanahalli printk(KERN_INFO "Kprobes globally enabled\n"); 1113bf8f6e5bSAnanth N Mavinakayanahalli 1114bf8f6e5bSAnanth N Mavinakayanahalli already_enabled: 1115bf8f6e5bSAnanth N Mavinakayanahalli mutex_unlock(&kprobe_mutex); 1116bf8f6e5bSAnanth N Mavinakayanahalli return; 1117bf8f6e5bSAnanth N Mavinakayanahalli } 1118bf8f6e5bSAnanth N Mavinakayanahalli 1119bf8f6e5bSAnanth N Mavinakayanahalli static void __kprobes disable_all_kprobes(void) 1120bf8f6e5bSAnanth N Mavinakayanahalli { 1121bf8f6e5bSAnanth N Mavinakayanahalli struct hlist_head *head; 1122bf8f6e5bSAnanth N Mavinakayanahalli struct hlist_node *node; 1123bf8f6e5bSAnanth N Mavinakayanahalli struct kprobe *p; 1124bf8f6e5bSAnanth N Mavinakayanahalli unsigned int i; 1125bf8f6e5bSAnanth N Mavinakayanahalli 1126bf8f6e5bSAnanth N Mavinakayanahalli mutex_lock(&kprobe_mutex); 1127bf8f6e5bSAnanth N Mavinakayanahalli 1128bf8f6e5bSAnanth N Mavinakayanahalli /* If kprobes are already disabled, just return */ 1129bf8f6e5bSAnanth N Mavinakayanahalli if (!kprobe_enabled) 1130bf8f6e5bSAnanth N Mavinakayanahalli goto already_disabled; 1131bf8f6e5bSAnanth N Mavinakayanahalli 1132bf8f6e5bSAnanth N Mavinakayanahalli kprobe_enabled = false; 1133bf8f6e5bSAnanth N Mavinakayanahalli printk(KERN_INFO "Kprobes globally disabled\n"); 1134bf8f6e5bSAnanth N Mavinakayanahalli for (i = 0; i < KPROBE_TABLE_SIZE; i++) { 1135bf8f6e5bSAnanth N Mavinakayanahalli head = &kprobe_table[i]; 1136bf8f6e5bSAnanth N Mavinakayanahalli hlist_for_each_entry_rcu(p, node, head, hlist) { 1137bf8f6e5bSAnanth N Mavinakayanahalli if (!arch_trampoline_kprobe(p)) 1138bf8f6e5bSAnanth N Mavinakayanahalli arch_disarm_kprobe(p); 1139bf8f6e5bSAnanth N Mavinakayanahalli } 1140bf8f6e5bSAnanth N Mavinakayanahalli } 1141bf8f6e5bSAnanth N Mavinakayanahalli 1142bf8f6e5bSAnanth N Mavinakayanahalli mutex_unlock(&kprobe_mutex); 1143bf8f6e5bSAnanth N Mavinakayanahalli /* Allow all currently running kprobes to complete */ 1144bf8f6e5bSAnanth N Mavinakayanahalli synchronize_sched(); 114574a0b576SChristoph Hellwig return; 1146bf8f6e5bSAnanth N Mavinakayanahalli 1147bf8f6e5bSAnanth N Mavinakayanahalli already_disabled: 1148bf8f6e5bSAnanth N Mavinakayanahalli mutex_unlock(&kprobe_mutex); 1149bf8f6e5bSAnanth N Mavinakayanahalli return; 1150bf8f6e5bSAnanth N Mavinakayanahalli } 1151bf8f6e5bSAnanth N Mavinakayanahalli 1152bf8f6e5bSAnanth N Mavinakayanahalli /* 1153bf8f6e5bSAnanth N Mavinakayanahalli * XXX: The debugfs bool file interface doesn't allow for callbacks 1154bf8f6e5bSAnanth N Mavinakayanahalli * when the bool state is switched. We can reuse that facility when 1155bf8f6e5bSAnanth N Mavinakayanahalli * available 1156bf8f6e5bSAnanth N Mavinakayanahalli */ 1157bf8f6e5bSAnanth N Mavinakayanahalli static ssize_t read_enabled_file_bool(struct file *file, 1158bf8f6e5bSAnanth N Mavinakayanahalli char __user *user_buf, size_t count, loff_t *ppos) 1159bf8f6e5bSAnanth N Mavinakayanahalli { 1160bf8f6e5bSAnanth N Mavinakayanahalli char buf[3]; 1161bf8f6e5bSAnanth N Mavinakayanahalli 1162bf8f6e5bSAnanth N Mavinakayanahalli if (kprobe_enabled) 1163bf8f6e5bSAnanth N Mavinakayanahalli buf[0] = '1'; 1164bf8f6e5bSAnanth N Mavinakayanahalli else 1165bf8f6e5bSAnanth N Mavinakayanahalli buf[0] = '0'; 1166bf8f6e5bSAnanth N Mavinakayanahalli buf[1] = '\n'; 1167bf8f6e5bSAnanth N Mavinakayanahalli buf[2] = 0x00; 1168bf8f6e5bSAnanth N Mavinakayanahalli return simple_read_from_buffer(user_buf, count, ppos, buf, 2); 1169bf8f6e5bSAnanth N Mavinakayanahalli } 1170bf8f6e5bSAnanth N Mavinakayanahalli 1171bf8f6e5bSAnanth N Mavinakayanahalli static ssize_t write_enabled_file_bool(struct file *file, 1172bf8f6e5bSAnanth N Mavinakayanahalli const char __user *user_buf, size_t count, loff_t *ppos) 1173bf8f6e5bSAnanth N Mavinakayanahalli { 1174bf8f6e5bSAnanth N Mavinakayanahalli char buf[32]; 1175bf8f6e5bSAnanth N Mavinakayanahalli int buf_size; 1176bf8f6e5bSAnanth N Mavinakayanahalli 1177bf8f6e5bSAnanth N Mavinakayanahalli buf_size = min(count, (sizeof(buf)-1)); 1178bf8f6e5bSAnanth N Mavinakayanahalli if (copy_from_user(buf, user_buf, buf_size)) 1179bf8f6e5bSAnanth N Mavinakayanahalli return -EFAULT; 1180bf8f6e5bSAnanth N Mavinakayanahalli 1181bf8f6e5bSAnanth N Mavinakayanahalli switch (buf[0]) { 1182bf8f6e5bSAnanth N Mavinakayanahalli case 'y': 1183bf8f6e5bSAnanth N Mavinakayanahalli case 'Y': 1184bf8f6e5bSAnanth N Mavinakayanahalli case '1': 1185bf8f6e5bSAnanth N Mavinakayanahalli enable_all_kprobes(); 1186bf8f6e5bSAnanth N Mavinakayanahalli break; 1187bf8f6e5bSAnanth N Mavinakayanahalli case 'n': 1188bf8f6e5bSAnanth N Mavinakayanahalli case 'N': 1189bf8f6e5bSAnanth N Mavinakayanahalli case '0': 1190bf8f6e5bSAnanth N Mavinakayanahalli disable_all_kprobes(); 1191bf8f6e5bSAnanth N Mavinakayanahalli break; 1192bf8f6e5bSAnanth N Mavinakayanahalli } 1193bf8f6e5bSAnanth N Mavinakayanahalli 1194bf8f6e5bSAnanth N Mavinakayanahalli return count; 1195bf8f6e5bSAnanth N Mavinakayanahalli } 1196bf8f6e5bSAnanth N Mavinakayanahalli 1197bf8f6e5bSAnanth N Mavinakayanahalli static struct file_operations fops_kp = { 1198bf8f6e5bSAnanth N Mavinakayanahalli .read = read_enabled_file_bool, 1199bf8f6e5bSAnanth N Mavinakayanahalli .write = write_enabled_file_bool, 1200bf8f6e5bSAnanth N Mavinakayanahalli }; 1201bf8f6e5bSAnanth N Mavinakayanahalli 1202346fd59bSSrinivasa Ds static int __kprobes debugfs_kprobe_init(void) 1203346fd59bSSrinivasa Ds { 1204346fd59bSSrinivasa Ds struct dentry *dir, *file; 1205bf8f6e5bSAnanth N Mavinakayanahalli unsigned int value = 1; 1206346fd59bSSrinivasa Ds 1207346fd59bSSrinivasa Ds dir = debugfs_create_dir("kprobes", NULL); 1208346fd59bSSrinivasa Ds if (!dir) 1209346fd59bSSrinivasa Ds return -ENOMEM; 1210346fd59bSSrinivasa Ds 1211e3869792SRandy Dunlap file = debugfs_create_file("list", 0444, dir, NULL, 1212346fd59bSSrinivasa Ds &debugfs_kprobes_operations); 1213346fd59bSSrinivasa Ds if (!file) { 1214346fd59bSSrinivasa Ds debugfs_remove(dir); 1215346fd59bSSrinivasa Ds return -ENOMEM; 1216346fd59bSSrinivasa Ds } 1217346fd59bSSrinivasa Ds 1218bf8f6e5bSAnanth N Mavinakayanahalli file = debugfs_create_file("enabled", 0600, dir, 1219bf8f6e5bSAnanth N Mavinakayanahalli &value, &fops_kp); 1220bf8f6e5bSAnanth N Mavinakayanahalli if (!file) { 1221bf8f6e5bSAnanth N Mavinakayanahalli debugfs_remove(dir); 1222bf8f6e5bSAnanth N Mavinakayanahalli return -ENOMEM; 1223bf8f6e5bSAnanth N Mavinakayanahalli } 1224bf8f6e5bSAnanth N Mavinakayanahalli 1225346fd59bSSrinivasa Ds return 0; 1226346fd59bSSrinivasa Ds } 1227346fd59bSSrinivasa Ds 1228346fd59bSSrinivasa Ds late_initcall(debugfs_kprobe_init); 1229346fd59bSSrinivasa Ds #endif /* CONFIG_DEBUG_FS */ 1230346fd59bSSrinivasa Ds 1231346fd59bSSrinivasa Ds module_init(init_kprobes); 12321da177e4SLinus Torvalds 12331da177e4SLinus Torvalds EXPORT_SYMBOL_GPL(register_kprobe); 12341da177e4SLinus Torvalds EXPORT_SYMBOL_GPL(unregister_kprobe); 12359861668fSMasami Hiramatsu EXPORT_SYMBOL_GPL(register_kprobes); 12369861668fSMasami Hiramatsu EXPORT_SYMBOL_GPL(unregister_kprobes); 12371da177e4SLinus Torvalds EXPORT_SYMBOL_GPL(register_jprobe); 12381da177e4SLinus Torvalds EXPORT_SYMBOL_GPL(unregister_jprobe); 1239cd5bfea2SPeter Chubb #ifdef CONFIG_KPROBES 12401da177e4SLinus Torvalds EXPORT_SYMBOL_GPL(jprobe_return); 1241cd5bfea2SPeter Chubb #endif 1242cd5bfea2SPeter Chubb 1243cd5bfea2SPeter Chubb #ifdef CONFIG_KPROBES 1244b94cce92SHien Nguyen EXPORT_SYMBOL_GPL(register_kretprobe); 1245b94cce92SHien Nguyen EXPORT_SYMBOL_GPL(unregister_kretprobe); 1246*4a296e07SMasami Hiramatsu EXPORT_SYMBOL_GPL(register_kretprobes); 1247*4a296e07SMasami Hiramatsu EXPORT_SYMBOL_GPL(unregister_kretprobes); 1248cd5bfea2SPeter Chubb #endif 1249