[PATCH] rtla: Fix segfault in save_trace_to_file call

From: Tomas Glozar
Date: Thu Mar 13 2025 - 10:10:54 EST


Running rtla with exit on threshold, but without saving trace leads to a
segmenetation fault:

$ rtla timerlat hist -T 10
...
Max timerlat IRQ latency from idle: 4.29 us in cpu 0
Segmentation fault

This is caused by null pointer deference in the call of
save_trace_to_file, which attempts to dereference an uninitialized
osnoise_tool variable:

save_trace_to_file(record->trace.inst, params->trace_output);
^ this is uninitialized if params->trace_output is
not set

Fix this by not attempting to dereference "record" if it is NULL and
passing NULL instead. As a safety measure, the first field is also
checked for NULL inside save_trace_to_file.

Fixes: dc4d4e7c72d1 ("rtla: Refactor save_trace_to_file")
Signed-off-by: Tomas Glozar <tglozar@xxxxxxxxxx>
---
Note: As this fixes a commit in linux-next, the Fixes commit ID might
have to be adjusted.

tools/tracing/rtla/src/osnoise_hist.c | 3 ++-
tools/tracing/rtla/src/osnoise_top.c | 3 ++-
tools/tracing/rtla/src/timerlat_hist.c | 3 ++-
tools/tracing/rtla/src/timerlat_top.c | 3 ++-
tools/tracing/rtla/src/trace.c | 2 +-
5 files changed, 9 insertions(+), 5 deletions(-)

diff --git a/tools/tracing/rtla/src/osnoise_hist.c b/tools/tracing/rtla/src/osnoise_hist.c
index 7c6ef67ef3e6..f4c9051c33c4 100644
--- a/tools/tracing/rtla/src/osnoise_hist.c
+++ b/tools/tracing/rtla/src/osnoise_hist.c
@@ -983,7 +983,8 @@ int osnoise_hist_main(int argc, char *argv[])

if (osnoise_trace_is_off(tool, record)) {
printf("rtla osnoise hit stop tracing\n");
- save_trace_to_file(record->trace.inst, params->trace_output);
+ save_trace_to_file(record ? record->trace.inst : NULL,
+ params->trace_output);
}

out_hist:
diff --git a/tools/tracing/rtla/src/osnoise_top.c b/tools/tracing/rtla/src/osnoise_top.c
index 0eeefbbbf317..dacec2f99017 100644
--- a/tools/tracing/rtla/src/osnoise_top.c
+++ b/tools/tracing/rtla/src/osnoise_top.c
@@ -813,7 +813,8 @@ int osnoise_top_main(int argc, char **argv)

if (osnoise_trace_is_off(tool, record)) {
printf("osnoise hit stop tracing\n");
- save_trace_to_file(record->trace.inst, params->trace_output);
+ save_trace_to_file(record ? record->trace.inst : NULL,
+ params->trace_output);
}

out_top:
diff --git a/tools/tracing/rtla/src/timerlat_hist.c b/tools/tracing/rtla/src/timerlat_hist.c
index 93d0c9e45020..822c068b4776 100644
--- a/tools/tracing/rtla/src/timerlat_hist.c
+++ b/tools/tracing/rtla/src/timerlat_hist.c
@@ -1473,7 +1473,8 @@ int timerlat_hist_main(int argc, char *argv[])
if (!params->no_aa)
timerlat_auto_analysis(params->stop_us, params->stop_total_us);

- save_trace_to_file(record->trace.inst, params->trace_output);
+ save_trace_to_file(record ? record->trace.inst : NULL,
+ params->trace_output);
}

out_hist:
diff --git a/tools/tracing/rtla/src/timerlat_top.c b/tools/tracing/rtla/src/timerlat_top.c
index 3894ac37d81c..c3196a0bb585 100644
--- a/tools/tracing/rtla/src/timerlat_top.c
+++ b/tools/tracing/rtla/src/timerlat_top.c
@@ -1295,7 +1295,8 @@ int timerlat_top_main(int argc, char *argv[])
if (!params->no_aa)
timerlat_auto_analysis(params->stop_us, params->stop_total_us);

- save_trace_to_file(record->trace.inst, params->trace_output);
+ save_trace_to_file(record ? record->trace.inst : NULL,
+ params->trace_output);
} else if (params->aa_only) {
/*
* If the trace did not stop with --aa-only, at least print the
diff --git a/tools/tracing/rtla/src/trace.c b/tools/tracing/rtla/src/trace.c
index 74ed2f6208ba..69cbc48d53d3 100644
--- a/tools/tracing/rtla/src/trace.c
+++ b/tools/tracing/rtla/src/trace.c
@@ -75,7 +75,7 @@ int save_trace_to_file(struct tracefs_instance *inst, const char *filename)
int out_fd, in_fd;
int retval = -1;

- if (!filename)
+ if (!inst || !filename)
return 0;

in_fd = tracefs_instance_file_open(inst, file, O_RDONLY);
--
2.48.1