]> Git Repo - J-linux.git/commitdiff
Merge tag 'trace-v6.4-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/trace...
authorLinus Torvalds <[email protected]>
Fri, 5 May 2023 20:11:02 +0000 (13:11 -0700)
committerLinus Torvalds <[email protected]>
Fri, 5 May 2023 20:11:02 +0000 (13:11 -0700)
Pull more tracing updates from Steven Rostedt:

 - Make buffer_percent read/write.

   The buffer_percent file is how users can state how long to block on
   the tracing buffer depending on how much is in the buffer. When it
   hits the "buffer_percent" it will wake the task waiting on the
   buffer. For some reason it was set to read-only.

   This was not noticed because testing was done as root without
   SELinux, but with SELinux it will prevent even root to write to it
   without having CAP_DAC_OVERRIDE.

 - The "touched_functions" was added this merge window, but one of the
   reasons for adding it was not implemented.

   That was to show what functions were not only touched, but had either
   a direct trampoline attached to it, or a kprobe or live kernel
   patching that can "hijack" the function to run a different function.
   The point is to know if there's functions in the kernel that may not
   be behaving as the kernel code shows. This can be used for debugging.

   TODO: Add this information to kernel oops too.

* tag 'trace-v6.4-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-trace:
  ftrace: Add MODIFIED flag to show if IPMODIFY or direct was attached
  tracing: Fix permissions for the buffer_percent file

1  2 
Documentation/trace/ftrace.rst
include/linux/ftrace.h
kernel/trace/ftrace.c
kernel/trace/trace.c

index a9c8bce4bc7b5ec444472dade717f5a89cd0dee0,d5766229c71ad0117fd5be412241dadb558f0a53..027437b745a0c6a0e49d33271ac027e204fbae0a
@@@ -350,6 -350,19 +350,19 @@@ of ftrace. Here is a list of some of th
        an 'I' will be displayed on the same line as the function that
        can be overridden.
  
+       If a non ftrace trampoline is attached (BPF) a 'D' will be displayed.
+       Note, normal ftrace trampolines can also be attached, but only one
+       "direct" trampoline can be attached to a given function at a time.
+       Some architectures can not call direct trampolines, but instead have
+       the ftrace ops function located above the function entry point. In
+       such cases an 'O' will be displayed.
+       If a function had either the "ip modify" or a "direct" call attached to
+       it in the past, a 'M' will be shown. This flag is never cleared. It is
+       used to know if a function was every modified by the ftrace infrastructure,
+       and can be used for debugging.
        If the architecture supports it, it will also show what callback
        is being directly called by the function. If the count is greater
        than 1 it most likely will be ftrace_ops_list_func().
        its address will be printed as well as the function that the
        trampoline calls.
  
+   touched_functions:
+       This file contains all the functions that ever had a function callback
+       to it via the ftrace infrastructure. It has the same format as
+       enabled_functions but shows all functions that have every been
+       traced.
+       To see any function that has every been modified by "ip modify" or a
+       direct trampoline, one can perform the following command:
+       grep ' M ' /sys/kernel/tracing/touched_functions
    function_profile_enabled:
  
        When set it will enable all functions with either the function
@@@ -3516,7 -3541,7 +3541,7 @@@ directories, the rmdir will fail with E
  Stack trace
  -----------
  Since the kernel has a fixed sized stack, it is important not to
 -waste it in functions. A kernel developer must be conscience of
 +waste it in functions. A kernel developer must be conscious of
  what they allocate on the stack. If they add too much, the system
  can be in danger of a stack overflow, and corruption will occur,
  usually leading to a system panic.
diff --combined include/linux/ftrace.h
index 6954e4ed5bbf29e31fb2c8d8eb7fc34f69a19c85,7dffd740e784f7cb2b54972b033022562515bdc4..b23bdd41439408c9fd1af2c22b4d6e76059832c1
@@@ -549,6 -549,7 +549,7 @@@ bool is_ftrace_trampoline(unsigned lon
   *  CALL_OPS - the record can use callsite-specific ops
   *  CALL_OPS_EN - the function is set up to use callsite-specific ops
   *  TOUCHED  - A callback was added since boot up
+  *  MODIFIED - The function had IPMODIFY or DIRECT attached to it
   *
   * When a new ftrace_ops is registered and wants a function to save
   * pt_regs, the rec->flags REGS is set. When the function has been
@@@ -569,9 -570,10 +570,10 @@@ enum 
        FTRACE_FL_CALL_OPS      = (1UL << 22),
        FTRACE_FL_CALL_OPS_EN   = (1UL << 21),
        FTRACE_FL_TOUCHED       = (1UL << 20),
+       FTRACE_FL_MODIFIED      = (1UL << 19),
  };
  
- #define FTRACE_REF_MAX_SHIFT  20
+ #define FTRACE_REF_MAX_SHIFT  19
  #define FTRACE_REF_MAX                ((1UL << FTRACE_REF_MAX_SHIFT) - 1)
  
  #define ftrace_rec_count(rec) ((rec)->flags & FTRACE_REF_MAX)
@@@ -964,7 -966,7 +966,7 @@@ static inline void __ftrace_enabled_res
  #define CALLER_ADDR5 ((unsigned long)ftrace_return_address(5))
  #define CALLER_ADDR6 ((unsigned long)ftrace_return_address(6))
  
 -static inline unsigned long get_lock_parent_ip(void)
 +static __always_inline unsigned long get_lock_parent_ip(void)
  {
        unsigned long addr = CALLER_ADDR0;
  
diff --combined kernel/trace/ftrace.c
index 76973a70ab9d8b8e0b8f511b4c54f4b339028af0,885845fc851dd39a65232f2f76037062586dac19..76466846715588c304bc9f14c17c7d341f7a6b21
@@@ -46,7 -46,8 +46,8 @@@
  #include "trace_stat.h"
  
  /* Flags that do not get reset */
- #define FTRACE_NOCLEAR_FLAGS  (FTRACE_FL_DISABLED | FTRACE_FL_TOUCHED)
+ #define FTRACE_NOCLEAR_FLAGS  (FTRACE_FL_DISABLED | FTRACE_FL_TOUCHED | \
+                                FTRACE_FL_MODIFIED)
  
  #define FTRACE_INVALID_FUNCTION               "__ftrace_invalid_address__"
  
@@@ -2273,6 -2274,10 +2274,10 @@@ static int ftrace_check_record(struct d
                                        rec->flags &= ~FTRACE_FL_TRAMP_EN;
                        }
  
+                       /* Keep track of anything that modifies the function */
+                       if (rec->flags & (FTRACE_FL_DIRECT | FTRACE_FL_IPMODIFY))
+                               rec->flags |= FTRACE_FL_MODIFIED;
                        if (flag & FTRACE_FL_DIRECT) {
                                /*
                                 * If there's only one user (direct_ops helper)
@@@ -3866,12 -3871,13 +3871,13 @@@ static int t_show(struct seq_file *m, v
        if (iter->flags & (FTRACE_ITER_ENABLED | FTRACE_ITER_TOUCHED)) {
                struct ftrace_ops *ops;
  
-               seq_printf(m, " (%ld)%s%s%s%s",
+               seq_printf(m, " (%ld)%s%s%s%s%s",
                           ftrace_rec_count(rec),
                           rec->flags & FTRACE_FL_REGS ? " R" : "  ",
                           rec->flags & FTRACE_FL_IPMODIFY ? " I" : "  ",
                           rec->flags & FTRACE_FL_DIRECT ? " D" : "  ",
-                          rec->flags & FTRACE_FL_CALL_OPS ? " O" : "  ");
+                          rec->flags & FTRACE_FL_CALL_OPS ? " O" : "  ",
+                          rec->flags & FTRACE_FL_MODIFIED ? " M " : "   ");
                if (rec->flags & FTRACE_FL_TRAMP_EN) {
                        ops = ftrace_find_tramp_ops_any(rec);
                        if (ops) {
@@@ -8047,7 -8053,8 +8053,7 @@@ struct kallsyms_data 
   * and returns 1 in case we resolved all the requested symbols,
   * 0 otherwise.
   */
 -static int kallsyms_callback(void *data, const char *name,
 -                           struct module *mod, unsigned long addr)
 +static int kallsyms_callback(void *data, const char *name, unsigned long addr)
  {
        struct kallsyms_data *args = data;
        const char **sym;
diff --combined kernel/trace/trace.c
index 427da2341bf0aafdbe61ba18c93c0c102a1406da,b9be1af23a73f47d1c4afb1584efc3f14acec2a9..ebc59781456a2188afe16ad0d92c4af6b466b913
@@@ -1149,22 -1149,22 +1149,22 @@@ static void tracing_snapshot_instance_c
        unsigned long flags;
  
        if (in_nmi()) {
 -              internal_trace_puts("*** SNAPSHOT CALLED FROM NMI CONTEXT ***\n");
 -              internal_trace_puts("*** snapshot is being ignored        ***\n");
 +              trace_array_puts(tr, "*** SNAPSHOT CALLED FROM NMI CONTEXT ***\n");
 +              trace_array_puts(tr, "*** snapshot is being ignored        ***\n");
                return;
        }
  
        if (!tr->allocated_snapshot) {
 -              internal_trace_puts("*** SNAPSHOT NOT ALLOCATED ***\n");
 -              internal_trace_puts("*** stopping trace here!   ***\n");
 -              tracing_off();
 +              trace_array_puts(tr, "*** SNAPSHOT NOT ALLOCATED ***\n");
 +              trace_array_puts(tr, "*** stopping trace here!   ***\n");
 +              tracer_tracing_off(tr);
                return;
        }
  
        /* Note, snapshot can not be used when the tracer uses it */
        if (tracer->use_max_tr) {
 -              internal_trace_puts("*** LATENCY TRACER ACTIVE ***\n");
 -              internal_trace_puts("*** Can not use snapshot (sorry) ***\n");
 +              trace_array_puts(tr, "*** LATENCY TRACER ACTIVE ***\n");
 +              trace_array_puts(tr, "*** Can not use snapshot (sorry) ***\n");
                return;
        }
  
@@@ -9519,7 -9519,6 +9519,7 @@@ static int __remove_instance(struct tra
        tracefs_remove(tr->dir);
        free_percpu(tr->last_func_repeats);
        free_trace_buffers(tr);
 +      clear_tracing_err_log(tr);
  
        for (i = 0; i < tr->nr_topts; i++) {
                kfree(tr->topts[i].topts);
@@@ -9661,7 -9660,7 +9661,7 @@@ init_tracer_tracefs(struct trace_array 
  
        tr->buffer_percent = 50;
  
-       trace_create_file("buffer_percent", TRACE_MODE_READ, d_tracer,
+       trace_create_file("buffer_percent", TRACE_MODE_WRITE, d_tracer,
                        tr, &buffer_percent_fops);
  
        create_trace_options_dir(tr);
  
  void __init ftrace_boot_snapshot(void)
  {
 +#ifdef CONFIG_TRACER_MAX_TRACE
        struct trace_array *tr;
  
 -      if (snapshot_at_boot) {
 -              tracing_snapshot();
 -              internal_trace_puts("** Boot snapshot taken **\n");
 -      }
 +      if (!snapshot_at_boot)
 +              return;
  
        list_for_each_entry(tr, &ftrace_trace_arrays, list) {
 -              if (tr == &global_trace)
 +              if (!tr->allocated_snapshot)
                        continue;
 -              trace_array_puts(tr, "** Boot snapshot taken **\n");
 +
                tracing_snapshot_instance(tr);
 +              trace_array_puts(tr, "** Boot snapshot taken **\n");
        }
 +#endif
  }
  
  void __init early_trace_init(void)
This page took 0.089941 seconds and 4 git commands to generate.