Commit 550d1f5b authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'trace-v5.2-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace

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()
parents 179c96d9 074376ac
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/list.h> #include <linux/list.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/memory.h>
#include <trace/syscall.h> #include <trace/syscall.h>
...@@ -34,16 +35,25 @@ ...@@ -34,16 +35,25 @@
#ifdef CONFIG_DYNAMIC_FTRACE #ifdef CONFIG_DYNAMIC_FTRACE
int ftrace_arch_code_modify_prepare(void) 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_kernel_text_rw();
set_all_modules_text_rw(); set_all_modules_text_rw();
return 0; return 0;
} }
int ftrace_arch_code_modify_post_process(void) int ftrace_arch_code_modify_post_process(void)
__releases(&text_mutex)
{ {
set_all_modules_text_ro(); set_all_modules_text_ro();
set_kernel_text_ro(); set_kernel_text_ro();
mutex_unlock(&text_mutex);
return 0; return 0;
} }
......
...@@ -34,7 +34,6 @@ ...@@ -34,7 +34,6 @@
#include <linux/hash.h> #include <linux/hash.h>
#include <linux/rcupdate.h> #include <linux/rcupdate.h>
#include <linux/kprobes.h> #include <linux/kprobes.h>
#include <linux/memory.h>
#include <trace/events/sched.h> #include <trace/events/sched.h>
...@@ -2611,12 +2610,10 @@ static void ftrace_run_update_code(int command) ...@@ -2611,12 +2610,10 @@ static void ftrace_run_update_code(int command)
{ {
int ret; int ret;
mutex_lock(&text_mutex);
ret = ftrace_arch_code_modify_prepare(); ret = ftrace_arch_code_modify_prepare();
FTRACE_WARN_ON(ret); FTRACE_WARN_ON(ret);
if (ret) if (ret)
goto out_unlock; return;
/* /*
* By default we use stop_machine() to modify the code. * By default we use stop_machine() to modify the code.
...@@ -2628,9 +2625,6 @@ static void ftrace_run_update_code(int command) ...@@ -2628,9 +2625,6 @@ static void ftrace_run_update_code(int command)
ret = ftrace_arch_code_modify_post_process(); ret = ftrace_arch_code_modify_post_process();
FTRACE_WARN_ON(ret); FTRACE_WARN_ON(ret);
out_unlock:
mutex_unlock(&text_mutex);
} }
static void ftrace_run_modify_code(struct ftrace_ops *ops, int command, static void ftrace_run_modify_code(struct ftrace_ops *ops, int command,
...@@ -5784,7 +5778,6 @@ void ftrace_module_enable(struct module *mod) ...@@ -5784,7 +5778,6 @@ void ftrace_module_enable(struct module *mod)
struct ftrace_page *pg; struct ftrace_page *pg;
mutex_lock(&ftrace_lock); mutex_lock(&ftrace_lock);
mutex_lock(&text_mutex);
if (ftrace_disabled) if (ftrace_disabled)
goto out_unlock; goto out_unlock;
...@@ -5846,7 +5839,6 @@ void ftrace_module_enable(struct module *mod) ...@@ -5846,7 +5839,6 @@ void ftrace_module_enable(struct module *mod)
ftrace_arch_code_modify_post_process(); ftrace_arch_code_modify_post_process();
out_unlock: out_unlock:
mutex_unlock(&text_mutex);
mutex_unlock(&ftrace_lock); mutex_unlock(&ftrace_lock);
process_cached_mods(mod->name); process_cached_mods(mod->name);
......
...@@ -6719,11 +6719,13 @@ tracing_snapshot_write(struct file *filp, const char __user *ubuf, size_t cnt, ...@@ -6719,11 +6719,13 @@ tracing_snapshot_write(struct file *filp, const char __user *ubuf, size_t cnt,
break; break;
} }
#endif #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); ret = tracing_alloc_snapshot_instance(tr);
if (ret < 0) if (ret < 0)
break; break;
}
local_irq_disable(); local_irq_disable();
/* Now, we're going to swap */ /* Now, we're going to swap */
if (iter->cpu_file == RING_BUFFER_ALL_CPUS) if (iter->cpu_file == RING_BUFFER_ALL_CPUS)
...@@ -7126,12 +7128,24 @@ static ssize_t tracing_err_log_write(struct file *file, ...@@ -7126,12 +7128,24 @@ static ssize_t tracing_err_log_write(struct file *file,
return count; 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 = { static const struct file_operations tracing_err_log_fops = {
.open = tracing_err_log_open, .open = tracing_err_log_open,
.write = tracing_err_log_write, .write = tracing_err_log_write,
.read = seq_read, .read = seq_read,
.llseek = seq_lseek, .llseek = seq_lseek,
.release = tracing_release_generic_tr, .release = tracing_err_log_release,
}; };
static int tracing_buffers_open(struct inode *inode, struct file *filp) static int tracing_buffers_open(struct inode *inode, struct file *filp)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment