* [PATCH v3 00/18] rtla: Robustness and code quality improvements
@ 2026-01-15 16:31 Wander Lairson Costa
2026-01-15 16:31 ` [PATCH v3 01/18] rtla: Exit on memory allocation failures during initialization Wander Lairson Costa
` (17 more replies)
0 siblings, 18 replies; 33+ messages in thread
From: Wander Lairson Costa @ 2026-01-15 16:31 UTC (permalink / raw)
To: Steven Rostedt, Tomas Glozar, Wander Lairson Costa, Crystal Wood,
Ivan Pravdin, Costa Shulyupin, John Kacur, Tiezhu Yang,
Daniel Wagner, Daniel Bristot de Oliveira,
open list:Real-time Linux Analysis (RTLA) tools,
open list:Real-time Linux Analysis (RTLA) tools,
open list:BPF [MISC]:Keyword:(?:b|_)bpf(?:b|_)
This series addresses multiple issues in the rtla codebase related to
error handling, string manipulation safety, and code maintainability.
The changes improve the tool's reliability and bring the code more in
line with kernel coding practices.
The series can be broadly divided into three categories:
Bug fixes address several correctness issues: a resource leak where
opendir() was not paired with closedir() on success paths, I/O loops
that failed to handle EINTR and partial writes correctly, a missing
bounds check when indexing the softirq_name array with kernel-provided
data, improper handling of pthread_create() failures, and a loop
condition that checked a pointer instead of the character it points to.
String handling improvements replace unsafe patterns throughout the
codebase. The strncpy() function is replaced with a new strscpy()
implementation that guarantees NUL-termination and provides truncation
detection. A str_has_prefix() helper replaces verbose strncmp/strlen
patterns for prefix matching. String comparisons are tightened to use
exact matching where appropriate, preventing silent acceptance of
malformed input like "100nsx" being parsed as "100ns".
Code quality improvements reduce duplication and improve readability.
A common_threshold_handler() consolidates repeated threshold action
logic. The extract_arg() macro simplifies key=value parsing. Magic
numbers are replaced with named constants (MAX_PATH, ARRAY_SIZE), and
redundant strlen() calls are cached in local variables.
All changes have been tested with the existing rtla test suite.
Changes:
v3:
- Address v2 feedback:
- Rename common_restart() to common_threshold_handler() to better
reflect its purpose (Tomas Glozar).
- Implement a proper strscpy() for safer string handling instead of
manual buffer sizing (Steven Rostedt).
- Remove restart_result enum in favor of simpler, direct return
values (Tomas Glozar).
- Add several new bug fixes, including a softirq vector bounds check,
pthread_create() failure handling, robust I/O handling for
EINTR/partial writes, and a resource leak fix.
- Introduce str_has_prefix() helper to replace verbose strncmp/strlen
patterns.
- Tighten string parsing to enforce exact matching and reject invalid
suffixes (e.g., "100nsx").
- Drop patches already merged via RTLA v6.20 pull request.
v2:
- exit on memory allocation failure
- remove redundant strlen() calls
- fix possible race on condition on stop_tracing variable access
- ensure null termination on read() calls
- fix checkpatch reports
- make extract_args() an inline function
- add the usage of common_restart() in more places
Wander Lairson Costa (18):
rtla: Exit on memory allocation failures during initialization
rtla: Use strdup() to simplify code
rtla: Simplify argument parsing
rtla: Introduce common_threshold_handler() helper
rtla: Replace magic number with MAX_PATH
rtla: Simplify code by caching string lengths
rtla: Add strscpy() and replace strncpy() calls
rtla/timerlat: Add bounds check for softirq vector
rtla: Handle pthread_create() failure properly
rtla: Add str_has_prefix() helper function
rtla: Use str_has_prefix() for prefix checks
rtla: Enforce exact match for time unit suffixes
rtla: Use str_has_prefix() for option prefix check
rtla/timerlat: Simplify RTLA_NO_BPF environment variable check
rtla/trace: Fix write loop in trace_event_save_hist()
rtla/trace: Fix I/O handling in save_trace_to_file()
rtla/utils: Fix resource leak in set_comm_sched_attr()
rtla/utils: Fix loop condition in PID validation
tools/tracing/rtla/src/actions.c | 103 ++++++++++++++----------
tools/tracing/rtla/src/actions.h | 8 +-
tools/tracing/rtla/src/common.c | 65 +++++++++++-----
tools/tracing/rtla/src/common.h | 18 +++++
tools/tracing/rtla/src/osnoise.c | 28 +++----
tools/tracing/rtla/src/osnoise_hist.c | 22 ++----
tools/tracing/rtla/src/osnoise_top.c | 22 ++----
tools/tracing/rtla/src/timerlat.c | 5 +-
tools/tracing/rtla/src/timerlat_aa.c | 10 +--
tools/tracing/rtla/src/timerlat_hist.c | 41 ++++------
tools/tracing/rtla/src/timerlat_top.c | 54 ++++++-------
tools/tracing/rtla/src/timerlat_u.c | 4 +-
tools/tracing/rtla/src/trace.c | 101 +++++++++++++-----------
tools/tracing/rtla/src/trace.h | 4 +-
tools/tracing/rtla/src/utils.c | 104 ++++++++++++++++++++-----
tools/tracing/rtla/src/utils.h | 31 +++++++-
16 files changed, 374 insertions(+), 246 deletions(-)
--
2.52.0
^ permalink raw reply [flat|nested] 33+ messages in thread
* [PATCH v3 01/18] rtla: Exit on memory allocation failures during initialization
2026-01-15 16:31 [PATCH v3 00/18] rtla: Robustness and code quality improvements Wander Lairson Costa
@ 2026-01-15 16:31 ` Wander Lairson Costa
2026-01-15 16:31 ` [PATCH v3 02/18] rtla: Use strdup() to simplify code Wander Lairson Costa
` (16 subsequent siblings)
17 siblings, 0 replies; 33+ messages in thread
From: Wander Lairson Costa @ 2026-01-15 16:31 UTC (permalink / raw)
To: Steven Rostedt, Tomas Glozar, Wander Lairson Costa, Crystal Wood,
Ivan Pravdin, Costa Shulyupin, John Kacur, Haiyong Sun,
Tiezhu Yang, Daniel Wagner, Daniel Bristot de Oliveira,
open list:Real-time Linux Analysis (RTLA) tools,
open list:Real-time Linux Analysis (RTLA) tools,
open list:BPF [MISC]:Keyword:(?:b|_)bpf(?:b|_)
Most memory allocations in rtla happen during early initialization
before any resources are acquired that would require cleanup. In these
cases, propagating allocation errors just adds complexity without any
benefit. There's nothing to clean up, and the program must exit anyway.
This patch introduces fatal allocation wrappers (calloc_fatal,
reallocarray_fatal, strdup_fatal) that call fatal() on allocation
failure. These wrappers simplify the code by eliminating unnecessary
error propagation paths.
The patch converts early allocations to use these wrappers in
actions_init() and related action functions, osnoise_context_alloc()
and osnoise_init_tool(), trace_instance_init() and trace event
functions, and parameter structure allocations in main functions.
This simplifies the code while maintaining the same behavior: immediate
exit on allocation failure during initialization. Allocations that
require cleanup, such as those in histogram allocation functions with
goto cleanup paths, are left unchanged and continue to return errors.
Signed-off-by: Wander Lairson Costa <wander@redhat.com>
---
tools/tracing/rtla/src/actions.c | 50 ++++++++++++--------------
tools/tracing/rtla/src/actions.h | 8 ++---
tools/tracing/rtla/src/osnoise.c | 22 ++++--------
tools/tracing/rtla/src/osnoise_hist.c | 22 ++++--------
tools/tracing/rtla/src/osnoise_top.c | 22 ++++--------
tools/tracing/rtla/src/timerlat_hist.c | 22 ++++--------
tools/tracing/rtla/src/timerlat_top.c | 22 ++++--------
tools/tracing/rtla/src/trace.c | 30 ++++------------
tools/tracing/rtla/src/trace.h | 4 +--
tools/tracing/rtla/src/utils.c | 35 ++++++++++++++++++
tools/tracing/rtla/src/utils.h | 3 ++
11 files changed, 108 insertions(+), 132 deletions(-)
diff --git a/tools/tracing/rtla/src/actions.c b/tools/tracing/rtla/src/actions.c
index a42615011962d..22b8283a183f3 100644
--- a/tools/tracing/rtla/src/actions.c
+++ b/tools/tracing/rtla/src/actions.c
@@ -15,7 +15,7 @@ void
actions_init(struct actions *self)
{
self->size = action_default_size;
- self->list = calloc(self->size, sizeof(struct action));
+ self->list = calloc_fatal(self->size, sizeof(struct action));
self->len = 0;
self->continue_flag = false;
@@ -50,8 +50,10 @@ static struct action *
actions_new(struct actions *self)
{
if (self->len >= self->size) {
- self->size *= 2;
- self->list = realloc(self->list, self->size * sizeof(struct action));
+ const size_t new_size = self->size * 2;
+
+ self->list = reallocarray_fatal(self->list, new_size, sizeof(struct action));
+ self->size = new_size;
}
return &self->list[self->len++];
@@ -60,25 +62,21 @@ actions_new(struct actions *self)
/*
* actions_add_trace_output - add an action to output trace
*/
-int
+void
actions_add_trace_output(struct actions *self, const char *trace_output)
{
struct action *action = actions_new(self);
self->present[ACTION_TRACE_OUTPUT] = true;
action->type = ACTION_TRACE_OUTPUT;
- action->trace_output = calloc(strlen(trace_output) + 1, sizeof(char));
- if (!action->trace_output)
- return -1;
+ action->trace_output = calloc_fatal(strlen(trace_output) + 1, sizeof(char));
strcpy(action->trace_output, trace_output);
-
- return 0;
}
/*
* actions_add_trace_output - add an action to send signal to a process
*/
-int
+void
actions_add_signal(struct actions *self, int signal, int pid)
{
struct action *action = actions_new(self);
@@ -87,40 +85,32 @@ actions_add_signal(struct actions *self, int signal, int pid)
action->type = ACTION_SIGNAL;
action->signal = signal;
action->pid = pid;
-
- return 0;
}
/*
* actions_add_shell - add an action to execute a shell command
*/
-int
+void
actions_add_shell(struct actions *self, const char *command)
{
struct action *action = actions_new(self);
self->present[ACTION_SHELL] = true;
action->type = ACTION_SHELL;
- action->command = calloc(strlen(command) + 1, sizeof(char));
- if (!action->command)
- return -1;
+ action->command = calloc_fatal(strlen(command) + 1, sizeof(char));
strcpy(action->command, command);
-
- return 0;
}
/*
* actions_add_continue - add an action to resume measurement
*/
-int
+void
actions_add_continue(struct actions *self)
{
struct action *action = actions_new(self);
self->present[ACTION_CONTINUE] = true;
action->type = ACTION_CONTINUE;
-
- return 0;
}
/*
@@ -176,7 +166,8 @@ actions_parse(struct actions *self, const char *trigger, const char *tracefn)
/* Only one argument allowed */
return -1;
}
- return actions_add_trace_output(self, trace_output);
+ actions_add_trace_output(self, trace_output);
+ break;
case ACTION_SIGNAL:
/* Takes two arguments, num (signal) and pid */
while (token != NULL) {
@@ -200,21 +191,26 @@ actions_parse(struct actions *self, const char *trigger, const char *tracefn)
/* Missing argument */
return -1;
- return actions_add_signal(self, signal, pid);
+ actions_add_signal(self, signal, pid);
+ break;
case ACTION_SHELL:
if (token == NULL)
return -1;
- if (strlen(token) > 8 && strncmp(token, "command=", 8) == 0)
- return actions_add_shell(self, token + 8);
- return -1;
+ if (strlen(token) > 8 && strncmp(token, "command=", 8))
+ return -1;
+ actions_add_shell(self, token + 8);
+ break;
case ACTION_CONTINUE:
/* Takes no argument */
if (token != NULL)
return -1;
- return actions_add_continue(self);
+ actions_add_continue(self);
+ break;
default:
return -1;
}
+
+ return 0;
}
/*
diff --git a/tools/tracing/rtla/src/actions.h b/tools/tracing/rtla/src/actions.h
index fb77069c972ba..034048682fefb 100644
--- a/tools/tracing/rtla/src/actions.h
+++ b/tools/tracing/rtla/src/actions.h
@@ -49,9 +49,9 @@ struct actions {
void actions_init(struct actions *self);
void actions_destroy(struct actions *self);
-int actions_add_trace_output(struct actions *self, const char *trace_output);
-int actions_add_signal(struct actions *self, int signal, int pid);
-int actions_add_shell(struct actions *self, const char *command);
-int actions_add_continue(struct actions *self);
+void actions_add_trace_output(struct actions *self, const char *trace_output);
+void actions_add_signal(struct actions *self, int signal, int pid);
+void actions_add_shell(struct actions *self, const char *command);
+void actions_add_continue(struct actions *self);
int actions_parse(struct actions *self, const char *trigger, const char *tracefn);
int actions_perform(struct actions *self);
diff --git a/tools/tracing/rtla/src/osnoise.c b/tools/tracing/rtla/src/osnoise.c
index 945eb61efc465..ec074cd53dd84 100644
--- a/tools/tracing/rtla/src/osnoise.c
+++ b/tools/tracing/rtla/src/osnoise.c
@@ -938,9 +938,7 @@ struct osnoise_context *osnoise_context_alloc(void)
{
struct osnoise_context *context;
- context = calloc(1, sizeof(*context));
- if (!context)
- return NULL;
+ context = calloc_fatal(1, sizeof(*context));
context->orig_stop_us = OSNOISE_OPTION_INIT_VAL;
context->stop_us = OSNOISE_OPTION_INIT_VAL;
@@ -1017,24 +1015,16 @@ void osnoise_destroy_tool(struct osnoise_tool *top)
struct osnoise_tool *osnoise_init_tool(char *tool_name)
{
struct osnoise_tool *top;
- int retval;
-
- top = calloc(1, sizeof(*top));
- if (!top)
- return NULL;
+ top = calloc_fatal(1, sizeof(*top));
top->context = osnoise_context_alloc();
- if (!top->context)
- goto out_err;
- retval = trace_instance_init(&top->trace, tool_name);
- if (retval)
- goto out_err;
+ if (trace_instance_init(&top->trace, tool_name)) {
+ osnoise_destroy_tool(top);
+ return NULL;
+ }
return top;
-out_err:
- osnoise_destroy_tool(top);
- return NULL;
}
/*
diff --git a/tools/tracing/rtla/src/osnoise_hist.c b/tools/tracing/rtla/src/osnoise_hist.c
index 9d70ea34807ff..efbd2e834cf0e 100644
--- a/tools/tracing/rtla/src/osnoise_hist.c
+++ b/tools/tracing/rtla/src/osnoise_hist.c
@@ -466,9 +466,7 @@ static struct common_params
int c;
char *trace_output = NULL;
- params = calloc(1, sizeof(*params));
- if (!params)
- exit(1);
+ params = calloc_fatal(1, sizeof(*params));
actions_init(¶ms->common.threshold_actions);
actions_init(¶ms->common.end_actions);
@@ -579,22 +577,16 @@ static struct common_params
params->common.hist.with_zeros = 1;
break;
case '4': /* trigger */
- if (params->common.events) {
- retval = trace_event_add_trigger(params->common.events, optarg);
- if (retval)
- fatal("Error adding trigger %s", optarg);
- } else {
+ if (params->common.events)
+ trace_event_add_trigger(params->common.events, optarg);
+ else
fatal("--trigger requires a previous -e");
- }
break;
case '5': /* filter */
- if (params->common.events) {
- retval = trace_event_add_filter(params->common.events, optarg);
- if (retval)
- fatal("Error adding filter %s", optarg);
- } else {
+ if (params->common.events)
+ trace_event_add_filter(params->common.events, optarg);
+ else
fatal("--filter requires a previous -e");
- }
break;
case '6':
params->common.warmup = get_llong_from_str(optarg);
diff --git a/tools/tracing/rtla/src/osnoise_top.c b/tools/tracing/rtla/src/osnoise_top.c
index d54d47947fb44..d2b4ac64e77b4 100644
--- a/tools/tracing/rtla/src/osnoise_top.c
+++ b/tools/tracing/rtla/src/osnoise_top.c
@@ -319,9 +319,7 @@ struct common_params *osnoise_top_parse_args(int argc, char **argv)
int c;
char *trace_output = NULL;
- params = calloc(1, sizeof(*params));
- if (!params)
- exit(1);
+ params = calloc_fatal(1, sizeof(*params));
actions_init(¶ms->common.threshold_actions);
actions_init(¶ms->common.end_actions);
@@ -410,22 +408,16 @@ struct common_params *osnoise_top_parse_args(int argc, char **argv)
params->threshold = get_llong_from_str(optarg);
break;
case '0': /* trigger */
- if (params->common.events) {
- retval = trace_event_add_trigger(params->common.events, optarg);
- if (retval)
- fatal("Error adding trigger %s", optarg);
- } else {
+ if (params->common.events)
+ trace_event_add_trigger(params->common.events, optarg);
+ else
fatal("--trigger requires a previous -e");
- }
break;
case '1': /* filter */
- if (params->common.events) {
- retval = trace_event_add_filter(params->common.events, optarg);
- if (retval)
- fatal("Error adding filter %s", optarg);
- } else {
+ if (params->common.events)
+ trace_event_add_filter(params->common.events, optarg);
+ else
fatal("--filter requires a previous -e");
- }
break;
case '2':
params->common.warmup = get_llong_from_str(optarg);
diff --git a/tools/tracing/rtla/src/timerlat_hist.c b/tools/tracing/rtla/src/timerlat_hist.c
index 4e8c38a61197c..6ea397421f1c9 100644
--- a/tools/tracing/rtla/src/timerlat_hist.c
+++ b/tools/tracing/rtla/src/timerlat_hist.c
@@ -766,9 +766,7 @@ static struct common_params
int c;
char *trace_output = NULL;
- params = calloc(1, sizeof(*params));
- if (!params)
- exit(1);
+ params = calloc_fatal(1, sizeof(*params));
actions_init(¶ms->common.threshold_actions);
actions_init(¶ms->common.end_actions);
@@ -914,22 +912,16 @@ static struct common_params
params->common.hist.with_zeros = 1;
break;
case '6': /* trigger */
- if (params->common.events) {
- retval = trace_event_add_trigger(params->common.events, optarg);
- if (retval)
- fatal("Error adding trigger %s", optarg);
- } else {
+ if (params->common.events)
+ trace_event_add_trigger(params->common.events, optarg);
+ else
fatal("--trigger requires a previous -e");
- }
break;
case '7': /* filter */
- if (params->common.events) {
- retval = trace_event_add_filter(params->common.events, optarg);
- if (retval)
- fatal("Error adding filter %s", optarg);
- } else {
+ if (params->common.events)
+ trace_event_add_filter(params->common.events, optarg);
+ else
fatal("--filter requires a previous -e");
- }
break;
case '8':
params->dma_latency = get_llong_from_str(optarg);
diff --git a/tools/tracing/rtla/src/timerlat_top.c b/tools/tracing/rtla/src/timerlat_top.c
index 284b74773c2b5..dd727cb48b551 100644
--- a/tools/tracing/rtla/src/timerlat_top.c
+++ b/tools/tracing/rtla/src/timerlat_top.c
@@ -537,9 +537,7 @@ static struct common_params
int c;
char *trace_output = NULL;
- params = calloc(1, sizeof(*params));
- if (!params)
- exit(1);
+ params = calloc_fatal(1, sizeof(*params));
actions_init(¶ms->common.threshold_actions);
actions_init(¶ms->common.end_actions);
@@ -664,22 +662,16 @@ static struct common_params
params->common.user_data = true;
break;
case '0': /* trigger */
- if (params->common.events) {
- retval = trace_event_add_trigger(params->common.events, optarg);
- if (retval)
- fatal("Error adding trigger %s", optarg);
- } else {
+ if (params->common.events)
+ trace_event_add_trigger(params->common.events, optarg);
+ else
fatal("--trigger requires a previous -e");
- }
break;
case '1': /* filter */
- if (params->common.events) {
- retval = trace_event_add_filter(params->common.events, optarg);
- if (retval)
- fatal("Error adding filter %s", optarg);
- } else {
+ if (params->common.events)
+ trace_event_add_filter(params->common.events, optarg);
+ else
fatal("--filter requires a previous -e");
- }
break;
case '2': /* dma-latency */
params->dma_latency = get_llong_from_str(optarg);
diff --git a/tools/tracing/rtla/src/trace.c b/tools/tracing/rtla/src/trace.c
index b8be3e28680ee..211ca54b15b0e 100644
--- a/tools/tracing/rtla/src/trace.c
+++ b/tools/tracing/rtla/src/trace.c
@@ -191,9 +191,7 @@ void trace_instance_destroy(struct trace_instance *trace)
*/
int trace_instance_init(struct trace_instance *trace, char *tool_name)
{
- trace->seq = calloc(1, sizeof(*trace->seq));
- if (!trace->seq)
- goto out_err;
+ trace->seq = calloc_fatal(1, sizeof(*trace->seq));
trace_seq_init(trace->seq);
@@ -274,15 +272,9 @@ struct trace_events *trace_event_alloc(const char *event_string)
{
struct trace_events *tevent;
- tevent = calloc(1, sizeof(*tevent));
- if (!tevent)
- return NULL;
+ tevent = calloc_fatal(1, sizeof(*tevent));
- tevent->system = strdup(event_string);
- if (!tevent->system) {
- free(tevent);
- return NULL;
- }
+ tevent->system = strdup_fatal(event_string);
tevent->event = strstr(tevent->system, ":");
if (tevent->event) {
@@ -296,31 +288,23 @@ struct trace_events *trace_event_alloc(const char *event_string)
/*
* trace_event_add_filter - record an event filter
*/
-int trace_event_add_filter(struct trace_events *event, char *filter)
+void trace_event_add_filter(struct trace_events *event, char *filter)
{
if (event->filter)
free(event->filter);
- event->filter = strdup(filter);
- if (!event->filter)
- return 1;
-
- return 0;
+ event->filter = strdup_fatal(filter);
}
/*
* trace_event_add_trigger - record an event trigger action
*/
-int trace_event_add_trigger(struct trace_events *event, char *trigger)
+void trace_event_add_trigger(struct trace_events *event, char *trigger)
{
if (event->trigger)
free(event->trigger);
- event->trigger = strdup(trigger);
- if (!event->trigger)
- return 1;
-
- return 0;
+ event->trigger = strdup_fatal(trigger);
}
/*
diff --git a/tools/tracing/rtla/src/trace.h b/tools/tracing/rtla/src/trace.h
index 1e5aee4b828dd..95b911a2228b2 100644
--- a/tools/tracing/rtla/src/trace.h
+++ b/tools/tracing/rtla/src/trace.h
@@ -45,6 +45,6 @@ void trace_events_destroy(struct trace_instance *instance,
int trace_events_enable(struct trace_instance *instance,
struct trace_events *events);
-int trace_event_add_filter(struct trace_events *event, char *filter);
-int trace_event_add_trigger(struct trace_events *event, char *trigger);
+void trace_event_add_filter(struct trace_events *event, char *filter);
+void trace_event_add_trigger(struct trace_events *event, char *trigger);
int trace_set_buffer_size(struct trace_instance *trace, int size);
diff --git a/tools/tracing/rtla/src/utils.c b/tools/tracing/rtla/src/utils.c
index 18986a5aed3c1..75cdcc63d5a15 100644
--- a/tools/tracing/rtla/src/utils.c
+++ b/tools/tracing/rtla/src/utils.c
@@ -1032,3 +1032,38 @@ int strtoi(const char *s, int *res)
*res = (int) lres;
return 0;
}
+
+static inline void fatal_alloc(void)
+{
+ fatal("Error allocating memory\n");
+}
+
+void *calloc_fatal(size_t n, size_t size)
+{
+ void *p = calloc(n, size);
+
+ if (!p)
+ fatal_alloc();
+
+ return p;
+}
+
+void *reallocarray_fatal(void *p, size_t n, size_t size)
+{
+ p = reallocarray(p, n, size);
+
+ if (!p)
+ fatal_alloc();
+
+ return p;
+}
+
+char *strdup_fatal(const char *s)
+{
+ char *p = strdup(s);
+
+ if (!p)
+ fatal_alloc();
+
+ return p;
+}
diff --git a/tools/tracing/rtla/src/utils.h b/tools/tracing/rtla/src/utils.h
index f7c2a52a0ab54..e29c2eb5d569d 100644
--- a/tools/tracing/rtla/src/utils.h
+++ b/tools/tracing/rtla/src/utils.h
@@ -69,6 +69,9 @@ int set_comm_sched_attr(const char *comm_prefix, struct sched_attr *attr);
int set_comm_cgroup(const char *comm_prefix, const char *cgroup);
int set_pid_cgroup(pid_t pid, const char *cgroup);
int set_cpu_dma_latency(int32_t latency);
+void *calloc_fatal(size_t n, size_t size);
+void *reallocarray_fatal(void *p, size_t n, size_t size);
+char *strdup_fatal(const char *s);
#ifdef HAVE_LIBCPUPOWER_SUPPORT
int save_cpu_idle_disable_state(unsigned int cpu);
int restore_cpu_idle_disable_state(unsigned int cpu);
--
2.52.0
^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH v3 02/18] rtla: Use strdup() to simplify code
2026-01-15 16:31 [PATCH v3 00/18] rtla: Robustness and code quality improvements Wander Lairson Costa
2026-01-15 16:31 ` [PATCH v3 01/18] rtla: Exit on memory allocation failures during initialization Wander Lairson Costa
@ 2026-01-15 16:31 ` Wander Lairson Costa
2026-01-15 16:31 ` [PATCH v3 03/18] rtla: Simplify argument parsing Wander Lairson Costa
` (15 subsequent siblings)
17 siblings, 0 replies; 33+ messages in thread
From: Wander Lairson Costa @ 2026-01-15 16:31 UTC (permalink / raw)
To: Steven Rostedt, Tomas Glozar, Wander Lairson Costa, Crystal Wood,
Ivan Pravdin, Costa Shulyupin, John Kacur, Tiezhu Yang,
Daniel Wagner, Daniel Bristot de Oliveira,
open list:Real-time Linux Analysis (RTLA) tools,
open list:Real-time Linux Analysis (RTLA) tools,
open list:BPF [MISC]:Keyword:(?:b|_)bpf(?:b|_)
The actions_add_trace_output() and actions_add_shell() functions were
using calloc() followed by strcpy() to allocate and copy a string.
This can be simplified by using strdup(), which allocates memory and
copies the string in a single step.
Replace the calloc() and strcpy() calls with strdup(), making the
code more concise and readable.
Signed-off-by: Wander Lairson Costa <wander@redhat.com>
---
tools/tracing/rtla/src/actions.c | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/tools/tracing/rtla/src/actions.c b/tools/tracing/rtla/src/actions.c
index 22b8283a183f3..0ac42ffd734a3 100644
--- a/tools/tracing/rtla/src/actions.c
+++ b/tools/tracing/rtla/src/actions.c
@@ -69,8 +69,7 @@ actions_add_trace_output(struct actions *self, const char *trace_output)
self->present[ACTION_TRACE_OUTPUT] = true;
action->type = ACTION_TRACE_OUTPUT;
- action->trace_output = calloc_fatal(strlen(trace_output) + 1, sizeof(char));
- strcpy(action->trace_output, trace_output);
+ action->trace_output = strdup_fatal(trace_output);
}
/*
@@ -97,8 +96,7 @@ actions_add_shell(struct actions *self, const char *command)
self->present[ACTION_SHELL] = true;
action->type = ACTION_SHELL;
- action->command = calloc_fatal(strlen(command) + 1, sizeof(char));
- strcpy(action->command, command);
+ action->command = strdup_fatal(command);
}
/*
--
2.52.0
^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH v3 03/18] rtla: Simplify argument parsing
2026-01-15 16:31 [PATCH v3 00/18] rtla: Robustness and code quality improvements Wander Lairson Costa
2026-01-15 16:31 ` [PATCH v3 01/18] rtla: Exit on memory allocation failures during initialization Wander Lairson Costa
2026-01-15 16:31 ` [PATCH v3 02/18] rtla: Use strdup() to simplify code Wander Lairson Costa
@ 2026-01-15 16:31 ` Wander Lairson Costa
2026-01-15 21:47 ` Costa Shulyupin
2026-03-03 11:58 ` Tomas Glozar
2026-01-15 16:31 ` [PATCH v3 04/18] rtla: Introduce common_threshold_handler() helper Wander Lairson Costa
` (14 subsequent siblings)
17 siblings, 2 replies; 33+ messages in thread
From: Wander Lairson Costa @ 2026-01-15 16:31 UTC (permalink / raw)
To: Steven Rostedt, Tomas Glozar, Wander Lairson Costa, Crystal Wood,
Ivan Pravdin, Costa Shulyupin, John Kacur, Haiyong Sun,
Tiezhu Yang, Daniel Wagner, Daniel Bristot de Oliveira,
open list:Real-time Linux Analysis (RTLA) tools,
open list:Real-time Linux Analysis (RTLA) tools,
open list:BPF [MISC]:Keyword:(?:b|_)bpf(?:b|_)
The actions_parse() function uses open-coded logic to extract arguments
from a string. This includes manual length checks and strncmp() calls,
which can be verbose and error-prone.
To simplify and improve the robustness of argument parsing, introduce a
new extract_arg() helper macro. This macro extracts the value from a
"key=value" pair, making the code more concise and readable.
Also, introduce STRING_LENGTH() and strncmp_static() macros to
perform compile-time calculations of string lengths and safer string
comparisons.
Refactor actions_parse() to use these new helpers, resulting in
cleaner and more maintainable code.
Signed-off-by: Wander Lairson Costa <wander@redhat.com>
---
tools/tracing/rtla/src/actions.c | 57 +++++++++++++++++++++++---------
tools/tracing/rtla/src/utils.h | 14 ++++++--
2 files changed, 54 insertions(+), 17 deletions(-)
diff --git a/tools/tracing/rtla/src/actions.c b/tools/tracing/rtla/src/actions.c
index 0ac42ffd734a3..b0d68b5de08db 100644
--- a/tools/tracing/rtla/src/actions.c
+++ b/tools/tracing/rtla/src/actions.c
@@ -111,6 +111,29 @@ actions_add_continue(struct actions *self)
action->type = ACTION_CONTINUE;
}
+static inline const char *__extract_arg(const char *token, const char *opt, size_t opt_len)
+{
+ const size_t tok_len = strlen(token);
+
+ if (tok_len <= opt_len)
+ return NULL;
+
+ if (strncmp(token, opt, opt_len))
+ return NULL;
+
+ return token + opt_len;
+}
+
+/*
+ * extract_arg - extract argument value from option token
+ * @token: option token (e.g., "file=trace.txt")
+ * @opt: option name to match (e.g., "file")
+ *
+ * Returns pointer to argument value after "=" if token matches "opt=",
+ * otherwise returns NULL.
+ */
+#define extract_arg(token, opt) __extract_arg(token, opt "=", STRING_LENGTH(opt "="))
+
/*
* actions_parse - add an action based on text specification
*/
@@ -120,6 +143,7 @@ actions_parse(struct actions *self, const char *trigger, const char *tracefn)
enum action_type type = ACTION_NONE;
const char *token;
char trigger_c[strlen(trigger) + 1];
+ const char *arg_value;
/* For ACTION_SIGNAL */
int signal = 0, pid = 0;
@@ -152,12 +176,10 @@ actions_parse(struct actions *self, const char *trigger, const char *tracefn)
if (token == NULL)
trace_output = tracefn;
else {
- if (strlen(token) > 5 && strncmp(token, "file=", 5) == 0) {
- trace_output = token + 5;
- } else {
+ trace_output = extract_arg(token, "file");
+ if (!trace_output)
/* Invalid argument */
return -1;
- }
token = strtok(NULL, ",");
if (token != NULL)
@@ -169,17 +191,21 @@ actions_parse(struct actions *self, const char *trigger, const char *tracefn)
case ACTION_SIGNAL:
/* Takes two arguments, num (signal) and pid */
while (token != NULL) {
- if (strlen(token) > 4 && strncmp(token, "num=", 4) == 0) {
- if (strtoi(token + 4, &signal))
- return -1;
- } else if (strlen(token) > 4 && strncmp(token, "pid=", 4) == 0) {
- if (strncmp(token + 4, "parent", 7) == 0)
- pid = -1;
- else if (strtoi(token + 4, &pid))
+ arg_value = extract_arg(token, "num");
+ if (arg_value) {
+ if (strtoi(arg_value, &signal))
return -1;
} else {
- /* Invalid argument */
- return -1;
+ arg_value = extract_arg(token, "pid");
+ if (arg_value) {
+ if (strncmp_static(arg_value, "parent") == 0)
+ pid = -1;
+ else if (strtoi(arg_value, &pid))
+ return -1;
+ } else {
+ /* Invalid argument */
+ return -1;
+ }
}
token = strtok(NULL, ",");
@@ -194,9 +220,10 @@ actions_parse(struct actions *self, const char *trigger, const char *tracefn)
case ACTION_SHELL:
if (token == NULL)
return -1;
- if (strlen(token) > 8 && strncmp(token, "command=", 8))
+ arg_value = extract_arg(token, "command");
+ if (!arg_value)
return -1;
- actions_add_shell(self, token + 8);
+ actions_add_shell(self, arg_value);
break;
case ACTION_CONTINUE:
/* Takes no argument */
diff --git a/tools/tracing/rtla/src/utils.h b/tools/tracing/rtla/src/utils.h
index e29c2eb5d569d..8323c999260c2 100644
--- a/tools/tracing/rtla/src/utils.h
+++ b/tools/tracing/rtla/src/utils.h
@@ -14,8 +14,18 @@
#define MAX_NICE 20
#define MIN_NICE -19
-#define container_of(ptr, type, member)({ \
- const typeof(((type *)0)->member) *__mptr = (ptr); \
+#ifndef ARRAY_SIZE
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof(*(x)))
+#endif
+
+/* Calculate string length at compile time (excluding null terminator) */
+#define STRING_LENGTH(s) (ARRAY_SIZE(s) - sizeof(*(s)))
+
+/* Compare string with static string, length determined at compile time */
+#define strncmp_static(s1, s2) strncmp(s1, s2, ARRAY_SIZE(s2))
+
+#define container_of(ptr, type, member)({ \
+ const typeof(((type *)0)->member) * __mptr = (ptr); \
(type *)((char *)__mptr - offsetof(type, member)) ; })
extern int config_debug;
--
2.52.0
^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH v3 04/18] rtla: Introduce common_threshold_handler() helper
2026-01-15 16:31 [PATCH v3 00/18] rtla: Robustness and code quality improvements Wander Lairson Costa
` (2 preceding siblings ...)
2026-01-15 16:31 ` [PATCH v3 03/18] rtla: Simplify argument parsing Wander Lairson Costa
@ 2026-01-15 16:31 ` Wander Lairson Costa
2026-01-15 16:31 ` [PATCH v3 05/18] rtla: Replace magic number with MAX_PATH Wander Lairson Costa
` (13 subsequent siblings)
17 siblings, 0 replies; 33+ messages in thread
From: Wander Lairson Costa @ 2026-01-15 16:31 UTC (permalink / raw)
To: Steven Rostedt, Tomas Glozar, Wander Lairson Costa, Ivan Pravdin,
Crystal Wood, Costa Shulyupin, John Kacur, Tiezhu Yang,
Daniel Wagner, Daniel Bristot de Oliveira,
open list:Real-time Linux Analysis (RTLA) tools,
open list:Real-time Linux Analysis (RTLA) tools,
open list:BPF [MISC]:Keyword:(?:b|_)bpf(?:b|_)
Several functions duplicate the logic for handling threshold actions.
When a threshold is reached, these functions stop the trace, perform
configured actions, and restart the trace if --on-threshold continue
is set.
Create common_threshold_handler() to centralize this shared logic and
avoid code duplication. The function executes the configured threshold
actions and restarts the necessary trace instances when appropriate.
Also add should_continue_tracing() helper to encapsulate the check
for whether tracing should continue after a threshold event, improving
code readability at call sites.
In timerlat_top_bpf_main_loop(), use common_params directly instead
of casting through timerlat_params when only common fields are needed.
Signed-off-by: Wander Lairson Costa <wander@redhat.com>
---
tools/tracing/rtla/src/common.c | 61 ++++++++++++++++++--------
tools/tracing/rtla/src/common.h | 18 ++++++++
tools/tracing/rtla/src/timerlat_hist.c | 19 ++++----
tools/tracing/rtla/src/timerlat_top.c | 32 +++++++-------
4 files changed, 86 insertions(+), 44 deletions(-)
diff --git a/tools/tracing/rtla/src/common.c b/tools/tracing/rtla/src/common.c
index ceff76a62a30b..cbc207fa58707 100644
--- a/tools/tracing/rtla/src/common.c
+++ b/tools/tracing/rtla/src/common.c
@@ -175,6 +175,38 @@ common_apply_config(struct osnoise_tool *tool, struct common_params *params)
}
+/**
+ * common_threshold_handler - handle latency threshold overflow
+ * @tool: pointer to the osnoise_tool instance containing trace contexts
+ *
+ * Executes the configured threshold actions (e.g., saving trace, printing,
+ * sending signals). If the continue flag is set (--on-threshold continue),
+ * restarts the auxiliary trace instances to continue monitoring.
+ *
+ * Return: 0 for success, -1 for error.
+ */
+int
+common_threshold_handler(const struct osnoise_tool *tool)
+{
+ actions_perform(&tool->params->threshold_actions);
+
+ if (!should_continue_tracing(tool->params))
+ /* continue flag not set, break */
+ return 0;
+
+ /* continue action reached, re-enable tracing */
+ if (tool->record && trace_instance_start(&tool->record->trace))
+ goto err;
+ if (tool->aa && trace_instance_start(&tool->aa->trace))
+ goto err;
+
+ return 0;
+
+err:
+ err_msg("Error restarting trace\n");
+ return -1;
+}
+
int run_tool(struct tool_ops *ops, int argc, char *argv[])
{
struct common_params *params;
@@ -352,17 +384,14 @@ int top_main_loop(struct osnoise_tool *tool)
/* stop tracing requested, do not perform actions */
return 0;
- actions_perform(¶ms->threshold_actions);
+ retval = common_threshold_handler(tool);
+ if (retval)
+ return retval;
+
- if (!params->threshold_actions.continue_flag)
- /* continue flag not set, break */
+ if (!should_continue_tracing(params))
return 0;
- /* continue action reached, re-enable tracing */
- if (record)
- trace_instance_start(&record->trace);
- if (tool->aa)
- trace_instance_start(&tool->aa->trace);
trace_instance_start(trace);
}
@@ -403,18 +432,14 @@ int hist_main_loop(struct osnoise_tool *tool)
/* stop tracing requested, do not perform actions */
break;
- actions_perform(¶ms->threshold_actions);
+ retval = common_threshold_handler(tool);
+ if (retval)
+ return retval;
- if (!params->threshold_actions.continue_flag)
- /* continue flag not set, break */
- break;
+ if (!should_continue_tracing(params))
+ return 0;
- /* continue action reached, re-enable tracing */
- if (tool->record)
- trace_instance_start(&tool->record->trace);
- if (tool->aa)
- trace_instance_start(&tool->aa->trace);
- trace_instance_start(&tool->trace);
+ trace_instance_start(trace);
}
/* is there still any user-threads ? */
diff --git a/tools/tracing/rtla/src/common.h b/tools/tracing/rtla/src/common.h
index 7602c5593ef5d..c548decd3c40f 100644
--- a/tools/tracing/rtla/src/common.h
+++ b/tools/tracing/rtla/src/common.h
@@ -143,6 +143,24 @@ struct tool_ops {
void (*free)(struct osnoise_tool *tool);
};
+/**
+ * should_continue_tracing - check if tracing should continue after threshold
+ * @params: pointer to the common parameters structure
+ *
+ * Returns true if the continue action was configured (--on-threshold continue),
+ * indicating that tracing should be restarted after handling the threshold event.
+ *
+ * Return: 1 if tracing should continue, 0 otherwise.
+ */
+static inline int
+should_continue_tracing(const struct common_params *params)
+{
+ return params->threshold_actions.continue_flag;
+}
+
+int
+common_threshold_handler(const struct osnoise_tool *tool);
+
int osnoise_set_cpus(struct osnoise_context *context, char *cpus);
void osnoise_restore_cpus(struct osnoise_context *context);
diff --git a/tools/tracing/rtla/src/timerlat_hist.c b/tools/tracing/rtla/src/timerlat_hist.c
index 6ea397421f1c9..6b8eaef8a3a09 100644
--- a/tools/tracing/rtla/src/timerlat_hist.c
+++ b/tools/tracing/rtla/src/timerlat_hist.c
@@ -17,6 +17,7 @@
#include "timerlat.h"
#include "timerlat_aa.h"
#include "timerlat_bpf.h"
+#include "common.h"
struct timerlat_hist_cpu {
int *irq;
@@ -1048,7 +1049,6 @@ static struct osnoise_tool
static int timerlat_hist_bpf_main_loop(struct osnoise_tool *tool)
{
- struct timerlat_params *params = to_timerlat_params(tool->params);
int retval;
while (!stop_tracing) {
@@ -1056,18 +1056,17 @@ static int timerlat_hist_bpf_main_loop(struct osnoise_tool *tool)
if (!stop_tracing) {
/* Threshold overflow, perform actions on threshold */
- actions_perform(¶ms->common.threshold_actions);
+ retval = common_threshold_handler(tool);
+ if (retval)
+ return retval;
- if (!params->common.threshold_actions.continue_flag)
- /* continue flag not set, break */
+ if (!should_continue_tracing(tool->params))
break;
- /* continue action reached, re-enable tracing */
- if (tool->record)
- trace_instance_start(&tool->record->trace);
- if (tool->aa)
- trace_instance_start(&tool->aa->trace);
- timerlat_bpf_restart_tracing();
+ if (timerlat_bpf_restart_tracing()) {
+ err_msg("Error restarting BPF trace\n");
+ return -1;
+ }
}
}
timerlat_bpf_detach();
diff --git a/tools/tracing/rtla/src/timerlat_top.c b/tools/tracing/rtla/src/timerlat_top.c
index dd727cb48b551..c6f6757c3fb6b 100644
--- a/tools/tracing/rtla/src/timerlat_top.c
+++ b/tools/tracing/rtla/src/timerlat_top.c
@@ -17,6 +17,7 @@
#include "timerlat.h"
#include "timerlat_aa.h"
#include "timerlat_bpf.h"
+#include "common.h"
struct timerlat_top_cpu {
unsigned long long irq_count;
@@ -801,10 +802,10 @@ static struct osnoise_tool
static int
timerlat_top_bpf_main_loop(struct osnoise_tool *tool)
{
- struct timerlat_params *params = to_timerlat_params(tool->params);
+ const struct common_params *params = tool->params;
int retval, wait_retval;
- if (params->common.aa_only) {
+ if (params->aa_only) {
/* Auto-analysis only, just wait for stop tracing */
timerlat_bpf_wait(-1);
return 0;
@@ -812,8 +813,8 @@ timerlat_top_bpf_main_loop(struct osnoise_tool *tool)
/* Pull and display data in a loop */
while (!stop_tracing) {
- wait_retval = timerlat_bpf_wait(params->common.quiet ? -1 :
- params->common.sleep_time);
+ wait_retval = timerlat_bpf_wait(params->quiet ? -1 :
+ params->sleep_time);
retval = timerlat_top_bpf_pull_data(tool);
if (retval) {
@@ -821,28 +822,27 @@ timerlat_top_bpf_main_loop(struct osnoise_tool *tool)
return retval;
}
- if (!params->common.quiet)
+ if (!params->quiet)
timerlat_print_stats(tool);
if (wait_retval != 0) {
/* Stopping requested by tracer */
- actions_perform(¶ms->common.threshold_actions);
+ retval = common_threshold_handler(tool);
+ if (retval)
+ return retval;
- if (!params->common.threshold_actions.continue_flag)
- /* continue flag not set, break */
+ if (!should_continue_tracing(tool->params))
break;
- /* continue action reached, re-enable tracing */
- if (tool->record)
- trace_instance_start(&tool->record->trace);
- if (tool->aa)
- trace_instance_start(&tool->aa->trace);
- timerlat_bpf_restart_tracing();
+ if (timerlat_bpf_restart_tracing()) {
+ err_msg("Error restarting BPF trace\n");
+ return -1;
+ }
}
/* is there still any user-threads ? */
- if (params->common.user_workload) {
- if (params->common.user.stopped_running) {
+ if (params->user_workload) {
+ if (params->user.stopped_running) {
debug_msg("timerlat user space threads stopped!\n");
break;
}
--
2.52.0
^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH v3 05/18] rtla: Replace magic number with MAX_PATH
2026-01-15 16:31 [PATCH v3 00/18] rtla: Robustness and code quality improvements Wander Lairson Costa
` (3 preceding siblings ...)
2026-01-15 16:31 ` [PATCH v3 04/18] rtla: Introduce common_threshold_handler() helper Wander Lairson Costa
@ 2026-01-15 16:31 ` Wander Lairson Costa
2026-03-03 12:46 ` Tomas Glozar
2026-01-15 16:31 ` [PATCH v3 06/18] rtla: Simplify code by caching string lengths Wander Lairson Costa
` (12 subsequent siblings)
17 siblings, 1 reply; 33+ messages in thread
From: Wander Lairson Costa @ 2026-01-15 16:31 UTC (permalink / raw)
To: Steven Rostedt, Tomas Glozar, Wander Lairson Costa, Ivan Pravdin,
Crystal Wood, Costa Shulyupin, John Kacur, Tiezhu Yang,
Daniel Wagner, Daniel Bristot de Oliveira,
open list:Real-time Linux Analysis (RTLA) tools,
open list:Real-time Linux Analysis (RTLA) tools,
open list:BPF [MISC]:Keyword:(?:b|_)bpf(?:b|_)
The trace functions use a buffer to manipulate strings that will be
written to tracefs files. These buffers are defined with a magic number
of 1024, which is a common source of vulnerabilities.
Replace the magic number 1024 with the MAX_PATH macro to make the code
safer and more readable. While at it, replace other instances of the
magic number with ARRAY_SIZE() when the buffer is locally defined.
Signed-off-by: Wander Lairson Costa <wander@redhat.com>
---
tools/tracing/rtla/src/osnoise.c | 4 ++--
tools/tracing/rtla/src/timerlat_u.c | 4 ++--
tools/tracing/rtla/src/trace.c | 20 ++++++++++----------
3 files changed, 14 insertions(+), 14 deletions(-)
diff --git a/tools/tracing/rtla/src/osnoise.c b/tools/tracing/rtla/src/osnoise.c
index ec074cd53dd84..4890a9a9d6466 100644
--- a/tools/tracing/rtla/src/osnoise.c
+++ b/tools/tracing/rtla/src/osnoise.c
@@ -52,7 +52,7 @@ char *osnoise_get_cpus(struct osnoise_context *context)
int osnoise_set_cpus(struct osnoise_context *context, char *cpus)
{
char *orig_cpus = osnoise_get_cpus(context);
- char buffer[1024];
+ char buffer[MAX_PATH];
int retval;
if (!orig_cpus)
@@ -62,7 +62,7 @@ int osnoise_set_cpus(struct osnoise_context *context, char *cpus)
if (!context->curr_cpus)
return -1;
- snprintf(buffer, 1024, "%s\n", cpus);
+ snprintf(buffer, ARRAY_SIZE(buffer), "%s\n", cpus);
debug_msg("setting cpus to %s from %s", cpus, context->orig_cpus);
diff --git a/tools/tracing/rtla/src/timerlat_u.c b/tools/tracing/rtla/src/timerlat_u.c
index ce68e39d25fde..efe2f72686486 100644
--- a/tools/tracing/rtla/src/timerlat_u.c
+++ b/tools/tracing/rtla/src/timerlat_u.c
@@ -32,7 +32,7 @@
static int timerlat_u_main(int cpu, struct timerlat_u_params *params)
{
struct sched_param sp = { .sched_priority = 95 };
- char buffer[1024];
+ char buffer[MAX_PATH];
int timerlat_fd;
cpu_set_t set;
int retval;
@@ -83,7 +83,7 @@ static int timerlat_u_main(int cpu, struct timerlat_u_params *params)
/* add should continue with a signal handler */
while (true) {
- retval = read(timerlat_fd, buffer, 1024);
+ retval = read(timerlat_fd, buffer, ARRAY_SIZE(buffer));
if (retval < 0)
break;
}
diff --git a/tools/tracing/rtla/src/trace.c b/tools/tracing/rtla/src/trace.c
index 211ca54b15b0e..e1af54f9531b8 100644
--- a/tools/tracing/rtla/src/trace.c
+++ b/tools/tracing/rtla/src/trace.c
@@ -313,7 +313,7 @@ void trace_event_add_trigger(struct trace_events *event, char *trigger)
static void trace_event_disable_filter(struct trace_instance *instance,
struct trace_events *tevent)
{
- char filter[1024];
+ char filter[MAX_PATH];
int retval;
if (!tevent->filter)
@@ -325,7 +325,7 @@ static void trace_event_disable_filter(struct trace_instance *instance,
debug_msg("Disabling %s:%s filter %s\n", tevent->system,
tevent->event ? : "*", tevent->filter);
- snprintf(filter, 1024, "!%s\n", tevent->filter);
+ snprintf(filter, ARRAY_SIZE(filter), "!%s\n", tevent->filter);
retval = tracefs_event_file_write(instance->inst, tevent->system,
tevent->event, "filter", filter);
@@ -344,7 +344,7 @@ static void trace_event_save_hist(struct trace_instance *instance,
{
int retval, index, out_fd;
mode_t mode = 0644;
- char path[1024];
+ char path[MAX_PATH];
char *hist;
if (!tevent)
@@ -359,7 +359,7 @@ static void trace_event_save_hist(struct trace_instance *instance,
if (retval)
return;
- snprintf(path, 1024, "%s_%s_hist.txt", tevent->system, tevent->event);
+ snprintf(path, ARRAY_SIZE(path), "%s_%s_hist.txt", tevent->system, tevent->event);
printf(" Saving event %s:%s hist to %s\n", tevent->system, tevent->event, path);
@@ -391,7 +391,7 @@ static void trace_event_save_hist(struct trace_instance *instance,
static void trace_event_disable_trigger(struct trace_instance *instance,
struct trace_events *tevent)
{
- char trigger[1024];
+ char trigger[MAX_PATH];
int retval;
if (!tevent->trigger)
@@ -405,7 +405,7 @@ static void trace_event_disable_trigger(struct trace_instance *instance,
trace_event_save_hist(instance, tevent);
- snprintf(trigger, 1024, "!%s\n", tevent->trigger);
+ snprintf(trigger, ARRAY_SIZE(trigger), "!%s\n", tevent->trigger);
retval = tracefs_event_file_write(instance->inst, tevent->system,
tevent->event, "trigger", trigger);
@@ -444,7 +444,7 @@ void trace_events_disable(struct trace_instance *instance,
static int trace_event_enable_filter(struct trace_instance *instance,
struct trace_events *tevent)
{
- char filter[1024];
+ char filter[MAX_PATH];
int retval;
if (!tevent->filter)
@@ -456,7 +456,7 @@ static int trace_event_enable_filter(struct trace_instance *instance,
return 1;
}
- snprintf(filter, 1024, "%s\n", tevent->filter);
+ snprintf(filter, ARRAY_SIZE(filter), "%s\n", tevent->filter);
debug_msg("Enabling %s:%s filter %s\n", tevent->system,
tevent->event ? : "*", tevent->filter);
@@ -479,7 +479,7 @@ static int trace_event_enable_filter(struct trace_instance *instance,
static int trace_event_enable_trigger(struct trace_instance *instance,
struct trace_events *tevent)
{
- char trigger[1024];
+ char trigger[MAX_PATH];
int retval;
if (!tevent->trigger)
@@ -491,7 +491,7 @@ static int trace_event_enable_trigger(struct trace_instance *instance,
return 1;
}
- snprintf(trigger, 1024, "%s\n", tevent->trigger);
+ snprintf(trigger, ARRAY_SIZE(trigger), "%s\n", tevent->trigger);
debug_msg("Enabling %s:%s trigger %s\n", tevent->system,
tevent->event ? : "*", tevent->trigger);
--
2.52.0
^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH v3 06/18] rtla: Simplify code by caching string lengths
2026-01-15 16:31 [PATCH v3 00/18] rtla: Robustness and code quality improvements Wander Lairson Costa
` (4 preceding siblings ...)
2026-01-15 16:31 ` [PATCH v3 05/18] rtla: Replace magic number with MAX_PATH Wander Lairson Costa
@ 2026-01-15 16:31 ` Wander Lairson Costa
2026-01-15 16:31 ` [PATCH v3 07/18] rtla: Add strscpy() and replace strncpy() calls Wander Lairson Costa
` (11 subsequent siblings)
17 siblings, 0 replies; 33+ messages in thread
From: Wander Lairson Costa @ 2026-01-15 16:31 UTC (permalink / raw)
To: Steven Rostedt, Tomas Glozar, Wander Lairson Costa, Ivan Pravdin,
Crystal Wood, Costa Shulyupin, John Kacur, Tiezhu Yang,
Daniel Wagner, Daniel Bristot de Oliveira,
open list:Real-time Linux Analysis (RTLA) tools,
open list:Real-time Linux Analysis (RTLA) tools,
open list:BPF [MISC]:Keyword:(?:b|_)bpf(?:b|_)
Simplify trace_event_save_hist() and set_comm_cgroup() by computing
string lengths once and storing them in local variables, rather than
calling strlen() multiple times on the same unchanged strings. This
makes the code clearer by eliminating redundant function calls and
improving readability.
In trace_event_save_hist(), the write loop previously called strlen()
on the hist buffer twice per iteration for both the size calculation
and loop condition. Store the length in hist_len before entering the
loop. In set_comm_cgroup(), strlen() was called on cgroup_path up to
three times in succession. Store the result in cg_path_len to use in
both the offset calculation and size parameter for subsequent append
operations.
This simplification makes the code easier to read and maintain without
changing program behavior.
Signed-off-by: Wander Lairson Costa <wander@redhat.com>
---
tools/tracing/rtla/src/trace.c | 6 ++++--
tools/tracing/rtla/src/utils.c | 11 +++++++----
2 files changed, 11 insertions(+), 6 deletions(-)
diff --git a/tools/tracing/rtla/src/trace.c b/tools/tracing/rtla/src/trace.c
index e1af54f9531b8..2f529aaf8deef 100644
--- a/tools/tracing/rtla/src/trace.c
+++ b/tools/tracing/rtla/src/trace.c
@@ -346,6 +346,7 @@ static void trace_event_save_hist(struct trace_instance *instance,
mode_t mode = 0644;
char path[MAX_PATH];
char *hist;
+ size_t hist_len;
if (!tevent)
return;
@@ -376,9 +377,10 @@ static void trace_event_save_hist(struct trace_instance *instance,
}
index = 0;
+ hist_len = strlen(hist);
do {
- index += write(out_fd, &hist[index], strlen(hist) - index);
- } while (index < strlen(hist));
+ index += write(out_fd, &hist[index], hist_len - index);
+ } while (index < hist_len);
free(hist);
out_close:
diff --git a/tools/tracing/rtla/src/utils.c b/tools/tracing/rtla/src/utils.c
index 75cdcc63d5a15..b5a6007b108d2 100644
--- a/tools/tracing/rtla/src/utils.c
+++ b/tools/tracing/rtla/src/utils.c
@@ -811,6 +811,7 @@ static int open_cgroup_procs(const char *cgroup)
char cgroup_procs[MAX_PATH];
int retval;
int cg_fd;
+ size_t cg_path_len;
retval = find_mount("cgroup2", cgroup_path, sizeof(cgroup_path));
if (!retval) {
@@ -818,16 +819,18 @@ static int open_cgroup_procs(const char *cgroup)
return -1;
}
+ cg_path_len = strlen(cgroup_path);
+
if (!cgroup) {
- retval = get_self_cgroup(&cgroup_path[strlen(cgroup_path)],
- sizeof(cgroup_path) - strlen(cgroup_path));
+ retval = get_self_cgroup(&cgroup_path[cg_path_len],
+ sizeof(cgroup_path) - cg_path_len);
if (!retval) {
err_msg("Did not find self cgroup\n");
return -1;
}
} else {
- snprintf(&cgroup_path[strlen(cgroup_path)],
- sizeof(cgroup_path) - strlen(cgroup_path), "%s/", cgroup);
+ snprintf(&cgroup_path[cg_path_len],
+ sizeof(cgroup_path) - cg_path_len, "%s/", cgroup);
}
snprintf(cgroup_procs, MAX_PATH, "%s/cgroup.procs", cgroup_path);
--
2.52.0
^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH v3 07/18] rtla: Add strscpy() and replace strncpy() calls
2026-01-15 16:31 [PATCH v3 00/18] rtla: Robustness and code quality improvements Wander Lairson Costa
` (5 preceding siblings ...)
2026-01-15 16:31 ` [PATCH v3 06/18] rtla: Simplify code by caching string lengths Wander Lairson Costa
@ 2026-01-15 16:31 ` Wander Lairson Costa
2026-03-02 14:33 ` Tomas Glozar
2026-01-15 16:31 ` [PATCH v3 08/18] rtla/timerlat: Add bounds check for softirq vector Wander Lairson Costa
` (10 subsequent siblings)
17 siblings, 1 reply; 33+ messages in thread
From: Wander Lairson Costa @ 2026-01-15 16:31 UTC (permalink / raw)
To: Steven Rostedt, Tomas Glozar, Wander Lairson Costa, Crystal Wood,
Ivan Pravdin, Costa Shulyupin, John Kacur, Tiezhu Yang,
Haiyong Sun, Daniel Wagner, Daniel Bristot de Oliveira,
open list:Real-time Linux Analysis (RTLA) tools,
open list:Real-time Linux Analysis (RTLA) tools,
open list:BPF [MISC]:Keyword:(?:b|_)bpf(?:b|_)
Introduce a userspace strscpy() implementation that matches the Linux
kernel's strscpy() semantics. The function is built on top of glibc's
strlcpy() and provides guaranteed NUL-termination along with proper
truncation detection through its return value.
The previous strncpy() calls had potential issues: strncpy() does not
guarantee NUL-termination when the source string length equals or
exceeds the destination buffer size. This required defensive patterns
like pre-zeroing buffers or manually setting the last byte to NUL.
The new strscpy() function always NUL-terminates the destination buffer
unless the size is zero, and returns -E2BIG on truncation, making error
handling cleaner and more consistent with kernel code.
Note that unlike the kernel's strscpy(), this implementation uses
strlcpy() internally, which reads the entire source string to determine
its length. The kernel avoids this to prevent potential DoS attacks from
extremely long untrusted strings. This is harmless for a userspace CLI
tool like rtla where input sources are bounded and trusted.
Replace all strncpy() calls in rtla with strscpy(), using sizeof() for
buffer sizes instead of magic constants to ensure the sizes stay in
sync with the actual buffer declarations. Also remove a now-redundant
memset() call that was previously needed to work around strncpy()
behavior.
Signed-off-by: Wander Lairson Costa <wander@redhat.com>
---
tools/tracing/rtla/src/timerlat_aa.c | 6 ++---
tools/tracing/rtla/src/utils.c | 34 ++++++++++++++++++++++++++--
tools/tracing/rtla/src/utils.h | 1 +
3 files changed, 36 insertions(+), 5 deletions(-)
diff --git a/tools/tracing/rtla/src/timerlat_aa.c b/tools/tracing/rtla/src/timerlat_aa.c
index 31e66ea2b144c..30ef56d644f9c 100644
--- a/tools/tracing/rtla/src/timerlat_aa.c
+++ b/tools/tracing/rtla/src/timerlat_aa.c
@@ -455,9 +455,9 @@ static int timerlat_aa_thread_handler(struct trace_seq *s, struct tep_record *re
taa_data->thread_blocking_duration = duration;
if (comm)
- strncpy(taa_data->run_thread_comm, comm, MAX_COMM);
+ strscpy(taa_data->run_thread_comm, comm, sizeof(taa_data->run_thread_comm));
else
- sprintf(taa_data->run_thread_comm, "<...>");
+ strscpy(taa_data->run_thread_comm, "<...>", sizeof(taa_data->run_thread_comm));
} else {
taa_data->thread_thread_sum += duration;
@@ -519,7 +519,7 @@ static int timerlat_aa_sched_switch_handler(struct trace_seq *s, struct tep_reco
tep_get_field_val(s, event, "next_pid", record, &taa_data->current_pid, 1);
comm = tep_get_field_raw(s, event, "next_comm", record, &val, 1);
- strncpy(taa_data->current_comm, comm, MAX_COMM);
+ strscpy(taa_data->current_comm, comm, sizeof(taa_data->current_comm));
/*
* If this was a kworker, clean the last kworkers that ran.
diff --git a/tools/tracing/rtla/src/utils.c b/tools/tracing/rtla/src/utils.c
index b5a6007b108d2..e98288e55db15 100644
--- a/tools/tracing/rtla/src/utils.c
+++ b/tools/tracing/rtla/src/utils.c
@@ -722,8 +722,7 @@ static const int find_mount(const char *fs, char *mp, int sizeof_mp)
if (!found)
return 0;
- memset(mp, 0, sizeof_mp);
- strncpy(mp, mount_point, sizeof_mp - 1);
+ strscpy(mp, mount_point, sizeof_mp);
debug_msg("Fs %s found at %s\n", fs, mp);
return 1;
@@ -1036,6 +1035,37 @@ int strtoi(const char *s, int *res)
return 0;
}
+/**
+ * strscpy - Copy a C-string into a sized buffer
+ * @dst: Where to copy the string to
+ * @src: Where to copy the string from
+ * @count: Size of destination buffer
+ *
+ * Copy the source string @src, or as much of it as fits, into the destination
+ * @dst buffer. The destination @dst buffer is always NUL-terminated, unless
+ * it's zero-sized.
+ *
+ * This is a userspace implementation matching the kernel's strscpy() semantics,
+ * built on top of glibc's strlcpy().
+ *
+ * Returns the number of characters copied (not including the trailing NUL)
+ * or -E2BIG if @count is 0 or the copy was truncated.
+ */
+ssize_t strscpy(char *dst, const char *src, size_t count)
+{
+ size_t len;
+
+ if (count == 0)
+ return -E2BIG;
+
+ len = strlcpy(dst, src, count);
+
+ if (len >= count)
+ return -E2BIG;
+
+ return (ssize_t) len;
+}
+
static inline void fatal_alloc(void)
{
fatal("Error allocating memory\n");
diff --git a/tools/tracing/rtla/src/utils.h b/tools/tracing/rtla/src/utils.h
index 8323c999260c2..25b08fc5e199a 100644
--- a/tools/tracing/rtla/src/utils.h
+++ b/tools/tracing/rtla/src/utils.h
@@ -97,6 +97,7 @@ static inline int have_libcpupower_support(void) { return 0; }
#endif /* HAVE_LIBCPUPOWER_SUPPORT */
int auto_house_keeping(cpu_set_t *monitored_cpus);
__attribute__((__warn_unused_result__)) int strtoi(const char *s, int *res);
+ssize_t strscpy(char *dst, const char *src, size_t count);
#define ns_to_usf(x) (((double)x/1000))
#define ns_to_per(total, part) ((part * 100) / (double)total)
--
2.52.0
^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH v3 08/18] rtla/timerlat: Add bounds check for softirq vector
2026-01-15 16:31 [PATCH v3 00/18] rtla: Robustness and code quality improvements Wander Lairson Costa
` (6 preceding siblings ...)
2026-01-15 16:31 ` [PATCH v3 07/18] rtla: Add strscpy() and replace strncpy() calls Wander Lairson Costa
@ 2026-01-15 16:31 ` Wander Lairson Costa
2026-01-15 16:31 ` [PATCH v3 09/18] rtla: Handle pthread_create() failure properly Wander Lairson Costa
` (9 subsequent siblings)
17 siblings, 0 replies; 33+ messages in thread
From: Wander Lairson Costa @ 2026-01-15 16:31 UTC (permalink / raw)
To: Steven Rostedt, Tomas Glozar, Wander Lairson Costa, Ivan Pravdin,
Crystal Wood, Costa Shulyupin, John Kacur, Tiezhu Yang,
Haiyong Sun, Daniel Wagner, Daniel Bristot de Oliveira,
open list:Real-time Linux Analysis (RTLA) tools,
open list:Real-time Linux Analysis (RTLA) tools,
open list:BPF [MISC]:Keyword:(?:b|_)bpf(?:b|_)
Add bounds checking when accessing the softirq_name array using the
vector value from kernel trace data. The vector field from the
osnoise:softirq_noise event is used directly as an array index without
validation, which could cause an out-of-bounds read if the kernel
provides an unexpected vector value.
The softirq_name array contains 10 elements corresponding to the
standard Linux softirq vectors. While the kernel should only provide
valid vector values in the range 0-9, defensive programming requires
validating untrusted input before using it as an array index. If an
out-of-range vector is encountered, display the word UNKNOWN instead
of attempting to read beyond the array bounds.
Signed-off-by: Wander Lairson Costa <wander@redhat.com>
---
tools/tracing/rtla/src/timerlat_aa.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/tools/tracing/rtla/src/timerlat_aa.c b/tools/tracing/rtla/src/timerlat_aa.c
index 30ef56d644f9c..bc421637cc19b 100644
--- a/tools/tracing/rtla/src/timerlat_aa.c
+++ b/tools/tracing/rtla/src/timerlat_aa.c
@@ -417,8 +417,8 @@ static int timerlat_aa_softirq_handler(struct trace_seq *s, struct tep_record *r
taa_data->thread_softirq_sum += duration;
trace_seq_printf(taa_data->softirqs_seq, " %24s:%-3llu %.*s %9.2f us\n",
- softirq_name[vector], vector,
- 24, spaces,
+ vector < ARRAY_SIZE(softirq_name) ? softirq_name[vector] : "UNKNOWN",
+ vector, 24, spaces,
ns_to_usf(duration));
return 0;
}
--
2.52.0
^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH v3 09/18] rtla: Handle pthread_create() failure properly
2026-01-15 16:31 [PATCH v3 00/18] rtla: Robustness and code quality improvements Wander Lairson Costa
` (7 preceding siblings ...)
2026-01-15 16:31 ` [PATCH v3 08/18] rtla/timerlat: Add bounds check for softirq vector Wander Lairson Costa
@ 2026-01-15 16:31 ` Wander Lairson Costa
2026-01-15 16:31 ` [PATCH v3 10/18] rtla: Add str_has_prefix() helper function Wander Lairson Costa
` (8 subsequent siblings)
17 siblings, 0 replies; 33+ messages in thread
From: Wander Lairson Costa @ 2026-01-15 16:31 UTC (permalink / raw)
To: Steven Rostedt, Tomas Glozar, Wander Lairson Costa, Ivan Pravdin,
Crystal Wood, Costa Shulyupin, John Kacur, Tiezhu Yang,
Daniel Wagner, Daniel Bristot de Oliveira,
open list:Real-time Linux Analysis (RTLA) tools,
open list:Real-time Linux Analysis (RTLA) tools,
open list:BPF [MISC]:Keyword:(?:b|_)bpf(?:b|_)
Add proper error handling when pthread_create() fails to create the
timerlat user-space dispatcher thread. Previously, the code only logged
an error message but continued execution, which could lead to undefined
behavior when the tool later expects the thread to be running.
When pthread_create() returns an error, the function now jumps to the
out_trace error path to properly clean up resources and exit. This
ensures consistent error handling and prevents the tool from running
in an invalid state without the required user-space thread.
Signed-off-by: Wander Lairson Costa <wander@redhat.com>
---
tools/tracing/rtla/src/common.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/tools/tracing/rtla/src/common.c b/tools/tracing/rtla/src/common.c
index cbc207fa58707..73906065e7772 100644
--- a/tools/tracing/rtla/src/common.c
+++ b/tools/tracing/rtla/src/common.c
@@ -303,8 +303,10 @@ int run_tool(struct tool_ops *ops, int argc, char *argv[])
params->user.cgroup_name = params->cgroup_name;
retval = pthread_create(&user_thread, NULL, timerlat_u_dispatcher, ¶ms->user);
- if (retval)
+ if (retval) {
err_msg("Error creating timerlat user-space threads\n");
+ goto out_trace;
+ }
}
retval = ops->enable(tool);
--
2.52.0
^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH v3 10/18] rtla: Add str_has_prefix() helper function
2026-01-15 16:31 [PATCH v3 00/18] rtla: Robustness and code quality improvements Wander Lairson Costa
` (8 preceding siblings ...)
2026-01-15 16:31 ` [PATCH v3 09/18] rtla: Handle pthread_create() failure properly Wander Lairson Costa
@ 2026-01-15 16:31 ` Wander Lairson Costa
2026-01-15 16:31 ` [PATCH v3 11/18] rtla: Use str_has_prefix() for prefix checks Wander Lairson Costa
` (7 subsequent siblings)
17 siblings, 0 replies; 33+ messages in thread
From: Wander Lairson Costa @ 2026-01-15 16:31 UTC (permalink / raw)
To: Steven Rostedt, Tomas Glozar, Wander Lairson Costa, Crystal Wood,
Ivan Pravdin, Costa Shulyupin, John Kacur, Tiezhu Yang,
Haiyong Sun, Daniel Wagner, Daniel Bristot de Oliveira,
open list:Real-time Linux Analysis (RTLA) tools,
open list:Real-time Linux Analysis (RTLA) tools,
open list:BPF [MISC]:Keyword:(?:b|_)bpf(?:b|_)
Add a str_has_prefix() helper function that tests whether a string
starts with a given prefix. This function provides a cleaner interface
for prefix matching compared to using strncmp() with strlen() directly.
The function returns a boolean value indicating whether the string
starts with the specified prefix. This helper will be used in
subsequent changes to simplify prefix matching code throughout rtla.
Also add the missing string.h include which is needed for the strlen()
and strncmp() functions used by str_has_prefix() and the existing
strncmp_static() macro.
Signed-off-by: Wander Lairson Costa <wander@redhat.com>
---
tools/tracing/rtla/src/utils.h | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/tools/tracing/rtla/src/utils.h b/tools/tracing/rtla/src/utils.h
index 25b08fc5e199a..1235d0f3a7bfd 100644
--- a/tools/tracing/rtla/src/utils.h
+++ b/tools/tracing/rtla/src/utils.h
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0
#include <stdint.h>
+#include <string.h>
#include <time.h>
#include <sched.h>
#include <stdbool.h>
@@ -24,6 +25,18 @@
/* Compare string with static string, length determined at compile time */
#define strncmp_static(s1, s2) strncmp(s1, s2, ARRAY_SIZE(s2))
+/**
+ * str_has_prefix - Test if a string has a given prefix
+ * @str: The string to test
+ * @prefix: The string to see if @str starts with
+ *
+ * Returns: true if @str starts with @prefix, false otherwise
+ */
+static inline bool str_has_prefix(const char *str, const char *prefix)
+{
+ return strncmp(str, prefix, strlen(prefix)) == 0;
+}
+
#define container_of(ptr, type, member)({ \
const typeof(((type *)0)->member) * __mptr = (ptr); \
(type *)((char *)__mptr - offsetof(type, member)) ; })
--
2.52.0
^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH v3 11/18] rtla: Use str_has_prefix() for prefix checks
2026-01-15 16:31 [PATCH v3 00/18] rtla: Robustness and code quality improvements Wander Lairson Costa
` (9 preceding siblings ...)
2026-01-15 16:31 ` [PATCH v3 10/18] rtla: Add str_has_prefix() helper function Wander Lairson Costa
@ 2026-01-15 16:31 ` Wander Lairson Costa
2026-01-15 16:31 ` [PATCH v3 12/18] rtla: Enforce exact match for time unit suffixes Wander Lairson Costa
` (6 subsequent siblings)
17 siblings, 0 replies; 33+ messages in thread
From: Wander Lairson Costa @ 2026-01-15 16:31 UTC (permalink / raw)
To: Steven Rostedt, Tomas Glozar, Wander Lairson Costa, Crystal Wood,
Ivan Pravdin, Costa Shulyupin, John Kacur, Tiezhu Yang,
Daniel Wagner, Daniel Bristot de Oliveira,
open list:Real-time Linux Analysis (RTLA) tools,
open list:Real-time Linux Analysis (RTLA) tools,
open list:BPF [MISC]:Keyword:(?:b|_)bpf(?:b|_)
The code currently uses strncmp() combined with strlen() to check if a
string starts with a specific prefix. This pattern is verbose and prone
to errors if the length does not match the prefix string.
Replace this pattern with the str_has_prefix() helper function in both
trace.c and utils.c. This improves code readability and safety by
handling the prefix length calculation automatically.
In addition, remove the unused retval variable from
trace_event_save_hist() in trace.c to clean up the function and
silence potential compiler warnings.
Signed-off-by: Wander Lairson Costa <wander@redhat.com>
---
tools/tracing/rtla/src/trace.c | 5 ++---
tools/tracing/rtla/src/utils.c | 3 +--
2 files changed, 3 insertions(+), 5 deletions(-)
diff --git a/tools/tracing/rtla/src/trace.c b/tools/tracing/rtla/src/trace.c
index 2f529aaf8deef..ed7db5f4115ce 100644
--- a/tools/tracing/rtla/src/trace.c
+++ b/tools/tracing/rtla/src/trace.c
@@ -342,7 +342,7 @@ static void trace_event_disable_filter(struct trace_instance *instance,
static void trace_event_save_hist(struct trace_instance *instance,
struct trace_events *tevent)
{
- int retval, index, out_fd;
+ int index, out_fd;
mode_t mode = 0644;
char path[MAX_PATH];
char *hist;
@@ -356,8 +356,7 @@ static void trace_event_save_hist(struct trace_instance *instance,
return;
/* is this a hist: trigger? */
- retval = strncmp(tevent->trigger, "hist:", strlen("hist:"));
- if (retval)
+ if (!str_has_prefix(tevent->trigger, "hist:"))
return;
snprintf(path, ARRAY_SIZE(path), "%s_%s_hist.txt", tevent->system, tevent->event);
diff --git a/tools/tracing/rtla/src/utils.c b/tools/tracing/rtla/src/utils.c
index e98288e55db15..486d96e8290fb 100644
--- a/tools/tracing/rtla/src/utils.c
+++ b/tools/tracing/rtla/src/utils.c
@@ -318,8 +318,7 @@ static int procfs_is_workload_pid(const char *comm_prefix, struct dirent *proc_e
return 0;
buffer[MAX_PATH-1] = '\0';
- retval = strncmp(comm_prefix, buffer, strlen(comm_prefix));
- if (retval)
+ if (!str_has_prefix(buffer, comm_prefix))
return 0;
/* comm already have \n */
--
2.52.0
^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH v3 12/18] rtla: Enforce exact match for time unit suffixes
2026-01-15 16:31 [PATCH v3 00/18] rtla: Robustness and code quality improvements Wander Lairson Costa
` (10 preceding siblings ...)
2026-01-15 16:31 ` [PATCH v3 11/18] rtla: Use str_has_prefix() for prefix checks Wander Lairson Costa
@ 2026-01-15 16:31 ` Wander Lairson Costa
2026-03-03 14:27 ` Tomas Glozar
2026-03-04 13:57 ` Tomas Glozar
2026-01-15 16:31 ` [PATCH v3 13/18] rtla: Use str_has_prefix() for option prefix check Wander Lairson Costa
` (5 subsequent siblings)
17 siblings, 2 replies; 33+ messages in thread
From: Wander Lairson Costa @ 2026-01-15 16:31 UTC (permalink / raw)
To: Steven Rostedt, Tomas Glozar, Wander Lairson Costa, Crystal Wood,
Ivan Pravdin, Costa Shulyupin, John Kacur, Tiezhu Yang,
Daniel Wagner, Daniel Bristot de Oliveira,
open list:Real-time Linux Analysis (RTLA) tools,
open list:Real-time Linux Analysis (RTLA) tools,
open list:BPF [MISC]:Keyword:(?:b|_)bpf(?:b|_)
The parse_ns_duration() function currently uses prefix matching for
detecting time units. This approach is problematic as it silently
accepts malformed strings such as "100nsx" or "100us_invalid" by
ignoring the trailing characters, leading to potential configuration
errors.
Switch to using strcmp() for suffix comparison to enforce exact matches.
This ensures that the parser strictly validates the time unit and
rejects any input containing invalid trailing characters, thereby
improving the robustness of the configuration parsing.
Signed-off-by: Wander Lairson Costa <wander@redhat.com>
---
tools/tracing/rtla/src/utils.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/tools/tracing/rtla/src/utils.c b/tools/tracing/rtla/src/utils.c
index 486d96e8290fb..b029fe5970c31 100644
--- a/tools/tracing/rtla/src/utils.c
+++ b/tools/tracing/rtla/src/utils.c
@@ -211,15 +211,15 @@ long parse_ns_duration(char *val)
t = strtol(val, &end, 10);
if (end) {
- if (!strncmp(end, "ns", 2)) {
+ if (strcmp(end, "ns") == 0) {
return t;
- } else if (!strncmp(end, "us", 2)) {
+ } else if (strcmp(end, "us") == 0) {
t *= 1000;
return t;
- } else if (!strncmp(end, "ms", 2)) {
+ } else if (strcmp(end, "ms") == 0) {
t *= 1000 * 1000;
return t;
- } else if (!strncmp(end, "s", 1)) {
+ } else if (strcmp(end, "s") == 0) {
t *= 1000 * 1000 * 1000;
return t;
}
--
2.52.0
^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH v3 13/18] rtla: Use str_has_prefix() for option prefix check
2026-01-15 16:31 [PATCH v3 00/18] rtla: Robustness and code quality improvements Wander Lairson Costa
` (11 preceding siblings ...)
2026-01-15 16:31 ` [PATCH v3 12/18] rtla: Enforce exact match for time unit suffixes Wander Lairson Costa
@ 2026-01-15 16:31 ` Wander Lairson Costa
2026-01-15 16:31 ` [PATCH v3 14/18] rtla/timerlat: Simplify RTLA_NO_BPF environment variable check Wander Lairson Costa
` (4 subsequent siblings)
17 siblings, 0 replies; 33+ messages in thread
From: Wander Lairson Costa @ 2026-01-15 16:31 UTC (permalink / raw)
To: Steven Rostedt, Tomas Glozar, Wander Lairson Costa, Ivan Pravdin,
Crystal Wood, Costa Shulyupin, John Kacur, Tiezhu Yang,
Daniel Wagner, Daniel Bristot de Oliveira,
open list:Real-time Linux Analysis (RTLA) tools,
open list:Real-time Linux Analysis (RTLA) tools,
open list:BPF [MISC]:Keyword:(?:b|_)bpf(?:b|_)
The argument parsing code in timerlat_main() and osnoise_main() uses
strncmp() with a length of 1 to check if the first argument starts
with a dash, indicating an option flag was passed.
Replace this pattern with str_has_prefix() for consistency with the
rest of the codebase. While character comparison would be slightly
more efficient, using str_has_prefix() provides better readability
and maintains a uniform coding style throughout the rtla tool.
Signed-off-by: Wander Lairson Costa <wander@redhat.com>
---
tools/tracing/rtla/src/osnoise.c | 2 +-
tools/tracing/rtla/src/timerlat.c | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/tools/tracing/rtla/src/osnoise.c b/tools/tracing/rtla/src/osnoise.c
index 4890a9a9d6466..5b342d945c5f6 100644
--- a/tools/tracing/rtla/src/osnoise.c
+++ b/tools/tracing/rtla/src/osnoise.c
@@ -1210,7 +1210,7 @@ int osnoise_main(int argc, char *argv[])
if ((strcmp(argv[1], "-h") == 0) || (strcmp(argv[1], "--help") == 0)) {
osnoise_usage(0);
- } else if (strncmp(argv[1], "-", 1) == 0) {
+ } else if (str_has_prefix(argv[1], "-")) {
/* the user skipped the tool, call the default one */
run_tool(&osnoise_top_ops, argc, argv);
exit(0);
diff --git a/tools/tracing/rtla/src/timerlat.c b/tools/tracing/rtla/src/timerlat.c
index 8f8811f7a13bd..84577daadd668 100644
--- a/tools/tracing/rtla/src/timerlat.c
+++ b/tools/tracing/rtla/src/timerlat.c
@@ -272,7 +272,7 @@ int timerlat_main(int argc, char *argv[])
if ((strcmp(argv[1], "-h") == 0) || (strcmp(argv[1], "--help") == 0)) {
timerlat_usage(0);
- } else if (strncmp(argv[1], "-", 1) == 0) {
+ } else if (str_has_prefix(argv[1], "-")) {
/* the user skipped the tool, call the default one */
run_tool(&timerlat_top_ops, argc, argv);
exit(0);
--
2.52.0
^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH v3 14/18] rtla/timerlat: Simplify RTLA_NO_BPF environment variable check
2026-01-15 16:31 [PATCH v3 00/18] rtla: Robustness and code quality improvements Wander Lairson Costa
` (12 preceding siblings ...)
2026-01-15 16:31 ` [PATCH v3 13/18] rtla: Use str_has_prefix() for option prefix check Wander Lairson Costa
@ 2026-01-15 16:31 ` Wander Lairson Costa
2026-03-03 14:38 ` Tomas Glozar
2026-01-15 16:31 ` [PATCH v3 15/18] rtla/trace: Fix write loop in trace_event_save_hist() Wander Lairson Costa
` (3 subsequent siblings)
17 siblings, 1 reply; 33+ messages in thread
From: Wander Lairson Costa @ 2026-01-15 16:31 UTC (permalink / raw)
To: Steven Rostedt, Tomas Glozar, Wander Lairson Costa, Crystal Wood,
Ivan Pravdin, Costa Shulyupin, John Kacur, Tiezhu Yang,
Daniel Wagner, Daniel Bristot de Oliveira,
open list:Real-time Linux Analysis (RTLA) tools,
open list:Real-time Linux Analysis (RTLA) tools,
open list:BPF [MISC]:Keyword:(?:b|_)bpf(?:b|_)
The code that checks the RTLA_NO_BPF environment variable calls
getenv() twice and uses strncmp() with a length of 2 to compare
against the single-character string "1". This is inefficient and
the comparison length is unnecessarily long.
Store the result of getenv() in a local variable to avoid the
redundant call, and replace strncmp() with strcmp() for the exact
match comparison. This follows the same pattern established in
recent commits that improved string comparison consistency
throughout the rtla codebase.
Signed-off-by: Wander Lairson Costa <wander@redhat.com>
---
tools/tracing/rtla/src/timerlat.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/tools/tracing/rtla/src/timerlat.c b/tools/tracing/rtla/src/timerlat.c
index 84577daadd668..d7aeaad975386 100644
--- a/tools/tracing/rtla/src/timerlat.c
+++ b/tools/tracing/rtla/src/timerlat.c
@@ -28,12 +28,13 @@ int
timerlat_apply_config(struct osnoise_tool *tool, struct timerlat_params *params)
{
int retval;
+ const char *const rtla_no_bpf = getenv("RTLA_NO_BPF");
/*
* Try to enable BPF, unless disabled explicitly.
* If BPF enablement fails, fall back to tracefs mode.
*/
- if (getenv("RTLA_NO_BPF") && strncmp(getenv("RTLA_NO_BPF"), "1", 2) == 0) {
+ if (rtla_no_bpf && strcmp(rtla_no_bpf, "1") == 0) {
debug_msg("RTLA_NO_BPF set, disabling BPF\n");
params->mode = TRACING_MODE_TRACEFS;
} else if (!tep_find_event_by_name(tool->trace.tep, "osnoise", "timerlat_sample")) {
--
2.52.0
^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH v3 15/18] rtla/trace: Fix write loop in trace_event_save_hist()
2026-01-15 16:31 [PATCH v3 00/18] rtla: Robustness and code quality improvements Wander Lairson Costa
` (13 preceding siblings ...)
2026-01-15 16:31 ` [PATCH v3 14/18] rtla/timerlat: Simplify RTLA_NO_BPF environment variable check Wander Lairson Costa
@ 2026-01-15 16:31 ` Wander Lairson Costa
2026-03-03 14:51 ` Tomas Glozar
2026-01-15 16:31 ` [PATCH v3 16/18] rtla/trace: Fix I/O handling in save_trace_to_file() Wander Lairson Costa
` (2 subsequent siblings)
17 siblings, 1 reply; 33+ messages in thread
From: Wander Lairson Costa @ 2026-01-15 16:31 UTC (permalink / raw)
To: Steven Rostedt, Tomas Glozar, Wander Lairson Costa, Crystal Wood,
Ivan Pravdin, Costa Shulyupin, John Kacur, Haiyong Sun,
Tiezhu Yang, Daniel Wagner, Daniel Bristot de Oliveira,
open list:Real-time Linux Analysis (RTLA) tools,
open list:Real-time Linux Analysis (RTLA) tools,
open list:BPF [MISC]:Keyword:(?:b|_)bpf(?:b|_)
The write loop in trace_event_save_hist() does not correctly handle
errors from the write() system call. If write() returns -1, this value
is added to the loop index, leading to an incorrect memory access on
the next iteration and potentially an infinite loop. The loop also
fails to handle EINTR.
Fix the write loop by introducing proper error handling. The return
value of write() is now stored in a ssize_t variable and checked for
errors. The loop retries the call if interrupted by a signal and breaks
on any other error after logging it with strerror().
Additionally, change the index variable type from int to size_t to
match the type used for buffer sizes and by strlen(), improving type
safety.
Signed-off-by: Wander Lairson Costa <wander@redhat.com>
---
tools/tracing/rtla/src/trace.c | 14 +++++++++++---
1 file changed, 11 insertions(+), 3 deletions(-)
diff --git a/tools/tracing/rtla/src/trace.c b/tools/tracing/rtla/src/trace.c
index ed7db5f4115ce..fed3362527b08 100644
--- a/tools/tracing/rtla/src/trace.c
+++ b/tools/tracing/rtla/src/trace.c
@@ -342,11 +342,11 @@ static void trace_event_disable_filter(struct trace_instance *instance,
static void trace_event_save_hist(struct trace_instance *instance,
struct trace_events *tevent)
{
- int index, out_fd;
+ size_t index, hist_len;
mode_t mode = 0644;
char path[MAX_PATH];
char *hist;
- size_t hist_len;
+ int out_fd;
if (!tevent)
return;
@@ -378,7 +378,15 @@ static void trace_event_save_hist(struct trace_instance *instance,
index = 0;
hist_len = strlen(hist);
do {
- index += write(out_fd, &hist[index], hist_len - index);
+ const ssize_t written = write(out_fd, &hist[index], hist_len - index);
+
+ if (written < 0) {
+ if (errno == EINTR)
+ continue;
+ err_msg(" Error writing hist file: %s\n", strerror(errno));
+ break;
+ }
+ index += written;
} while (index < hist_len);
free(hist);
--
2.52.0
^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH v3 16/18] rtla/trace: Fix I/O handling in save_trace_to_file()
2026-01-15 16:31 [PATCH v3 00/18] rtla: Robustness and code quality improvements Wander Lairson Costa
` (14 preceding siblings ...)
2026-01-15 16:31 ` [PATCH v3 15/18] rtla/trace: Fix write loop in trace_event_save_hist() Wander Lairson Costa
@ 2026-01-15 16:31 ` Wander Lairson Costa
2026-03-04 10:30 ` Tomas Glozar
2026-01-15 16:32 ` [PATCH v3 17/18] rtla/utils: Fix resource leak in set_comm_sched_attr() Wander Lairson Costa
2026-01-15 16:32 ` [PATCH v3 18/18] rtla/utils: Fix loop condition in PID validation Wander Lairson Costa
17 siblings, 1 reply; 33+ messages in thread
From: Wander Lairson Costa @ 2026-01-15 16:31 UTC (permalink / raw)
To: Steven Rostedt, Tomas Glozar, Wander Lairson Costa, Ivan Pravdin,
Crystal Wood, Costa Shulyupin, John Kacur, Haiyong Sun,
Tiezhu Yang, Daniel Wagner, Daniel Bristot de Oliveira,
open list:Real-time Linux Analysis (RTLA) tools,
open list:Real-time Linux Analysis (RTLA) tools,
open list:BPF [MISC]:Keyword:(?:b|_)bpf(?:b|_)
The read/write loop in save_trace_to_file() does not correctly handle
errors from the read() and write() system calls. If either call is
interrupted by a signal, it returns -1 with errno set to EINTR, but
the code treats this as a fatal error and aborts the save operation.
Additionally, write() may perform a partial write, returning fewer
bytes than requested, which the code does not handle.
Fix the I/O loop by introducing proper error handling. The return
value of read() is now stored in a ssize_t variable and checked for
errors, with EINTR causing a retry. For write(), an inner loop ensures
all bytes are written, handling both EINTR and partial writes. Error
messages now include strerror() output for better debugging.
This follows the same pattern established in the previous commit that
fixed trace_event_save_hist(), ensuring consistent and robust I/O
handling throughout the trace saving code.
Signed-off-by: Wander Lairson Costa <wander@redhat.com>
---
tools/tracing/rtla/src/trace.c | 30 +++++++++++++++++++++++-------
1 file changed, 23 insertions(+), 7 deletions(-)
diff --git a/tools/tracing/rtla/src/trace.c b/tools/tracing/rtla/src/trace.c
index fed3362527b08..8e93b48d33ef8 100644
--- a/tools/tracing/rtla/src/trace.c
+++ b/tools/tracing/rtla/src/trace.c
@@ -73,6 +73,7 @@ int save_trace_to_file(struct tracefs_instance *inst, const char *filename)
char buffer[4096];
int out_fd, in_fd;
int retval = -1;
+ ssize_t n_read;
if (!inst || !filename)
return 0;
@@ -90,15 +91,30 @@ int save_trace_to_file(struct tracefs_instance *inst, const char *filename)
goto out_close_in;
}
- do {
- retval = read(in_fd, buffer, sizeof(buffer));
- if (retval <= 0)
+ for (;;) {
+ n_read = read(in_fd, buffer, sizeof(buffer));
+ if (n_read < 0) {
+ if (errno == EINTR)
+ continue;
+ err_msg("Error reading trace file: %s\n", strerror(errno));
goto out_close;
+ }
+ if (n_read == 0)
+ break;
- retval = write(out_fd, buffer, retval);
- if (retval < 0)
- goto out_close;
- } while (retval > 0);
+ ssize_t n_written = 0;
+ while (n_written < n_read) {
+ ssize_t w = write(out_fd, buffer + n_written, n_read - n_written);
+
+ if (w < 0) {
+ if (errno == EINTR)
+ continue;
+ err_msg("Error writing trace file: %s\n", strerror(errno));
+ goto out_close;
+ }
+ n_written += w;
+ }
+ }
retval = 0;
out_close:
--
2.52.0
^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH v3 17/18] rtla/utils: Fix resource leak in set_comm_sched_attr()
2026-01-15 16:31 [PATCH v3 00/18] rtla: Robustness and code quality improvements Wander Lairson Costa
` (15 preceding siblings ...)
2026-01-15 16:31 ` [PATCH v3 16/18] rtla/trace: Fix I/O handling in save_trace_to_file() Wander Lairson Costa
@ 2026-01-15 16:32 ` Wander Lairson Costa
2026-01-15 16:32 ` [PATCH v3 18/18] rtla/utils: Fix loop condition in PID validation Wander Lairson Costa
17 siblings, 0 replies; 33+ messages in thread
From: Wander Lairson Costa @ 2026-01-15 16:32 UTC (permalink / raw)
To: Steven Rostedt, Tomas Glozar, Wander Lairson Costa, Ivan Pravdin,
Crystal Wood, Costa Shulyupin, John Kacur, Haiyong Sun,
Tiezhu Yang, Daniel Wagner, Daniel Bristot de Oliveira,
open list:Real-time Linux Analysis (RTLA) tools,
open list:Real-time Linux Analysis (RTLA) tools,
open list:BPF [MISC]:Keyword:(?:b|_)bpf(?:b|_)
The set_comm_sched_attr() function opens the /proc directory via
opendir() but fails to call closedir() on its successful exit path.
If the function iterates through all processes without error, it
returns 0 directly, leaking the DIR stream pointer.
Fix this by refactoring the function to use a single exit path. A
retval variable is introduced to track the success or failure status.
All exit points now jump to a unified out label that calls closedir()
before the function returns, ensuring the resource is always freed.
Fixes: dada03db9bb19 ("rtla: Remove procps-ng dependency")
Signed-off-by: Wander Lairson Costa <wander@redhat.com>
---
tools/tracing/rtla/src/utils.c | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)
diff --git a/tools/tracing/rtla/src/utils.c b/tools/tracing/rtla/src/utils.c
index b029fe5970c31..1ea9980d8ecd3 100644
--- a/tools/tracing/rtla/src/utils.c
+++ b/tools/tracing/rtla/src/utils.c
@@ -362,22 +362,23 @@ int set_comm_sched_attr(const char *comm_prefix, struct sched_attr *attr)
if (strtoi(proc_entry->d_name, &pid)) {
err_msg("'%s' is not a valid pid", proc_entry->d_name);
- goto out_err;
+ retval = 1;
+ goto out;
}
/* procfs_is_workload_pid confirmed it is a pid */
retval = __set_sched_attr(pid, attr);
if (retval) {
err_msg("Error setting sched attributes for pid:%s\n", proc_entry->d_name);
- goto out_err;
+ goto out;
}
debug_msg("Set sched attributes for pid:%s\n", proc_entry->d_name);
}
- return 0;
-out_err:
+ retval = 0;
+out:
closedir(procfs);
- return 1;
+ return retval;
}
#define INVALID_VAL (~0L)
--
2.52.0
^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH v3 18/18] rtla/utils: Fix loop condition in PID validation
2026-01-15 16:31 [PATCH v3 00/18] rtla: Robustness and code quality improvements Wander Lairson Costa
` (16 preceding siblings ...)
2026-01-15 16:32 ` [PATCH v3 17/18] rtla/utils: Fix resource leak in set_comm_sched_attr() Wander Lairson Costa
@ 2026-01-15 16:32 ` Wander Lairson Costa
17 siblings, 0 replies; 33+ messages in thread
From: Wander Lairson Costa @ 2026-01-15 16:32 UTC (permalink / raw)
To: Steven Rostedt, Tomas Glozar, Wander Lairson Costa, Crystal Wood,
Ivan Pravdin, Costa Shulyupin, John Kacur, Tiezhu Yang,
Daniel Wagner, Daniel Bristot de Oliveira,
open list:Real-time Linux Analysis (RTLA) tools,
open list:Real-time Linux Analysis (RTLA) tools,
open list:BPF [MISC]:Keyword:(?:b|_)bpf(?:b|_)
The procfs_is_workload_pid() function iterates through a directory
entry name to validate if it represents a process ID. The loop
condition checks if the pointer t_name is non-NULL, but since
incrementing a pointer never makes it NULL, this condition is always
true within the loop's context. Although the inner isdigit() check
catches the NUL terminator and breaks out of the loop, the condition
is semantically misleading and not idiomatic for C string processing.
Correct the loop condition from checking the pointer (t_name) to
checking the character it points to (*t_name). This ensures the loop
terminates when the NUL terminator is reached, aligning with standard
C string iteration practices. While the original code functioned
correctly due to the existing character validation, this change
improves code clarity and maintainability.
Signed-off-by: Wander Lairson Costa <wander@redhat.com>
---
tools/tracing/rtla/src/utils.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tools/tracing/rtla/src/utils.c b/tools/tracing/rtla/src/utils.c
index 1ea9980d8ecd3..3d47f3ed52dee 100644
--- a/tools/tracing/rtla/src/utils.c
+++ b/tools/tracing/rtla/src/utils.c
@@ -296,7 +296,7 @@ static int procfs_is_workload_pid(const char *comm_prefix, struct dirent *proc_e
return 0;
/* check if the string is a pid */
- for (t_name = proc_entry->d_name; t_name; t_name++) {
+ for (t_name = proc_entry->d_name; *t_name; t_name++) {
if (!isdigit(*t_name))
break;
}
--
2.52.0
^ permalink raw reply related [flat|nested] 33+ messages in thread
* Re: [PATCH v3 03/18] rtla: Simplify argument parsing
2026-01-15 16:31 ` [PATCH v3 03/18] rtla: Simplify argument parsing Wander Lairson Costa
@ 2026-01-15 21:47 ` Costa Shulyupin
2026-01-16 11:38 ` Wander Lairson Costa
2026-03-03 11:58 ` Tomas Glozar
1 sibling, 1 reply; 33+ messages in thread
From: Costa Shulyupin @ 2026-01-15 21:47 UTC (permalink / raw)
To: Wander Lairson Costa
Cc: Steven Rostedt, Tomas Glozar, Crystal Wood, Ivan Pravdin,
John Kacur, Haiyong Sun, Tiezhu Yang, Daniel Wagner,
Daniel Bristot de Oliveira,
open list:Real-time Linux Analysis (RTLA) tools,
open list:Real-time Linux Analysis (RTLA) tools,
open list:BPF [MISC]:Keyword:(?:b|_)bpf(?:b|_)
On Thu, 15 Jan 2026 at 19:25, Wander Lairson Costa <wander@redhat.com> wrote:
> To simplify and improve the robustness of argument parsing, introduce a
> new extract_arg() helper macro. This macro extracts the value from a
> "key=value" pair, making the code more concise and readable.
Would you consider using getsubopt?
Costa
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [PATCH v3 03/18] rtla: Simplify argument parsing
2026-01-15 21:47 ` Costa Shulyupin
@ 2026-01-16 11:38 ` Wander Lairson Costa
0 siblings, 0 replies; 33+ messages in thread
From: Wander Lairson Costa @ 2026-01-16 11:38 UTC (permalink / raw)
To: Costa Shulyupin
Cc: Steven Rostedt, Tomas Glozar, Crystal Wood, Ivan Pravdin,
John Kacur, Haiyong Sun, Tiezhu Yang, Daniel Wagner,
Daniel Bristot de Oliveira,
open list:Real-time Linux Analysis (RTLA) tools,
open list:Real-time Linux Analysis (RTLA) tools,
open list:BPF [MISC]:Keyword:(?:b|_)bpf(?:b|_)
On Thu, Jan 15, 2026 at 6:47 PM Costa Shulyupin <costa.shul@redhat.com> wrote:
>
> On Thu, 15 Jan 2026 at 19:25, Wander Lairson Costa <wander@redhat.com> wrote:
> > To simplify and improve the robustness of argument parsing, introduce a
> > new extract_arg() helper macro. This macro extracts the value from a
> > "key=value" pair, making the code more concise and readable.
>
> Would you consider using getsubopt?
>
That's a good idea. But I would like to defer this to a following up patch.
> Costa
>
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [PATCH v3 07/18] rtla: Add strscpy() and replace strncpy() calls
2026-01-15 16:31 ` [PATCH v3 07/18] rtla: Add strscpy() and replace strncpy() calls Wander Lairson Costa
@ 2026-03-02 14:33 ` Tomas Glozar
2026-03-03 11:02 ` Wander Lairson Costa
0 siblings, 1 reply; 33+ messages in thread
From: Tomas Glozar @ 2026-03-02 14:33 UTC (permalink / raw)
To: Wander Lairson Costa
Cc: Steven Rostedt, Crystal Wood, Ivan Pravdin, Costa Shulyupin,
John Kacur, Tiezhu Yang, Haiyong Sun, Daniel Wagner,
Daniel Bristot de Oliveira,
open list:Real-time Linux Analysis (RTLA) tools,
open list:Real-time Linux Analysis (RTLA) tools,
open list:BPF [MISC]:Keyword:(?:b|_)bpf(?:b|_)
čt 15. 1. 2026 v 18:26 odesílatel Wander Lairson Costa
<wander@redhat.com> napsal:
>
> Introduce a userspace strscpy() implementation that matches the Linux
> kernel's strscpy() semantics. The function is built on top of glibc's
> strlcpy() and provides guaranteed NUL-termination along with proper
> truncation detection through its return value.
>
> The previous strncpy() calls had potential issues: strncpy() does not
> guarantee NUL-termination when the source string length equals or
> exceeds the destination buffer size. This required defensive patterns
> like pre-zeroing buffers or manually setting the last byte to NUL.
> The new strscpy() function always NUL-terminates the destination buffer
> unless the size is zero, and returns -E2BIG on truncation, making error
> handling cleaner and more consistent with kernel code.
>
> Note that unlike the kernel's strscpy(), this implementation uses
> strlcpy() internally, which reads the entire source string to determine
> its length. The kernel avoids this to prevent potential DoS attacks from
> extremely long untrusted strings. This is harmless for a userspace CLI
> tool like rtla where input sources are bounded and trusted.
>
strlcpy() was only added in glibc 2.38 [1]. It is thus not available
on systems with older glibc, like RHEL 9. Using it for strscpy()
implementation causes RTLA to fail to build on those systems.
[1] https://www.gnu.org/software/gnulib/manual/html_node/strlcpy.html
> Replace all strncpy() calls in rtla with strscpy(), using sizeof() for
> buffer sizes instead of magic constants to ensure the sizes stay in
> sync with the actual buffer declarations. Also remove a now-redundant
> memset() call that was previously needed to work around strncpy()
> behavior.
>
> Signed-off-by: Wander Lairson Costa <wander@redhat.com>
> ---
> tools/tracing/rtla/src/timerlat_aa.c | 6 ++---
> tools/tracing/rtla/src/utils.c | 34 ++++++++++++++++++++++++++--
> tools/tracing/rtla/src/utils.h | 1 +
> 3 files changed, 36 insertions(+), 5 deletions(-)
>
Tomas
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [PATCH v3 07/18] rtla: Add strscpy() and replace strncpy() calls
2026-03-02 14:33 ` Tomas Glozar
@ 2026-03-03 11:02 ` Wander Lairson Costa
0 siblings, 0 replies; 33+ messages in thread
From: Wander Lairson Costa @ 2026-03-03 11:02 UTC (permalink / raw)
To: Tomas Glozar
Cc: Steven Rostedt, Crystal Wood, Ivan Pravdin, Costa Shulyupin,
John Kacur, Tiezhu Yang, Haiyong Sun, Daniel Wagner,
Daniel Bristot de Oliveira,
open list:Real-time Linux Analysis (RTLA) tools,
open list:Real-time Linux Analysis (RTLA) tools,
open list:BPF [MISC]:Keyword:(?:b|_)bpf(?:b|_)
On Mon, Mar 2, 2026 at 11:33 AM Tomas Glozar <tglozar@redhat.com> wrote:
>
> čt 15. 1. 2026 v 18:26 odesílatel Wander Lairson Costa
> <wander@redhat.com> napsal:
> >
> > Introduce a userspace strscpy() implementation that matches the Linux
> > kernel's strscpy() semantics. The function is built on top of glibc's
> > strlcpy() and provides guaranteed NUL-termination along with proper
> > truncation detection through its return value.
> >
> > The previous strncpy() calls had potential issues: strncpy() does not
> > guarantee NUL-termination when the source string length equals or
> > exceeds the destination buffer size. This required defensive patterns
> > like pre-zeroing buffers or manually setting the last byte to NUL.
> > The new strscpy() function always NUL-terminates the destination buffer
> > unless the size is zero, and returns -E2BIG on truncation, making error
> > handling cleaner and more consistent with kernel code.
> >
> > Note that unlike the kernel's strscpy(), this implementation uses
> > strlcpy() internally, which reads the entire source string to determine
> > its length. The kernel avoids this to prevent potential DoS attacks from
> > extremely long untrusted strings. This is harmless for a userspace CLI
> > tool like rtla where input sources are bounded and trusted.
> >
>
> strlcpy() was only added in glibc 2.38 [1]. It is thus not available
> on systems with older glibc, like RHEL 9. Using it for strscpy()
> implementation causes RTLA to fail to build on those systems.
>
Thanks for pointing this. I will fix that in v4.
> [1] https://www.gnu.org/software/gnulib/manual/html_node/strlcpy.html
>
> > Replace all strncpy() calls in rtla with strscpy(), using sizeof() for
> > buffer sizes instead of magic constants to ensure the sizes stay in
> > sync with the actual buffer declarations. Also remove a now-redundant
> > memset() call that was previously needed to work around strncpy()
> > behavior.
> >
> > Signed-off-by: Wander Lairson Costa <wander@redhat.com>
> > ---
> > tools/tracing/rtla/src/timerlat_aa.c | 6 ++---
> > tools/tracing/rtla/src/utils.c | 34 ++++++++++++++++++++++++++--
> > tools/tracing/rtla/src/utils.h | 1 +
> > 3 files changed, 36 insertions(+), 5 deletions(-)
> >
>
> Tomas
>
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [PATCH v3 03/18] rtla: Simplify argument parsing
2026-01-15 16:31 ` [PATCH v3 03/18] rtla: Simplify argument parsing Wander Lairson Costa
2026-01-15 21:47 ` Costa Shulyupin
@ 2026-03-03 11:58 ` Tomas Glozar
1 sibling, 0 replies; 33+ messages in thread
From: Tomas Glozar @ 2026-03-03 11:58 UTC (permalink / raw)
To: Wander Lairson Costa
Cc: Steven Rostedt, Crystal Wood, Ivan Pravdin, Costa Shulyupin,
John Kacur, Haiyong Sun, Tiezhu Yang, Daniel Wagner,
Daniel Bristot de Oliveira,
open list:Real-time Linux Analysis (RTLA) tools,
open list:Real-time Linux Analysis (RTLA) tools,
open list:BPF [MISC]:Keyword:(?:b|_)bpf(?:b|_)
čt 15. 1. 2026 v 18:25 odesílatel Wander Lairson Costa
<wander@redhat.com> napsal:
>
> The actions_parse() function uses open-coded logic to extract arguments
> from a string. This includes manual length checks and strncmp() calls,
> which can be verbose and error-prone.
>
> To simplify and improve the robustness of argument parsing, introduce a
> new extract_arg() helper macro. This macro extracts the value from a
> "key=value" pair, making the code more concise and readable.
>
> Also, introduce STRING_LENGTH() and strncmp_static() macros to
> perform compile-time calculations of string lengths and safer string
> comparisons.
>
> Refactor actions_parse() to use these new helpers, resulting in
> cleaner and more maintainable code.
>
> Signed-off-by: Wander Lairson Costa <wander@redhat.com>
> ---
> tools/tracing/rtla/src/actions.c | 57 +++++++++++++++++++++++---------
> tools/tracing/rtla/src/utils.h | 14 ++++++--
> 2 files changed, 54 insertions(+), 17 deletions(-)
>
Suggestion in case you will be sending a v4 of the patchset: the
commit description could be more descriptive, something like,
"rtla/actions: Simplify argument parsing", or "rtla: Simply action
argument parsing", to make it clear this affects *action* arguments,
not command-line argument parsing in general.
> diff --git a/tools/tracing/rtla/src/utils.h b/tools/tracing/rtla/src/utils.h
> index e29c2eb5d569d..8323c999260c2 100644
> --- a/tools/tracing/rtla/src/utils.h
> +++ b/tools/tracing/rtla/src/utils.h
> @@ -14,8 +14,18 @@
> #define MAX_NICE 20
> #define MIN_NICE -19
>
> -#define container_of(ptr, type, member)({ \
> - const typeof(((type *)0)->member) *__mptr = (ptr); \
As Crystal pointed out already [1], this part removes container_of,
only to restore it (see below).
[1] https://lore.kernel.org/linux-trace-kernel/301c25518ff81dc967187497a0577f8ee2fb2e29.camel@redhat.com/
> +#ifndef ARRAY_SIZE
> +#define ARRAY_SIZE(x) (sizeof(x) / sizeof(*(x)))
> +#endif
> +
> +/* Calculate string length at compile time (excluding null terminator) */
> +#define STRING_LENGTH(s) (ARRAY_SIZE(s) - sizeof(*(s)))
> +
> +/* Compare string with static string, length determined at compile time */
> +#define strncmp_static(s1, s2) strncmp(s1, s2, ARRAY_SIZE(s2))
> +
> +#define container_of(ptr, type, member)({ \
> + const typeof(((type *)0)->member) * __mptr = (ptr); \
> (type *)((char *)__mptr - offsetof(type, member)) ; })
>
...here, container_of is restored, only with one more tab which is
unnecessary - that is why Git includes it into the diff. If you remove
one tab and update the commit, the change should be dropped.
Otherwise, looks good!
Tomas
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [PATCH v3 05/18] rtla: Replace magic number with MAX_PATH
2026-01-15 16:31 ` [PATCH v3 05/18] rtla: Replace magic number with MAX_PATH Wander Lairson Costa
@ 2026-03-03 12:46 ` Tomas Glozar
0 siblings, 0 replies; 33+ messages in thread
From: Tomas Glozar @ 2026-03-03 12:46 UTC (permalink / raw)
To: Wander Lairson Costa
Cc: Steven Rostedt, Ivan Pravdin, Crystal Wood, Costa Shulyupin,
John Kacur, Tiezhu Yang, Daniel Wagner,
Daniel Bristot de Oliveira,
open list:Real-time Linux Analysis (RTLA) tools,
open list:Real-time Linux Analysis (RTLA) tools,
open list:BPF [MISC]:Keyword:(?:b|_)bpf(?:b|_)
čt 15. 1. 2026 v 18:26 odesílatel Wander Lairson Costa
<wander@redhat.com> napsal:
> --- a/tools/tracing/rtla/src/osnoise.c
> +++ b/tools/tracing/rtla/src/osnoise.c
> @@ -52,7 +52,7 @@ char *osnoise_get_cpus(struct osnoise_context *context)
> int osnoise_set_cpus(struct osnoise_context *context, char *cpus)
> {
> char *orig_cpus = osnoise_get_cpus(context);
> - char buffer[1024];
> + char buffer[MAX_PATH];
Shouldn't this rather be strlen(cpus), a new constant, something like
CPU_STRING_MAX, or a value dynamically computed from nr_cpus? The
buffer is used to store "cpus" concatenated with "\n" to be written to
the osnoise/cpus file, it has nothing to do with MAX_PATH.
The contents of osnoise/cpus can be arbitrarily long [1], if you
specify more than 1040 CPUs - which is theoretically possible, as
CONFIG_NR_CPUs on e.g. Fedora 43 is 8192, although rather unlikely -
it will be truncated.
[1] 17f89102fe23 ("tracing/osnoise: Allow arbitrarily long CPU string")
Tomas
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [PATCH v3 12/18] rtla: Enforce exact match for time unit suffixes
2026-01-15 16:31 ` [PATCH v3 12/18] rtla: Enforce exact match for time unit suffixes Wander Lairson Costa
@ 2026-03-03 14:27 ` Tomas Glozar
2026-03-09 17:17 ` Wander Lairson Costa
2026-03-04 13:57 ` Tomas Glozar
1 sibling, 1 reply; 33+ messages in thread
From: Tomas Glozar @ 2026-03-03 14:27 UTC (permalink / raw)
To: Wander Lairson Costa
Cc: Steven Rostedt, Crystal Wood, Ivan Pravdin, Costa Shulyupin,
John Kacur, Tiezhu Yang, Daniel Wagner,
Daniel Bristot de Oliveira,
open list:Real-time Linux Analysis (RTLA) tools,
open list:Real-time Linux Analysis (RTLA) tools,
open list:BPF [MISC]:Keyword:(?:b|_)bpf(?:b|_)
čt 15. 1. 2026 v 18:28 odesílatel Wander Lairson Costa
<wander@redhat.com> napsal:
>
> The parse_ns_duration() function currently uses prefix matching for
> detecting time units. This approach is problematic as it silently
> accepts malformed strings such as "100nsx" or "100us_invalid" by
> ignoring the trailing characters, leading to potential configuration
> errors.
>
> Switch to using strcmp() for suffix comparison to enforce exact matches.
> This ensures that the parser strictly validates the time unit and
> rejects any input containing invalid trailing characters, thereby
> improving the robustness of the configuration parsing.
>
Why not use your strncmp_static() helper to protect from overrun?
> Signed-off-by: Wander Lairson Costa <wander@redhat.com>
> ---
> tools/tracing/rtla/src/utils.c | 8 ++++----
> 1 file changed, 4 insertions(+), 4 deletions(-)
>
> diff --git a/tools/tracing/rtla/src/utils.c b/tools/tracing/rtla/src/utils.c
> index 486d96e8290fb..b029fe5970c31 100644
> --- a/tools/tracing/rtla/src/utils.c
> +++ b/tools/tracing/rtla/src/utils.c
> @@ -211,15 +211,15 @@ long parse_ns_duration(char *val)
> t = strtol(val, &end, 10);
>
> if (end) {
> - if (!strncmp(end, "ns", 2)) {
> + if (strcmp(end, "ns") == 0) {
> return t;
> - } else if (!strncmp(end, "us", 2)) {
> + } else if (strcmp(end, "us") == 0) {
> t *= 1000;
> return t;
> - } else if (!strncmp(end, "ms", 2)) {
> + } else if (strcmp(end, "ms") == 0) {
> t *= 1000 * 1000;
> return t;
> - } else if (!strncmp(end, "s", 1)) {
> + } else if (strcmp(end, "s") == 0) {
> t *= 1000 * 1000 * 1000;
> return t;
> }
> --
> 2.52.0
>
Tomas
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [PATCH v3 14/18] rtla/timerlat: Simplify RTLA_NO_BPF environment variable check
2026-01-15 16:31 ` [PATCH v3 14/18] rtla/timerlat: Simplify RTLA_NO_BPF environment variable check Wander Lairson Costa
@ 2026-03-03 14:38 ` Tomas Glozar
0 siblings, 0 replies; 33+ messages in thread
From: Tomas Glozar @ 2026-03-03 14:38 UTC (permalink / raw)
To: Wander Lairson Costa
Cc: Steven Rostedt, Crystal Wood, Ivan Pravdin, Costa Shulyupin,
John Kacur, Tiezhu Yang, Daniel Wagner,
Daniel Bristot de Oliveira,
open list:Real-time Linux Analysis (RTLA) tools,
open list:Real-time Linux Analysis (RTLA) tools,
open list:BPF [MISC]:Keyword:(?:b|_)bpf(?:b|_)
čt 15. 1. 2026 v 18:29 odesílatel Wander Lairson Costa
<wander@redhat.com> napsal:
> - if (getenv("RTLA_NO_BPF") && strncmp(getenv("RTLA_NO_BPF"), "1", 2) == 0) {
> + if (rtla_no_bpf && strcmp(rtla_no_bpf, "1") == 0) {
Another use case for strncmp_static()?
> debug_msg("RTLA_NO_BPF set, disabling BPF\n");
> params->mode = TRACING_MODE_TRACEFS;
> } else if (!tep_find_event_by_name(tool->trace.tep, "osnoise", "timerlat_sample")) {
> --
> 2.52.0
>
Tomas
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [PATCH v3 15/18] rtla/trace: Fix write loop in trace_event_save_hist()
2026-01-15 16:31 ` [PATCH v3 15/18] rtla/trace: Fix write loop in trace_event_save_hist() Wander Lairson Costa
@ 2026-03-03 14:51 ` Tomas Glozar
0 siblings, 0 replies; 33+ messages in thread
From: Tomas Glozar @ 2026-03-03 14:51 UTC (permalink / raw)
To: Wander Lairson Costa
Cc: Steven Rostedt, Crystal Wood, Ivan Pravdin, Costa Shulyupin,
John Kacur, Haiyong Sun, Tiezhu Yang, Daniel Wagner,
Daniel Bristot de Oliveira,
open list:Real-time Linux Analysis (RTLA) tools,
open list:Real-time Linux Analysis (RTLA) tools,
open list:BPF [MISC]:Keyword:(?:b|_)bpf(?:b|_)
čt 15. 1. 2026 v 18:29 odesílatel Wander Lairson Costa
<wander@redhat.com> napsal:
>
> The write loop in trace_event_save_hist() does not correctly handle
> errors from the write() system call. If write() returns -1, this value
> is added to the loop index, leading to an incorrect memory access on
> the next iteration and potentially an infinite loop. The loop also
> fails to handle EINTR.
>
> Fix the write loop by introducing proper error handling. The return
> value of write() is now stored in a ssize_t variable and checked for
> errors. The loop retries the call if interrupted by a signal and breaks
> on any other error after logging it with strerror().
>
> Additionally, change the index variable type from int to size_t to
> match the type used for buffer sizes and by strlen(), improving type
> safety.
>
> Signed-off-by: Wander Lairson Costa <wander@redhat.com>
Looks good. Only thing is that it should have a Fixes tag so that it
can be detected by automation (e.g. stable backports - as this is
relatively old code), like this:
Fixes: 761916fd02c2 ("rtla/trace: Save event histogram output to a file")
(on one line, Gmail may truncate that)
Tomas
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [PATCH v3 16/18] rtla/trace: Fix I/O handling in save_trace_to_file()
2026-01-15 16:31 ` [PATCH v3 16/18] rtla/trace: Fix I/O handling in save_trace_to_file() Wander Lairson Costa
@ 2026-03-04 10:30 ` Tomas Glozar
2026-03-09 16:46 ` Wander Lairson Costa
0 siblings, 1 reply; 33+ messages in thread
From: Tomas Glozar @ 2026-03-04 10:30 UTC (permalink / raw)
To: Wander Lairson Costa
Cc: Steven Rostedt, Ivan Pravdin, Crystal Wood, Costa Shulyupin,
John Kacur, Haiyong Sun, Tiezhu Yang, Daniel Wagner,
Daniel Bristot de Oliveira,
open list:Real-time Linux Analysis (RTLA) tools,
open list:Real-time Linux Analysis (RTLA) tools,
open list:BPF [MISC]:Keyword:(?:b|_)bpf(?:b|_)
čt 15. 1. 2026 v 18:29 odesílatel Wander Lairson Costa
<wander@redhat.com> napsal:
> diff --git a/tools/tracing/rtla/src/trace.c b/tools/tracing/rtla/src/trace.c
> index fed3362527b08..8e93b48d33ef8 100644
> --- a/tools/tracing/rtla/src/trace.c
> +++ b/tools/tracing/rtla/src/trace.c
> @@ -73,6 +73,7 @@ int save_trace_to_file(struct tracefs_instance *inst, const char *filename)
> char buffer[4096];
> int out_fd, in_fd;
> int retval = -1;
> + ssize_t n_read;
>
> if (!inst || !filename)
> return 0;
> @@ -90,15 +91,30 @@ int save_trace_to_file(struct tracefs_instance *inst, const char *filename)
> goto out_close_in;
> }
>
> - do {
> - retval = read(in_fd, buffer, sizeof(buffer));
> - if (retval <= 0)
> + for (;;) {
> + n_read = read(in_fd, buffer, sizeof(buffer));
> + if (n_read < 0) {
> + if (errno == EINTR)
> + continue;
> + err_msg("Error reading trace file: %s\n", strerror(errno));
> goto out_close;
> + }
> + if (n_read == 0)
> + break;
>
> - retval = write(out_fd, buffer, retval);
> - if (retval < 0)
> - goto out_close;
> - } while (retval > 0);
> + ssize_t n_written = 0;
Why break the style of declaring all variables at the beginning of the
function? n_read, added in the same commit, keeps the style.
This also applies to the previous patch.
Tomas
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [PATCH v3 12/18] rtla: Enforce exact match for time unit suffixes
2026-01-15 16:31 ` [PATCH v3 12/18] rtla: Enforce exact match for time unit suffixes Wander Lairson Costa
2026-03-03 14:27 ` Tomas Glozar
@ 2026-03-04 13:57 ` Tomas Glozar
2026-03-09 17:15 ` Wander Lairson Costa
1 sibling, 1 reply; 33+ messages in thread
From: Tomas Glozar @ 2026-03-04 13:57 UTC (permalink / raw)
To: Wander Lairson Costa
Cc: Steven Rostedt, Crystal Wood, Ivan Pravdin, Costa Shulyupin,
John Kacur, Tiezhu Yang, Daniel Wagner,
Daniel Bristot de Oliveira,
open list:Real-time Linux Analysis (RTLA) tools,
open list:Real-time Linux Analysis (RTLA) tools,
open list:BPF [MISC]:Keyword:(?:b|_)bpf(?:b|_)
čt 15. 1. 2026 v 18:28 odesílatel Wander Lairson Costa
<wander@redhat.com> napsal:
>
> The parse_ns_duration() function currently uses prefix matching for
> detecting time units. This approach is problematic as it silently
> accepts malformed strings such as "100nsx" or "100us_invalid" by
> ignoring the trailing characters, leading to potential configuration
> errors.
>
> Switch to using strcmp() for suffix comparison to enforce exact matches.
> This ensures that the parser strictly validates the time unit and
> rejects any input containing invalid trailing characters, thereby
> improving the robustness of the configuration parsing.
This solution is incorrect. We need to be able to parse deadline
priority correctly, whose format includes two suffixes:
d:runtime[us|ms|s]:period[us|ms|s]
(see manpages)
and is parsed like this:
int parse_prio(char *arg, struct sched_attr *sched_param)
{
...
switch (arg[0]) {
case 'd':
case 'D':
/* d:runtime:period */
if (strlen(arg) < 4)
return -1;
runtime = get_long_ns_after_colon(arg);
if (runtime == INVALID_VAL)
return -1;
period = get_long_ns_after_colon(&arg[2]);
if (period == INVALID_VAL)
return -1;
...
Your commit breaks that:
$ rtla timerlat -P d:10ms:100ms
Invalid -P priority
Tomas
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [PATCH v3 16/18] rtla/trace: Fix I/O handling in save_trace_to_file()
2026-03-04 10:30 ` Tomas Glozar
@ 2026-03-09 16:46 ` Wander Lairson Costa
0 siblings, 0 replies; 33+ messages in thread
From: Wander Lairson Costa @ 2026-03-09 16:46 UTC (permalink / raw)
To: Tomas Glozar
Cc: Steven Rostedt, Ivan Pravdin, Crystal Wood, Costa Shulyupin,
John Kacur, Haiyong Sun, Tiezhu Yang, Daniel Wagner,
Daniel Bristot de Oliveira,
open list:Real-time Linux Analysis (RTLA) tools,
open list:Real-time Linux Analysis (RTLA) tools,
open list:BPF [MISC]:Keyword:(?:b|_)bpf(?:b|_)
On Wed, Mar 04, 2026 at 11:30:13AM +0100, Tomas Glozar wrote:
> čt 15. 1. 2026 v 18:29 odesílatel Wander Lairson Costa
> <wander@redhat.com> napsal:
> > diff --git a/tools/tracing/rtla/src/trace.c b/tools/tracing/rtla/src/trace.c
> > index fed3362527b08..8e93b48d33ef8 100644
> > --- a/tools/tracing/rtla/src/trace.c
> > +++ b/tools/tracing/rtla/src/trace.c
> > @@ -73,6 +73,7 @@ int save_trace_to_file(struct tracefs_instance *inst, const char *filename)
> > char buffer[4096];
> > int out_fd, in_fd;
> > int retval = -1;
> > + ssize_t n_read;
> >
> > if (!inst || !filename)
> > return 0;
> > @@ -90,15 +91,30 @@ int save_trace_to_file(struct tracefs_instance *inst, const char *filename)
> > goto out_close_in;
> > }
> >
> > - do {
> > - retval = read(in_fd, buffer, sizeof(buffer));
> > - if (retval <= 0)
> > + for (;;) {
> > + n_read = read(in_fd, buffer, sizeof(buffer));
> > + if (n_read < 0) {
> > + if (errno == EINTR)
> > + continue;
> > + err_msg("Error reading trace file: %s\n", strerror(errno));
> > goto out_close;
> > + }
> > + if (n_read == 0)
> > + break;
> >
> > - retval = write(out_fd, buffer, retval);
> > - if (retval < 0)
> > - goto out_close;
> > - } while (retval > 0);
> > + ssize_t n_written = 0;
>
> Why break the style of declaring all variables at the beginning of the
> function? n_read, added in the same commit, keeps the style.
>
> This also applies to the previous patch.
In this case `n_written` is harmless and I see no problem in moving it to the
beginning of the function.
For `written` and `w`, declaring them where they are right now brings the
benefit of making them const correct. If we move them to the top of the
function, we lose that. Since the kernel moved to gnu11, the C89 top-of-block
declarations are relaxed. Keeping them at the point of initialization minimizes
their scope and documents the intent. This helps avoid programmer mistakes.
However, I fail to follow my own advice more than I am willing to admit.
>
> Tomas
>
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [PATCH v3 12/18] rtla: Enforce exact match for time unit suffixes
2026-03-04 13:57 ` Tomas Glozar
@ 2026-03-09 17:15 ` Wander Lairson Costa
0 siblings, 0 replies; 33+ messages in thread
From: Wander Lairson Costa @ 2026-03-09 17:15 UTC (permalink / raw)
To: Tomas Glozar
Cc: Steven Rostedt, Crystal Wood, Ivan Pravdin, Costa Shulyupin,
John Kacur, Tiezhu Yang, Daniel Wagner,
Daniel Bristot de Oliveira,
open list:Real-time Linux Analysis (RTLA) tools,
open list:Real-time Linux Analysis (RTLA) tools,
open list:BPF [MISC]:Keyword:(?:b|_)bpf(?:b|_)
On Wed, Mar 04, 2026 at 02:57:26PM +0100, Tomas Glozar wrote:
> čt 15. 1. 2026 v 18:28 odesílatel Wander Lairson Costa
> <wander@redhat.com> napsal:
> >
> > The parse_ns_duration() function currently uses prefix matching for
> > detecting time units. This approach is problematic as it silently
> > accepts malformed strings such as "100nsx" or "100us_invalid" by
> > ignoring the trailing characters, leading to potential configuration
> > errors.
> >
> > Switch to using strcmp() for suffix comparison to enforce exact matches.
> > This ensures that the parser strictly validates the time unit and
> > rejects any input containing invalid trailing characters, thereby
> > improving the robustness of the configuration parsing.
>
> This solution is incorrect. We need to be able to parse deadline
> priority correctly, whose format includes two suffixes:
>
> d:runtime[us|ms|s]:period[us|ms|s]
> (see manpages)
>
> and is parsed like this:
>
> int parse_prio(char *arg, struct sched_attr *sched_param)
> {
> ...
> switch (arg[0]) {
> case 'd':
> case 'D':
> /* d:runtime:period */
> if (strlen(arg) < 4)
> return -1;
>
> runtime = get_long_ns_after_colon(arg);
> if (runtime == INVALID_VAL)
> return -1;
>
> period = get_long_ns_after_colon(&arg[2]);
> if (period == INVALID_VAL)
> return -1;
> ...
>
> Your commit breaks that:
>
> $ rtla timerlat -P d:10ms:100ms
> Invalid -P priority
You're right, I will fix the bug.
>
> Tomas
>
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [PATCH v3 12/18] rtla: Enforce exact match for time unit suffixes
2026-03-03 14:27 ` Tomas Glozar
@ 2026-03-09 17:17 ` Wander Lairson Costa
0 siblings, 0 replies; 33+ messages in thread
From: Wander Lairson Costa @ 2026-03-09 17:17 UTC (permalink / raw)
To: Tomas Glozar
Cc: Steven Rostedt, Crystal Wood, Ivan Pravdin, Costa Shulyupin,
John Kacur, Tiezhu Yang, Daniel Wagner,
Daniel Bristot de Oliveira,
open list:Real-time Linux Analysis (RTLA) tools,
open list:Real-time Linux Analysis (RTLA) tools,
open list:BPF [MISC]:Keyword:(?:b|_)bpf(?:b|_)
On Tue, Mar 03, 2026 at 03:27:35PM +0100, Tomas Glozar wrote:
> čt 15. 1. 2026 v 18:28 odesílatel Wander Lairson Costa
> <wander@redhat.com> napsal:
> >
> > The parse_ns_duration() function currently uses prefix matching for
> > detecting time units. This approach is problematic as it silently
> > accepts malformed strings such as "100nsx" or "100us_invalid" by
> > ignoring the trailing characters, leading to potential configuration
> > errors.
> >
> > Switch to using strcmp() for suffix comparison to enforce exact matches.
> > This ensures that the parser strictly validates the time unit and
> > rejects any input containing invalid trailing characters, thereby
> > improving the robustness of the configuration parsing.
> >
>
> Why not use your strncmp_static() helper to protect from overrun?
As I said before, sometime I fail to follow my own rules *facepalm*.
>
> > Signed-off-by: Wander Lairson Costa <wander@redhat.com>
> > ---
> > tools/tracing/rtla/src/utils.c | 8 ++++----
> > 1 file changed, 4 insertions(+), 4 deletions(-)
> >
> > diff --git a/tools/tracing/rtla/src/utils.c b/tools/tracing/rtla/src/utils.c
> > index 486d96e8290fb..b029fe5970c31 100644
> > --- a/tools/tracing/rtla/src/utils.c
> > +++ b/tools/tracing/rtla/src/utils.c
> > @@ -211,15 +211,15 @@ long parse_ns_duration(char *val)
> > t = strtol(val, &end, 10);
> >
> > if (end) {
> > - if (!strncmp(end, "ns", 2)) {
> > + if (strcmp(end, "ns") == 0) {
> > return t;
> > - } else if (!strncmp(end, "us", 2)) {
> > + } else if (strcmp(end, "us") == 0) {
> > t *= 1000;
> > return t;
> > - } else if (!strncmp(end, "ms", 2)) {
> > + } else if (strcmp(end, "ms") == 0) {
> > t *= 1000 * 1000;
> > return t;
> > - } else if (!strncmp(end, "s", 1)) {
> > + } else if (strcmp(end, "s") == 0) {
> > t *= 1000 * 1000 * 1000;
> > return t;
> > }
> > --
> > 2.52.0
> >
>
> Tomas
>
^ permalink raw reply [flat|nested] 33+ messages in thread
end of thread, other threads:[~2026-03-09 17:18 UTC | newest]
Thread overview: 33+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-01-15 16:31 [PATCH v3 00/18] rtla: Robustness and code quality improvements Wander Lairson Costa
2026-01-15 16:31 ` [PATCH v3 01/18] rtla: Exit on memory allocation failures during initialization Wander Lairson Costa
2026-01-15 16:31 ` [PATCH v3 02/18] rtla: Use strdup() to simplify code Wander Lairson Costa
2026-01-15 16:31 ` [PATCH v3 03/18] rtla: Simplify argument parsing Wander Lairson Costa
2026-01-15 21:47 ` Costa Shulyupin
2026-01-16 11:38 ` Wander Lairson Costa
2026-03-03 11:58 ` Tomas Glozar
2026-01-15 16:31 ` [PATCH v3 04/18] rtla: Introduce common_threshold_handler() helper Wander Lairson Costa
2026-01-15 16:31 ` [PATCH v3 05/18] rtla: Replace magic number with MAX_PATH Wander Lairson Costa
2026-03-03 12:46 ` Tomas Glozar
2026-01-15 16:31 ` [PATCH v3 06/18] rtla: Simplify code by caching string lengths Wander Lairson Costa
2026-01-15 16:31 ` [PATCH v3 07/18] rtla: Add strscpy() and replace strncpy() calls Wander Lairson Costa
2026-03-02 14:33 ` Tomas Glozar
2026-03-03 11:02 ` Wander Lairson Costa
2026-01-15 16:31 ` [PATCH v3 08/18] rtla/timerlat: Add bounds check for softirq vector Wander Lairson Costa
2026-01-15 16:31 ` [PATCH v3 09/18] rtla: Handle pthread_create() failure properly Wander Lairson Costa
2026-01-15 16:31 ` [PATCH v3 10/18] rtla: Add str_has_prefix() helper function Wander Lairson Costa
2026-01-15 16:31 ` [PATCH v3 11/18] rtla: Use str_has_prefix() for prefix checks Wander Lairson Costa
2026-01-15 16:31 ` [PATCH v3 12/18] rtla: Enforce exact match for time unit suffixes Wander Lairson Costa
2026-03-03 14:27 ` Tomas Glozar
2026-03-09 17:17 ` Wander Lairson Costa
2026-03-04 13:57 ` Tomas Glozar
2026-03-09 17:15 ` Wander Lairson Costa
2026-01-15 16:31 ` [PATCH v3 13/18] rtla: Use str_has_prefix() for option prefix check Wander Lairson Costa
2026-01-15 16:31 ` [PATCH v3 14/18] rtla/timerlat: Simplify RTLA_NO_BPF environment variable check Wander Lairson Costa
2026-03-03 14:38 ` Tomas Glozar
2026-01-15 16:31 ` [PATCH v3 15/18] rtla/trace: Fix write loop in trace_event_save_hist() Wander Lairson Costa
2026-03-03 14:51 ` Tomas Glozar
2026-01-15 16:31 ` [PATCH v3 16/18] rtla/trace: Fix I/O handling in save_trace_to_file() Wander Lairson Costa
2026-03-04 10:30 ` Tomas Glozar
2026-03-09 16:46 ` Wander Lairson Costa
2026-01-15 16:32 ` [PATCH v3 17/18] rtla/utils: Fix resource leak in set_comm_sched_attr() Wander Lairson Costa
2026-01-15 16:32 ` [PATCH v3 18/18] rtla/utils: Fix loop condition in PID validation Wander Lairson Costa
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox