OSDN Git Service

bpf: Refactor and streamline bounds check into helper
authorDaniel Borkmann <daniel@iogearbox.net>
Fri, 28 May 2021 10:38:03 +0000 (13:38 +0300)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 3 Jun 2021 06:38:06 +0000 (08:38 +0200)
commit 073815b756c51ba9d8384d924c5d1c03ca3d1ae4 upstream.

Move the bounds check in adjust_ptr_min_max_vals() into a small helper named
sanitize_check_bounds() in order to simplify the former a bit.

Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Reviewed-by: John Fastabend <john.fastabend@gmail.com>
Acked-by: Alexei Starovoitov <ast@kernel.org>
[fllinden@amazon.com: backport to 5.4]
Signed-off-by: Frank van der Linden <fllinden@amazon.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Ovidiu Panait <ovidiu.panait@windriver.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
kernel/bpf/verifier.c

index 473b591..faa2a4c 100644 (file)
@@ -2911,6 +2911,41 @@ static int sanitize_err(struct bpf_verifier_env *env,
        return -EACCES;
 }
 
+static int sanitize_check_bounds(struct bpf_verifier_env *env,
+                                const struct bpf_insn *insn,
+                                const struct bpf_reg_state *dst_reg)
+{
+       u32 dst = insn->dst_reg;
+
+       /* For unprivileged we require that resulting offset must be in bounds
+        * in order to be able to sanitize access later on.
+        */
+       if (env->allow_ptr_leaks)
+               return 0;
+
+       switch (dst_reg->type) {
+       case PTR_TO_STACK:
+               if (check_stack_access(env, dst_reg, dst_reg->off +
+                                      dst_reg->var_off.value, 1)) {
+                       verbose(env, "R%d stack pointer arithmetic goes out of range, "
+                               "prohibited for !root\n", dst);
+                       return -EACCES;
+               }
+               break;
+       case PTR_TO_MAP_VALUE:
+               if (check_map_access(env, dst, dst_reg->off, 1, false)) {
+                       verbose(env, "R%d pointer arithmetic of map value goes out of range, "
+                               "prohibited for !root\n", dst);
+                       return -EACCES;
+               }
+               break;
+       default:
+               break;
+       }
+
+       return 0;
+}
+
 /* Handles arithmetic on a pointer and a scalar: computes new min/max and var_off.
  * Caller should also handle BPF_MOV case separately.
  * If we return -EACCES, caller may want to try again treating pointer as a
@@ -3118,23 +3153,8 @@ static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env,
        __reg_deduce_bounds(dst_reg);
        __reg_bound_offset(dst_reg);
 
-       /* For unprivileged we require that resulting offset must be in bounds
-        * in order to be able to sanitize access later on.
-        */
-       if (!env->allow_ptr_leaks) {
-               if (dst_reg->type == PTR_TO_MAP_VALUE &&
-                   check_map_access(env, dst, dst_reg->off, 1, false)) {
-                       verbose(env, "R%d pointer arithmetic of map value goes out of range, "
-                               "prohibited for !root\n", dst);
-                       return -EACCES;
-               } else if (dst_reg->type == PTR_TO_STACK &&
-                          check_stack_access(env, dst_reg, dst_reg->off +
-                                             dst_reg->var_off.value, 1)) {
-                       verbose(env, "R%d stack pointer arithmetic goes out of range, "
-                               "prohibited for !root\n", dst);
-                       return -EACCES;
-               }
-       }
+       if (sanitize_check_bounds(env, insn, dst_reg) < 0)
+               return -EACCES;
 
        return 0;
 }