rtla: fix cgroup and trace options parsing
Subsystems (3)
v2 cover rtla: fix cgroup and trace options parsing
This series fixes 3 issue in rtla timerlat and osnoise parsing.
1. Fix buffer overflow when using --on-threshold option. Currently passing --on-threshold trace causes rtla timerlat to segfault. First patch addresses this issue.
2. Make -C/--cgroup option more user-friendly. Currently rtla timerlat and osnoise parses does not allow to specify tracer's threads cgroup name as -C [cgroup] or --cgroup [cgroup]. Second patch fixes this by allowing users to specify cgroup in the aforementioned manner.
3. When specifying -t/--trace before -a/--auto, trace filename is override to default <osnoise|timerlat>_trace.txt. For example, when running rtla as
rtla timerlat top -t custom_file.txt -a 100
when the threshold is reached, timerlat_trace.txt file is created instead of specified custom_file.txt. Third patch addresses this issue.
changes v1 -> v2:
- Moved removing clear_terminal from fix -C/--cgroup interface patch to fix -a overriding -t argument patch
- Added clarification why to remove clear_terminal
- Added Fixes: tag to the fix -C/--cgroup interface patch
v1: https://lore.kernel.org/linux-trace-kernel/[email protected]/T/#t
Ivan Pravdin (3):
rtla: fix buffer overflow in actions_parse
rtla: fix -C/--cgroup interface
rtla: fix -a overriding -t argument
Documentation/tools/rtla/common_options.rst | 2 +- tools/tracing/rtla/src/actions.c | 2 +- tools/tracing/rtla/src/osnoise_hist.c | 25 +++++++++----- tools/tracing/rtla/src/osnoise_top.c | 25 +++++++++----- tools/tracing/rtla/src/timerlat_hist.c | 25 +++++++++----- tools/tracing/rtla/src/timerlat_top.c | 37 +++++++++------------ 6 files changed, 66 insertions(+), 50 deletions(-)
Signature · 1 line
2.48.1
PATCH v2 1/3 rtla: fix buffer overflow in actions_parse
Currently, tests 3 and 13-22 in tests/timerlat.t fail with error:
*** buffer overflow detected ***: terminated
timeout: the monitored command dumped core
The result of running sudo make check is
tests/timerlat.t (Wstat: 0 Tests: 22 Failed: 11)
Failed tests: 3, 13-22
Files=3, Tests=34, 140 wallclock secs ( 0.07 usr 0.01 sys + 27.63 cusr
27.96 csys = 55.67 CPU)
Result: FAILFix buffer overflow in actions_parse to avoid this error. After this change, the tests results are
tests/hwnoise.t ... ok
tests/osnoise.t ... ok
tests/timerlat.t .. ok
All tests successful.
Files=3, Tests=34, 186 wallclock secs ( 0.06 usr 0.01 sys + 41.10 cusr 44.38 csys = 85.55 CPU)
Result: PASS
--- tools/tracing/rtla/src/actions.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
tools/tracing/rtla/src/actions.c +1 -1
@@ -131,7 +131,7 @@ actions_parse(struct actions *self, const char *trigger) {enum action_type type =ACTION_NONE ;char *token; -char trigger_c[strlen (trigger)]; +char trigger_c[strlen (trigger) +1 ];/* For ACTION_SIGNAL */ int signal =0 , pid =0 ;
Signature · 1 line
2.48.1
Re: [PATCH v2 1/3] rtla: fix buffer overflow in actions_parse
út 12. 8. 2025 v 19:21 odesílatel Ivan Pravdin
<[email protected]> napsal:
Quoted 6 lines
Currently, tests 3 and 13-22 in tests/timerlat.t fail with error:
*** buffer overflow detected ***: terminated
timeout: the monitored command dumped core
Quoted 8 lines
The result of running
sudo make checkistests/timerlat.t (Wstat: 0 Tests: 22 Failed: 11) Failed tests: 3, 13-22 Files=3, Tests=34, 140 wallclock secs ( 0.07 usr 0.01 sys + 27.63 cusr 27.96 csys = 55.67 CPU) Result: FAIL
Interestingly, I don't get this failure on my machine. Maybe due to some compiler difference, the buffer overflow is not caught. Thank you for the fix. Since the "signal" field is next to the buffer, and is written after the strcpy, this might corrupt the PID number reading for a command like:
$ rtla timerlat hist -D --on-threshold signal,num=2,pid=42
Tomas
PATCH v2 2/3 rtla: fix -C/--cgroup interface
In reply to Ivan PravdinCurrently, user can only specify cgroup to the tracer's thread the following ways:
`-C[cgroup]`
`-C[=cgroup]`
`--cgroup[=cgroup]`If user tries to specify cgroup as -C [cgroup] or --cgroup [cgroup], the parser silently fails and rtla's cgroup is used for the tracer threads.
To make interface more user-friendly, allow user to specify cgroup in the aforementioned way, i.e. -C [cgroup] and --cgroup [cgroup]
Change documentation to reflect this user interface change.
--- Documentation/tools/rtla/common_options.rst | 2 +- tools/tracing/rtla/src/osnoise_hist.c | 17 +++++++++++------ tools/tracing/rtla/src/osnoise_top.c | 17 +++++++++++------ tools/tracing/rtla/src/timerlat_hist.c | 17 +++++++++++------ tools/tracing/rtla/src/timerlat_top.c | 17 +++++++++++------ 5 files changed, 45 insertions(+), 25 deletions(-)
Documentation/tools/rtla/common_options.rst +1 -1
@@ -42,7 +42,7 @@ - *f:prio* - use SCHED_FIFO with *prio*; - *d:runtime[us|ms|s]:period[us|ms|s]* - use SCHED_DEADLINE with *runtime* and *period* in nanoseconds. -**-C**, **--cgroup**\[*=cgroup*] +**-C**, **--cgroup** \[*cgroup*] Set a *cgroup* to the tracer's threads. If the **-C** option is passed without arguments, the tracer's thread will inherit **rtla**'s *cgroup*. Otherwise, the threads will be placed on the *cgroup* passed to the option.
tools/tracing/rtla/src/osnoise_hist.c +11 -6
@@ -435,7 +435,7 @@ static void osnoise_hist_usage(char *usage)" -T/--threshold us: the minimum delta to be considered a noise" ," -c/--cpus cpu-list: list of cpus to run osnoise threads" ," -H/--house-keeping cpus: run rtla control threads only on the given cpus" , -" -C/--cgroup[=cgroup_name]: set cgroup, if no cgroup_name is passed, the rtla's cgroup will be inherited" , +" -C/--cgroup [cgroup_name]: set cgroup, if no cgroup_name is passed, the rtla's cgroup will be inherited" ," -d/--duration time[s|m|h|d]: duration of the session" ," -D/--debug: print debug info" , " -t/--trace[file]: save the stopped trace to [file|osnoise_trace.txt]",
@@ -559,12 +559,17 @@ static struct osnoise_paramsbreak ;case 'C' : params->cgroup =1 ; -if (!optarg) { -/* will inherit this cgroup */ +if (optarg) { +if (optarg[0 ] =='=' ) { +/* skip the = */ + params->cgroup_name = &optarg[1 ]; + }else { + params->cgroup_name = optarg; + } + }else if (optind < argc && argv[optind][0 ] !='-' ) { + params->cgroup_name = argv[optind]; + }else { params->cgroup_name =NULL ; - }else if (*optarg =='=' ) { -/* skip the = */ - params->cgroup_name = ++optarg; }break ;case 'D' :
tools/tracing/rtla/src/osnoise_top.c +11 -6
@@ -269,7 +269,7 @@ static void osnoise_top_usage(struct osnoise_params *params, char *usage)" -T/--threshold us: the minimum delta to be considered a noise" ," -c/--cpus cpu-list: list of cpus to run osnoise threads" ," -H/--house-keeping cpus: run rtla control threads only on the given cpus" , -" -C/--cgroup[=cgroup_name]: set cgroup, if no cgroup_name is passed, the rtla's cgroup will be inherited" , +" -C/--cgroup [cgroup_name]: set cgroup, if no cgroup_name is passed, the rtla's cgroup will be inherited" ," -d/--duration time[s|m|h|d]: duration of the session" ," -D/--debug: print debug info" , " -t/--trace[file]: save the stopped trace to [file|osnoise_trace.txt]",
@@ -394,12 +394,17 @@ struct osnoise_params *osnoise_top_parse_args(int argc, char **argv)break ;case 'C' : params->cgroup =1 ; -if (!optarg) { -/* will inherit this cgroup */ +if (optarg) { +if (optarg[0 ] =='=' ) { +/* skip the = */ + params->cgroup_name = &optarg[1 ]; + }else { + params->cgroup_name = optarg; + } + }else if (optind < argc && argv[optind][0 ] !='-' ) { + params->cgroup_name = argv[optind]; + }else { params->cgroup_name =NULL ; - }else if (*optarg =='=' ) { -/* skip the = */ - params->cgroup_name = ++optarg; }break ;case 'D' :
tools/tracing/rtla/src/timerlat_hist.c +11 -6
@@ -726,7 +726,7 @@ static void timerlat_hist_usage(char *usage)" -s/--stack us: save the stack trace at the IRQ if a thread latency is higher than the argument in us" ," -c/--cpus cpus: run the tracer only on the given cpus" ," -H/--house-keeping cpus: run rtla control threads only on the given cpus" , -" -C/--cgroup[=cgroup_name]: set cgroup, if no cgroup_name is passed, the rtla's cgroup will be inherited" , +" -C/--cgroup [cgroup_name]: set cgroup, if no cgroup_name is passed, the rtla's cgroup will be inherited" ," -d/--duration time[m|h|d]: duration of the session in seconds" ," --dump-tasks: prints the task running on all CPUs if stop conditions are met (depends on !--no-aa)" , " -D/--debug: print debug info",
@@ -885,12 +885,17 @@ static struct timerlat_paramsbreak ;case 'C' : params->cgroup =1 ; -if (!optarg) { -/* will inherit this cgroup */ +if (optarg) { +if (optarg[0 ] =='=' ) { +/* skip the = */ + params->cgroup_name = &optarg[1 ]; + }else { + params->cgroup_name = optarg; + } + }else if (optind < argc && argv[optind][0 ] !='-' ) { + params->cgroup_name = argv[optind]; + }else { params->cgroup_name =NULL ; - }else if (*optarg =='=' ) { -/* skip the = */ - params->cgroup_name = ++optarg; }break ;case 'b' :
tools/tracing/rtla/src/timerlat_top.c +11 -6
@@ -492,7 +492,7 @@ static void timerlat_top_usage(char *usage)" -s/--stack us: save the stack trace at the IRQ if a thread latency is higher than the argument in us" ," -c/--cpus cpus: run the tracer only on the given cpus" ," -H/--house-keeping cpus: run rtla control threads only on the given cpus" , -" -C/--cgroup[=cgroup_name]: set cgroup, if no cgroup_name is passed, the rtla's cgroup will be inherited" , +" -C/--cgroup [cgroup_name]: set cgroup, if no cgroup_name is passed, the rtla's cgroup will be inherited" ," -d/--duration time[s|m|h|d]: duration of the session" ," -D/--debug: print debug info" , " --dump-tasks: prints the task running on all CPUs if stop conditions are met (depends on !--no-aa)",
@@ -650,12 +650,17 @@ static struct timerlat_paramsbreak ;case 'C' : params->cgroup =1 ; -if (!optarg) { -/* will inherit this cgroup */ +if (optarg) { +if (optarg[0 ] =='=' ) { +/* skip the = */ + params->cgroup_name = &optarg[1 ]; + }else { + params->cgroup_name = optarg; + } + }else if (optind < argc && argv[optind][0 ] !='-' ) { + params->cgroup_name = argv[optind]; + }else { params->cgroup_name =NULL ; - }else if (*optarg =='=' ) { -/* skip the = */ - params->cgroup_name = ++optarg; }break ;case 'D' :
Signature · 1 line
2.48.1
Re: [PATCH v2 2/3] rtla: fix -C/--cgroup interface
Quoted 7 lines · Ivan Pravdin
Currently, user can only specify cgroup to the tracer's thread the following ways:
`-C[cgroup]` `-C[=cgroup]` `--cgroup[=cgroup]`
Quoted 8 lines
If user tries to specify cgroup as
-C [cgroup]or--cgroup [cgroup], the parser silently fails and rtla's cgroup is used for the tracer threads.To make interface more user-friendly, allow user to specify cgroup in the aforementioned way, i.e.
-C [cgroup]and--cgroup [cgroup]Change documentation to reflect this user interface change.
I know these are the semantics that --trace implements, but they're rather atypical... especially -C=group.
Quoted 10 lines
tools/tracing/rtla/src/osnoise_hist.c +4
-2@@ -559,12 +559,17 @@ static struct osnoise_paramsbreak ;case 'C' : params->cgroup =1 ; -if (!optarg) { -/* will inherit this cgroup */ +if (optarg) { +if (optarg[0 ] =='=' ) { +/* skip the = */ + params->cgroup_name = &optarg[1 ];
tools/tracing/rtla/src/osnoise_hist.c static struct osnoise_params · line 567
Quoted 10 lines
tools/tracing/rtla/src/osnoise_hist.c +6
-3+ }else { + params->cgroup_name = optarg; + } + }else if (optind < argc && argv[optind][0 ] !='-' ) { + params->cgroup_name = argv[optind]; + }else { params->cgroup_name =NULL ; - }else if (*optarg =='=' ) { -/* skip the = */ - params->cgroup_name = ++optarg;
If we're going to be consistently using these semantics, we should move this logic into a utility function rather than open-coding it everywhere.
Also, theoretically, shouldn't we be advancing optind for the case where that's consumed? Not that it matters much if we don't have positional arguments once the options begin, and if we did, then allowing "--arg optional-thing" would be ambiguous...
-Crystal
Re: [PATCH v2 2/3] rtla: fix -C/--cgroup interface
Quoted 12 lines · Crystal Wood
Quoted 11 lines · Ivan Pravdin
Currently, user can only specify cgroup to the tracer's thread the following ways:
`-C[cgroup]` `-C[=cgroup]` `--cgroup[=cgroup]`If user tries to specify cgroup as
-C [cgroup]or--cgroup [cgroup], the parser silently fails and rtla's cgroup is used for the tracer threads.
Quoted 7 lines
Quoted 4 lines
To make interface more user-friendly, allow user to specify cgroup in the aforementioned way, i.e.
-C [cgroup]and--cgroup [cgroup]Change documentation to reflect this user interface change.
I know these are the semantics that --trace implements, but they're rather atypical... especially -C=group.
The new semantics allow for -C [group] which is the same as -t [filename] that has been fixed for -t/--trace.
Quoted 17 lines
Quoted 17 lines
tools/tracing/rtla/src/osnoise_hist.c +10
-2@@ -559,12 +559,17 @@ static struct osnoise_paramsbreak ;case 'C' : params->cgroup =1 ; -if (!optarg) { -/* will inherit this cgroup */ +if (optarg) { +if (optarg[0 ] =='=' ) { +/* skip the = */ + params->cgroup_name = &optarg[1 ]; + }else { + params->cgroup_name = optarg; + } + }else if (optind < argc && argv[optind][0 ] !='-' ) { + params->cgroup_name = argv[optind]; + }else {
Quoted 8 lines
tools/tracing/rtla/src/osnoise_hist.c static struct osnoise_params · line 567
Quoted 4 lines
tools/tracing/rtla/src/osnoise_hist.c +0
-3params->cgroup_name =NULL ; - }else if (*optarg =='=' ) { -/* skip the = */ - params->cgroup_name = ++optarg;If we're going to be consistently using these semantics, we should move this logic into a utility function rather than open-coding it everywhere.
Sure, I will move it into a utility function in the next version.
Quoted 4 lines
Also, theoretically, shouldn't we be advancing optind for the case where that's consumed? Not that it matters much if we don't have positional arguments once the options begin, and if we did, then allowing "--arg optional-thing" would be ambiguous...
It does seem that we should advance optind when optional argument is provided. Good catch. I will fix it in the next version.
Quoted 2 lines
-Crystal
Ivan Pravdin
PATCH v2 3/3 rtla: fix -a overriding -t argument
In reply to Ivan PravdinWhen running rtla as
rtla <timerlat|osnoise> <top|hist> -t custom_file.txt -a 100
-a options override trace output filename specified by -t option. Running the command above will create <timerlat|osnoise>_trace.txt file instead of custom_file.txt. Fix this by making sure that -a option does not override trace output filename even if it's passed after trace output filename is specified.
Remove clear_terminal in timerlat top as it removes "Saving trace to <filename>" line from the terminal and is not used in other modes.
--- tools/tracing/rtla/src/osnoise_hist.c | 8 +++++--- tools/tracing/rtla/src/osnoise_top.c | 8 +++++--- tools/tracing/rtla/src/timerlat_hist.c | 8 +++++--- tools/tracing/rtla/src/timerlat_top.c | 20 +++++--------------- 4 files changed, 20 insertions(+), 24 deletions(-)
tools/tracing/rtla/src/osnoise_hist.c +5 -3
@@ -543,7 +543,8 @@ static struct osnoise_params params->threshold =1 ;/* set trace */ - params->trace_output ="osnoise_trace.txt" ; +if (!params->trace_output) + params->trace_output ="osnoise_trace.txt" ;break ;case 'b' :
@@ -640,10 +641,11 @@ static struct osnoise_params params->trace_output = &optarg[1 ]; else params->trace_output = &optarg[0]; - }else if (optind < argc && argv[optind][0 ] !='0' ) + }else if (optind < argc && argv[optind][0 ] !='0' ) { params->trace_output = argv[optind]; -else + }else { params->trace_output ="osnoise_trace.txt" ; + }break ;case '0' :/* no header */ params->no_header =1 ;
tools/tracing/rtla/src/osnoise_top.c +5 -3
@@ -383,7 +383,8 @@ struct osnoise_params *osnoise_top_parse_args(int argc, char **argv) params->threshold =1 ;/* set trace */ - params->trace_output ="osnoise_trace.txt" ; +if (!params->trace_output) + params->trace_output ="osnoise_trace.txt" ;break ;case 'c' :
@@ -470,10 +471,11 @@ struct osnoise_params *osnoise_top_parse_args(int argc, char **argv) params->trace_output = &optarg[1 ]; else params->trace_output = &optarg[0]; - }else if (optind < argc && argv[optind][0 ] !='-' ) + }else if (optind < argc && argv[optind][0 ] !='-' ) { params->trace_output = argv[optind]; -else + }else { params->trace_output ="osnoise_trace.txt" ; + }break ;case 'T' : params->threshold =get_llong_from_str (optarg);
tools/tracing/rtla/src/timerlat_hist.c +5 -3
@@ -874,7 +874,8 @@ static struct timerlat_params params->print_stack = auto_thresh;/* set trace */ - trace_output ="timerlat_trace.txt" ; +if (!trace_output) + trace_output ="timerlat_trace.txt" ;break ;case 'c' :
@@ -972,10 +973,11 @@ static struct timerlat_params trace_output = &optarg[1 ]; else trace_output = &optarg[0 ]; - }else if (optind < argc && argv[optind][0 ] !='-' ) + }else if (optind < argc && argv[optind][0 ] !='-' ) { trace_output = argv[optind]; -else + }else { trace_output ="timerlat_trace.txt" ; + }break ;case 'u' : params->user_workload =1 ;
tools/tracing/rtla/src/timerlat_top.c +5 -15
@@ -423,15 +423,6 @@ timerlat_top_print_sum(struct osnoise_tool *top, struct timerlat_top_cpu *summar } } -/* -* clear_terminal - clears the output terminal -*/ -static void clear_terminal (struct trace_seq *seq) -{ -if (!config_debug) -trace_seq_printf (seq,"\033c" ); -} -/* * timerlat_print_stats - print data for all cpus */
@@ -449,9 +440,6 @@ timerlat_print_stats(struct timerlat_params *params, struct osnoise_tool *top)if (nr_cpus ==-1 ) nr_cpus =sysconf (_SC_NPROCESSORS_CONF); -if (!params->quiet) -clear_terminal (trace->seq); -timerlat_top_reset_sum (&summary);timerlat_top_header (params, top);
@@ -625,7 +613,8 @@ static struct timerlat_params params->print_stack = auto_thresh;/* set trace */ - trace_output ="timerlat_trace.txt" ; +if (!trace_output) + trace_output ="timerlat_trace.txt" ;break ;case '5' :
@@ -729,10 +718,11 @@ static struct timerlat_params trace_output = &optarg[1 ]; else trace_output = &optarg[0 ]; - }else if (optind < argc && argv[optind][0 ] !='-' ) + }else if (optind < argc && argv[optind][0 ] !='-' ) { trace_output = argv[optind]; -else + }else { trace_output ="timerlat_trace.txt" ; + }break ;case 'u' : params->user_workload = true;
Signature · 1 line
2.48.1
Tomas Glozar
maintainerRe: [PATCH v2 3/3] rtla: fix -a overriding -t argument
út 12. 8. 2025 v 19:22 odesílatel Ivan Pravdin
<[email protected]> napsal:
Quoted 11 lines
When running rtla as
rtla <timerlat|osnoise> <top|hist> -t custom_file.txt -a 100-a options override trace output filename specified by -t option. Running the command above will create <timerlat|osnoise>_trace.txt file instead of custom_file.txt. Fix this by making sure that -a option does not override trace output filename even if it's passed after trace output filename is specified.
Yes, this should not be overridden, it's a bug in both the old implementation and the new one using actions. Thank you for the fix.
Quoted 3 lines
Remove
clear_terminalin timerlat top as it removes "Saving trace to <filename>" line from the terminal and is not used in other modes.
This is not the correct fix for the issue. clear_terminal is needed in timerlat top (and osnoise top) to clear the terminal before the updated status is printed, the fix removes it without a replacement, breaking this behavior. Also, this is a different issue that appeared only when the actions patchset [1] was merged, and should go into a separate patch with a different Fixes tag.
[1] https://lore.kernel.org/linux-trace-kernel/[email protected]/T/#t
Tomas
Re: [PATCH v2 3/3] rtla: fix -a overriding -t argument
Quoted 21 lines · Tomas Glozar
út 12. 8. 2025 v 19:22 odesílatel Ivan Pravdin
<[email protected]> napsal:Quoted 11 lines
When running rtla as
rtla <timerlat|osnoise> <top|hist> -t custom_file.txt -a 100-a options override trace output filename specified by -t option. Running the command above will create <timerlat|osnoise>_trace.txt file instead of custom_file.txt. Fix this by making sure that -a option does not override trace output filename even if it's passed after trace output filename is specified.
Yes, this should not be overridden, it's a bug in both the old implementation and the new one using actions. Thank you for the fix.
Quoted 3 lines
Remove
clear_terminalin timerlat top as it removes "Saving trace to <filename>" line from the terminal and is not used in other modes.
Quoted 8 lines
This is not the correct fix for the issue.
clear_terminalis needed in timerlat top (and osnoise top) to clear the terminal before the updated status is printed, the fix removes it without a replacement, breaking this behavior. Also, this is a different issue that appeared only when the actions patchset [1] was merged, and should go into a separate patch with a different Fixes tag.[1] https://lore.kernel.org/linux-trace-kernel/[email protected]/T/#t
Makes sense. This problem indeed does not happend for osnoise. I will update it in the next version of the patch.
Quoted 3 lines
Tomas
Ivan Pravdin