lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <7xttv65omwux7q4rpjsfety234qqfdmgwezskg4m6rgal4aaq2@r7vpdvfepiro>
Date: Mon, 20 Oct 2025 11:04:35 -0300
From: Wander Lairson Costa <wander@...hat.com>
To: Tomas Glozar <tglozar@...hat.com>
Cc: Steven Rostedt <rostedt@...dmis.org>, 
	LKML <linux-kernel@...r.kernel.org>, Linux Trace Kernel <linux-trace-kernel@...r.kernel.org>, 
	John Kacur <jkacur@...hat.com>, Luis Goncalves <lgoncalv@...hat.com>, 
	Costa Shulyupin <costa.shul@...hat.com>, Crystal Wood <crwood@...hat.com>, 
	Arnaldo Carvalho de Melo <acme@...nel.org>
Subject: Re: [PATCH 2/4] rtla/timerlat: Add --bpf-action option

On Fri, Oct 17, 2025 at 04:46:48PM +0200, Tomas Glozar wrote:
> Add option --bpf-action that allows the user to attach an external BPF
> program that will be executed via BPF tail call on latency threshold
> overflow.
> 
> Executing additional BPF code on latency threshold overflow allows doing
> doing low-latency and in-kernel troubleshooting of the cause of the
> overflow.
> 
> The option takes an argument, which is a path to a BPF ELF file
> expected to contain a function named "action_handler" in a section named
> "tp/timerlat_action" (the section is necessary for libbpf to asssign the
> correct BPF program type to it).
> 
> Signed-off-by: Tomas Glozar <tglozar@...hat.com>
> ---
>  tools/tracing/rtla/src/timerlat.c      | 11 ++++++
>  tools/tracing/rtla/src/timerlat.h      |  2 +-
>  tools/tracing/rtla/src/timerlat_bpf.c  | 54 ++++++++++++++++++++++++++
>  tools/tracing/rtla/src/timerlat_bpf.h  |  6 ++-
>  tools/tracing/rtla/src/timerlat_hist.c |  5 +++
>  tools/tracing/rtla/src/timerlat_top.c  |  5 +++
>  6 files changed, 81 insertions(+), 2 deletions(-)
> 
> diff --git a/tools/tracing/rtla/src/timerlat.c b/tools/tracing/rtla/src/timerlat.c
> index b69212874127..6907a323f9ec 100644
> --- a/tools/tracing/rtla/src/timerlat.c
> +++ b/tools/tracing/rtla/src/timerlat.c
> @@ -48,6 +48,17 @@ timerlat_apply_config(struct osnoise_tool *tool, struct timerlat_params *params)
>  		}
>  	}
>  
> +	/* Check if BPF action program is requested but BPF is not available */
> +	if (params->bpf_action_program) {
> +		if (params->mode == TRACING_MODE_TRACEFS) {
> +			err_msg("BPF actions are not supported in tracefs-only mode\n");
> +			goto out_err;
> +		}
> +
> +		if (timerlat_load_bpf_action_program(params->bpf_action_program))
> +			goto out_err;
> +	}
> +
>  	if (params->mode != TRACING_MODE_BPF) {
>  		/*
>  		 * In tracefs and mixed mode, timerlat tracer handles stopping
> diff --git a/tools/tracing/rtla/src/timerlat.h b/tools/tracing/rtla/src/timerlat.h
> index fd6065f48bb7..8dd5d134ce08 100644
> --- a/tools/tracing/rtla/src/timerlat.h
> +++ b/tools/tracing/rtla/src/timerlat.h
> @@ -27,6 +27,7 @@ struct timerlat_params {
>  	int			dump_tasks;
>  	int			deepest_idle_state;
>  	enum timerlat_tracing_mode mode;
> +	const char		*bpf_action_program;
>  };
>  
>  #define to_timerlat_params(ptr) container_of(ptr, struct timerlat_params, common)
> @@ -36,4 +37,3 @@ int timerlat_main(int argc, char *argv[]);
>  int timerlat_enable(struct osnoise_tool *tool);
>  void timerlat_analyze(struct osnoise_tool *tool, bool stopped);
>  void timerlat_free(struct osnoise_tool *tool);
> -
> diff --git a/tools/tracing/rtla/src/timerlat_bpf.c b/tools/tracing/rtla/src/timerlat_bpf.c
> index 1d619e502c65..3c63bf7aa607 100644
> --- a/tools/tracing/rtla/src/timerlat_bpf.c
> +++ b/tools/tracing/rtla/src/timerlat_bpf.c
> @@ -7,6 +7,10 @@
>  
>  static struct timerlat_bpf *bpf;
>  
> +/* BPF object and program for action program */
> +static struct bpf_object *obj;
> +static struct bpf_program *prog;
> +
>  /*
>   * timerlat_bpf_init - load and initialize BPF program to collect timerlat data
>   */
> @@ -56,6 +60,10 @@ int timerlat_bpf_init(struct timerlat_params *params)
>  		return err;
>  	}
>  
> +	/* Set BPF action program to NULL */
> +	prog = NULL;
> +	obj = NULL;
> +
>  	return 0;
>  }
>  
> @@ -96,6 +104,11 @@ void timerlat_bpf_detach(void)
>  void timerlat_bpf_destroy(void)
>  {
>  	timerlat_bpf__destroy(bpf);
> +	bpf = NULL;
> +	if (obj)
> +		bpf_object__close(obj);
> +	obj = NULL;
> +	prog = NULL;
>  }
>  
>  static int handle_rb_event(void *ctx, void *data, size_t data_sz)
> @@ -190,4 +203,45 @@ int timerlat_bpf_get_summary_value(enum summary_field key,
>  			 bpf->maps.summary_user,
>  			 key, value_irq, value_thread, value_user, cpus);
>  }
> +
> +/*
> + * timerlat_load_bpf_action_program - load and register a BPF action program
> + */
> +int timerlat_load_bpf_action_program(const char *program_path)
> +{
> +	int err;
> +
> +	obj = bpf_object__open_file(program_path, NULL);
> +	if (!obj) {
> +		err_msg("Failed to open BPF action program: %s\n", program_path);
> +		return -1;
> +	}
> +
> +	err = bpf_object__load(obj);
> +	if (err) {
> +		err_msg("Failed to load BPF action program: %s\n", program_path);

This error path misses the call to to bpf_object__close()

> +		return -1;
> +	}
> +
> +	prog = bpf_object__find_program_by_name(obj, "action_handler");
> +	if (!prog) {
> +		err_msg("BPF action program must have 'action_handler' function: %s\n",
> +			program_path);
> +		bpf_object__close(obj);
> +		obj = NULL;
> +		return -1;
> +	}
> +
> +	err = timerlat_bpf_set_action(prog);
> +	if (err) {
> +		err_msg("Failed to register BPF action program: %s\n", program_path);
> +		bpf_object__close(obj);
> +		obj = NULL;
> +		prog = NULL;
> +		return -1;
> +	}
> +
> +	return 0;
> +}
> +
>  #endif /* HAVE_BPF_SKEL */
> diff --git a/tools/tracing/rtla/src/timerlat_bpf.h b/tools/tracing/rtla/src/timerlat_bpf.h
> index b5009092c7a3..169abeaf4363 100644
> --- a/tools/tracing/rtla/src/timerlat_bpf.h
> +++ b/tools/tracing/rtla/src/timerlat_bpf.h
> @@ -30,7 +30,7 @@ int timerlat_bpf_get_summary_value(enum summary_field key,
>  				   long long *value_thread,
>  				   long long *value_user,
>  				   int cpus);
> -
> +int timerlat_load_bpf_action_program(const char *program_path);
>  static inline int have_libbpf_support(void) { return 1; }
>  #else
>  static inline int timerlat_bpf_init(struct timerlat_params *params)
> @@ -58,6 +58,10 @@ static inline int timerlat_bpf_get_summary_value(enum summary_field key,
>  {
>  	return -1;
>  }
> +static inline int timerlat_load_bpf_action_program(const char *program_path)
> +{
> +	return -1;
> +}
>  static inline int have_libbpf_support(void) { return 0; }
>  #endif /* HAVE_BPF_SKEL */
>  #endif /* __bpf__ */
> diff --git a/tools/tracing/rtla/src/timerlat_hist.c b/tools/tracing/rtla/src/timerlat_hist.c
> index 606c1688057b..5e639cc34f64 100644
> --- a/tools/tracing/rtla/src/timerlat_hist.c
> +++ b/tools/tracing/rtla/src/timerlat_hist.c
> @@ -763,6 +763,7 @@ static void timerlat_hist_usage(char *usage)
>  		"	     --deepest-idle-state n: only go down to idle state n on cpus used by timerlat to reduce exit from idle latency",
>  		"	     --on-threshold <action>: define action to be executed at latency threshold, multiple are allowed",
>  		"	     --on-end <action>: define action to be executed at measurement end, multiple are allowed",
> +		"	     --bpf-action <program>: load and execute BPF program when latency threshold is exceeded",
>  		NULL,
>  	};
>  
> @@ -853,6 +854,7 @@ static struct common_params
>  			{"deepest-idle-state",	required_argument,	0, '\4'},
>  			{"on-threshold",	required_argument,	0, '\5'},
>  			{"on-end",		required_argument,	0, '\6'},
> +			{"bpf-action",		required_argument,	0, '\7'},
>  			{0, 0, 0, 0}
>  		};
>  
> @@ -1062,6 +1064,9 @@ static struct common_params
>  				exit(EXIT_FAILURE);
>  			}
>  			break;
> +		case '\7':
> +			params->bpf_action_program = optarg;
> +			break;
>  		default:
>  			timerlat_hist_usage("Invalid option");
>  		}
> diff --git a/tools/tracing/rtla/src/timerlat_top.c b/tools/tracing/rtla/src/timerlat_top.c
> index fc479a0dcb59..da5d5db1bc17 100644
> --- a/tools/tracing/rtla/src/timerlat_top.c
> +++ b/tools/tracing/rtla/src/timerlat_top.c
> @@ -521,6 +521,7 @@ static void timerlat_top_usage(char *usage)
>  		"	     --deepest-idle-state n: only go down to idle state n on cpus used by timerlat to reduce exit from idle latency",
>  		"	     --on-threshold <action>: define action to be executed at latency threshold, multiple are allowed",
>  		"	     --on-end: define action to be executed at measurement end, multiple are allowed",
> +		"	     --bpf-action <program>: load and execute BPF program when latency threshold is exceeded",
>  		NULL,
>  	};
>  
> @@ -603,6 +604,7 @@ static struct common_params
>  			{"deepest-idle-state",	required_argument,	0, '8'},
>  			{"on-threshold",	required_argument,	0, '9'},
>  			{"on-end",		required_argument,	0, '\1'},
> +			{"bpf-action",		required_argument,	0, '\2'},
>  			{0, 0, 0, 0}
>  		};
>  
> @@ -798,6 +800,9 @@ static struct common_params
>  				exit(EXIT_FAILURE);
>  			}
>  			break;
> +		case '\2':
> +			params->bpf_action_program = optarg;
> +			break;
>  		default:
>  			timerlat_top_usage("Invalid option");
>  		}
> -- 
> 2.51.0
> 


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ