diff mbox series

[RFC,bpf-next,v1,6/9] bpf: Add KF_THROW annotation for kfuncs

Message ID 20230405004239.1375399-7-memxor@gmail.com (mailing list archive)
State RFC
Delegated to: BPF
Headers show
Series Exceptions - 1/2 | expand

Checks

Context Check Description
bpf/vmtest-bpf-next-PR success PR summary
bpf/vmtest-bpf-next-VM_Test-1 success Logs for ShellCheck
bpf/vmtest-bpf-next-VM_Test-4 pending Logs for build for s390x with gcc
bpf/vmtest-bpf-next-VM_Test-7 success Logs for set-matrix
bpf/vmtest-bpf-next-VM_Test-2 success Logs for build for aarch64 with gcc
bpf/vmtest-bpf-next-VM_Test-3 success Logs for build for aarch64 with llvm-16
bpf/vmtest-bpf-next-VM_Test-5 success Logs for build for x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-6 success Logs for build for x86_64 with llvm-16
netdev/series_format success Posting correctly formatted
netdev/tree_selection success Clearly marked for bpf-next, async
netdev/fixes_present success Fixes tag not required for -next series
netdev/header_inline success No static functions without inline keyword in header files
netdev/build_32bit fail Errors and warnings before: 1469 this patch: 1471
netdev/cc_maintainers warning 13 maintainers not CCed: pabeni@redhat.com song@kernel.org sdf@google.com haoluo@google.com yhs@fb.com kuba@kernel.org edumazet@google.com john.fastabend@gmail.com kpsingh@kernel.org jolsa@kernel.org netdev@vger.kernel.org martin.lau@linux.dev davem@davemloft.net
netdev/build_clang success Errors and warnings before: 170 this patch: 170
netdev/verify_signedoff success Signed-off-by tag matches author and committer
netdev/deprecated_api success None detected
netdev/check_selftest success No net selftest shell script
netdev/verify_fixes success No Fixes tag
netdev/build_allmodconfig_warn fail Errors and warnings before: 1463 this patch: 1465
netdev/checkpatch warning CHECK: Prefer using the BIT macro WARNING: line length of 92 exceeds 80 columns WARNING: void function return statements are not generally useful
netdev/kdoc success Errors and warnings before: 0 this patch: 0
netdev/source_inline success Was 0 now: 0

Commit Message

Kumar Kartikeya Dwivedi April 5, 2023, 12:42 a.m. UTC
Add KF_THROW annotation to kfuncs to indicate that they may throw. This
is mostly for testing for now, but in the future it could be used by
kfuncs to throw on invalid arguments or invalid conditions based on
their input arguments, causing the program to abort, and simplify the
overall user experience of kfuncs for the happy case, without having to
deal with corner cases that never occur at runtime.

Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
---
 include/linux/btf.h   |  1 +
 kernel/bpf/verifier.c | 12 ++++++++++--
 net/bpf/test_run.c    | 12 ++++++++++++
 3 files changed, 23 insertions(+), 2 deletions(-)
diff mbox series

Patch

diff --git a/include/linux/btf.h b/include/linux/btf.h
index d53b10cc55f2..8dfa4113822b 100644
--- a/include/linux/btf.h
+++ b/include/linux/btf.h
@@ -75,6 +75,7 @@ 
 #define KF_ITER_NEW     (1 << 8) /* kfunc implements BPF iter constructor */
 #define KF_ITER_NEXT    (1 << 9) /* kfunc implements BPF iter next method */
 #define KF_ITER_DESTROY (1 << 10) /* kfunc implements BPF iter destructor */
+#define KF_THROW	(1 << 11) /* kfunc may throw a BPF exception */
 
 /*
  * Tag marking a kernel function as a kfunc. This is meant to minimize the
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index acfcaadca3b6..b9f4b1849647 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -9454,6 +9454,11 @@  static bool is_kfunc_arg_kptr_get(struct bpf_kfunc_call_arg_meta *meta, int arg)
 	return arg == 0 && (meta->kfunc_flags & KF_KPTR_GET);
 }
 
+static bool is_kfunc_throwing(struct bpf_kfunc_call_arg_meta *meta)
+{
+	return meta->kfunc_flags & KF_THROW;
+}
+
 static bool __kfunc_param_match_suffix(const struct btf *btf,
 				       const struct btf_param *arg,
 				       const char *suffix)
@@ -10813,11 +10818,14 @@  static int check_kfunc_call(struct bpf_verifier_env *env, struct bpf_insn *insn,
 		}
 	}
 
-	if (meta.btf == btf_vmlinux && meta.func_id == special_kfunc_list[KF_bpf_throw]) {
+	if (is_kfunc_throwing(&meta) ||
+	    (meta.btf == btf_vmlinux && meta.func_id == special_kfunc_list[KF_bpf_throw])) {
 		err = mark_chain_throw(env, insn_idx);
 		if (err < 0)
 			return err;
-		return 1;
+		/* Halt exploration only for bpf_throw */
+		if (!is_kfunc_throwing(&meta))
+			return 1;
 	}
 
 	for (i = 0; i < CALLER_SAVED_REGS; i++)
diff --git a/net/bpf/test_run.c b/net/bpf/test_run.c
index f1652f5fbd2e..31f76ee4218b 100644
--- a/net/bpf/test_run.c
+++ b/net/bpf/test_run.c
@@ -766,6 +766,16 @@  __bpf_kfunc static u32 bpf_kfunc_call_test_static_unused_arg(u32 arg, u32 unused
 	return arg;
 }
 
+__bpf_kfunc notrace void bpf_kfunc_call_test_always_throws(void)
+{
+	bpf_throw();
+}
+
+__bpf_kfunc notrace void bpf_kfunc_call_test_never_throws(void)
+{
+	return;
+}
+
 __diag_pop();
 
 BTF_SET8_START(bpf_test_modify_return_ids)
@@ -806,6 +816,8 @@  BTF_ID_FLAGS(func, bpf_kfunc_call_test_ref, KF_TRUSTED_ARGS | KF_RCU)
 BTF_ID_FLAGS(func, bpf_kfunc_call_test_destructive, KF_DESTRUCTIVE)
 BTF_ID_FLAGS(func, bpf_kfunc_call_test_static_unused_arg)
 BTF_ID_FLAGS(func, bpf_kfunc_call_test_offset)
+BTF_ID_FLAGS(func, bpf_kfunc_call_test_always_throws, KF_THROW)
+BTF_ID_FLAGS(func, bpf_kfunc_call_test_never_throws, KF_THROW)
 BTF_SET8_END(test_sk_check_kfunc_ids)
 
 static void *bpf_test_init(const union bpf_attr *kattr, u32 user_size,