Improve stack depth verification stats output
Subsystems (4)
Kumar Kartikeya Dwivedi
maintainercover Improve stack depth verification stats output
Some improvements for more clarity in the stack depth verification statistics output. See commit logs for details.
Kumar Kartikeya Dwivedi (3):
bpf: Show more useful info in stack depth stats selftests/bpf: Adjust veristat stack depth parsing selftests/bpf: Test stack depth stats without BTF subprog names
kernel/bpf/verifier.c | 16 +++++++++--- .../bpf/progs/verifier_basic_stack.c | 4 +-- .../bpf/progs/verifier_bpf_fastcall.c | 19 ++++++++------ .../bpf/progs/verifier_private_stack.c | 9 ++++--- .../selftests/bpf/progs/verifier_var_off.c | 4 +-- tools/testing/selftests/bpf/test_verifier.c | 5 +++- tools/testing/selftests/bpf/verifier/calls.c | 4 ++- tools/testing/selftests/bpf/veristat.c | 25 ++++++++++++------- 8 files changed, 56 insertions(+), 30 deletions(-)
base-commit: 28e911d61d66b92a3bded8b54622ed3cd2795bf6
Signature · 1 line
2.53.0
Kumar Kartikeya Dwivedi
maintainerPATCH 1/3 bpf: Show more useful info in stack depth stats
Currently, the output of stack depth statistics is two crude, with a list of captured stack depths ordered by the subprog numbers. The actual subprog numbers are determined by libbpf, hence it is hard to associate the stack depth statistic back to the subprog by name.
Change the format to:
stack depth <subprog>=<depth> ... max=<depth>
In case the subprog name is not specified, use subprog[N] as the string.
--- kernel/bpf/verifier.c | 16 ++++++++++++---- .../bpf/progs/verifier_basic_stack.c | 4 ++-- .../bpf/progs/verifier_bpf_fastcall.c | 19 +++++++++++-------- .../bpf/progs/verifier_private_stack.c | 9 ++++++--- .../selftests/bpf/progs/verifier_var_off.c | 4 ++-- 5 files changed, 33 insertions(+), 19 deletions(-)
kernel/bpf/verifier.c +12 -4
@@ -18703,10 +18703,18 @@ static void print_verification_stats(struct bpf_verifier_env *env)if (env->log.level &BPF_LOG_STATS ) {verbose (env,"verification time %lld usec\n" ,div_u64 (env->verification_time,1000 )); -verbose (env,"stack depth %d" , env->subprog_info[0 ].stack_depth); -for (i =1 ; i < subprog_cnt; i++) -verbose (env,"+%d" , env->subprog_info[i].stack_depth); -verbose (env," max %d\n" , env->max_stack_depth); +verbose (env,"stack depth" ); +for (i =0 ; i < subprog_cnt; i++) { +const char *name = env->subprog_info[i].name; + +if (name && name[0 ]) +verbose (env," %s=%d" , name, + env->subprog_info[i].stack_depth); +else +verbose (env," subprog[%d]=%d" , i, + env->subprog_info[i].stack_depth); + } +verbose (env," max=%d\n" , env->max_stack_depth);verbose (env,"insns processed %d" , env->subprog_info[0 ].insn_processed);for (i =1 ; i < subprog_cnt; i++)if (bpf_subprog_is_global (env, i))
tools/testing/selftests/bpf/progs/verifier_basic_stack.c +2 -2
@@ -27,7 +27,7 @@ __naked void stack_out_of_bounds(void) SEC("socket") __description("uninitialized stack1") -__success __log_level(4) __msg("stack depth 8") +__success __log_level(4) __msg("stack depth uninitialized_stack1=8") __failure_unpriv __msg_unpriv("invalid read from stack") __naked void uninitialized_stack1(void) {
@@ -45,7 +45,7 @@ __naked void uninitialized_stack1(void) SEC("socket") __description("uninitialized stack2") -__success __log_level(4) __msg("stack depth 8") +__success __log_level(4) __msg("stack depth uninitialized_stack2=8") __failure_unpriv __msg_unpriv("invalid read from stack") __naked void uninitialized_stack2(void) {
tools/testing/selftests/bpf/progs/verifier_bpf_fastcall.c +11 -8
@@ -10,7 +10,7 @@ SEC("raw_tp") __arch_x86_64 -__log_level(4) __msg("stack depth 8") +__log_level(4) __msg("stack depth simple=8") __xlated("4: r5 = 5") __xlated("5: r0 = ")__xlated ("6: r0 = &(void __percpu *)(r0)" )
@@ -96,7 +96,7 @@ __naked void canary_zero_spills(void) SEC("raw_tp") __arch_x86_64 -__log_level(4) __msg("stack depth 16") +__log_level(4) __msg("stack depth wrong_reg_in_pattern1=16") __xlated("1: *(u64 *)(r10 -16) = r1") __xlated("...")__xlated ("3: r0 = &(void __percpu *)(r0)" )
@@ -598,7 +598,7 @@ __naked static void subprogs_use_independent_offsets_aux(void) SEC("raw_tp") __arch_x86_64 -__log_level(4) __msg("stack depth 8") +__log_level(4) __msg("stack depth helper_call_does_not_prevent_bpf_fastcall=8") __xlated("2: r0 = &(void __percpu *)(r0)") __success__naked void helper_call_does_not_prevent_bpf_fastcall (void )
@@ -620,7 +620,7 @@ __naked void helper_call_does_not_prevent_bpf_fastcall(void) SEC("raw_tp") __arch_x86_64 -__log_level(4) __msg("stack depth 24") +__log_level(4) __msg("stack depth may_goto_interaction_x86_64=24")/* may_goto counter at -24 */ __xlated ("0: *(u64 *)(r10 -24) =" )/* may_goto timestamp at -16 */
@@ -661,7 +661,7 @@ __naked void may_goto_interaction_x86_64(void) SEC("raw_tp") __arch_arm64 __arch_riscv64 -__log_level(4) __msg("stack depth 24") +__log_level(4) __msg("stack depth may_goto_interaction=24")/* may_goto counter at -24 */ __xlated ("0: *(u64 *)(r10 -24) =" )/* may_goto timestamp at -16 */
@@ -708,7 +708,8 @@ __naked static void dummy_loop_callback(void) SEC("raw_tp") __arch_x86_64 -__log_level(4) __msg("stack depth 32+0") +__log_level(4) +__msg("stack depth bpf_loop_interaction1=32 dummy_loop_callback=0") __xlated("2: r1 = 1") __xlated("3: r0 =")__xlated ("4: r0 = &(void __percpu *)(r0)" )
@@ -756,7 +757,8 @@ __naked int bpf_loop_interaction1(void) SEC("raw_tp") __arch_x86_64 -__log_level(4) __msg("stack depth 40+0") +__log_level(4) +__msg("stack depth bpf_loop_interaction2=40 dummy_loop_callback=0")/* call bpf_get_smp_processor_id */ __xlated("2: r1 = 42")__xlated ("3: r0 =" )
@@ -800,7 +802,8 @@ __naked int bpf_loop_interaction2(void) SEC("raw_tp") __arch_x86_64 -__log_level(4) __msg("stack depth 512+0 max 512") +__log_level(4) +__msg("stack depth cumulative_stack_depth=512 cumulative_stack_depth_subprog=0 max=512")/* just to print xlated version when debugging */ __xlated ("r0 = &(void __percpu *)(r0)" ) __success
tools/testing/selftests/bpf/progs/verifier_private_stack.c +6 -3
@@ -86,7 +86,8 @@ __naked static void cumulative_stack_depth_subprog(void) SEC("kprobe") __description("Private stack, subtree > MAX_BPF_STACK") __success -__log_level(4) __msg("stack depth 512+32 max 512") +__log_level(4) +__msg("stack depth private_stack_nested_1=512 cumulative_stack_depth_subprog=32 max=512") __arch_x86_64 /* private stack fp for the main prog */ __jited(" movabsq $0x{{.*}}, %r9")
@@ -331,7 +332,8 @@ SEC("fentry/bpf_fentry_test9") __description("Private stack, async callback, potential nesting") __success __retval(0) __load_if_JITed() -__log_level(4) __msg("stack depth 8+0+256+0 max 272") +__log_level(4) +__msg("stack depth private_stack_async_callback_2=8 timer_cb1=0 subprog1=256 subprog2=0 max=272") __arch_x86_64 __jited(" subq $0x100, %rsp")__arch_arm64
@@ -355,7 +357,8 @@ int private_stack_async_callback_2(void) SEC("fentry/bpf_fentry_test9") __description("private stack, max stack depth is private stack") __success -__log_level(4) __msg("stack depth 8+256+0 max 256") +__log_level(4) +__msg("stack depth private_stack_max_depth=8 subprog1=256 subprog2=0 max=256")int private_stack_max_depth (void ) {int x =0 ;
tools/testing/selftests/bpf/progs/verifier_var_off.c +2 -2
@@ -198,7 +198,7 @@ __success/* Check that the maximum stack depth is correctly maintained according to the * maximum possible variable offset. */ -__log_level(4) __msg("stack depth 16") +__log_level(4) __msg("stack depth stack_write_priv_vs_unpriv=16") __failure_unpriv/* Variable stack access is rejected for unprivileged. */
@@ -238,7 +238,7 @@ __success/* Check that the maximum stack depth is correctly maintained according to the * maximum possible variable offset. */ -__log_level(4) __msg("stack depth 16") +__log_level(4) __msg("stack depth stack_write_followed_by_read=16") __failure_unpriv __msg_unpriv("R2 variable stack access prohibited for !root")__retval (0 )
Signature · 1 line
2.53.0
[email protected]
AI reviewRe: [PATCH bpf-next v1 1/3] bpf: Show more useful info in stack depth stats
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider: - [Medium] The new stack depth verifier log format breaks stack metrics parsing in the `veristat` tool. --
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] The new stack depth verifier log format breaks stack metrics parsing in the veristat tool. --
--- Patch [1]: [PATCH bpf-next v1 1/3] bpf: Show more useful info in stack depth stats --- commit f7cb915ff02de7a02fe7b2353a1f2d77e1852496
Author: Kumar Kartikeya Dwivedi <[email protected]>
bpf: Show more useful info in stack depth stats
This commit changes the output format of stack depth statistics in the BPF verifier log. It replaces the old subprogram index-based format with a clearer name and depth format, avoiding hard-to-read sequences.
Quoted 14 lines
kernel/bpf/verifier.c +2
-4@@ -18703,10 +18703,18 @@ static void print_verification_stats(struct bpf_verifier_env *env)if (env->log.level &BPF_LOG_STATS ) {verbose (env,"verification time %lld usec\n" ,div_u64 (env->verification_time,1000 )); -verbose (env,"stack depth %d" , env->subprog_info[0 ].stack_depth); -for (i =1 ; i < subprog_cnt; i++) -verbose (env,"+%d" , env->subprog_info[i].stack_depth); -verbose (env," max %d\n" , env->max_stack_depth); +verbose (env,"stack depth" ); +for (i =0 ; i < subprog_cnt; i++) {
kernel/bpf/verifier.c static void print_verification_stats(struct bpf_verifier_env *env) · line 18717
Quoted 10 lines
kernel/bpf/verifier.c +10
-0+const char *name = env->subprog_info[i].name; + +if (name && name[0 ]) +verbose (env," %s=%d" , name, + env->subprog_info[i].stack_depth); +else +verbose (env," subprog[%d]=%d" , i, + env->subprog_info[i].stack_depth); + } +verbose (env," max=%d\n" , env->max_stack_depth);
[Severity: Medium]
Does this change break the veristat tool's parsing of stack depths?
Looking at tools/testing/selftests/bpf/veristat.c in parse_verif_log(), it appears to rely on the old format using a hardcoded string and splitting by the plus sign:
tools/testing/selftests/bpf/veristat.c:parse_verif_log() {
...
if (2 == sscanf(cur, "stack depth %511s max %ld", stack, &s->stats[MAX_STACK]))
...
while ((token = strtok_r(cnt++ ? NULL : stack, "+", &state))) {
if (sscanf(token, "%d", &sub_stack) == 0)
break;
...
}Since the verifier now outputs max=%ld instead of max %ld, and the individual depths are formatted as name=depth rather than numbers separated by a plus sign, will veristat silently fail to parse STACK and MAX_STACK metrics when processing BPF objects?
[ ... ]
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=1
Kumar Kartikeya Dwivedi
maintainerRe: [PATCH bpf-next v1 1/3] bpf: Show more useful info in stack depth stats
Quoted 56 lines · sashiko-bot
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] The new stack depth verifier log format breaks stack metrics parsing in theveristattool. ----- Patch [1]: [PATCH bpf-next v1 1/3] bpf: Show more useful info in stack depth stats --- commit
f7cb915ff02de7a02fe7b2353a1f2d77e1852496
Author: Kumar Kartikeya Dwivedi <[email protected]>bpf: Show more useful info in stack depth stats
This commit changes the output format of stack depth statistics in the BPF verifier log. It replaces the old subprogram index-based format with a clearer name and depth format, avoiding hard-to-read sequences.
Quoted 14 lines
kernel/bpf/verifier.c +2
-4@@ -18703,10 +18703,18 @@ static void print_verification_stats(struct bpf_verifier_env *env)if (env->log.level &BPF_LOG_STATS ) {verbose (env,"verification time %lld usec\n" ,div_u64 (env->verification_time,1000 )); -verbose (env,"stack depth %d" , env->subprog_info[0 ].stack_depth); -for (i =1 ; i < subprog_cnt; i++) -verbose (env,"+%d" , env->subprog_info[i].stack_depth); -verbose (env," max %d\n" , env->max_stack_depth); +verbose (env,"stack depth" ); +for (i =0 ; i < subprog_cnt; i++) {kernel/bpf/verifier.c static void print_verification_stats(struct bpf_verifier_env *env) · line 18717
Quoted 10 lines
kernel/bpf/verifier.c +10
-0+const char *name = env->subprog_info[i].name; + +if (name && name[0 ]) +verbose (env," %s=%d" , name, + env->subprog_info[i].stack_depth); +else +verbose (env," subprog[%d]=%d" , i, + env->subprog_info[i].stack_depth); + } +verbose (env," max=%d\n" , env->max_stack_depth);[Severity: Medium]
Does this change break the veristat tool's parsing of stack depths?Looking at
tools/testing/selftests/bpf/veristat.cinparse_verif_log(), it appears to rely on the old format using a hardcoded string and splitting by the plus sign:tools/testing/selftests/bpf/veristat.c:parse_verif_log() { ... if (2 == sscanf(cur, "stack depth %511s max %ld", stack, &s->stats[MAX_STACK])) ... while ((token = strtok_r(cnt++ ? NULL : stack, "+", &state))) { if (sscanf(token, "%d", &sub_stack) == 0) break; ... }
Quoted 5 lines
Since the verifier now outputs max=%ld instead of max %ld, and the individual depths are formatted as name=depth rather than numbers separated by a plus sign, will veristat silently fail to parse STACK and
MAX_STACKmetrics when processing BPF objects?
Fixed in patch 2. It is an open question whether we care about format compatibility, in that case we will need further adjustments to parse both kinds of output (for older and newer kernels).
Quoted 1 line
[ ... ]
[email protected]
AI reviewRe: [PATCH bpf-next v1 1/3] bpf: Show more useful info in stack depth stats
In reply to Kumar Kartikeya DwivediThis isn't a bug, but there's a typo here - "is two crude" should be "is too crude".
Quoted 6 lines
bpf: Show more useful info in stack depth stats
Currently, the output of stack depth statistics is two crude, with a list of captured stack depths ordered by the subprog numbers. The actual subprog numbers are determined by libbpf, hence it is hard to associate the stack depth statistic back to the subprog by name.
This isn't a bug, but there's a typo here - "is two crude" should be "is too crude".
---
AI reviewed your patch. Please fix the bug or email reply why it's not a bug.
See: https://github.com/kernel-patches/vmtest/blob/master/ci/claude/README.md
CI run summary: https://github.com/kernel-patches/bpf/actions/runs/30723212958
Eduard Zingerman
maintainerRe: [PATCH bpf-next v1 1/3] bpf: Show more useful info in stack depth stats
In reply to Kumar Kartikeya DwivediQuoted 32 lines · Kumar Kartikeya Dwivedi
Currently, the output of stack depth statistics is two crude, with a list of captured stack depths ordered by the subprog numbers. The actual subprog numbers are determined by libbpf, hence it is hard to associate the stack depth statistic back to the subprog by name.
Change the format to:
stack depth <subprog>=<depth> ... max=<depth>In case the subprog name is not specified, use subprog[N] as the string.
Suggested-by Andrii Nakryiko <[email protected]>Signed-off-by Kumar Kartikeya Dwivedi <[email protected]>---
kernel/bpf/verifier.c | 16 ++++++++++++---- .../bpf/progs/verifier_basic_stack.c | 4 ++-- .../bpf/progs/verifier_bpf_fastcall.c | 19 +++++++++++-------- .../bpf/progs/verifier_private_stack.c | 9 ++++++--- .../selftests/bpf/progs/verifier_var_off.c | 4 ++--5 files changed, 33 insertions(+), 19 deletions(-)kernel/bpf/verifier.c +0
-4@@ -18703,10 +18703,18 @@ static void print_verification_stats(struct bpf_verifier_env *env) if (env->log.level & BPF_LOG_STATS) { verbose(env, "verification time %lld usec\n", div_u64(env->verification_time, 1000)); -verbose (env,"stack depth %d" , env->subprog_info[0 ].stack_depth); -for (i =1 ; i < subprog_cnt; i++) -verbose (env,"+%d" , env->subprog_info[i].stack_depth); -verbose (env," max %d\n" , env->max_stack_depth);
kernel/bpf/verifier.c static void print_verification_stats(struct bpf_verifier_env *env) · line 18715
Quoted 10 lines
kernel/bpf/verifier.c +10
-0+verbose (env,"stack depth" ); +for (i =0 ; i < subprog_cnt; i++) { +const char *name = env->subprog_info[i].name; + +if (name && name[0 ]) +verbose (env," %s=%d" , name, + env->subprog_info[i].stack_depth); +else +verbose (env," subprog[%d]=%d" , i, + env->subprog_info[i].stack_depth);
That would be not very convenient to parse by veristat, but I'd print every subprogram on it's own line.
kernel/bpf/verifier.c static void print_verification_stats(struct bpf_verifier_env *env) · line 18717
Quoted 2 lines
kernel/bpf/verifier.c +2
-0+ } +verbose (env," max=%d\n" , env->max_stack_depth);
I think check_max_stack_depth_subprog() needs a similar update, at the moment it reports a not very helpful error like this:
combined stack size of 34 calls is 528. Too large
Printing the offending spine would be helpful.
...
Kumar Kartikeya Dwivedi
maintainerRe: [PATCH bpf-next v1 1/3] bpf: Show more useful info in stack depth stats
Quoted 38 lines · Eduard Zingerman
Quoted 37 lines · Kumar Kartikeya Dwivedi
Currently, the output of stack depth statistics is two crude, with a list of captured stack depths ordered by the subprog numbers. The actual subprog numbers are determined by libbpf, hence it is hard to associate the stack depth statistic back to the subprog by name.
Change the format to:
stack depth <subprog>=<depth> ... max=<depth>In case the subprog name is not specified, use subprog[N] as the string.
Suggested-by Andrii Nakryiko <[email protected]>Signed-off-by Kumar Kartikeya Dwivedi <[email protected]>---
kernel/bpf/verifier.c | 16 ++++++++++++---- .../bpf/progs/verifier_basic_stack.c | 4 ++-- .../bpf/progs/verifier_bpf_fastcall.c | 19 +++++++++++-------- .../bpf/progs/verifier_private_stack.c | 9 ++++++--- .../selftests/bpf/progs/verifier_var_off.c | 4 ++--5 files changed, 33 insertions(+), 19 deletions(-)kernel/bpf/verifier.c +5
-4@@ -18703,10 +18703,18 @@ static void print_verification_stats(struct bpf_verifier_env *env) if (env->log.level & BPF_LOG_STATS) { verbose(env, "verification time %lld usec\n", div_u64(env->verification_time, 1000)); -verbose (env,"stack depth %d" , env->subprog_info[0 ].stack_depth); -for (i =1 ; i < subprog_cnt; i++) -verbose (env,"+%d" , env->subprog_info[i].stack_depth); -verbose (env," max %d\n" , env->max_stack_depth); +verbose (env,"stack depth" ); +for (i =0 ; i < subprog_cnt; i++) { +const char *name = env->subprog_info[i].name; + +if (name && name[0 ])
Quoted 9 lines
kernel/bpf/verifier.c static void print_verification_stats(struct bpf_verifier_env *env) · line 18715
Quoted 5 lines
kernel/bpf/verifier.c +5
-0+verbose (env," %s=%d" , name, + env->subprog_info[i].stack_depth); + else + verbose(env, " subprog[%d]=%d", i, + env->subprog_info[i].stack_depth);That would be not very convenient to parse by veristat, but I'd print every subprogram on it's own line.
I can do that, but let's agree on the format before I get to it. How should it look like? Prefix with stack depth every line, and print stack depth max ... as the very first line? Like so:
stack depth max N
stack depth subprog 0 <name> N
...
stack depth subprog N <name> N
?
Quoted 10 lines
kernel/bpf/verifier.c static void print_verification_stats(struct bpf_verifier_env *env) · line 18717
Quoted 2 lines
kernel/bpf/verifier.c +2
-0+ } +verbose (env," max=%d\n" , env->max_stack_depth);I think
check_max_stack_depth_subprog()needs a similar update, at the moment it reports a not very helpful error like this:combined stack size of 34 calls is 528. Too large
Printing the offending spine would be helpful.
I'll do that in verifier errors patch set. This is just for the verification stats, that are outside its scope.
Quoted 1 line
...
Eduard Zingerman
maintainerRe: [PATCH bpf-next v1 1/3] bpf: Show more useful info in stack depth stats
Quoted 53 lines · Kumar Kartikeya Dwivedi
Quoted 38 lines · Eduard Zingerman
Quoted 37 lines · Kumar Kartikeya Dwivedi
Currently, the output of stack depth statistics is two crude, with a list of captured stack depths ordered by the subprog numbers. The actual subprog numbers are determined by libbpf, hence it is hard to associate the stack depth statistic back to the subprog by name.
Change the format to:
stack depth <subprog>=<depth> ... max=<depth>In case the subprog name is not specified, use subprog[N] as the string.
Suggested-by Andrii Nakryiko <[email protected]>Signed-off-by Kumar Kartikeya Dwivedi <[email protected]>---
kernel/bpf/verifier.c | 16 ++++++++++++---- .../bpf/progs/verifier_basic_stack.c | 4 ++-- .../bpf/progs/verifier_bpf_fastcall.c | 19 +++++++++++-------- .../bpf/progs/verifier_private_stack.c | 9 ++++++--- .../selftests/bpf/progs/verifier_var_off.c | 4 ++--5 files changed, 33 insertions(+), 19 deletions(-)kernel/bpf/verifier.c +5
-4@@ -18703,10 +18703,18 @@ static void print_verification_stats(struct bpf_verifier_env *env) if (env->log.level & BPF_LOG_STATS) { verbose(env, "verification time %lld usec\n", div_u64(env->verification_time, 1000)); -verbose (env,"stack depth %d" , env->subprog_info[0 ].stack_depth); -for (i =1 ; i < subprog_cnt; i++) -verbose (env,"+%d" , env->subprog_info[i].stack_depth); -verbose (env," max %d\n" , env->max_stack_depth); +verbose (env,"stack depth" ); +for (i =0 ; i < subprog_cnt; i++) { +const char *name = env->subprog_info[i].name; + +if (name && name[0 ])Quoted 9 lines
kernel/bpf/verifier.c static void print_verification_stats(struct bpf_verifier_env *env) · line 18715
Quoted 5 lines
kernel/bpf/verifier.c +5
-0+verbose (env," %s=%d" , name, + env->subprog_info[i].stack_depth); + else + verbose(env, " subprog[%d]=%d", i, + env->subprog_info[i].stack_depth);That would be not very convenient to parse by veristat, but I'd print every subprogram on it's own line.
I can do that, but let's agree on the format before I get to it. How should it look like? Prefix with stack depth every line, and print stack depth max ... as the very first line? Like so:
Quoted 6 lines
stack depth max N
stack depth subprog 0 <name> N
...
stack depth subprog N <name> N?
Ideally I'd drop the "stack depth " prefix after the first one and just add an indentation instead. But that would be hard for veristat to parse. So let's settle on your suggested version.
Quoted 6 lines
Quoted 6 lines
kernel/bpf/verifier.c static void print_verification_stats(struct bpf_verifier_env *env) · line 18717
Quoted 2 lines
kernel/bpf/verifier.c +2
-0+ } +verbose (env," max=%d\n" , env->max_stack_depth);I think
check_max_stack_depth_subprog()needs a similar update, at the moment it reports a not very helpful error like this:
Quoted 7 lines
Quoted 4 lines
combined stack size of 34 calls is 528. Too large
Printing the offending spine would be helpful.
I'll do that in verifier errors patch set. This is just for the verification stats, that are outside its scope.
Fine by me
Kumar Kartikeya Dwivedi
maintainerPATCH 2/3 selftests/bpf: Adjust veristat stack depth parsing
In reply to Kumar Kartikeya DwivediThe verifier changed the output format for stack depth verification statistics. Adjust the parsing code.
--- tools/testing/selftests/bpf/veristat.c | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-)
tools/testing/selftests/bpf/veristat.c +16 -9
@@ -997,9 +997,10 @@ static char verif_log_buf[64 * 1024];static int parse_verif_log (char *const buf,size_t buf_sz,struct verif_stats *s) { -const char *cur; -int pos, lines, sub_stack, cnt =0 ; -char *state =NULL , *token, stack[512 ]; +long stack_total, sub_stack; +const char *cur, *p; +int pos, lines; +char *end; buf[buf_sz -1 ] ='\0' ;
@@ -1025,13 +1026,19 @@ static int parse_verif_log(char * const buf, size_t buf_sz, struct verif_stats * &s->stats[MARK_READ_MAX_LEN]))continue ; -if (2 ==sscanf (cur,"stack depth %511s max %ld" , stack, &s->stats[MAX_STACK ])) +if (strncmp (cur,"stack depth " ,sizeof ("stack depth " ) -1 ))continue ; - } -while ((token =strtok_r (cnt++ ?NULL : stack,"+" , &state))) { -if (sscanf (token,"%d" , &sub_stack) ==0 ) -break ; - s->stats[STACK ] += sub_stack; + + stack_total =0 ; +for (p = cur +sizeof ("stack depth " ) -1 ; (p =strchr (p,'=' )); p = end) { + sub_stack =strtol (p +1 , &end,10 ); +if (*end =='\n' ) { + s->stats[STACK ] = stack_total; + s->stats[MAX_STACK ] = sub_stack; +break ; + } + stack_total += sub_stack; + } }return 0 ; }
Signature · 1 line
2.53.0
Eduard Zingerman
maintainerRe: [PATCH bpf-next v1 2/3] selftests/bpf: Adjust veristat stack depth parsing
Quoted 5 lines · Kumar Kartikeya Dwivedi
The verifier changed the output format for stack depth verification statistics. Adjust the parsing code.
Signed-off-by Kumar Kartikeya Dwivedi <[email protected]>---
Do we care about backwards compatibility in veristat? E.g. I see it packaged in my debian system.
This won't be able to parse the output of an old kernel. On the other hand, I personally do not use stack metrics, so the change does not really affect me.
...
Kumar Kartikeya Dwivedi
maintainerRe: [PATCH bpf-next v1 2/3] selftests/bpf: Adjust veristat stack depth parsing
Quoted 4 lines · Eduard Zingerman
Quoted 3 lines · Kumar Kartikeya Dwivedi
The verifier changed the output format for stack depth verification statistics. Adjust the parsing code.
Quoted 9 lines
Quoted 2 lines
Signed-off-by Kumar Kartikeya Dwivedi <[email protected]>---
Do we care about backwards compatibility in veristat? E.g. I see it packaged in my debian system.
This won't be able to parse the output of an old kernel. On the other hand, I personally do not use stack metrics, so the change does not really affect me.
It is an open question, given it is packaged, my instinct now is to parse both formats, to cause the last amount of disruption. So that's what I'll do unless someone tells me otherwise.
Quoted 1 line
...
Kumar Kartikeya Dwivedi
maintainerPATCH 3/3 selftests/bpf: Test stack depth stats without BTF subprog names
In reply to Kumar Kartikeya DwivediTest the case where we don't supply names for the subprogs.
--- tools/testing/selftests/bpf/test_verifier.c | 5 ++++- tools/testing/selftests/bpf/verifier/calls.c | 4 +++- 2 files changed, 7 insertions(+), 2 deletions(-)
tools/testing/selftests/bpf/test_verifier.c +4 -1
@@ -133,6 +133,7 @@ struct bpf_test {const char *errstr;const char *errstr_unpriv;uint32_t insn_processed; +uint32_t log_level;int prog_len;enum {UNDEF ,
@@ -1559,7 +1560,9 @@ static void do_test_single(struct bpf_test *test, bool unpriv, test->errstr_unpriv : test->errstr; opts.expected_attach_type = test->expected_attach_type; -if (expected_ret ==VERBOSE_ACCEPT ) +if (test->log_level) + opts.log_level = test->log_level; +else if (expected_ret ==VERBOSE_ACCEPT ) opts.log_level =2 ;else if (verbose) opts.log_level = verif_log_level |4 ;/* force stats */
tools/testing/selftests/bpf/verifier/calls.c +3 -1
@@ -1091,7 +1091,9 @@/* stack_main=32, stack_A=256, stack_B=64 * and max(main+A, main+A+B) < 512 */ - .result = ACCEPT, + .result = VERBOSE_ACCEPT, + .errstr = "stack depth subprog[0]=32 subprog[1]=256 subprog[2]=64 max=352", + .log_level = DEFAULT_LIBBPF_LOG_LEVEL, }, { "calls: stack depth check using three frames. test2",
Signature · 1 line
2.53.0
Eduard Zingerman
maintainerRe: [PATCH bpf-next v1 3/3] selftests/bpf: Test stack depth stats without BTF subprog names
On Sun, 2026-08-02 at 01:03 +0200, Kumar Kartikeya Dwivedi wrote:
...
Quoted 9 lines
tools/testing/selftests/bpf/test_verifier.c +0
-0@@ -1559,7 +1560,9 @@ static void do_test_single(struct bpf_test *test, bool unpriv, test->errstr_unpriv : test->errstr;
opts.expected_attach_type =test->expected_attach_type;tools/testing/selftests/bpf/test_verifier.c +3
-1-if (expected_ret ==VERBOSE_ACCEPT ) +if (test->log_level) + opts.log_level = test->log_level; +else if (expected_ret ==VERBOSE_ACCEPT )opts.log_level = 2;
I did this:
else if (expected_ret == VERBOSE_ACCEPT)
- opts.log_level = 2;
+ opts.log_level = 2 | 4;
And all test_verifier tests passed.
There is no need to a new option.
Quoted 2 lines
else if (verbose)
opts.log_level =verif_log_level| 4; /* force stats */
...
Kumar Kartikeya Dwivedi
maintainerRe: [PATCH bpf-next v1 3/3] selftests/bpf: Test stack depth stats without BTF subprog names
Quoted 16 lines · Eduard Zingerman
On Sun, 2026-08-02 at 01:03 +0200, Kumar Kartikeya Dwivedi wrote:
...
Quoted 9 lines
tools/testing/selftests/bpf/test_verifier.c +0
-0@@ -1559,7 +1560,9 @@ static void do_test_single(struct bpf_test *test, bool unpriv, test->errstr_unpriv : test->errstr;
opts.expected_attach_type =test->expected_attach_type;tools/testing/selftests/bpf/test_verifier.c +3
-1-if (expected_ret ==VERBOSE_ACCEPT ) +if (test->log_level) + opts.log_level = test->log_level; +else if (expected_ret ==VERBOSE_ACCEPT )opts.log_level = 2;
I did this:
Quoted 7 lines
else if (expected_ret == VERBOSE_ACCEPT)- opts.log_level = 2;
+ opts.log_level = 2 | 4;And all
test_verifiertests passed.
There is no need to a new option.
Ack.
Quoted 4 lines
Quoted 2 lines
else if (verbose)
opts.log_level =verif_log_level| 4; /* force stats */...