Add a test case to exercise verifier logic where a global function that may potentially throw an exception is invoked from the main subprog, such that during exploration, the reference state is not visible when the bpf_throw instruction is explored. Without the fixes in prior commits, bpf_throw will not complain when unreleased resources are lingering in the program when a possible exception may be thrown. Signed-off-by: Kumar Kartikeya Dwivedi <memxor@xxxxxxxxx> --- .../selftests/bpf/progs/exceptions_fail.c | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/tools/testing/selftests/bpf/progs/exceptions_fail.c b/tools/testing/selftests/bpf/progs/exceptions_fail.c index 9cceb6521143..28602f905d7d 100644 --- a/tools/testing/selftests/bpf/progs/exceptions_fail.c +++ b/tools/testing/selftests/bpf/progs/exceptions_fail.c @@ -146,6 +146,13 @@ __noinline static int throwing_subprog(struct __sk_buff *ctx) return 0; } +__noinline int throwing_global_subprog(struct __sk_buff *ctx) +{ + if (ctx->len) + bpf_throw(0); + return 0; +} + SEC("?tc") __failure __msg("bpf_rcu_read_unlock is missing") int reject_subprog_with_rcu_read_lock(void *ctx) @@ -346,4 +353,18 @@ int reject_exception_throw_cb_diff(struct __sk_buff *ctx) return 0; } +SEC("?tc") +__failure __msg("exploring program path where exception is thrown") +int reject_exception_throw_ref_call_throwing_global(struct __sk_buff *ctx) +{ + struct { long a; } *p = bpf_obj_new(typeof(*p)); + + if (!p) + return 0; + if (ctx->protocol) + throwing_global_subprog(ctx); + bpf_obj_drop(p); + return 0; +} + char _license[] SEC("license") = "GPL"; -- 2.40.1