Merge tag 'trace-v6.6-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/trace...
authorLinus Torvalds <torvalds@linux-foundation.org>
Wed, 13 Sep 2023 18:30:11 +0000 (11:30 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 13 Sep 2023 18:30:11 +0000 (11:30 -0700)
Pull tracing fixes from Steven Rostedt:

 - Add missing LOCKDOWN checks for eventfs callers

   When LOCKDOWN is active for tracing, it causes inconsistent state
   when some functions succeed and others fail.

 - Use dput() to free the top level eventfs descriptor

   There was a race between accesses and freeing it.

 - Fix a long standing bug that eventfs exposed due to changing timings
   by dynamically creating files. That is, If a event file is opened for
   an instance, there's nothing preventing the instance from being
   removed which will make accessing the files cause use-after-free
   bugs.

 - Fix a ring buffer race that happens when iterating over the ring
   buffer while writers are active. Check to make sure not to read the
   event meta data if it's beyond the end of the ring buffer sub buffer.

 - Fix the print trigger that disappeared because the test to create it
   was looking for the event dir field being filled, but now it has the
   "ef" field filled for the eventfs structure.

 - Remove the unused "dir" field from the event structure.

 - Fix the order of the trace_dynamic_info as it had it backwards for
   the offset and len fields for which one was for which endianess.

 - Fix NULL pointer dereference with eventfs_remove_rec()

   If an allocation fails in one of the eventfs_add_*() functions, the
   caller of it in event_subsystem_dir() or event_create_dir() assigns
   the result to the structure. But it's assigning the ERR_PTR and not
   NULL. This was passed to eventfs_remove_rec() which expects either a
   good pointer or a NULL, not ERR_PTR. The fix is to not assign the
   ERR_PTR to the structure, but to keep it NULL on error.

 - Fix list_for_each_rcu() to use list_for_each_srcu() in
   dcache_dir_open_wrapper(). One iteration of the code used RCU but
   because it had to call sleepable code, it had to be changed to use
   SRCU, but one of the iterations was missed.

 - Fix synthetic event print function to use "as_u64" instead of passing
   in a pointer to the union. To fix big/little endian issues, the u64
   that represented several types was turned into a union to define the
   types properly.

* tag 'trace-v6.6-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-trace:
  eventfs: Fix the NULL pointer dereference bug in eventfs_remove_rec()
  tracefs/eventfs: Use list_for_each_srcu() in dcache_dir_open_wrapper()
  tracing/synthetic: Print out u64 values properly
  tracing/synthetic: Fix order of struct trace_dynamic_info
  selftests/ftrace: Fix dependencies for some of the synthetic event tests
  tracing: Remove unused trace_event_file dir field
  tracing: Use the new eventfs descriptor for print trigger
  ring-buffer: Do not attempt to read past "commit"
  tracefs/eventfs: Free top level files on removal
  ring-buffer: Avoid softlockup in ring_buffer_resize()
  tracing: Have event inject files inc the trace array ref count
  tracing: Have option files inc the trace array ref count
  tracing: Have current_trace inc the trace array ref count
  tracing: Have tracing_max_latency inc the trace array ref count
  tracing: Increase trace array ref count on enable and filter files
  tracefs/eventfs: Use dput to free the toplevel events directory
  tracefs/eventfs: Add missing lockdown checks
  tracefs: Add missing lockdown check to tracefs_create_dir()

1  2 
kernel/trace/trace.c

diff --combined kernel/trace/trace.c
@@@ -1772,7 -1772,7 +1772,7 @@@ static void trace_create_maxlat_file(st
        init_irq_work(&tr->fsnotify_irqwork, latency_fsnotify_workfn_irq);
        tr->d_max_latency = trace_create_file("tracing_max_latency",
                                              TRACE_MODE_WRITE,
-                                             d_tracer, &tr->max_latency,
+                                             d_tracer, tr,
                                              &tracing_max_lat_fops);
  }
  
@@@ -1805,7 -1805,7 +1805,7 @@@ void latency_fsnotify(struct trace_arra
  
  #define trace_create_maxlat_file(tr, d_tracer)                                \
        trace_create_file("tracing_max_latency", TRACE_MODE_WRITE,      \
-                         d_tracer, &tr->max_latency, &tracing_max_lat_fops)
+                         d_tracer, tr, &tracing_max_lat_fops)
  
  #endif
  
@@@ -4973,6 -4973,33 +4973,33 @@@ int tracing_open_generic_tr(struct inod
        return 0;
  }
  
+ /*
+  * The private pointer of the inode is the trace_event_file.
+  * Update the tr ref count associated to it.
+  */
+ int tracing_open_file_tr(struct inode *inode, struct file *filp)
+ {
+       struct trace_event_file *file = inode->i_private;
+       int ret;
+       ret = tracing_check_open_get_tr(file->tr);
+       if (ret)
+               return ret;
+       filp->private_data = inode->i_private;
+       return 0;
+ }
+ int tracing_release_file_tr(struct inode *inode, struct file *filp)
+ {
+       struct trace_event_file *file = inode->i_private;
+       trace_array_put(file->tr);
+       return 0;
+ }
  static int tracing_mark_open(struct inode *inode, struct file *filp)
  {
        stream_open(inode, filp);
@@@ -5711,8 -5738,7 +5738,8 @@@ static const char readme_msg[] 
        "\t fetcharg: (%<register>|$<efield>), @<address>, @<symbol>[+|-<offset>],\n"
  #ifdef CONFIG_HAVE_FUNCTION_ARG_ACCESS_API
  #ifdef CONFIG_PROBE_EVENTS_BTF_ARGS
 -      "\t           $stack<index>, $stack, $retval, $comm, $arg<N>, <argname>\n"
 +      "\t           $stack<index>, $stack, $retval, $comm, $arg<N>,\n"
 +      "\t           <argname>[->field[->field|.field...]],\n"
  #else
        "\t           $stack<index>, $stack, $retval, $comm, $arg<N>,\n"
  #endif
@@@ -6691,14 -6717,18 +6718,18 @@@ static ssize_
  tracing_max_lat_read(struct file *filp, char __user *ubuf,
                     size_t cnt, loff_t *ppos)
  {
-       return tracing_nsecs_read(filp->private_data, ubuf, cnt, ppos);
+       struct trace_array *tr = filp->private_data;
+       return tracing_nsecs_read(&tr->max_latency, ubuf, cnt, ppos);
  }
  
  static ssize_t
  tracing_max_lat_write(struct file *filp, const char __user *ubuf,
                      size_t cnt, loff_t *ppos)
  {
-       return tracing_nsecs_write(filp->private_data, ubuf, cnt, ppos);
+       struct trace_array *tr = filp->private_data;
+       return tracing_nsecs_write(&tr->max_latency, ubuf, cnt, ppos);
  }
  
  #endif
@@@ -7752,18 -7782,20 +7783,20 @@@ static const struct file_operations tra
  
  #ifdef CONFIG_TRACER_MAX_TRACE
  static const struct file_operations tracing_max_lat_fops = {
-       .open           = tracing_open_generic,
+       .open           = tracing_open_generic_tr,
        .read           = tracing_max_lat_read,
        .write          = tracing_max_lat_write,
        .llseek         = generic_file_llseek,
+       .release        = tracing_release_generic_tr,
  };
  #endif
  
  static const struct file_operations set_tracer_fops = {
-       .open           = tracing_open_generic,
+       .open           = tracing_open_generic_tr,
        .read           = tracing_set_trace_read,
        .write          = tracing_set_trace_write,
        .llseek         = generic_file_llseek,
+       .release        = tracing_release_generic_tr,
  };
  
  static const struct file_operations tracing_pipe_fops = {
@@@ -8956,12 -8988,33 +8989,33 @@@ trace_options_write(struct file *filp, 
        return cnt;
  }
  
+ static int tracing_open_options(struct inode *inode, struct file *filp)
+ {
+       struct trace_option_dentry *topt = inode->i_private;
+       int ret;
+       ret = tracing_check_open_get_tr(topt->tr);
+       if (ret)
+               return ret;
+       filp->private_data = inode->i_private;
+       return 0;
+ }
+ static int tracing_release_options(struct inode *inode, struct file *file)
+ {
+       struct trace_option_dentry *topt = file->private_data;
+       trace_array_put(topt->tr);
+       return 0;
+ }
  
  static const struct file_operations trace_options_fops = {
-       .open = tracing_open_generic,
+       .open = tracing_open_options,
        .read = trace_options_read,
        .write = trace_options_write,
        .llseek = generic_file_llseek,
+       .release = tracing_release_options,
  };
  
  /*
@@@ -9739,8 -9792,8 +9793,8 @@@ init_tracer_tracefs(struct trace_array 
                          tr, &tracing_mark_fops);
  
        file = __find_event_file(tr, "ftrace", "print");
-       if (file && file->dir)
-               trace_create_file("trigger", TRACE_MODE_WRITE, file->dir,
+       if (file && file->ef)
+               eventfs_add_file("trigger", TRACE_MODE_WRITE, file->ef,
                                  file, &event_trigger_fops);
        tr->trace_marker_file = file;