LCOV - code coverage report
Current view: top level - kernel - extable.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 34 53 64.2 %
Date: 2022-03-28 13:20:08 Functions: 6 9 66.7 %
Branches: 31 62 50.0 %

           Branch data     Line data    Source code
       1                 :            : // SPDX-License-Identifier: GPL-2.0-or-later
       2                 :            : /* Rewritten by Rusty Russell, on the backs of many others...
       3                 :            :    Copyright (C) 2001 Rusty Russell, 2002 Rusty Russell IBM.
       4                 :            : 
       5                 :            : */
       6                 :            : #include <linux/ftrace.h>
       7                 :            : #include <linux/memory.h>
       8                 :            : #include <linux/extable.h>
       9                 :            : #include <linux/module.h>
      10                 :            : #include <linux/mutex.h>
      11                 :            : #include <linux/init.h>
      12                 :            : #include <linux/kprobes.h>
      13                 :            : #include <linux/filter.h>
      14                 :            : 
      15                 :            : #include <asm/sections.h>
      16                 :            : #include <linux/uaccess.h>
      17                 :            : 
      18                 :            : /*
      19                 :            :  * mutex protecting text section modification (dynamic code patching).
      20                 :            :  * some users need to sleep (allocating memory...) while they hold this lock.
      21                 :            :  *
      22                 :            :  * Note: Also protects SMP-alternatives modification on x86.
      23                 :            :  *
      24                 :            :  * NOT exported to modules - patching kernel text is a really delicate matter.
      25                 :            :  */
      26                 :            : DEFINE_MUTEX(text_mutex);
      27                 :            : 
      28                 :            : extern struct exception_table_entry __start___ex_table[];
      29                 :            : extern struct exception_table_entry __stop___ex_table[];
      30                 :            : 
      31                 :            : /* Cleared by build time tools if the table is already sorted. */
      32                 :            : u32 __initdata __visible main_extable_sort_needed = 1;
      33                 :            : 
      34                 :            : /* Sort the kernel's built-in exception table */
      35                 :         30 : void __init sort_main_extable(void)
      36                 :            : {
      37   [ -  +  -  - ]:         30 :         if (main_extable_sort_needed && __stop___ex_table > __start___ex_table) {
      38                 :          0 :                 pr_notice("Sorting __ex_table...\n");
      39                 :          0 :                 sort_extable(__start___ex_table, __stop___ex_table);
      40                 :            :         }
      41                 :         30 : }
      42                 :            : 
      43                 :            : /* Given an address, look for it in the kernel exception table */
      44                 :            : const
      45                 :        652 : struct exception_table_entry *search_kernel_exception_table(unsigned long addr)
      46                 :            : {
      47                 :        652 :         return search_extable(__start___ex_table,
      48                 :          0 :                               __stop___ex_table - __start___ex_table, addr);
      49                 :            : }
      50                 :            : 
      51                 :            : /* Given an address, look for it in the exception tables. */
      52                 :        652 : const struct exception_table_entry *search_exception_tables(unsigned long addr)
      53                 :            : {
      54                 :        652 :         const struct exception_table_entry *e;
      55                 :            : 
      56                 :        652 :         e = search_kernel_exception_table(addr);
      57         [ -  + ]:        652 :         if (!e)
      58                 :          0 :                 e = search_module_extables(addr);
      59         [ -  + ]:        652 :         if (!e)
      60                 :          0 :                 e = search_bpf_extables(addr);
      61                 :        652 :         return e;
      62                 :            : }
      63                 :            : 
      64                 :      45205 : int init_kernel_text(unsigned long addr)
      65                 :            : {
      66   [ -  -  +  +  :      11509 :         if (addr >= (unsigned long)_sinittext &&
             -  -  +  - ]
      67   [ -  -  +  +  :      12162 :             addr < (unsigned long)_einittext)
          -  +  -  -  +  
                      + ]
      68                 :        120 :                 return 1;
      69                 :            :         return 0;
      70                 :            : }
      71                 :            : 
      72                 :    1248556 : int notrace core_kernel_text(unsigned long addr)
      73                 :            : {
      74         [ +  - ]:     299760 :         if (addr >= (unsigned long)_stext &&
      75   [ -  -  +  +  :    1218056 :             addr < (unsigned long)_etext)
                   +  + ]
      76                 :            :                 return 1;
      77                 :            : 
      78   [ -  -  +  +  :      46729 :         if (system_state < SYSTEM_RUNNING &&
                   -  + ]
      79                 :            :             init_kernel_text(addr))
      80                 :          0 :                 return 1;
      81                 :            :         return 0;
      82                 :            : }
      83                 :            : 
      84                 :            : /**
      85                 :            :  * core_kernel_data - tell if addr points to kernel data
      86                 :            :  * @addr: address to test
      87                 :            :  *
      88                 :            :  * Returns true if @addr passed in is from the core kernel data
      89                 :            :  * section.
      90                 :            :  *
      91                 :            :  * Note: On some archs it may return true for core RODATA, and false
      92                 :            :  *  for others. But will always be true for core RW data.
      93                 :            :  */
      94                 :          0 : int core_kernel_data(unsigned long addr)
      95                 :            : {
      96         [ #  # ]:          0 :         if (addr >= (unsigned long)_sdata &&
      97         [ #  # ]:          0 :             addr < (unsigned long)_edata)
      98                 :          0 :                 return 1;
      99                 :            :         return 0;
     100                 :            : }
     101                 :            : 
     102                 :     912616 : int __kernel_text_address(unsigned long addr)
     103                 :            : {
     104         [ +  + ]:     912616 :         if (kernel_text_address(addr))
     105                 :            :                 return 1;
     106                 :            :         /*
     107                 :            :          * There might be init symbols in saved stacktraces.
     108                 :            :          * Give those symbols a chance to be printed in
     109                 :            :          * backtraces (such as lockdep traces).
     110                 :            :          *
     111                 :            :          * Since we are after the module-symbols check, there's
     112                 :            :          * no danger of address overlap:
     113                 :            :          */
     114         [ +  + ]:      33696 :         if (init_kernel_text(addr))
     115                 :          0 :                 return 1;
     116                 :            :         return 0;
     117                 :            : }
     118                 :            : 
     119                 :     948796 : int kernel_text_address(unsigned long addr)
     120                 :            : {
     121                 :     948796 :         bool no_rcu;
     122                 :     948796 :         int ret = 1;
     123                 :            : 
     124         [ +  + ]:     948796 :         if (core_kernel_text(addr))
     125                 :            :                 return 1;
     126                 :            : 
     127                 :            :         /*
     128                 :            :          * If a stack dump happens while RCU is not watching, then
     129                 :            :          * RCU needs to be notified that it requires to start
     130                 :            :          * watching again. This can happen either by tracing that
     131                 :            :          * triggers a stack trace, or a WARN() that happens during
     132                 :            :          * coming back from idle, or cpu on or offlining.
     133                 :            :          *
     134                 :            :          * is_module_text_address() as well as the kprobe slots,
     135                 :            :          * is_bpf_text_address() and is_bpf_image_address require
     136                 :            :          * RCU to be watching.
     137                 :            :          */
     138                 :      44239 :         no_rcu = !rcu_is_watching();
     139                 :            : 
     140                 :            :         /* Treat this like an NMI as it can happen anywhere */
     141         [ -  + ]:      44239 :         if (no_rcu)
     142                 :          0 :                 rcu_nmi_enter();
     143                 :            : 
     144         [ +  + ]:      44239 :         if (is_module_text_address(addr))
     145                 :      10543 :                 goto out;
     146                 :      33696 :         if (is_ftrace_trampoline(addr))
     147                 :            :                 goto out;
     148   [ +  -  -  + ]:      67392 :         if (is_kprobe_optinsn_slot(addr) || is_kprobe_insn_slot(addr))
     149                 :          0 :                 goto out;
     150                 :            :         if (is_bpf_text_address(addr))
     151                 :            :                 goto out;
     152                 :            :         if (is_bpf_image_address(addr))
     153                 :            :                 goto out;
     154                 :            :         ret = 0;
     155                 :      44239 : out:
     156         [ -  + ]:      44239 :         if (no_rcu)
     157                 :          0 :                 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                 :            :  */
     169                 :          0 : int func_ptr_is_kernel_text(void *ptr)
     170                 :            : {
     171                 :          0 :         unsigned long addr;
     172                 :          0 :         addr = (unsigned long) dereference_function_descriptor(ptr);
     173         [ #  # ]:          0 :         if (core_kernel_text(addr))
     174                 :            :                 return 1;
     175                 :          0 :         return is_module_text_address(addr);
     176                 :            : }

Generated by: LCOV version 1.14