diff options
author | Steven Rostedt <srostedt@redhat.com> | 2009-03-16 19:20:15 -0400 |
---|---|---|
committer | Steven Rostedt <srostedt@redhat.com> | 2009-03-16 23:27:06 -0400 |
commit | 4ca530852346be239b7c19e7bec5d2b78855bebe (patch) | |
tree | 96e5252faaf362115a96ed6df7c4e4f698a027dc /kernel | |
parent | 03303549b1695dc024d4a653cc16bd79f78f9750 (diff) |
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>
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/trace/blktrace.c | 23 | ||||
-rw-r--r-- | kernel/trace/trace.c | 20 | ||||
-rw-r--r-- | kernel/trace/trace.h | 2 | ||||
-rw-r--r-- | kernel/trace/trace_functions_graph.c | 12 | ||||
-rw-r--r-- | kernel/trace/trace_output.c | 18 |
5 files changed, 49 insertions, 26 deletions
diff --git a/kernel/trace/blktrace.c b/kernel/trace/blktrace.c index 1f32e4edf490..b171778e3863 100644 --- a/kernel/trace/blktrace.c +++ b/kernel/trace/blktrace.c | |||
@@ -1027,7 +1027,9 @@ static int blk_log_action_seq(struct trace_seq *s, const struct blk_io_trace *t, | |||
1027 | 1027 | ||
1028 | static int blk_log_generic(struct trace_seq *s, const struct trace_entry *ent) | 1028 | static int blk_log_generic(struct trace_seq *s, const struct trace_entry *ent) |
1029 | { | 1029 | { |
1030 | const char *cmd = trace_find_cmdline(ent->pid); | 1030 | char cmd[TASK_COMM_LEN]; |
1031 | |||
1032 | trace_find_cmdline(ent->pid, cmd); | ||
1031 | 1033 | ||
1032 | if (t_sec(ent)) | 1034 | if (t_sec(ent)) |
1033 | return trace_seq_printf(s, "%llu + %u [%s]\n", | 1035 | 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) | |||
1057 | 1059 | ||
1058 | static int blk_log_plug(struct trace_seq *s, const struct trace_entry *ent) | 1060 | static int blk_log_plug(struct trace_seq *s, const struct trace_entry *ent) |
1059 | { | 1061 | { |
1060 | return trace_seq_printf(s, "[%s]\n", trace_find_cmdline(ent->pid)); | 1062 | char cmd[TASK_COMM_LEN]; |
1063 | |||
1064 | trace_find_cmdline(ent->pid, cmd); | ||
1065 | |||
1066 | return trace_seq_printf(s, "[%s]\n", cmd); | ||
1061 | } | 1067 | } |
1062 | 1068 | ||
1063 | static int blk_log_unplug(struct trace_seq *s, const struct trace_entry *ent) | 1069 | static int blk_log_unplug(struct trace_seq *s, const struct trace_entry *ent) |
1064 | { | 1070 | { |
1065 | return trace_seq_printf(s, "[%s] %llu\n", trace_find_cmdline(ent->pid), | 1071 | char cmd[TASK_COMM_LEN]; |
1066 | get_pdu_int(ent)); | 1072 | |
1073 | trace_find_cmdline(ent->pid, cmd); | ||
1074 | |||
1075 | return trace_seq_printf(s, "[%s] %llu\n", cmd, get_pdu_int(ent)); | ||
1067 | } | 1076 | } |
1068 | 1077 | ||
1069 | static int blk_log_split(struct trace_seq *s, const struct trace_entry *ent) | 1078 | static int blk_log_split(struct trace_seq *s, const struct trace_entry *ent) |
1070 | { | 1079 | { |
1080 | char cmd[TASK_COMM_LEN]; | ||
1081 | |||
1082 | trace_find_cmdline(ent->pid, cmd); | ||
1083 | |||
1071 | return trace_seq_printf(s, "%llu / %llu [%s]\n", t_sector(ent), | 1084 | return trace_seq_printf(s, "%llu / %llu [%s]\n", t_sector(ent), |
1072 | get_pdu_int(ent), trace_find_cmdline(ent->pid)); | 1085 | get_pdu_int(ent), cmd); |
1073 | } | 1086 | } |
1074 | 1087 | ||
1075 | /* | 1088 | /* |
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index efe3202c0209..2796bd2b17e4 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c | |||
@@ -770,25 +770,29 @@ static void trace_save_cmdline(struct task_struct *tsk) | |||
770 | __raw_spin_unlock(&trace_cmdline_lock); | 770 | __raw_spin_unlock(&trace_cmdline_lock); |
771 | } | 771 | } |
772 | 772 | ||
773 | char *trace_find_cmdline(int pid) | 773 | void trace_find_cmdline(int pid, char comm[]) |
774 | { | 774 | { |
775 | char *cmdline = "<...>"; | ||
776 | unsigned map; | 775 | unsigned map; |
777 | 776 | ||
778 | if (!pid) | 777 | if (!pid) { |
779 | return "<idle>"; | 778 | strcpy(comm, "<idle>"); |
779 | return; | ||
780 | } | ||
780 | 781 | ||
781 | if (pid > PID_MAX_DEFAULT) | 782 | if (pid > PID_MAX_DEFAULT) { |
782 | goto out; | 783 | strcpy(comm, "<...>"); |
784 | return; | ||
785 | } | ||
783 | 786 | ||
787 | __raw_spin_lock(&trace_cmdline_lock); | ||
784 | map = map_pid_to_cmdline[pid]; | 788 | map = map_pid_to_cmdline[pid]; |
785 | if (map >= SAVED_CMDLINES) | 789 | if (map >= SAVED_CMDLINES) |
786 | goto out; | 790 | goto out; |
787 | 791 | ||
788 | cmdline = saved_cmdlines[map]; | 792 | strcpy(comm, saved_cmdlines[map]); |
789 | 793 | ||
790 | out: | 794 | out: |
791 | return cmdline; | 795 | __raw_spin_unlock(&trace_cmdline_lock); |
792 | } | 796 | } |
793 | 797 | ||
794 | void tracing_record_cmdline(struct task_struct *tsk) | 798 | void tracing_record_cmdline(struct task_struct *tsk) |
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h index 56ce34d90b03..b0ecad8ecc34 100644 --- a/kernel/trace/trace.h +++ b/kernel/trace/trace.h | |||
@@ -547,7 +547,7 @@ struct tracer_switch_ops { | |||
547 | }; | 547 | }; |
548 | #endif /* CONFIG_CONTEXT_SWITCH_TRACER */ | 548 | #endif /* CONFIG_CONTEXT_SWITCH_TRACER */ |
549 | 549 | ||
550 | extern char *trace_find_cmdline(int pid); | 550 | extern void trace_find_cmdline(int pid, char comm[]); |
551 | 551 | ||
552 | #ifdef CONFIG_DYNAMIC_FTRACE | 552 | #ifdef CONFIG_DYNAMIC_FTRACE |
553 | extern unsigned long ftrace_update_tot_cnt; | 553 | extern unsigned long ftrace_update_tot_cnt; |
diff --git a/kernel/trace/trace_functions_graph.c b/kernel/trace/trace_functions_graph.c index 4c388607ed67..6004ccac2dd7 100644 --- a/kernel/trace/trace_functions_graph.c +++ b/kernel/trace/trace_functions_graph.c | |||
@@ -190,15 +190,15 @@ print_graph_cpu(struct trace_seq *s, int cpu) | |||
190 | static enum print_line_t | 190 | static enum print_line_t |
191 | print_graph_proc(struct trace_seq *s, pid_t pid) | 191 | print_graph_proc(struct trace_seq *s, pid_t pid) |
192 | { | 192 | { |
193 | int i; | 193 | char comm[TASK_COMM_LEN]; |
194 | int ret; | ||
195 | int len; | ||
196 | char comm[8]; | ||
197 | int spaces = 0; | ||
198 | /* sign + log10(MAX_INT) + '\0' */ | 194 | /* sign + log10(MAX_INT) + '\0' */ |
199 | char pid_str[11]; | 195 | char pid_str[11]; |
196 | int spaces = 0; | ||
197 | int ret; | ||
198 | int len; | ||
199 | int i; | ||
200 | 200 | ||
201 | strncpy(comm, trace_find_cmdline(pid), 7); | 201 | trace_find_cmdline(pid, comm); |
202 | comm[7] = '\0'; | 202 | comm[7] = '\0'; |
203 | sprintf(pid_str, "%d", pid); | 203 | sprintf(pid_str, "%d", pid); |
204 | 204 | ||
diff --git a/kernel/trace/trace_output.c b/kernel/trace/trace_output.c index ea9d3b410c7a..6a4c9dea191e 100644 --- a/kernel/trace/trace_output.c +++ b/kernel/trace/trace_output.c | |||
@@ -309,9 +309,9 @@ static int | |||
309 | lat_print_generic(struct trace_seq *s, struct trace_entry *entry, int cpu) | 309 | lat_print_generic(struct trace_seq *s, struct trace_entry *entry, int cpu) |
310 | { | 310 | { |
311 | int hardirq, softirq; | 311 | int hardirq, softirq; |
312 | char *comm; | 312 | char comm[TASK_COMM_LEN]; |
313 | 313 | ||
314 | comm = trace_find_cmdline(entry->pid); | 314 | trace_find_cmdline(entry->pid, comm); |
315 | hardirq = entry->flags & TRACE_FLAG_HARDIRQ; | 315 | hardirq = entry->flags & TRACE_FLAG_HARDIRQ; |
316 | softirq = entry->flags & TRACE_FLAG_SOFTIRQ; | 316 | softirq = entry->flags & TRACE_FLAG_SOFTIRQ; |
317 | 317 | ||
@@ -346,10 +346,12 @@ int trace_print_context(struct trace_iterator *iter) | |||
346 | { | 346 | { |
347 | struct trace_seq *s = &iter->seq; | 347 | struct trace_seq *s = &iter->seq; |
348 | struct trace_entry *entry = iter->ent; | 348 | struct trace_entry *entry = iter->ent; |
349 | char *comm = trace_find_cmdline(entry->pid); | ||
350 | unsigned long long t = ns2usecs(iter->ts); | 349 | unsigned long long t = ns2usecs(iter->ts); |
351 | unsigned long usec_rem = do_div(t, USEC_PER_SEC); | 350 | unsigned long usec_rem = do_div(t, USEC_PER_SEC); |
352 | unsigned long secs = (unsigned long)t; | 351 | unsigned long secs = (unsigned long)t; |
352 | char comm[TASK_COMM_LEN]; | ||
353 | |||
354 | trace_find_cmdline(entry->pid, comm); | ||
353 | 355 | ||
354 | return trace_seq_printf(s, "%16s-%-5d [%03d] %5lu.%06lu: ", | 356 | return trace_seq_printf(s, "%16s-%-5d [%03d] %5lu.%06lu: ", |
355 | comm, entry->pid, iter->cpu, secs, usec_rem); | 357 | comm, entry->pid, iter->cpu, secs, usec_rem); |
@@ -372,7 +374,10 @@ int trace_print_lat_context(struct trace_iterator *iter) | |||
372 | rel_usecs = ns2usecs(next_ts - iter->ts); | 374 | rel_usecs = ns2usecs(next_ts - iter->ts); |
373 | 375 | ||
374 | if (verbose) { | 376 | if (verbose) { |
375 | char *comm = trace_find_cmdline(entry->pid); | 377 | char comm[TASK_COMM_LEN]; |
378 | |||
379 | trace_find_cmdline(entry->pid, comm); | ||
380 | |||
376 | ret = trace_seq_printf(s, "%16s %5d %3d %d %08x %08lx [%08lx]" | 381 | ret = trace_seq_printf(s, "%16s %5d %3d %d %08x %08lx [%08lx]" |
377 | " %ld.%03ldms (+%ld.%03ldms): ", comm, | 382 | " %ld.%03ldms (+%ld.%03ldms): ", comm, |
378 | entry->pid, iter->cpu, entry->flags, | 383 | entry->pid, iter->cpu, entry->flags, |
@@ -577,14 +582,15 @@ static enum print_line_t trace_ctxwake_print(struct trace_iterator *iter, | |||
577 | char *delim) | 582 | char *delim) |
578 | { | 583 | { |
579 | struct ctx_switch_entry *field; | 584 | struct ctx_switch_entry *field; |
580 | char *comm; | 585 | char comm[TASK_COMM_LEN]; |
581 | int S, T; | 586 | int S, T; |
582 | 587 | ||
588 | |||
583 | trace_assign_type(field, iter->ent); | 589 | trace_assign_type(field, iter->ent); |
584 | 590 | ||
585 | T = task_state_char(field->next_state); | 591 | T = task_state_char(field->next_state); |
586 | S = task_state_char(field->prev_state); | 592 | S = task_state_char(field->prev_state); |
587 | comm = trace_find_cmdline(field->next_pid); | 593 | trace_find_cmdline(field->next_pid, comm); |
588 | if (!trace_seq_printf(&iter->seq, | 594 | if (!trace_seq_printf(&iter->seq, |
589 | " %5d:%3d:%c %s [%03d] %5d:%3d:%c %s\n", | 595 | " %5d:%3d:%c %s [%03d] %5d:%3d:%c %s\n", |
590 | field->prev_pid, | 596 | field->prev_pid, |