Merge tag 'trace-v5.2-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt...
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 4 Jul 2019 01:26:17 +0000 (10:26 +0900)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 4 Jul 2019 01:26:17 +0000 (10:26 +0900)
Pull tracing fixes from Steven Rostedt:
 "This includes three fixes:

   - Fix a deadlock from a previous fix to keep module loading and
     function tracing text modifications from stepping on each other
     (this has a few patches to help document the issue in comments)

   - Fix a crash when the snapshot buffer gets out of sync with the main
     ring buffer

   - Fix a memory leak when reading the memory logs"

* tag 'trace-v5.2-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace:
  ftrace/x86: Anotate text_mutex split between ftrace_arch_code_modify_post_process() and ftrace_arch_code_modify_prepare()
  tracing/snapshot: Resize spare buffer if size changed
  tracing: Fix memory leak in tracing_err_log_open()
  ftrace/x86: Add a comment to why we take text_mutex in ftrace_arch_code_modify_prepare()
  ftrace/x86: Remove possible deadlock between register_kprobe() and ftrace_run_update_code()

arch/x86/kernel/ftrace.c
kernel/trace/ftrace.c
kernel/trace/trace.c

index 0927bb1..7622852 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/init.h>
 #include <linux/list.h>
 #include <linux/module.h>
+#include <linux/memory.h>
 
 #include <trace/syscall.h>
 
 #ifdef CONFIG_DYNAMIC_FTRACE
 
 int ftrace_arch_code_modify_prepare(void)
+    __acquires(&text_mutex)
 {
+       /*
+        * Need to grab text_mutex to prevent a race from module loading
+        * and live kernel patching from changing the text permissions while
+        * ftrace has it set to "read/write".
+        */
+       mutex_lock(&text_mutex);
        set_kernel_text_rw();
        set_all_modules_text_rw();
        return 0;
 }
 
 int ftrace_arch_code_modify_post_process(void)
+    __releases(&text_mutex)
 {
        set_all_modules_text_ro();
        set_kernel_text_ro();
+       mutex_unlock(&text_mutex);
        return 0;
 }
 
index 38277af..576c416 100644 (file)
@@ -34,7 +34,6 @@
 #include <linux/hash.h>
 #include <linux/rcupdate.h>
 #include <linux/kprobes.h>
-#include <linux/memory.h>
 
 #include <trace/events/sched.h>
 
@@ -2611,12 +2610,10 @@ static void ftrace_run_update_code(int command)
 {
        int ret;
 
-       mutex_lock(&text_mutex);
-
        ret = ftrace_arch_code_modify_prepare();
        FTRACE_WARN_ON(ret);
        if (ret)
-               goto out_unlock;
+               return;
 
        /*
         * By default we use stop_machine() to modify the code.
@@ -2628,9 +2625,6 @@ static void ftrace_run_update_code(int command)
 
        ret = ftrace_arch_code_modify_post_process();
        FTRACE_WARN_ON(ret);
-
-out_unlock:
-       mutex_unlock(&text_mutex);
 }
 
 static void ftrace_run_modify_code(struct ftrace_ops *ops, int command,
@@ -5784,7 +5778,6 @@ void ftrace_module_enable(struct module *mod)
        struct ftrace_page *pg;
 
        mutex_lock(&ftrace_lock);
-       mutex_lock(&text_mutex);
 
        if (ftrace_disabled)
                goto out_unlock;
@@ -5846,7 +5839,6 @@ void ftrace_module_enable(struct module *mod)
                ftrace_arch_code_modify_post_process();
 
  out_unlock:
-       mutex_unlock(&text_mutex);
        mutex_unlock(&ftrace_lock);
 
        process_cached_mods(mod->name);
index 83e08b7..c3aabb5 100644 (file)
@@ -6719,11 +6719,13 @@ tracing_snapshot_write(struct file *filp, const char __user *ubuf, size_t cnt,
                        break;
                }
 #endif
-               if (!tr->allocated_snapshot) {
+               if (tr->allocated_snapshot)
+                       ret = resize_buffer_duplicate_size(&tr->max_buffer,
+                                       &tr->trace_buffer, iter->cpu_file);
+               else
                        ret = tracing_alloc_snapshot_instance(tr);
-                       if (ret < 0)
-                               break;
-               }
+               if (ret < 0)
+                       break;
                local_irq_disable();
                /* Now, we're going to swap */
                if (iter->cpu_file == RING_BUFFER_ALL_CPUS)
@@ -7126,12 +7128,24 @@ static ssize_t tracing_err_log_write(struct file *file,
        return count;
 }
 
+static int tracing_err_log_release(struct inode *inode, struct file *file)
+{
+       struct trace_array *tr = inode->i_private;
+
+       trace_array_put(tr);
+
+       if (file->f_mode & FMODE_READ)
+               seq_release(inode, file);
+
+       return 0;
+}
+
 static const struct file_operations tracing_err_log_fops = {
        .open           = tracing_err_log_open,
        .write          = tracing_err_log_write,
        .read           = seq_read,
        .llseek         = seq_lseek,
-       .release        = tracing_release_generic_tr,
+       .release        = tracing_err_log_release,
 };
 
 static int tracing_buffers_open(struct inode *inode, struct file *filp)