bpf: add a get_helper_proto() utility function
authorEduard Zingerman <eddyz87@gmail.com>
Mon, 22 Jul 2024 23:38:35 +0000 (16:38 -0700)
committerAndrii Nakryiko <andrii@kernel.org>
Mon, 29 Jul 2024 22:05:05 +0000 (15:05 -0700)
Extract the part of check_helper_call() as a utility function allowing
to query 'struct bpf_func_proto' for a specific helper function id.

Acked-by: Andrii Nakryiko <andrii@kernel.org>
Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
Link: https://lore.kernel.org/r/20240722233844.1406874-2-eddyz87@gmail.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
kernel/bpf/verifier.c

index 4759c0b..3ed6745 100644 (file)
@@ -10369,6 +10369,19 @@ static void update_loop_inline_state(struct bpf_verifier_env *env, u32 subprogno
                                 state->callback_subprogno == subprogno);
 }
 
+static int get_helper_proto(struct bpf_verifier_env *env, int func_id,
+                           const struct bpf_func_proto **ptr)
+{
+       if (func_id < 0 || func_id >= __BPF_FUNC_MAX_ID)
+               return -ERANGE;
+
+       if (!env->ops->get_func_proto)
+               return -EINVAL;
+
+       *ptr = env->ops->get_func_proto(func_id, env->prog);
+       return *ptr ? 0 : -EINVAL;
+}
+
 static int check_helper_call(struct bpf_verifier_env *env, struct bpf_insn *insn,
                             int *insn_idx_p)
 {
@@ -10385,18 +10398,16 @@ static int check_helper_call(struct bpf_verifier_env *env, struct bpf_insn *insn
 
        /* find function prototype */
        func_id = insn->imm;
-       if (func_id < 0 || func_id >= __BPF_FUNC_MAX_ID) {
-               verbose(env, "invalid func %s#%d\n", func_id_name(func_id),
-                       func_id);
+       err = get_helper_proto(env, insn->imm, &fn);
+       if (err == -ERANGE) {
+               verbose(env, "invalid func %s#%d\n", func_id_name(func_id), func_id);
                return -EINVAL;
        }
 
-       if (env->ops->get_func_proto)
-               fn = env->ops->get_func_proto(func_id, env->prog);
-       if (!fn) {
+       if (err) {
                verbose(env, "program of this type cannot use helper %s#%d\n",
                        func_id_name(func_id), func_id);
-               return -EINVAL;
+               return err;
        }
 
        /* eBPF programs must be GPL compatible to use GPL-ed functions */