xref: /openbmc/linux/kernel/extable.c (revision e8cac8b1d10589be45671a5ade0926a639b543b7)
11da177e4SLinus Torvalds /* Rewritten by Rusty Russell, on the backs of many others...
21da177e4SLinus Torvalds    Copyright (C) 2001 Rusty Russell, 2002 Rusty Russell IBM.
31da177e4SLinus Torvalds 
41da177e4SLinus Torvalds     This program is free software; you can redistribute it and/or modify
51da177e4SLinus Torvalds     it under the terms of the GNU General Public License as published by
61da177e4SLinus Torvalds     the Free Software Foundation; either version 2 of the License, or
71da177e4SLinus Torvalds     (at your option) any later version.
81da177e4SLinus Torvalds 
91da177e4SLinus Torvalds     This program is distributed in the hope that it will be useful,
101da177e4SLinus Torvalds     but WITHOUT ANY WARRANTY; without even the implied warranty of
111da177e4SLinus Torvalds     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
121da177e4SLinus Torvalds     GNU General Public License for more details.
131da177e4SLinus Torvalds 
141da177e4SLinus Torvalds     You should have received a copy of the GNU General Public License
151da177e4SLinus Torvalds     along with this program; if not, write to the Free Software
161da177e4SLinus Torvalds     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
171da177e4SLinus Torvalds */
188b96f011SFrederic Weisbecker #include <linux/ftrace.h>
19f80d2d77SDmitri Vorobiev #include <linux/memory.h>
208a293be0SPaul Gortmaker #include <linux/extable.h>
21505f2b97SIngo Molnar #include <linux/module.h>
22505f2b97SIngo Molnar #include <linux/mutex.h>
23505f2b97SIngo Molnar #include <linux/init.h>
245b485629SMasami Hiramatsu #include <linux/kprobes.h>
2574451e66SDaniel Borkmann #include <linux/filter.h>
26505f2b97SIngo Molnar 
271da177e4SLinus Torvalds #include <asm/sections.h>
287c0f6ba6SLinus Torvalds #include <linux/uaccess.h>
29505f2b97SIngo Molnar 
30505f2b97SIngo Molnar /*
31505f2b97SIngo Molnar  * mutex protecting text section modification (dynamic code patching).
32505f2b97SIngo Molnar  * some users need to sleep (allocating memory...) while they hold this lock.
33505f2b97SIngo Molnar  *
34505f2b97SIngo Molnar  * NOT exported to modules - patching kernel text is a really delicate matter.
35505f2b97SIngo Molnar  */
36505f2b97SIngo Molnar DEFINE_MUTEX(text_mutex);
371da177e4SLinus Torvalds 
381da177e4SLinus Torvalds extern struct exception_table_entry __start___ex_table[];
391da177e4SLinus Torvalds extern struct exception_table_entry __stop___ex_table[];
401da177e4SLinus Torvalds 
41d219e2e8SDavid Daney /* Cleared by build time tools if the table is already sorted. */
4200b71030SAndi Kleen u32 __initdata __visible main_extable_sort_needed = 1;
43d219e2e8SDavid Daney 
441da177e4SLinus Torvalds /* Sort the kernel's built-in exception table */
451da177e4SLinus Torvalds void __init sort_main_extable(void)
461da177e4SLinus Torvalds {
47e656a634SUwe Kleine-König 	if (main_extable_sort_needed && __stop___ex_table > __start___ex_table) {
48bec1b9e7SBorislav Petkov 		pr_notice("Sorting __ex_table...\n");
491da177e4SLinus Torvalds 		sort_extable(__start___ex_table, __stop___ex_table);
50bec1b9e7SBorislav Petkov 	}
511da177e4SLinus Torvalds }
521da177e4SLinus Torvalds 
531da177e4SLinus Torvalds /* Given an address, look for it in the exception tables. */
541da177e4SLinus Torvalds const struct exception_table_entry *search_exception_tables(unsigned long addr)
551da177e4SLinus Torvalds {
561da177e4SLinus Torvalds 	const struct exception_table_entry *e;
571da177e4SLinus Torvalds 
58a94c33ddSThomas Meyer 	e = search_extable(__start___ex_table,
59a94c33ddSThomas Meyer 			   __stop___ex_table - __start___ex_table, addr);
601da177e4SLinus Torvalds 	if (!e)
611da177e4SLinus Torvalds 		e = search_module_extables(addr);
621da177e4SLinus Torvalds 	return e;
631da177e4SLinus Torvalds }
641da177e4SLinus Torvalds 
654a44bac1SIngo Molnar static inline int init_kernel_text(unsigned long addr)
664a44bac1SIngo Molnar {
674a44bac1SIngo Molnar 	if (addr >= (unsigned long)_sinittext &&
685ecbe3c3SHelge Deller 	    addr < (unsigned long)_einittext)
694a44bac1SIngo Molnar 		return 1;
704a44bac1SIngo Molnar 	return 0;
714a44bac1SIngo Molnar }
724a44bac1SIngo Molnar 
73c0d80ddaSMarcin Nowakowski int notrace core_kernel_text(unsigned long addr)
741da177e4SLinus Torvalds {
751da177e4SLinus Torvalds 	if (addr >= (unsigned long)_stext &&
765ecbe3c3SHelge Deller 	    addr < (unsigned long)_etext)
771da177e4SLinus Torvalds 		return 1;
781da177e4SLinus Torvalds 
790594729cSThomas Gleixner 	if (system_state < SYSTEM_RUNNING &&
804a44bac1SIngo Molnar 	    init_kernel_text(addr))
811da177e4SLinus Torvalds 		return 1;
821da177e4SLinus Torvalds 	return 0;
831da177e4SLinus Torvalds }
841da177e4SLinus Torvalds 
85a2d063acSSteven Rostedt /**
86a2d063acSSteven Rostedt  * core_kernel_data - tell if addr points to kernel data
87a2d063acSSteven Rostedt  * @addr: address to test
88a2d063acSSteven Rostedt  *
89a2d063acSSteven Rostedt  * Returns true if @addr passed in is from the core kernel data
90a2d063acSSteven Rostedt  * section.
91a2d063acSSteven Rostedt  *
92a2d063acSSteven Rostedt  * Note: On some archs it may return true for core RODATA, and false
93a2d063acSSteven Rostedt  *  for others. But will always be true for core RW data.
94a2d063acSSteven Rostedt  */
95cdbe61bfSSteven Rostedt int core_kernel_data(unsigned long addr)
96cdbe61bfSSteven Rostedt {
97a2d063acSSteven Rostedt 	if (addr >= (unsigned long)_sdata &&
98cdbe61bfSSteven Rostedt 	    addr < (unsigned long)_edata)
99cdbe61bfSSteven Rostedt 		return 1;
100cdbe61bfSSteven Rostedt 	return 0;
101cdbe61bfSSteven Rostedt }
102cdbe61bfSSteven Rostedt 
1033861a17bSFrederic Weisbecker int __kernel_text_address(unsigned long addr)
1041da177e4SLinus Torvalds {
1059aadde91SSteven Rostedt (VMware) 	if (kernel_text_address(addr))
10674451e66SDaniel Borkmann 		return 1;
1074a44bac1SIngo Molnar 	/*
1084a44bac1SIngo Molnar 	 * There might be init symbols in saved stacktraces.
1094a44bac1SIngo Molnar 	 * Give those symbols a chance to be printed in
1104a44bac1SIngo Molnar 	 * backtraces (such as lockdep traces).
1114a44bac1SIngo Molnar 	 *
1124a44bac1SIngo Molnar 	 * Since we are after the module-symbols check, there's
1134a44bac1SIngo Molnar 	 * no danger of address overlap:
1144a44bac1SIngo Molnar 	 */
1154a44bac1SIngo Molnar 	if (init_kernel_text(addr))
1164a44bac1SIngo Molnar 		return 1;
1174a44bac1SIngo Molnar 	return 0;
1181da177e4SLinus Torvalds }
1191da177e4SLinus Torvalds 
1201da177e4SLinus Torvalds int kernel_text_address(unsigned long addr)
1211da177e4SLinus Torvalds {
122*e8cac8b1SSteven Rostedt (VMware) 	bool no_rcu;
123*e8cac8b1SSteven Rostedt (VMware) 	int ret = 1;
124*e8cac8b1SSteven Rostedt (VMware) 
1251da177e4SLinus Torvalds 	if (core_kernel_text(addr))
1261da177e4SLinus Torvalds 		return 1;
127*e8cac8b1SSteven Rostedt (VMware) 
128*e8cac8b1SSteven Rostedt (VMware) 	/*
129*e8cac8b1SSteven Rostedt (VMware) 	 * If a stack dump happens while RCU is not watching, then
130*e8cac8b1SSteven Rostedt (VMware) 	 * RCU needs to be notified that it requires to start
131*e8cac8b1SSteven Rostedt (VMware) 	 * watching again. This can happen either by tracing that
132*e8cac8b1SSteven Rostedt (VMware) 	 * triggers a stack trace, or a WARN() that happens during
133*e8cac8b1SSteven Rostedt (VMware) 	 * coming back from idle, or cpu on or offlining.
134*e8cac8b1SSteven Rostedt (VMware) 	 *
135*e8cac8b1SSteven Rostedt (VMware) 	 * is_module_text_address() as well as the kprobe slots
136*e8cac8b1SSteven Rostedt (VMware) 	 * and is_bpf_text_address() require RCU to be watching.
137*e8cac8b1SSteven Rostedt (VMware) 	 */
138*e8cac8b1SSteven Rostedt (VMware) 	no_rcu = !rcu_is_watching();
139*e8cac8b1SSteven Rostedt (VMware) 
140*e8cac8b1SSteven Rostedt (VMware) 	/* Treat this like an NMI as it can happen anywhere */
141*e8cac8b1SSteven Rostedt (VMware) 	if (no_rcu)
142*e8cac8b1SSteven Rostedt (VMware) 		rcu_nmi_enter();
143*e8cac8b1SSteven Rostedt (VMware) 
144aec0be2dSSteven Rostedt (Red Hat) 	if (is_module_text_address(addr))
145*e8cac8b1SSteven Rostedt (VMware) 		goto out;
1465b485629SMasami Hiramatsu 	if (is_ftrace_trampoline(addr))
147*e8cac8b1SSteven Rostedt (VMware) 		goto out;
1485b485629SMasami Hiramatsu 	if (is_kprobe_optinsn_slot(addr) || is_kprobe_insn_slot(addr))
149*e8cac8b1SSteven Rostedt (VMware) 		goto out;
15074451e66SDaniel Borkmann 	if (is_bpf_text_address(addr))
151*e8cac8b1SSteven Rostedt (VMware) 		goto out;
152*e8cac8b1SSteven Rostedt (VMware) 	ret = 0;
153*e8cac8b1SSteven Rostedt (VMware) out:
154*e8cac8b1SSteven Rostedt (VMware) 	if (no_rcu)
155*e8cac8b1SSteven Rostedt (VMware) 		rcu_nmi_exit();
156*e8cac8b1SSteven Rostedt (VMware) 
157*e8cac8b1SSteven Rostedt (VMware) 	return ret;
1581da177e4SLinus Torvalds }
159ab7476cfSArjan van de Ven 
160ab7476cfSArjan van de Ven /*
161ab7476cfSArjan van de Ven  * On some architectures (PPC64, IA64) function pointers
162ab7476cfSArjan van de Ven  * are actually only tokens to some data that then holds the
163ab7476cfSArjan van de Ven  * real function address. As a result, to find if a function
164ab7476cfSArjan van de Ven  * pointer is part of the kernel text, we need to do some
165ab7476cfSArjan van de Ven  * special dereferencing first.
166ab7476cfSArjan van de Ven  */
167ab7476cfSArjan van de Ven int func_ptr_is_kernel_text(void *ptr)
168ab7476cfSArjan van de Ven {
169ab7476cfSArjan van de Ven 	unsigned long addr;
170ab7476cfSArjan van de Ven 	addr = (unsigned long) dereference_function_descriptor(ptr);
171ab7476cfSArjan van de Ven 	if (core_kernel_text(addr))
172ab7476cfSArjan van de Ven 		return 1;
173a6e6abd5SRusty Russell 	return is_module_text_address(addr);
174ab7476cfSArjan van de Ven }
175