mirror of
https://github.com/torvalds/linux.git
synced 2026-11-07 06:17:02 +01:00
rtla: Discard trace entries with cpu >= nr_cpus
The "cpu" field of trace entries processed by rtla in tracefs mode is used as an index into an array of size nr_cpus. In case the cpu numbers mismatch because either the kernel or rtla reporting the number incorrectly, out-of-bounds read/write may occur. Guard against this by dropping trace entries with cpu >= nr_cpus in collect_registered_events(). A new counter, "invalid_events", is added to struct trace_instance, and printed (if non zero) next to the pre-existing missed events counter. Link: https://lore.kernel.org/r/20260814135511.2207190-3-tglozar@redhat.com Signed-off-by: Tomas Glozar <tglozar@redhat.com>
This commit is contained in:
parent
b3dc9905d7
commit
bdb4d4d5db
|
|
@ -114,8 +114,6 @@ struct common_params {
|
|||
struct timerlat_u_params user;
|
||||
};
|
||||
|
||||
extern int nr_cpus;
|
||||
|
||||
#define for_each_monitored_cpu(cpu, common) \
|
||||
for (cpu = 0; cpu < nr_cpus; cpu++) \
|
||||
if (!(common)->cpus || CPU_ISSET(cpu, &(common)->monitored_cpus))
|
||||
|
|
|
|||
|
|
@ -1224,6 +1224,29 @@ bool osnoise_trace_is_off(struct osnoise_tool *tool, struct osnoise_tool *record
|
|||
return record && !tracefs_trace_is_on(record->trace.inst);
|
||||
}
|
||||
|
||||
/*
|
||||
* osnoise_report_invalid_events - report number of invalid events
|
||||
*/
|
||||
void
|
||||
osnoise_report_invalid_events(struct osnoise_tool *tool)
|
||||
{
|
||||
unsigned long long total_events;
|
||||
|
||||
if (tool->trace.invalid_events > 0) {
|
||||
if (tool->trace.missed_events != UINT64_MAX) {
|
||||
total_events = tool->trace.processed_events + tool->trace.invalid_events +
|
||||
tool->trace.missed_events;
|
||||
|
||||
printf("%lld (%.2f%%) invalid events, results might not be accurate\n",
|
||||
tool->trace.invalid_events,
|
||||
(double) tool->trace.invalid_events / total_events * 100.0);
|
||||
} else {
|
||||
printf("%lld invalid events, results might not be accurate\n",
|
||||
tool->trace.invalid_events);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* osnoise_report_missed_events - report number of events dropped by trace
|
||||
* buffer
|
||||
|
|
@ -1236,7 +1259,8 @@ osnoise_report_missed_events(struct osnoise_tool *tool)
|
|||
if (tool->trace.missed_events == UINT64_MAX)
|
||||
printf("unknown number of events missed, results might not be accurate\n");
|
||||
else if (tool->trace.missed_events > 0) {
|
||||
total_events = tool->trace.processed_events + tool->trace.missed_events;
|
||||
total_events = tool->trace.processed_events + tool->trace.invalid_events +
|
||||
tool->trace.missed_events;
|
||||
|
||||
printf("%lld (%.2f%%) events missed, results might not be accurate\n",
|
||||
tool->trace.missed_events,
|
||||
|
|
|
|||
|
|
@ -56,6 +56,8 @@ void osnoise_restore_timerlat_align_us(struct osnoise_context *context);
|
|||
int osnoise_set_timerlat_align(struct osnoise_context *context, bool onoff);
|
||||
|
||||
int osnoise_set_irq_disable(struct osnoise_context *context, bool onoff);
|
||||
|
||||
void osnoise_report_invalid_events(struct osnoise_tool *tool);
|
||||
void osnoise_report_missed_events(struct osnoise_tool *tool);
|
||||
int osnoise_apply_config(struct osnoise_tool *tool, struct osnoise_params *params);
|
||||
|
||||
|
|
|
|||
|
|
@ -397,6 +397,7 @@ osnoise_print_stats(struct osnoise_tool *tool)
|
|||
trace_seq_reset(trace->seq);
|
||||
|
||||
osnoise_print_summary(params, trace, data);
|
||||
osnoise_report_invalid_events(tool);
|
||||
osnoise_report_missed_events(tool);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -242,6 +242,7 @@ osnoise_print_stats(struct osnoise_tool *top)
|
|||
|
||||
trace_seq_do_printf(trace->seq);
|
||||
trace_seq_reset(trace->seq);
|
||||
osnoise_report_invalid_events(top);
|
||||
osnoise_report_missed_events(top);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -682,6 +682,7 @@ timerlat_print_stats(struct osnoise_tool *tool)
|
|||
|
||||
timerlat_print_summary(params, trace, data);
|
||||
timerlat_print_stats_all(params, trace, data);
|
||||
osnoise_report_invalid_events(tool);
|
||||
osnoise_report_missed_events(tool);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -456,6 +456,7 @@ timerlat_print_stats(struct osnoise_tool *top)
|
|||
|
||||
trace_seq_do_printf(trace->seq);
|
||||
trace_seq_reset(trace->seq);
|
||||
osnoise_report_invalid_events(top);
|
||||
osnoise_report_missed_events(top);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -138,6 +138,12 @@ collect_registered_events(struct tep_event *event, struct tep_record *record,
|
|||
struct trace_instance *trace = context;
|
||||
struct trace_seq *s = trace->seq;
|
||||
|
||||
if (cpu >= nr_cpus) {
|
||||
/* Kernel reports event on CPU we don't see, corrupt data? */
|
||||
trace->invalid_events++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
trace->processed_events++;
|
||||
|
||||
if (!event->handler)
|
||||
|
|
@ -236,6 +242,7 @@ int trace_instance_init(struct trace_instance *trace, char *tool_name)
|
|||
trace);
|
||||
|
||||
trace->processed_events = 0;
|
||||
trace->invalid_events = 0;
|
||||
|
||||
return 0;
|
||||
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ struct trace_instance {
|
|||
struct tep_handle *tep;
|
||||
struct trace_seq *seq;
|
||||
unsigned long long missed_events;
|
||||
unsigned long long invalid_events;
|
||||
unsigned long long processed_events;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -40,6 +40,8 @@ static inline bool str_has_prefix(const char *str, const char *prefix)
|
|||
}
|
||||
|
||||
extern bool config_debug;
|
||||
extern int nr_cpus;
|
||||
|
||||
void debug_msg(const char *fmt, ...);
|
||||
void err_msg(const char *fmt, ...);
|
||||
void fatal(const char *fmt, ...);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user