diff mbox series

[bpf-next,v4,7/7] bpf/verifier: improve code after range computation recent changes.

Message ID 20240429212250.78420-8-cupertino.miranda@oracle.com (mailing list archive)
State Superseded
Delegated to: BPF
Headers show
Series bpf/verifier: range computation improvements | expand

Checks

Context Check Description
bpf/vmtest-bpf-next-PR success PR summary
netdev/series_format success Posting correctly formatted
netdev/tree_selection success Clearly marked for bpf-next
netdev/ynl success Generated files up to date; no warnings/errors; no diff in generated;
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 success Errors and warnings before: 938 this patch: 938
netdev/build_tools success No tools touched, skip
netdev/cc_maintainers warning 9 maintainers not CCed: kpsingh@kernel.org john.fastabend@gmail.com andrii@kernel.org jolsa@kernel.org song@kernel.org daniel@iogearbox.net martin.lau@linux.dev haoluo@google.com sdf@google.com
netdev/build_clang success Errors and warnings before: 938 this patch: 938
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 success Errors and warnings before: 949 this patch: 949
netdev/checkpatch success total: 0 errors, 0 warnings, 0 checks, 59 lines checked
netdev/build_clang_rust success No Rust files in patch. Skipping build
netdev/kdoc success Errors and warnings before: 0 this patch: 0
netdev/source_inline success Was 0 now: 0
bpf/vmtest-bpf-next-VM_Test-0 success Logs for Lint
bpf/vmtest-bpf-next-VM_Test-12 success Logs for s390x-gcc / build-release
bpf/vmtest-bpf-next-VM_Test-2 success Logs for Unittests
bpf/vmtest-bpf-next-VM_Test-10 success Logs for aarch64-gcc / veristat
bpf/vmtest-bpf-next-VM_Test-9 success Logs for aarch64-gcc / test (test_verifier, false, 360) / test_verifier on aarch64 with gcc
bpf/vmtest-bpf-next-VM_Test-1 success Logs for ShellCheck
bpf/vmtest-bpf-next-VM_Test-3 success Logs for Validate matrix.py
bpf/vmtest-bpf-next-VM_Test-11 success Logs for s390x-gcc / build / build for s390x with gcc
bpf/vmtest-bpf-next-VM_Test-13 success Logs for s390x-gcc / test (test_maps, false, 360) / test_maps on s390x with gcc
bpf/vmtest-bpf-next-VM_Test-4 success Logs for aarch64-gcc / build / build for aarch64 with gcc
bpf/vmtest-bpf-next-VM_Test-16 success Logs for s390x-gcc / test (test_verifier, false, 360) / test_verifier on s390x with gcc
bpf/vmtest-bpf-next-VM_Test-5 success Logs for aarch64-gcc / build-release
bpf/vmtest-bpf-next-VM_Test-17 success Logs for s390x-gcc / veristat
bpf/vmtest-bpf-next-VM_Test-18 success Logs for set-matrix
bpf/vmtest-bpf-next-VM_Test-19 success Logs for x86_64-gcc / build / build for x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-20 success Logs for x86_64-gcc / build-release
bpf/vmtest-bpf-next-VM_Test-28 success Logs for x86_64-llvm-17 / build / build for x86_64 with llvm-17
bpf/vmtest-bpf-next-VM_Test-29 success Logs for x86_64-llvm-17 / build-release / build for x86_64 with llvm-17 and -O2 optimization
bpf/vmtest-bpf-next-VM_Test-34 success Logs for x86_64-llvm-17 / veristat
bpf/vmtest-bpf-next-VM_Test-35 success Logs for x86_64-llvm-18 / build / build for x86_64 with llvm-18
bpf/vmtest-bpf-next-VM_Test-36 success Logs for x86_64-llvm-18 / build-release / build for x86_64 with llvm-18 and -O2 optimization
bpf/vmtest-bpf-next-VM_Test-42 success Logs for x86_64-llvm-18 / veristat
bpf/vmtest-bpf-next-VM_Test-7 success Logs for aarch64-gcc / test (test_progs, false, 360) / test_progs on aarch64 with gcc
bpf/vmtest-bpf-next-VM_Test-6 success Logs for aarch64-gcc / test (test_maps, false, 360) / test_maps on aarch64 with gcc
bpf/vmtest-bpf-next-VM_Test-8 success Logs for aarch64-gcc / test (test_progs_no_alu32, false, 360) / test_progs_no_alu32 on aarch64 with gcc
bpf/vmtest-bpf-next-VM_Test-14 success Logs for s390x-gcc / test (test_progs, false, 360) / test_progs on s390x with gcc
bpf/vmtest-bpf-next-VM_Test-15 success Logs for s390x-gcc / test (test_progs_no_alu32, false, 360) / test_progs_no_alu32 on s390x with gcc
bpf/vmtest-bpf-next-VM_Test-21 success Logs for x86_64-gcc / test (test_maps, false, 360) / test_maps on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-22 success Logs for x86_64-gcc / test (test_progs, false, 360) / test_progs on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-23 success Logs for x86_64-gcc / test (test_progs_no_alu32, false, 360) / test_progs_no_alu32 on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-24 success Logs for x86_64-gcc / test (test_progs_no_alu32_parallel, true, 30) / test_progs_no_alu32_parallel on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-25 success Logs for x86_64-gcc / test (test_progs_parallel, true, 30) / test_progs_parallel on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-26 success Logs for x86_64-gcc / test (test_verifier, false, 360) / test_verifier on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-27 success Logs for x86_64-gcc / veristat / veristat on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-30 success Logs for x86_64-llvm-17 / test (test_maps, false, 360) / test_maps on x86_64 with llvm-17
bpf/vmtest-bpf-next-VM_Test-31 success Logs for x86_64-llvm-17 / test (test_progs, false, 360) / test_progs on x86_64 with llvm-17
bpf/vmtest-bpf-next-VM_Test-32 success Logs for x86_64-llvm-17 / test (test_progs_no_alu32, false, 360) / test_progs_no_alu32 on x86_64 with llvm-17
bpf/vmtest-bpf-next-VM_Test-33 success Logs for x86_64-llvm-17 / test (test_verifier, false, 360) / test_verifier on x86_64 with llvm-17
bpf/vmtest-bpf-next-VM_Test-37 success Logs for x86_64-llvm-18 / test (test_maps, false, 360) / test_maps on x86_64 with llvm-18
bpf/vmtest-bpf-next-VM_Test-38 success Logs for x86_64-llvm-18 / test (test_progs, false, 360) / test_progs on x86_64 with llvm-18
bpf/vmtest-bpf-next-VM_Test-39 success Logs for x86_64-llvm-18 / test (test_progs_cpuv4, false, 360) / test_progs_cpuv4 on x86_64 with llvm-18
bpf/vmtest-bpf-next-VM_Test-40 success Logs for x86_64-llvm-18 / test (test_progs_no_alu32, false, 360) / test_progs_no_alu32 on x86_64 with llvm-18
bpf/vmtest-bpf-next-VM_Test-41 success Logs for x86_64-llvm-18 / test (test_verifier, false, 360) / test_verifier on x86_64 with llvm-18

Commit Message

Cupertino Miranda April 29, 2024, 9:22 p.m. UTC
Recent changes in range computation had simplified code making some
checks unnecessary. This patch improves the code taking in consideration
those changes.

Signed-off-by: Cupertino Miranda <cupertino.miranda@oracle.com>
Cc: Yonghong Song <yonghong.song@linux.dev>
Cc: Alexei Starovoitov <alexei.starovoitov@gmail.com>
Cc: David Faust <david.faust@oracle.com>
Cc: Jose Marchesi <jose.marchesi@oracle.com>
Cc: Elena Zannoni <elena.zannoni@oracle.com>
Cc: Andrii Nakryiko <andrii.nakryiko@gmail.com>
Cc: Eduard Zingerman <eddyz87@gmail.com>
---
 kernel/bpf/verifier.c | 42 ++++++++++--------------------------------
 1 file changed, 10 insertions(+), 32 deletions(-)

Comments

Eduard Zingerman April 29, 2024, 11:16 p.m. UTC | #1
[...]


> diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
> index b6344cead2e2..a6fd10b119ba 100644
> --- a/kernel/bpf/verifier.c
> +++ b/kernel/bpf/verifier.c
> @@ -13695,33 +13695,19 @@ static void scalar_min_max_arsh(struct bpf_reg_state *dst_reg,
>  	__update_reg_bounds(dst_reg);
>  }
>  
> -static bool is_const_reg_and_valid(const struct bpf_reg_state *reg, bool alu32,
> -				   bool *valid)
> -{
> -	s64 smin_val = reg->smin_value;
> -	s64 smax_val = reg->smax_value;
> -	u64 umin_val = reg->umin_value;
> -	u64 umax_val = reg->umax_value;
> -	s32 s32_min_val = reg->s32_min_value;
> -	s32 s32_max_val = reg->s32_max_value;
> -	u32 u32_min_val = reg->u32_min_value;
> -	u32 u32_max_val = reg->u32_max_value;
> -	bool is_const = alu32 ? tnum_subreg_is_const(reg->var_off) :
> -				tnum_is_const(reg->var_off);
> -
> +static bool is_valid_const_reg(const struct bpf_reg_state *reg, bool alu32)
> +{
>  	if (alu32) {
> -		if ((is_const &&
> -		     (s32_min_val != s32_max_val || u32_min_val != u32_max_val)) ||
> -		      s32_min_val > s32_max_val || u32_min_val > u32_max_val)
> -			*valid = false;

This check first originated in the following commit from 2018:

6f16101e6a8b ("bpf: mark dst unknown on inconsistent {s, u}bounds adjustments")

Back then it was added to handle the following program:

  0: (b7) r0 = 0
  1: (d5) if r0 s<= 0x0 goto pc+0          <---- note pc+0 here
   R0=inv0 R1=ctx(id=0,off=0,imm=0) R10=fp0
  2: (1f) r0 -= r1
   R0=inv0 R1=ctx(id=0,off=0,imm=0) R10=fp0
  verifier internal error: known but bad sbounds

Apparently, verifier visited both conditional branches for this program
deducing impossible bounds for the 'false' branch.
Nowadays is_scalar_branch_taken() should handle such situations w/o issues.
Still, I'm not sure if we want to remove this safety check.

[...]
Eduard Zingerman April 29, 2024, 11:29 p.m. UTC | #2
On Mon, 2024-04-29 at 16:16 -0700, Eduard Zingerman wrote:
[...]

> Still, I'm not sure if we want to remove this safety check.

... and if we are going to remove the safety check,
then at-least there should be a warning like there was before the
commit from 2018. Which is almost the same amount of code as current
'check + invalid flag'.
Eduard Zingerman April 30, 2024, 4:48 p.m. UTC | #3
On Mon, 2024-04-29 at 16:29 -0700, Eduard Zingerman wrote:
> On Mon, 2024-04-29 at 16:16 -0700, Eduard Zingerman wrote:
> [...]
> 
> > Still, I'm not sure if we want to remove this safety check.
> 
> ... and if we are going to remove the safety check,
> then at-least there should be a warning like there was before the
> commit from 2018. Which is almost the same amount of code as current
> 'check + invalid flag'.

My bad. I've been reminded by Yonghong that adjust_reg_min_max_vals()
is called from check_alu_op(), which does reg_bounds_sanity_check()
upon return.

This patch is fine and there is also no need to change anything in
patch #2, as it would be removed. Sorry for the noise.

Acked-by: Eduard Zingerman <eddyz87@gmail.com>
diff mbox series

Patch

diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index b6344cead2e2..a6fd10b119ba 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -13695,33 +13695,19 @@  static void scalar_min_max_arsh(struct bpf_reg_state *dst_reg,
 	__update_reg_bounds(dst_reg);
 }
 
-static bool is_const_reg_and_valid(const struct bpf_reg_state *reg, bool alu32,
-				   bool *valid)
-{
-	s64 smin_val = reg->smin_value;
-	s64 smax_val = reg->smax_value;
-	u64 umin_val = reg->umin_value;
-	u64 umax_val = reg->umax_value;
-	s32 s32_min_val = reg->s32_min_value;
-	s32 s32_max_val = reg->s32_max_value;
-	u32 u32_min_val = reg->u32_min_value;
-	u32 u32_max_val = reg->u32_max_value;
-	bool is_const = alu32 ? tnum_subreg_is_const(reg->var_off) :
-				tnum_is_const(reg->var_off);
-
+static bool is_valid_const_reg(const struct bpf_reg_state *reg, bool alu32)
+{
 	if (alu32) {
-		if ((is_const &&
-		     (s32_min_val != s32_max_val || u32_min_val != u32_max_val)) ||
-		      s32_min_val > s32_max_val || u32_min_val > u32_max_val)
-			*valid = false;
+		if (tnum_subreg_is_const(reg->var_off))
+			return reg->s32_min_value == reg->s32_max_value &&
+			       reg->u32_min_value == reg->u32_max_value;
 	} else {
-		if ((is_const &&
-		     (smin_val != smax_val || umin_val != umax_val)) ||
-		    smin_val > smax_val || umin_val > umax_val)
-			*valid = false;
+		if (tnum_is_const(reg->var_off))
+			return reg->smin_value == reg->smax_value &&
+			       reg->umin_value == reg->umax_value;
 	}
 
-	return is_const;
+	return false;
 }
 
 static bool is_safe_to_compute_dst_reg_range(struct bpf_insn *insn,
@@ -13729,16 +13715,8 @@  static bool is_safe_to_compute_dst_reg_range(struct bpf_insn *insn,
 {
 	bool src_is_const;
 	u64 insn_bitness = (BPF_CLASS(insn->code) == BPF_ALU64) ? 64 : 32;
-	bool valid_const = true;
 
-	src_is_const = is_const_reg_and_valid(src_reg, insn_bitness == 32,
-					      &valid_const);
-
-	/* Taint dst register if offset had invalid bounds
-	 * derived from e.g. dead branches.
-	 */
-	if (valid_const == false)
-		return false;
+	src_is_const = is_valid_const_reg(src_reg, insn_bitness == 32);
 
 	switch (BPF_OP(insn->code)) {
 	case BPF_ADD: