]> git.proxmox.com Git - mirror_ubuntu-kernels.git/commitdiff
bpf: Add check_func_arg_reg_off function
authorKumar Kartikeya Dwivedi <memxor@gmail.com>
Fri, 4 Mar 2022 22:46:38 +0000 (04:16 +0530)
committerAlexei Starovoitov <ast@kernel.org>
Sat, 5 Mar 2022 23:29:35 +0000 (15:29 -0800)
Lift the list of register types allowed for having fixed and variable
offsets when passed as helper function arguments into a common helper,
so that they can be reused for kfunc checks in later commits. Keeping a
common helper aids maintainability and allows us to follow the same
consistent rules across helpers and kfuncs. Also, convert check_func_arg
to use this function.

Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Link: https://lore.kernel.org/bpf/20220304224645.3677453-2-memxor@gmail.com
include/linux/bpf_verifier.h
kernel/bpf/verifier.c

index 7a7be8c057f2c2c2e971d02e248d9bfcfcb1f18f..38b24ee8d8c25786764a25c61436697204727172 100644 (file)
@@ -521,6 +521,9 @@ bpf_prog_offload_remove_insns(struct bpf_verifier_env *env, u32 off, u32 cnt);
 
 int check_ptr_off_reg(struct bpf_verifier_env *env,
                      const struct bpf_reg_state *reg, int regno);
+int check_func_arg_reg_off(struct bpf_verifier_env *env,
+                          const struct bpf_reg_state *reg, int regno,
+                          enum bpf_arg_type arg_type);
 int check_kfunc_mem_size_reg(struct bpf_verifier_env *env, struct bpf_reg_state *reg,
                             u32 regno);
 int check_mem_reg(struct bpf_verifier_env *env, struct bpf_reg_state *reg,
index a57db4b2803cec219918d6857d50c9fb10cb4829..e37eb6020253c4be9a695929465fe296b8044110 100644 (file)
@@ -5359,6 +5359,44 @@ found:
        return 0;
 }
 
+int check_func_arg_reg_off(struct bpf_verifier_env *env,
+                          const struct bpf_reg_state *reg, int regno,
+                          enum bpf_arg_type arg_type)
+{
+       enum bpf_reg_type type = reg->type;
+       bool fixed_off_ok = false;
+
+       switch ((u32)type) {
+       case SCALAR_VALUE:
+       /* Pointer types where reg offset is explicitly allowed: */
+       case PTR_TO_PACKET:
+       case PTR_TO_PACKET_META:
+       case PTR_TO_MAP_KEY:
+       case PTR_TO_MAP_VALUE:
+       case PTR_TO_MEM:
+       case PTR_TO_MEM | MEM_RDONLY:
+       case PTR_TO_MEM | MEM_ALLOC:
+       case PTR_TO_BUF:
+       case PTR_TO_BUF | MEM_RDONLY:
+       case PTR_TO_STACK:
+               /* Some of the argument types nevertheless require a
+                * zero register offset.
+                */
+               if (arg_type != ARG_PTR_TO_ALLOC_MEM)
+                       return 0;
+               break;
+       /* All the rest must be rejected, except PTR_TO_BTF_ID which allows
+        * fixed offset.
+        */
+       case PTR_TO_BTF_ID:
+               fixed_off_ok = true;
+               break;
+       default:
+               break;
+       }
+       return __check_ptr_off_reg(env, reg, regno, fixed_off_ok);
+}
+
 static int check_func_arg(struct bpf_verifier_env *env, u32 arg,
                          struct bpf_call_arg_meta *meta,
                          const struct bpf_func_proto *fn)
@@ -5408,34 +5446,9 @@ static int check_func_arg(struct bpf_verifier_env *env, u32 arg,
        if (err)
                return err;
 
-       switch ((u32)type) {
-       case SCALAR_VALUE:
-       /* Pointer types where reg offset is explicitly allowed: */
-       case PTR_TO_PACKET:
-       case PTR_TO_PACKET_META:
-       case PTR_TO_MAP_KEY:
-       case PTR_TO_MAP_VALUE:
-       case PTR_TO_MEM:
-       case PTR_TO_MEM | MEM_RDONLY:
-       case PTR_TO_MEM | MEM_ALLOC:
-       case PTR_TO_BUF:
-       case PTR_TO_BUF | MEM_RDONLY:
-       case PTR_TO_STACK:
-               /* Some of the argument types nevertheless require a
-                * zero register offset.
-                */
-               if (arg_type == ARG_PTR_TO_ALLOC_MEM)
-                       goto force_off_check;
-               break;
-       /* All the rest must be rejected: */
-       default:
-force_off_check:
-               err = __check_ptr_off_reg(env, reg, regno,
-                                         type == PTR_TO_BTF_ID);
-               if (err < 0)
-                       return err;
-               break;
-       }
+       err = check_func_arg_reg_off(env, reg, regno, arg_type);
+       if (err)
+               return err;
 
 skip_type_check:
        if (reg->ref_obj_id) {