tracing: protect reader of cmdline output

Impact: fix to one cause of incorrect comm outputs in trace

The spinlock only protected the creation of a comm <=> pid pair.
But it was possible that a reader could look up a pid, and get the
wrong comm because it had no locking.

This also required changing trace_find_cmdline to copy the comm cache
and not just send back a pointer to it.

Signed-off-by: Steven Rostedt <srostedt@redhat.com>
This commit is contained in:
Steven Rostedt 2009-03-16 19:20:15 -04:00
parent 03303549b1
commit 4ca5308523
5 changed files with 49 additions and 26 deletions

View File

@ -1027,7 +1027,9 @@ static int blk_log_action_seq(struct trace_seq *s, const struct blk_io_trace *t,
static int blk_log_generic(struct trace_seq *s, const struct trace_entry *ent) static int blk_log_generic(struct trace_seq *s, const struct trace_entry *ent)
{ {
const char *cmd = trace_find_cmdline(ent->pid); char cmd[TASK_COMM_LEN];
trace_find_cmdline(ent->pid, cmd);
if (t_sec(ent)) if (t_sec(ent))
return trace_seq_printf(s, "%llu + %u [%s]\n", return trace_seq_printf(s, "%llu + %u [%s]\n",
@ -1057,19 +1059,30 @@ static int blk_log_remap(struct trace_seq *s, const struct trace_entry *ent)
static int blk_log_plug(struct trace_seq *s, const struct trace_entry *ent) static int blk_log_plug(struct trace_seq *s, const struct trace_entry *ent)
{ {
return trace_seq_printf(s, "[%s]\n", trace_find_cmdline(ent->pid)); char cmd[TASK_COMM_LEN];
trace_find_cmdline(ent->pid, cmd);
return trace_seq_printf(s, "[%s]\n", cmd);
} }
static int blk_log_unplug(struct trace_seq *s, const struct trace_entry *ent) static int blk_log_unplug(struct trace_seq *s, const struct trace_entry *ent)
{ {
return trace_seq_printf(s, "[%s] %llu\n", trace_find_cmdline(ent->pid), char cmd[TASK_COMM_LEN];
get_pdu_int(ent));
trace_find_cmdline(ent->pid, cmd);
return trace_seq_printf(s, "[%s] %llu\n", cmd, get_pdu_int(ent));
} }
static int blk_log_split(struct trace_seq *s, const struct trace_entry *ent) static int blk_log_split(struct trace_seq *s, const struct trace_entry *ent)
{ {
char cmd[TASK_COMM_LEN];
trace_find_cmdline(ent->pid, cmd);
return trace_seq_printf(s, "%llu / %llu [%s]\n", t_sector(ent), return trace_seq_printf(s, "%llu / %llu [%s]\n", t_sector(ent),
get_pdu_int(ent), trace_find_cmdline(ent->pid)); get_pdu_int(ent), cmd);
} }
/* /*

View File

@ -770,25 +770,29 @@ static void trace_save_cmdline(struct task_struct *tsk)
__raw_spin_unlock(&trace_cmdline_lock); __raw_spin_unlock(&trace_cmdline_lock);
} }
char *trace_find_cmdline(int pid) void trace_find_cmdline(int pid, char comm[])
{ {
char *cmdline = "<...>";
unsigned map; unsigned map;
if (!pid) if (!pid) {
return "<idle>"; strcpy(comm, "<idle>");
return;
}
if (pid > PID_MAX_DEFAULT) if (pid > PID_MAX_DEFAULT) {
goto out; strcpy(comm, "<...>");
return;
}
__raw_spin_lock(&trace_cmdline_lock);
map = map_pid_to_cmdline[pid]; map = map_pid_to_cmdline[pid];
if (map >= SAVED_CMDLINES) if (map >= SAVED_CMDLINES)
goto out; goto out;
cmdline = saved_cmdlines[map]; strcpy(comm, saved_cmdlines[map]);
out: out:
return cmdline; __raw_spin_unlock(&trace_cmdline_lock);
} }
void tracing_record_cmdline(struct task_struct *tsk) void tracing_record_cmdline(struct task_struct *tsk)

View File

@ -547,7 +547,7 @@ struct tracer_switch_ops {
}; };
#endif /* CONFIG_CONTEXT_SWITCH_TRACER */ #endif /* CONFIG_CONTEXT_SWITCH_TRACER */
extern char *trace_find_cmdline(int pid); extern void trace_find_cmdline(int pid, char comm[]);
#ifdef CONFIG_DYNAMIC_FTRACE #ifdef CONFIG_DYNAMIC_FTRACE
extern unsigned long ftrace_update_tot_cnt; extern unsigned long ftrace_update_tot_cnt;

View File

@ -190,15 +190,15 @@ print_graph_cpu(struct trace_seq *s, int cpu)
static enum print_line_t static enum print_line_t
print_graph_proc(struct trace_seq *s, pid_t pid) print_graph_proc(struct trace_seq *s, pid_t pid)
{ {
int i; char comm[TASK_COMM_LEN];
int ret;
int len;
char comm[8];
int spaces = 0;
/* sign + log10(MAX_INT) + '\0' */ /* sign + log10(MAX_INT) + '\0' */
char pid_str[11]; char pid_str[11];
int spaces = 0;
int ret;
int len;
int i;
strncpy(comm, trace_find_cmdline(pid), 7); trace_find_cmdline(pid, comm);
comm[7] = '\0'; comm[7] = '\0';
sprintf(pid_str, "%d", pid); sprintf(pid_str, "%d", pid);

View File

@ -309,9 +309,9 @@ static int
lat_print_generic(struct trace_seq *s, struct trace_entry *entry, int cpu) lat_print_generic(struct trace_seq *s, struct trace_entry *entry, int cpu)
{ {
int hardirq, softirq; int hardirq, softirq;
char *comm; char comm[TASK_COMM_LEN];
comm = trace_find_cmdline(entry->pid); trace_find_cmdline(entry->pid, comm);
hardirq = entry->flags & TRACE_FLAG_HARDIRQ; hardirq = entry->flags & TRACE_FLAG_HARDIRQ;
softirq = entry->flags & TRACE_FLAG_SOFTIRQ; softirq = entry->flags & TRACE_FLAG_SOFTIRQ;
@ -346,10 +346,12 @@ int trace_print_context(struct trace_iterator *iter)
{ {
struct trace_seq *s = &iter->seq; struct trace_seq *s = &iter->seq;
struct trace_entry *entry = iter->ent; struct trace_entry *entry = iter->ent;
char *comm = trace_find_cmdline(entry->pid);
unsigned long long t = ns2usecs(iter->ts); unsigned long long t = ns2usecs(iter->ts);
unsigned long usec_rem = do_div(t, USEC_PER_SEC); unsigned long usec_rem = do_div(t, USEC_PER_SEC);
unsigned long secs = (unsigned long)t; unsigned long secs = (unsigned long)t;
char comm[TASK_COMM_LEN];
trace_find_cmdline(entry->pid, comm);
return trace_seq_printf(s, "%16s-%-5d [%03d] %5lu.%06lu: ", return trace_seq_printf(s, "%16s-%-5d [%03d] %5lu.%06lu: ",
comm, entry->pid, iter->cpu, secs, usec_rem); comm, entry->pid, iter->cpu, secs, usec_rem);
@ -372,7 +374,10 @@ int trace_print_lat_context(struct trace_iterator *iter)
rel_usecs = ns2usecs(next_ts - iter->ts); rel_usecs = ns2usecs(next_ts - iter->ts);
if (verbose) { if (verbose) {
char *comm = trace_find_cmdline(entry->pid); char comm[TASK_COMM_LEN];
trace_find_cmdline(entry->pid, comm);
ret = trace_seq_printf(s, "%16s %5d %3d %d %08x %08lx [%08lx]" ret = trace_seq_printf(s, "%16s %5d %3d %d %08x %08lx [%08lx]"
" %ld.%03ldms (+%ld.%03ldms): ", comm, " %ld.%03ldms (+%ld.%03ldms): ", comm,
entry->pid, iter->cpu, entry->flags, entry->pid, iter->cpu, entry->flags,
@ -577,14 +582,15 @@ static enum print_line_t trace_ctxwake_print(struct trace_iterator *iter,
char *delim) char *delim)
{ {
struct ctx_switch_entry *field; struct ctx_switch_entry *field;
char *comm; char comm[TASK_COMM_LEN];
int S, T; int S, T;
trace_assign_type(field, iter->ent); trace_assign_type(field, iter->ent);
T = task_state_char(field->next_state); T = task_state_char(field->next_state);
S = task_state_char(field->prev_state); S = task_state_char(field->prev_state);
comm = trace_find_cmdline(field->next_pid); trace_find_cmdline(field->next_pid, comm);
if (!trace_seq_printf(&iter->seq, if (!trace_seq_printf(&iter->seq,
" %5d:%3d:%c %s [%03d] %5d:%3d:%c %s\n", " %5d:%3d:%c %s [%03d] %5d:%3d:%c %s\n",
field->prev_pid, field->prev_pid,