11a59d1b8SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later 21da177e4SLinus Torvalds /* Rewritten by Rusty Russell, on the backs of many others... 31da177e4SLinus Torvalds Copyright (C) 2001 Rusty Russell, 2002 Rusty Russell IBM. 41da177e4SLinus Torvalds 51da177e4SLinus Torvalds */ 68b96f011SFrederic Weisbecker #include <linux/ftrace.h> 7f80d2d77SDmitri Vorobiev #include <linux/memory.h> 88a293be0SPaul Gortmaker #include <linux/extable.h> 9505f2b97SIngo Molnar #include <linux/module.h> 10505f2b97SIngo Molnar #include <linux/mutex.h> 11505f2b97SIngo Molnar #include <linux/init.h> 125b485629SMasami Hiramatsu #include <linux/kprobes.h> 1374451e66SDaniel Borkmann #include <linux/filter.h> 14505f2b97SIngo Molnar 151da177e4SLinus Torvalds #include <asm/sections.h> 167c0f6ba6SLinus Torvalds #include <linux/uaccess.h> 17505f2b97SIngo Molnar 18505f2b97SIngo Molnar /* 19505f2b97SIngo Molnar * mutex protecting text section modification (dynamic code patching). 20505f2b97SIngo Molnar * some users need to sleep (allocating memory...) while they hold this lock. 21505f2b97SIngo Molnar * 22e846d139SZhou Chengming * Note: Also protects SMP-alternatives modification on x86. 23e846d139SZhou Chengming * 24505f2b97SIngo Molnar * NOT exported to modules - patching kernel text is a really delicate matter. 25505f2b97SIngo Molnar */ 26505f2b97SIngo Molnar DEFINE_MUTEX(text_mutex); 271da177e4SLinus Torvalds 281da177e4SLinus Torvalds extern struct exception_table_entry __start___ex_table[]; 291da177e4SLinus Torvalds extern struct exception_table_entry __stop___ex_table[]; 301da177e4SLinus Torvalds 31d219e2e8SDavid Daney /* Cleared by build time tools if the table is already sorted. */ 3200b71030SAndi Kleen u32 __initdata __visible main_extable_sort_needed = 1; 33d219e2e8SDavid Daney 341da177e4SLinus Torvalds /* Sort the kernel's built-in exception table */ 351da177e4SLinus Torvalds void __init sort_main_extable(void) 361da177e4SLinus Torvalds { 37e656a634SUwe Kleine-König if (main_extable_sort_needed && __stop___ex_table > __start___ex_table) { 38bec1b9e7SBorislav Petkov pr_notice("Sorting __ex_table...\n"); 391da177e4SLinus Torvalds sort_extable(__start___ex_table, __stop___ex_table); 40bec1b9e7SBorislav Petkov } 411da177e4SLinus Torvalds } 421da177e4SLinus Torvalds 43*49ec9177SSantosh Sivaraj /* Given an address, look for it in the kernel exception table */ 44*49ec9177SSantosh Sivaraj const 45*49ec9177SSantosh Sivaraj struct exception_table_entry *search_kernel_exception_table(unsigned long addr) 46*49ec9177SSantosh Sivaraj { 47*49ec9177SSantosh Sivaraj return search_extable(__start___ex_table, 48*49ec9177SSantosh Sivaraj __stop___ex_table - __start___ex_table, addr); 49*49ec9177SSantosh Sivaraj } 50*49ec9177SSantosh Sivaraj 511da177e4SLinus Torvalds /* Given an address, look for it in the exception tables. */ 521da177e4SLinus Torvalds const struct exception_table_entry *search_exception_tables(unsigned long addr) 531da177e4SLinus Torvalds { 541da177e4SLinus Torvalds const struct exception_table_entry *e; 551da177e4SLinus Torvalds 56*49ec9177SSantosh Sivaraj e = search_kernel_exception_table(addr); 571da177e4SLinus Torvalds if (!e) 581da177e4SLinus Torvalds e = search_module_extables(addr); 591da177e4SLinus Torvalds return e; 601da177e4SLinus Torvalds } 611da177e4SLinus Torvalds 629fbcc57aSJosh Poimboeuf int init_kernel_text(unsigned long addr) 634a44bac1SIngo Molnar { 644a44bac1SIngo Molnar if (addr >= (unsigned long)_sinittext && 655ecbe3c3SHelge Deller addr < (unsigned long)_einittext) 664a44bac1SIngo Molnar return 1; 674a44bac1SIngo Molnar return 0; 684a44bac1SIngo Molnar } 694a44bac1SIngo Molnar 70c0d80ddaSMarcin Nowakowski int notrace core_kernel_text(unsigned long addr) 711da177e4SLinus Torvalds { 721da177e4SLinus Torvalds if (addr >= (unsigned long)_stext && 735ecbe3c3SHelge Deller addr < (unsigned long)_etext) 741da177e4SLinus Torvalds return 1; 751da177e4SLinus Torvalds 760594729cSThomas Gleixner if (system_state < SYSTEM_RUNNING && 774a44bac1SIngo Molnar init_kernel_text(addr)) 781da177e4SLinus Torvalds return 1; 791da177e4SLinus Torvalds return 0; 801da177e4SLinus Torvalds } 811da177e4SLinus Torvalds 82a2d063acSSteven Rostedt /** 83a2d063acSSteven Rostedt * core_kernel_data - tell if addr points to kernel data 84a2d063acSSteven Rostedt * @addr: address to test 85a2d063acSSteven Rostedt * 86a2d063acSSteven Rostedt * Returns true if @addr passed in is from the core kernel data 87a2d063acSSteven Rostedt * section. 88a2d063acSSteven Rostedt * 89a2d063acSSteven Rostedt * Note: On some archs it may return true for core RODATA, and false 90a2d063acSSteven Rostedt * for others. But will always be true for core RW data. 91a2d063acSSteven Rostedt */ 92cdbe61bfSSteven Rostedt int core_kernel_data(unsigned long addr) 93cdbe61bfSSteven Rostedt { 94a2d063acSSteven Rostedt if (addr >= (unsigned long)_sdata && 95cdbe61bfSSteven Rostedt addr < (unsigned long)_edata) 96cdbe61bfSSteven Rostedt return 1; 97cdbe61bfSSteven Rostedt return 0; 98cdbe61bfSSteven Rostedt } 99cdbe61bfSSteven Rostedt 1003861a17bSFrederic Weisbecker int __kernel_text_address(unsigned long addr) 1011da177e4SLinus Torvalds { 1029aadde91SSteven Rostedt (VMware) if (kernel_text_address(addr)) 10374451e66SDaniel Borkmann return 1; 1044a44bac1SIngo Molnar /* 1054a44bac1SIngo Molnar * There might be init symbols in saved stacktraces. 1064a44bac1SIngo Molnar * Give those symbols a chance to be printed in 1074a44bac1SIngo Molnar * backtraces (such as lockdep traces). 1084a44bac1SIngo Molnar * 1094a44bac1SIngo Molnar * Since we are after the module-symbols check, there's 1104a44bac1SIngo Molnar * no danger of address overlap: 1114a44bac1SIngo Molnar */ 1124a44bac1SIngo Molnar if (init_kernel_text(addr)) 1134a44bac1SIngo Molnar return 1; 1144a44bac1SIngo Molnar return 0; 1151da177e4SLinus Torvalds } 1161da177e4SLinus Torvalds 1171da177e4SLinus Torvalds int kernel_text_address(unsigned long addr) 1181da177e4SLinus Torvalds { 119e8cac8b1SSteven Rostedt (VMware) bool no_rcu; 120e8cac8b1SSteven Rostedt (VMware) int ret = 1; 121e8cac8b1SSteven Rostedt (VMware) 1221da177e4SLinus Torvalds if (core_kernel_text(addr)) 1231da177e4SLinus Torvalds return 1; 124e8cac8b1SSteven Rostedt (VMware) 125e8cac8b1SSteven Rostedt (VMware) /* 126e8cac8b1SSteven Rostedt (VMware) * If a stack dump happens while RCU is not watching, then 127e8cac8b1SSteven Rostedt (VMware) * RCU needs to be notified that it requires to start 128e8cac8b1SSteven Rostedt (VMware) * watching again. This can happen either by tracing that 129e8cac8b1SSteven Rostedt (VMware) * triggers a stack trace, or a WARN() that happens during 130e8cac8b1SSteven Rostedt (VMware) * coming back from idle, or cpu on or offlining. 131e8cac8b1SSteven Rostedt (VMware) * 132e8cac8b1SSteven Rostedt (VMware) * is_module_text_address() as well as the kprobe slots 133e8cac8b1SSteven Rostedt (VMware) * and is_bpf_text_address() require RCU to be watching. 134e8cac8b1SSteven Rostedt (VMware) */ 135e8cac8b1SSteven Rostedt (VMware) no_rcu = !rcu_is_watching(); 136e8cac8b1SSteven Rostedt (VMware) 137e8cac8b1SSteven Rostedt (VMware) /* Treat this like an NMI as it can happen anywhere */ 138e8cac8b1SSteven Rostedt (VMware) if (no_rcu) 139e8cac8b1SSteven Rostedt (VMware) rcu_nmi_enter(); 140e8cac8b1SSteven Rostedt (VMware) 141aec0be2dSSteven Rostedt (Red Hat) if (is_module_text_address(addr)) 142e8cac8b1SSteven Rostedt (VMware) goto out; 1435b485629SMasami Hiramatsu if (is_ftrace_trampoline(addr)) 144e8cac8b1SSteven Rostedt (VMware) goto out; 1455b485629SMasami Hiramatsu if (is_kprobe_optinsn_slot(addr) || is_kprobe_insn_slot(addr)) 146e8cac8b1SSteven Rostedt (VMware) goto out; 14774451e66SDaniel Borkmann if (is_bpf_text_address(addr)) 148e8cac8b1SSteven Rostedt (VMware) goto out; 149e8cac8b1SSteven Rostedt (VMware) ret = 0; 150e8cac8b1SSteven Rostedt (VMware) out: 151e8cac8b1SSteven Rostedt (VMware) if (no_rcu) 152e8cac8b1SSteven Rostedt (VMware) rcu_nmi_exit(); 153e8cac8b1SSteven Rostedt (VMware) 154e8cac8b1SSteven Rostedt (VMware) return ret; 1551da177e4SLinus Torvalds } 156ab7476cfSArjan van de Ven 157ab7476cfSArjan van de Ven /* 158ab7476cfSArjan van de Ven * On some architectures (PPC64, IA64) function pointers 159ab7476cfSArjan van de Ven * are actually only tokens to some data that then holds the 160ab7476cfSArjan van de Ven * real function address. As a result, to find if a function 161ab7476cfSArjan van de Ven * pointer is part of the kernel text, we need to do some 162ab7476cfSArjan van de Ven * special dereferencing first. 163ab7476cfSArjan van de Ven */ 164ab7476cfSArjan van de Ven int func_ptr_is_kernel_text(void *ptr) 165ab7476cfSArjan van de Ven { 166ab7476cfSArjan van de Ven unsigned long addr; 167ab7476cfSArjan van de Ven addr = (unsigned long) dereference_function_descriptor(ptr); 168ab7476cfSArjan van de Ven if (core_kernel_text(addr)) 169ab7476cfSArjan van de Ven return 1; 170a6e6abd5SRusty Russell return is_module_text_address(addr); 171ab7476cfSArjan van de Ven } 172