linux/kernel/extable.c
<<
>>
Prefs
   1/* Rewritten by Rusty Russell, on the backs of many others...
   2   Copyright (C) 2001 Rusty Russell, 2002 Rusty Russell IBM.
   3
   4    This program is free software; you can redistribute it and/or modify
   5    it under the terms of the GNU General Public License as published by
   6    the Free Software Foundation; either version 2 of the License, or
   7    (at your option) any later version.
   8
   9    This program is distributed in the hope that it will be useful,
  10    but WITHOUT ANY WARRANTY; without even the implied warranty of
  11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12    GNU General Public License for more details.
  13
  14    You should have received a copy of the GNU General Public License
  15    along with this program; if not, write to the Free Software
  16    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  17*/
  18#include <linux/ftrace.h>
  19#include <linux/memory.h>
  20#include <linux/extable.h>
  21#include <linux/module.h>
  22#include <linux/mutex.h>
  23#include <linux/init.h>
  24#include <linux/kprobes.h>
  25#include <linux/filter.h>
  26
  27#include <asm/sections.h>
  28#include <linux/uaccess.h>
  29
  30/*
  31 * mutex protecting text section modification (dynamic code patching).
  32 * some users need to sleep (allocating memory...) while they hold this lock.
  33 *
  34 * Note: Also protects SMP-alternatives modification on x86.
  35 *
  36 * NOT exported to modules - patching kernel text is a really delicate matter.
  37 */
  38DEFINE_MUTEX(text_mutex);
  39
  40extern struct exception_table_entry __start___ex_table[];
  41extern struct exception_table_entry __stop___ex_table[];
  42
  43/* Cleared by build time tools if the table is already sorted. */
  44u32 __initdata __visible main_extable_sort_needed = 1;
  45
  46/* Sort the kernel's built-in exception table */
  47void __init sort_main_extable(void)
  48{
  49        if (main_extable_sort_needed && __stop___ex_table > __start___ex_table) {
  50                pr_notice("Sorting __ex_table...\n");
  51                sort_extable(__start___ex_table, __stop___ex_table);
  52        }
  53}
  54
  55/* Given an address, look for it in the exception tables. */
  56const struct exception_table_entry *search_exception_tables(unsigned long addr)
  57{
  58        const struct exception_table_entry *e;
  59
  60        e = search_extable(__start___ex_table,
  61                           __stop___ex_table - __start___ex_table, addr);
  62        if (!e)
  63                e = search_module_extables(addr);
  64        return e;
  65}
  66
  67int init_kernel_text(unsigned long addr)
  68{
  69        if (addr >= (unsigned long)_sinittext &&
  70            addr < (unsigned long)_einittext)
  71                return 1;
  72        return 0;
  73}
  74
  75int notrace core_kernel_text(unsigned long addr)
  76{
  77        if (addr >= (unsigned long)_stext &&
  78            addr < (unsigned long)_etext)
  79                return 1;
  80
  81        if (system_state < SYSTEM_RUNNING &&
  82            init_kernel_text(addr))
  83                return 1;
  84        return 0;
  85}
  86
  87/**
  88 * core_kernel_data - tell if addr points to kernel data
  89 * @addr: address to test
  90 *
  91 * Returns true if @addr passed in is from the core kernel data
  92 * section.
  93 *
  94 * Note: On some archs it may return true for core RODATA, and false
  95 *  for others. But will always be true for core RW data.
  96 */
  97int core_kernel_data(unsigned long addr)
  98{
  99        if (addr >= (unsigned long)_sdata &&
 100            addr < (unsigned long)_edata)
 101                return 1;
 102        return 0;
 103}
 104
 105int __kernel_text_address(unsigned long addr)
 106{
 107        if (kernel_text_address(addr))
 108                return 1;
 109        /*
 110         * There might be init symbols in saved stacktraces.
 111         * Give those symbols a chance to be printed in
 112         * backtraces (such as lockdep traces).
 113         *
 114         * Since we are after the module-symbols check, there's
 115         * no danger of address overlap:
 116         */
 117        if (init_kernel_text(addr))
 118                return 1;
 119        return 0;
 120}
 121
 122int kernel_text_address(unsigned long addr)
 123{
 124        bool no_rcu;
 125        int ret = 1;
 126
 127        if (core_kernel_text(addr))
 128                return 1;
 129
 130        /*
 131         * If a stack dump happens while RCU is not watching, then
 132         * RCU needs to be notified that it requires to start
 133         * watching again. This can happen either by tracing that
 134         * triggers a stack trace, or a WARN() that happens during
 135         * coming back from idle, or cpu on or offlining.
 136         *
 137         * is_module_text_address() as well as the kprobe slots
 138         * and is_bpf_text_address() require RCU to be watching.
 139         */
 140        no_rcu = !rcu_is_watching();
 141
 142        /* Treat this like an NMI as it can happen anywhere */
 143        if (no_rcu)
 144                rcu_nmi_enter();
 145
 146        if (is_module_text_address(addr))
 147                goto out;
 148        if (is_ftrace_trampoline(addr))
 149                goto out;
 150        if (is_kprobe_optinsn_slot(addr) || is_kprobe_insn_slot(addr))
 151                goto out;
 152        if (is_bpf_text_address(addr))
 153                goto out;
 154        ret = 0;
 155out:
 156        if (no_rcu)
 157                rcu_nmi_exit();
 158
 159        return ret;
 160}
 161
 162/*
 163 * On some architectures (PPC64, IA64) function pointers
 164 * are actually only tokens to some data that then holds the
 165 * real function address. As a result, to find if a function
 166 * pointer is part of the kernel text, we need to do some
 167 * special dereferencing first.
 168 */
 169int func_ptr_is_kernel_text(void *ptr)
 170{
 171        unsigned long addr;
 172        addr = (unsigned long) dereference_function_descriptor(ptr);
 173        if (core_kernel_text(addr))
 174                return 1;
 175        return is_module_text_address(addr);
 176}
 177