Re: [PATCH bpf-next v4 15/16] bpf: Report Verifier Limit errors

Eduard Zingerman <[email protected]>
Newsgroups org.kernel.vger.bpf
Message-ID <[email protected]>
On Thu, 2026-08-13 at 01:33 +0200, Kumar Kartikeya Dwivedi wrote:

...

> diff --git a/kernel/bpf/liveness.c b/kernel/bpf/liveness.c
> index 1c997aeba6fa..f39f01637ac0 100644
> --- a/kernel/bpf/liveness.c
> +++ b/kernel/bpf/liveness.c
> @@ -8,6 +8,8 @@
>  #include <linux/slab.h>
>  #include <linux/sort.h>
>  
> +#include "diagnostics.h"
> +
>  #define verbose(env, fmt, args...) bpf_verifier_log_write(env, fmt, ##args)
>  
>  struct per_frame_masks {
> @@ -1856,6 +1858,10 @@ static int analyze_subprog(struct bpf_verifier_env *env,
>  	if (++env->liveness->subprog_calls > 10000) {
>  		verbose(env, "liveness analysis exceeded complexity limit (%d calls)\n",
>  			env->liveness->subprog_calls);
> +		bpf_diag_limit(
> +			env, start, "liveness analysis complexity",
> +			"Reduce the number of distinct call paths or argument patterns reaching these subprograms.",

Nit: "these subprograms" is not very clear here, drop it?

> +			"The verifier recomputed subprogram liveness too many times while tracking stack and register reads across call paths");

Nit: it's not a "subprogram liveness" ->

     "Stack liveness analysis failed to reach a fixed point after %d iterations".

>  		return -E2BIG;
>  	}
>  
> diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
> index 8e5319f47ccb..a14315d19866 100644
> --- a/kernel/bpf/verifier.c
> +++ b/kernel/bpf/verifier.c
> @@ -5252,6 +5252,38 @@ struct bpf_subprog_call_depth_info {
>  	int frame; /* # of consecutive static call stack frames on top of stack */
>  };
>  
> +static const char *bpf_diag_append_subprog_chain(struct bpf_verifier_env *env,
> +						 const char *chain, int subprog)
> +{
> +	const char *prefix = chain && *chain ? " -> " : "";
> +	const char *name = bpf_subprog_name(env, subprog);
> +	const char *old = chain ?: "";
> +
> +	if (name && *name)
> +		return bpf_diag_fmt(env, "%s%s%s", old, prefix, name);
> +	return bpf_diag_fmt(env, "%s%ssubprogram %d", old, prefix, subprog);
> +}
> +
> +static const char *bpf_diag_alloc_subprog_call_chain(struct bpf_verifier_env *env,
> +						     struct bpf_subprog_call_depth_info *dinfo,
> +						     int idx)

Nit: drop the 'bpf_diag_' prefix.

> +{
> +	int call_chain[MAX_CALL_FRAMES + 1];
> +	int i, subprog, cnt = 0;
> +	const char *chain = NULL;
> +
> +	for (subprog = idx; subprog >= 0 && cnt < ARRAY_SIZE(call_chain);
> +	     subprog = dinfo[subprog].caller)
> +		call_chain[cnt++] = subprog;
> +
> +	if (subprog >= 0)
> +		chain = "...";
> +	for (i = cnt - 1; i >= 0; i--)
> +		chain = bpf_diag_append_subprog_chain(env, chain, call_chain[i]);
> +
> +	return chain;
> +}
> +
>  /* starting from main bpf function walk all instructions of the function
>   * and recursively walk all callees that given function can call.
>   * Ignore jump and exit insns.
> @@ -5294,9 +5326,17 @@ static int check_max_stack_depth_subprog(struct bpf_verifier_env *env, int idx,
>  	 * of caller's stack as shown on the example above.
>  	 */
>  	if (idx && subprog[idx].has_tail_call && depth >= 256) {
> +		const char *chain = bpf_diag_alloc_subprog_call_chain(env, dinfo, idx);

Nit: bubble up `chain` definition to the top of the function.

> +
>  		verbose(env,
>  			"tail_calls are not allowed when call stack of previous frames is %d bytes. Too large\n",
>  			depth);
> +		bpf_diag_limit(
> +			env, subprog[idx].start, "call stack with tail calls",

"call stack with tail calls" -> "stack depth at tail call"

> +			"Reduce stack usage in caller frames, or avoid combining deep bpf2bpf calls with tail calls.",
> +			"Call chain %s reaches a subprogram with tail calls after caller frames already use %d bytes; "
> +			"tail-call paths are limited to 256 bytes in caller frames",
> +			chain ?: "the current call chain", depth);

"the current call chain" is useless, if it's a guard for ENOMEM,
let's make it "<can't render callchain>".

>  		return -EACCES;
>  	}
>  

...
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.