LCOV - code coverage report
Current view: top level - kernel - stacktrace.c (source / functions) Hit Total Coverage
Test: landlock.info Lines: 14 65 21.5 %
Date: 2021-04-22 12:43:58 Functions: 2 9 22.2 %

          Line data    Source code
       1             : // SPDX-License-Identifier: GPL-2.0-only
       2             : /*
       3             :  * kernel/stacktrace.c
       4             :  *
       5             :  * Stack trace management functions
       6             :  *
       7             :  *  Copyright (C) 2006 Red Hat, Inc., Ingo Molnar <mingo@redhat.com>
       8             :  */
       9             : #include <linux/sched/task_stack.h>
      10             : #include <linux/sched/debug.h>
      11             : #include <linux/sched.h>
      12             : #include <linux/kernel.h>
      13             : #include <linux/export.h>
      14             : #include <linux/kallsyms.h>
      15             : #include <linux/stacktrace.h>
      16             : 
      17             : /**
      18             :  * stack_trace_print - Print the entries in the stack trace
      19             :  * @entries:    Pointer to storage array
      20             :  * @nr_entries: Number of entries in the storage array
      21             :  * @spaces:     Number of leading spaces to print
      22             :  */
      23           0 : void stack_trace_print(const unsigned long *entries, unsigned int nr_entries,
      24             :                        int spaces)
      25             : {
      26           0 :         unsigned int i;
      27             : 
      28           0 :         if (WARN_ON(!entries))
      29             :                 return;
      30             : 
      31           0 :         for (i = 0; i < nr_entries; i++)
      32           0 :                 printk("%*c%pS\n", 1 + spaces, ' ', (void *)entries[i]);
      33             : }
      34             : EXPORT_SYMBOL_GPL(stack_trace_print);
      35             : 
      36             : /**
      37             :  * stack_trace_snprint - Print the entries in the stack trace into a buffer
      38             :  * @buf:        Pointer to the print buffer
      39             :  * @size:       Size of the print buffer
      40             :  * @entries:    Pointer to storage array
      41             :  * @nr_entries: Number of entries in the storage array
      42             :  * @spaces:     Number of leading spaces to print
      43             :  *
      44             :  * Return: Number of bytes printed.
      45             :  */
      46           0 : int stack_trace_snprint(char *buf, size_t size, const unsigned long *entries,
      47             :                         unsigned int nr_entries, int spaces)
      48             : {
      49           0 :         unsigned int generated, i, total = 0;
      50             : 
      51           0 :         if (WARN_ON(!entries))
      52             :                 return 0;
      53             : 
      54           0 :         for (i = 0; i < nr_entries && size; i++) {
      55           0 :                 generated = snprintf(buf, size, "%*c%pS\n", 1 + spaces, ' ',
      56           0 :                                      (void *)entries[i]);
      57             : 
      58           0 :                 total += generated;
      59           0 :                 if (generated >= size) {
      60           0 :                         buf += size;
      61           0 :                         size = 0;
      62             :                 } else {
      63           0 :                         buf += generated;
      64           0 :                         size -= generated;
      65             :                 }
      66             :         }
      67             : 
      68           0 :         return total;
      69             : }
      70             : EXPORT_SYMBOL_GPL(stack_trace_snprint);
      71             : 
      72             : #ifdef CONFIG_ARCH_STACKWALK
      73             : 
      74             : struct stacktrace_cookie {
      75             :         unsigned long   *store;
      76             :         unsigned int    size;
      77             :         unsigned int    skip;
      78             :         unsigned int    len;
      79             : };
      80             : 
      81    61988239 : static bool stack_trace_consume_entry(void *cookie, unsigned long addr)
      82             : {
      83    61988239 :         struct stacktrace_cookie *c = cookie;
      84             : 
      85    61988239 :         if (c->len >= c->size)
      86             :                 return false;
      87             : 
      88    61988239 :         if (c->skip > 0) {
      89     4847956 :                 c->skip--;
      90     4847956 :                 return true;
      91             :         }
      92    57140283 :         c->store[c->len++] = addr;
      93    57140283 :         return c->len < c->size;
      94             : }
      95             : 
      96           0 : static bool stack_trace_consume_entry_nosched(void *cookie, unsigned long addr)
      97             : {
      98           0 :         if (in_sched_functions(addr))
      99             :                 return true;
     100           0 :         return stack_trace_consume_entry(cookie, addr);
     101             : }
     102             : 
     103             : /**
     104             :  * stack_trace_save - Save a stack trace into a storage array
     105             :  * @store:      Pointer to storage array
     106             :  * @size:       Size of the storage array
     107             :  * @skipnr:     Number of entries to skip at the start of the stack trace
     108             :  *
     109             :  * Return: Number of trace entries stored.
     110             :  */
     111     3596956 : unsigned int stack_trace_save(unsigned long *store, unsigned int size,
     112             :                               unsigned int skipnr)
     113             : {
     114     3596956 :         stack_trace_consume_fn consume_entry = stack_trace_consume_entry;
     115     3596956 :         struct stacktrace_cookie c = {
     116             :                 .store  = store,
     117             :                 .size   = size,
     118     3596956 :                 .skip   = skipnr + 1,
     119             :         };
     120             : 
     121     3596956 :         arch_stack_walk(consume_entry, &c, current, NULL);
     122     3603365 :         return c.len;
     123             : }
     124             : EXPORT_SYMBOL_GPL(stack_trace_save);
     125             : 
     126             : /**
     127             :  * stack_trace_save_tsk - Save a task stack trace into a storage array
     128             :  * @task:       The task to examine
     129             :  * @store:      Pointer to storage array
     130             :  * @size:       Size of the storage array
     131             :  * @skipnr:     Number of entries to skip at the start of the stack trace
     132             :  *
     133             :  * Return: Number of trace entries stored.
     134             :  */
     135           0 : unsigned int stack_trace_save_tsk(struct task_struct *tsk, unsigned long *store,
     136             :                                   unsigned int size, unsigned int skipnr)
     137             : {
     138           0 :         stack_trace_consume_fn consume_entry = stack_trace_consume_entry_nosched;
     139           0 :         struct stacktrace_cookie c = {
     140             :                 .store  = store,
     141             :                 .size   = size,
     142             :                 /* skip this function if they are tracing us */
     143           0 :                 .skip   = skipnr + (current == tsk),
     144             :         };
     145             : 
     146           0 :         if (!try_get_task_stack(tsk))
     147             :                 return 0;
     148             : 
     149           0 :         arch_stack_walk(consume_entry, &c, tsk, NULL);
     150           0 :         put_task_stack(tsk);
     151           0 :         return c.len;
     152             : }
     153             : 
     154             : /**
     155             :  * stack_trace_save_regs - Save a stack trace based on pt_regs into a storage array
     156             :  * @regs:       Pointer to pt_regs to examine
     157             :  * @store:      Pointer to storage array
     158             :  * @size:       Size of the storage array
     159             :  * @skipnr:     Number of entries to skip at the start of the stack trace
     160             :  *
     161             :  * Return: Number of trace entries stored.
     162             :  */
     163           0 : unsigned int stack_trace_save_regs(struct pt_regs *regs, unsigned long *store,
     164             :                                    unsigned int size, unsigned int skipnr)
     165             : {
     166           0 :         stack_trace_consume_fn consume_entry = stack_trace_consume_entry;
     167           0 :         struct stacktrace_cookie c = {
     168             :                 .store  = store,
     169             :                 .size   = size,
     170             :                 .skip   = skipnr,
     171             :         };
     172             : 
     173           0 :         arch_stack_walk(consume_entry, &c, current, regs);
     174           0 :         return c.len;
     175             : }
     176             : 
     177             : #ifdef CONFIG_HAVE_RELIABLE_STACKTRACE
     178             : /**
     179             :  * stack_trace_save_tsk_reliable - Save task stack with verification
     180             :  * @tsk:        Pointer to the task to examine
     181             :  * @store:      Pointer to storage array
     182             :  * @size:       Size of the storage array
     183             :  *
     184             :  * Return:      An error if it detects any unreliable features of the
     185             :  *              stack. Otherwise it guarantees that the stack trace is
     186             :  *              reliable and returns the number of entries stored.
     187             :  *
     188             :  * If the task is not 'current', the caller *must* ensure the task is inactive.
     189             :  */
     190           0 : int stack_trace_save_tsk_reliable(struct task_struct *tsk, unsigned long *store,
     191             :                                   unsigned int size)
     192             : {
     193           0 :         stack_trace_consume_fn consume_entry = stack_trace_consume_entry;
     194           0 :         struct stacktrace_cookie c = {
     195             :                 .store  = store,
     196             :                 .size   = size,
     197             :         };
     198           0 :         int ret;
     199             : 
     200             :         /*
     201             :          * If the task doesn't have a stack (e.g., a zombie), the stack is
     202             :          * "reliably" empty.
     203             :          */
     204           0 :         if (!try_get_task_stack(tsk))
     205             :                 return 0;
     206             : 
     207           0 :         ret = arch_stack_walk_reliable(consume_entry, &c, tsk);
     208           0 :         put_task_stack(tsk);
     209           0 :         return ret ? ret : c.len;
     210             : }
     211             : #endif
     212             : 
     213             : #ifdef CONFIG_USER_STACKTRACE_SUPPORT
     214             : /**
     215             :  * stack_trace_save_user - Save a user space stack trace into a storage array
     216             :  * @store:      Pointer to storage array
     217             :  * @size:       Size of the storage array
     218             :  *
     219             :  * Return: Number of trace entries stored.
     220             :  */
     221           0 : unsigned int stack_trace_save_user(unsigned long *store, unsigned int size)
     222             : {
     223           0 :         stack_trace_consume_fn consume_entry = stack_trace_consume_entry;
     224           0 :         struct stacktrace_cookie c = {
     225             :                 .store  = store,
     226             :                 .size   = size,
     227             :         };
     228           0 :         mm_segment_t fs;
     229             : 
     230             :         /* Trace user stack if not a kernel thread */
     231           0 :         if (current->flags & PF_KTHREAD)
     232             :                 return 0;
     233             : 
     234           0 :         fs = force_uaccess_begin();
     235           0 :         arch_stack_walk_user(consume_entry, &c, task_pt_regs(current));
     236           0 :         force_uaccess_end(fs);
     237             : 
     238           0 :         return c.len;
     239             : }
     240             : #endif
     241             : 
     242             : #else /* CONFIG_ARCH_STACKWALK */
     243             : 
     244             : /*
     245             :  * Architectures that do not implement save_stack_trace_*()
     246             :  * get these weak aliases and once-per-bootup warnings
     247             :  * (whenever this facility is utilized - for example by procfs):
     248             :  */
     249             : __weak void
     250             : save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
     251             : {
     252             :         WARN_ONCE(1, KERN_INFO "save_stack_trace_tsk() not implemented yet.\n");
     253             : }
     254             : 
     255             : __weak void
     256             : save_stack_trace_regs(struct pt_regs *regs, struct stack_trace *trace)
     257             : {
     258             :         WARN_ONCE(1, KERN_INFO "save_stack_trace_regs() not implemented yet.\n");
     259             : }
     260             : 
     261             : /**
     262             :  * stack_trace_save - Save a stack trace into a storage array
     263             :  * @store:      Pointer to storage array
     264             :  * @size:       Size of the storage array
     265             :  * @skipnr:     Number of entries to skip at the start of the stack trace
     266             :  *
     267             :  * Return: Number of trace entries stored
     268             :  */
     269             : unsigned int stack_trace_save(unsigned long *store, unsigned int size,
     270             :                               unsigned int skipnr)
     271             : {
     272             :         struct stack_trace trace = {
     273             :                 .entries        = store,
     274             :                 .max_entries    = size,
     275             :                 .skip           = skipnr + 1,
     276             :         };
     277             : 
     278             :         save_stack_trace(&trace);
     279             :         return trace.nr_entries;
     280             : }
     281             : EXPORT_SYMBOL_GPL(stack_trace_save);
     282             : 
     283             : /**
     284             :  * stack_trace_save_tsk - Save a task stack trace into a storage array
     285             :  * @task:       The task to examine
     286             :  * @store:      Pointer to storage array
     287             :  * @size:       Size of the storage array
     288             :  * @skipnr:     Number of entries to skip at the start of the stack trace
     289             :  *
     290             :  * Return: Number of trace entries stored
     291             :  */
     292             : unsigned int stack_trace_save_tsk(struct task_struct *task,
     293             :                                   unsigned long *store, unsigned int size,
     294             :                                   unsigned int skipnr)
     295             : {
     296             :         struct stack_trace trace = {
     297             :                 .entries        = store,
     298             :                 .max_entries    = size,
     299             :                 /* skip this function if they are tracing us */
     300             :                 .skip   = skipnr + (current == task),
     301             :         };
     302             : 
     303             :         save_stack_trace_tsk(task, &trace);
     304             :         return trace.nr_entries;
     305             : }
     306             : 
     307             : /**
     308             :  * stack_trace_save_regs - Save a stack trace based on pt_regs into a storage array
     309             :  * @regs:       Pointer to pt_regs to examine
     310             :  * @store:      Pointer to storage array
     311             :  * @size:       Size of the storage array
     312             :  * @skipnr:     Number of entries to skip at the start of the stack trace
     313             :  *
     314             :  * Return: Number of trace entries stored
     315             :  */
     316             : unsigned int stack_trace_save_regs(struct pt_regs *regs, unsigned long *store,
     317             :                                    unsigned int size, unsigned int skipnr)
     318             : {
     319             :         struct stack_trace trace = {
     320             :                 .entries        = store,
     321             :                 .max_entries    = size,
     322             :                 .skip           = skipnr,
     323             :         };
     324             : 
     325             :         save_stack_trace_regs(regs, &trace);
     326             :         return trace.nr_entries;
     327             : }
     328             : 
     329             : #ifdef CONFIG_HAVE_RELIABLE_STACKTRACE
     330             : /**
     331             :  * stack_trace_save_tsk_reliable - Save task stack with verification
     332             :  * @tsk:        Pointer to the task to examine
     333             :  * @store:      Pointer to storage array
     334             :  * @size:       Size of the storage array
     335             :  *
     336             :  * Return:      An error if it detects any unreliable features of the
     337             :  *              stack. Otherwise it guarantees that the stack trace is
     338             :  *              reliable and returns the number of entries stored.
     339             :  *
     340             :  * If the task is not 'current', the caller *must* ensure the task is inactive.
     341             :  */
     342             : int stack_trace_save_tsk_reliable(struct task_struct *tsk, unsigned long *store,
     343             :                                   unsigned int size)
     344             : {
     345             :         struct stack_trace trace = {
     346             :                 .entries        = store,
     347             :                 .max_entries    = size,
     348             :         };
     349             :         int ret = save_stack_trace_tsk_reliable(tsk, &trace);
     350             : 
     351             :         return ret ? ret : trace.nr_entries;
     352             : }
     353             : #endif
     354             : 
     355             : #ifdef CONFIG_USER_STACKTRACE_SUPPORT
     356             : /**
     357             :  * stack_trace_save_user - Save a user space stack trace into a storage array
     358             :  * @store:      Pointer to storage array
     359             :  * @size:       Size of the storage array
     360             :  *
     361             :  * Return: Number of trace entries stored
     362             :  */
     363             : unsigned int stack_trace_save_user(unsigned long *store, unsigned int size)
     364             : {
     365             :         struct stack_trace trace = {
     366             :                 .entries        = store,
     367             :                 .max_entries    = size,
     368             :         };
     369             : 
     370             :         save_stack_trace_user(&trace);
     371             :         return trace.nr_entries;
     372             : }
     373             : #endif /* CONFIG_USER_STACKTRACE_SUPPORT */
     374             : 
     375             : #endif /* !CONFIG_ARCH_STACKWALK */

Generated by: LCOV version 1.14