ksym_tracer: Remove trace_stat
trace_stat is problematic. Don't use it, use seqfile instead. This fixes a race that reading the stat file is not protected by any lock, which can lead to use after free. Signed-off-by: Li Zefan <lizf@cn.fujitsu.com> Cc: Steven Rostedt <rostedt@goodmis.org> Cc: K.Prasad <prasad@linux.vnet.ibm.com> Cc: Frederic Weisbecker <fweisbec@gmail.com> LKML-Reference: <4B3AF203.40200@cn.fujitsu.com> Signed-off-by: Ingo Molnar <mingo@elte.hu>
This commit is contained in:
@@ -26,7 +26,6 @@
|
|||||||
#include <linux/fs.h>
|
#include <linux/fs.h>
|
||||||
|
|
||||||
#include "trace_output.h"
|
#include "trace_output.h"
|
||||||
#include "trace_stat.h"
|
|
||||||
#include "trace.h"
|
#include "trace.h"
|
||||||
|
|
||||||
#include <linux/hw_breakpoint.h>
|
#include <linux/hw_breakpoint.h>
|
||||||
@@ -444,43 +443,21 @@ struct tracer ksym_tracer __read_mostly =
|
|||||||
.print_line = ksym_trace_output
|
.print_line = ksym_trace_output
|
||||||
};
|
};
|
||||||
|
|
||||||
__init static int init_ksym_trace(void)
|
|
||||||
{
|
|
||||||
struct dentry *d_tracer;
|
|
||||||
struct dentry *entry;
|
|
||||||
|
|
||||||
d_tracer = tracing_init_dentry();
|
|
||||||
ksym_filter_entry_count = 0;
|
|
||||||
|
|
||||||
entry = debugfs_create_file("ksym_trace_filter", 0644, d_tracer,
|
|
||||||
NULL, &ksym_tracing_fops);
|
|
||||||
if (!entry)
|
|
||||||
pr_warning("Could not create debugfs "
|
|
||||||
"'ksym_trace_filter' file\n");
|
|
||||||
|
|
||||||
return register_tracer(&ksym_tracer);
|
|
||||||
}
|
|
||||||
device_initcall(init_ksym_trace);
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef CONFIG_PROFILE_KSYM_TRACER
|
#ifdef CONFIG_PROFILE_KSYM_TRACER
|
||||||
static int ksym_tracer_stat_headers(struct seq_file *m)
|
static int ksym_profile_show(struct seq_file *m, void *v)
|
||||||
{
|
{
|
||||||
seq_puts(m, " Access Type ");
|
struct hlist_node *node;
|
||||||
seq_puts(m, " Symbol Counter\n");
|
|
||||||
seq_puts(m, " ----------- ");
|
|
||||||
seq_puts(m, " ------ -------\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int ksym_tracer_stat_show(struct seq_file *m, void *v)
|
|
||||||
{
|
|
||||||
struct hlist_node *stat = v;
|
|
||||||
struct trace_ksym *entry;
|
struct trace_ksym *entry;
|
||||||
int access_type = 0;
|
int access_type = 0;
|
||||||
char fn_name[KSYM_NAME_LEN];
|
char fn_name[KSYM_NAME_LEN];
|
||||||
|
|
||||||
entry = hlist_entry(stat, struct trace_ksym, ksym_hlist);
|
seq_puts(m, " Access Type ");
|
||||||
|
seq_puts(m, " Symbol Counter\n");
|
||||||
|
seq_puts(m, " ----------- ");
|
||||||
|
seq_puts(m, " ------ -------\n");
|
||||||
|
|
||||||
|
rcu_read_lock();
|
||||||
|
hlist_for_each_entry_rcu(entry, node, &ksym_filter_head, ksym_hlist) {
|
||||||
|
|
||||||
access_type = entry->attr.bp_type;
|
access_type = entry->attr.bp_type;
|
||||||
|
|
||||||
@@ -504,43 +481,39 @@ static int ksym_tracer_stat_show(struct seq_file *m, void *v)
|
|||||||
seq_printf(m, " %-36s", "<NA>");
|
seq_printf(m, " %-36s", "<NA>");
|
||||||
seq_printf(m, " %15llu\n",
|
seq_printf(m, " %15llu\n",
|
||||||
(unsigned long long)atomic64_read(&entry->counter));
|
(unsigned long long)atomic64_read(&entry->counter));
|
||||||
|
}
|
||||||
|
rcu_read_unlock();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void *ksym_tracer_stat_start(struct tracer_stat *trace)
|
static int ksym_profile_open(struct inode *node, struct file *file)
|
||||||
{
|
{
|
||||||
return ksym_filter_head.first;
|
return single_open(file, ksym_profile_show, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void *
|
static const struct file_operations ksym_profile_fops = {
|
||||||
ksym_tracer_stat_next(void *v, int idx)
|
.open = ksym_profile_open,
|
||||||
{
|
.read = seq_read,
|
||||||
struct hlist_node *stat = v;
|
.llseek = seq_lseek,
|
||||||
|
.release = single_release,
|
||||||
return stat->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct tracer_stat ksym_tracer_stats = {
|
|
||||||
.name = "ksym_tracer",
|
|
||||||
.stat_start = ksym_tracer_stat_start,
|
|
||||||
.stat_next = ksym_tracer_stat_next,
|
|
||||||
.stat_headers = ksym_tracer_stat_headers,
|
|
||||||
.stat_show = ksym_tracer_stat_show
|
|
||||||
};
|
};
|
||||||
|
|
||||||
__init static int ksym_tracer_stat_init(void)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
ret = register_stat_tracer(&ksym_tracer_stats);
|
|
||||||
if (ret) {
|
|
||||||
printk(KERN_WARNING "Warning: could not register "
|
|
||||||
"ksym tracer stats\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
fs_initcall(ksym_tracer_stat_init);
|
|
||||||
#endif /* CONFIG_PROFILE_KSYM_TRACER */
|
#endif /* CONFIG_PROFILE_KSYM_TRACER */
|
||||||
|
|
||||||
|
__init static int init_ksym_trace(void)
|
||||||
|
{
|
||||||
|
struct dentry *d_tracer;
|
||||||
|
|
||||||
|
d_tracer = tracing_init_dentry();
|
||||||
|
|
||||||
|
trace_create_file("ksym_trace_filter", 0644, d_tracer,
|
||||||
|
NULL, &ksym_tracing_fops);
|
||||||
|
|
||||||
|
#ifdef CONFIG_PROFILE_KSYM_TRACER
|
||||||
|
trace_create_file("ksym_profile", 0444, d_tracer,
|
||||||
|
NULL, &ksym_profile_fops);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return register_tracer(&ksym_tracer);
|
||||||
|
}
|
||||||
|
device_initcall(init_ksym_trace);
|
||||||
|
Reference in New Issue
Block a user