All of lore.kernel.org
 help / color / mirror / Atom feed
From: KaFai Wan <kafai.wan@linux.dev>
To: ast@kernel.org, daniel@iogearbox.net, john.fastabend@gmail.com,
	andrii@kernel.org, martin.lau@linux.dev, eddyz87@gmail.com,
	song@kernel.org, yonghong.song@linux.dev, kpsingh@kernel.org,
	sdf@fomichev.me, haoluo@google.com, jolsa@kernel.org,
	shuah@kernel.org, paul.chaignon@gmail.com, m.shachnai@gmail.com,
	harishankar.vishwanathan@gmail.com, colin.i.king@gmail.com,
	luis.gerhorst@fau.de, bpf@vger.kernel.org,
	linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org
Cc: KaFai Wan <kafai.wan@linux.dev>,
	Kaiyan Mei <M202472210@hust.edu.cn>,
	Yinhao Hu <dddddd@hust.edu.cn>
Subject: [PATCH bpf-next v2 1/2] bpf: Skip bounds adjustment for conditional jumps on same register
Date: Sat, 25 Oct 2025 13:30:16 +0800	[thread overview]
Message-ID: <20251025053017.2308823-2-kafai.wan@linux.dev> (raw)
In-Reply-To: <20251025053017.2308823-1-kafai.wan@linux.dev>

When conditional jumps are performed on the same register (e.g., r0 <= r0,
r0 > r0, r0 < r0) where the register holds a scalar with range, the verifier
incorrectly attempts to adjust the register's min/max bounds. This leads to
invalid range bounds and triggers a BUG warning:

verifier bug: REG INVARIANTS VIOLATION (true_reg1): range bounds violation u64=[0x1, 0x0] s64=[0x1, 0x0] u32=[0x1, 0x0] s32=[0x1, 0x0] var_off=(0x0, 0x0)
WARNING: CPU: 0 PID: 92 at kernel/bpf/verifier.c:2731 reg_bounds_sanity_check+0x163/0x220
Hardware name: QEMU Ubuntu 24.04 PC (i440FX + PIIX, 1996), BIOS 1.16.3-debian-1.16.3-2 04/01/2014
RIP: 0010:reg_bounds_sanity_check+0x163/0x220
Call Trace:
 <TASK>
 reg_set_min_max+0xf7/0x1d0
 check_cond_jmp_op+0x57b/0x1730
 ? print_bpf_insn+0x3d5/0xa50
 do_check_common+0x33ac/0x33c0
 ...

The root cause is in regs_refine_cond_op() where BPF_JLT/BPF_JSLT operations
adjust both min/max bounds on the same register, causing invalid bounds.

Since comparing a register with itself should not change its bounds (the
comparison result is always known: r0 == r0 is always true, r0 < r0 is
always false), the bounds adjustment is unnecessary.

Fix this by:
1. Enhance is_branch_taken() and is_scalar_branch_taken() to properly
   handle branch direction computation for same register comparisons
   across all BPF jump operations
2. For unknown branch directions (e.g., BPF_JSET), add early return in
   reg_set_min_max() to avoid bounds adjustment on the same register

The fix ensures that unnecessary bounds adjustments are skipped, preventing
the verifier bug while maintaining correct branch direction analysis.

Reported-by: Kaiyan Mei <M202472210@hust.edu.cn>
Reported-by: Yinhao Hu <dddddd@hust.edu.cn>
Closes: https://lore.kernel.org/all/1881f0f5.300df.199f2576a01.Coremail.kaiyanm@hust.edu.cn/
Fixes: 0df1a55afa83 ("bpf: Warn on internal verifier errors")
Signed-off-by: KaFai Wan <kafai.wan@linux.dev>
---
 kernel/bpf/verifier.c | 32 ++++++++++++++++++++++++++++++++
 1 file changed, 32 insertions(+)

diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index 6d175849e57a..653fa96ed0df 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -16037,6 +16037,12 @@ static int is_scalar_branch_taken(struct bpf_reg_state *reg1, struct bpf_reg_sta
 		}
 		break;
 	case BPF_JSET:
+		if (reg1 == reg2) {
+			if (tnum_is_const(t1))
+				return t1.value != 0;
+			else
+				return (smin1 <= 0 && smax1 >= 0) ? -1 : 1;
+		}
 		if (!is_reg_const(reg2, is_jmp32)) {
 			swap(reg1, reg2);
 			swap(t1, t2);
@@ -16172,6 +16178,25 @@ static int is_pkt_ptr_branch_taken(struct bpf_reg_state *dst_reg,
 static int is_branch_taken(struct bpf_reg_state *reg1, struct bpf_reg_state *reg2,
 			   u8 opcode, bool is_jmp32)
 {
+	if (reg1 == reg2) {
+		switch (opcode) {
+		case BPF_JGE:
+		case BPF_JLE:
+		case BPF_JSGE:
+		case BPF_JSLE:
+		case BPF_JEQ:
+			return 1;
+		case BPF_JGT:
+		case BPF_JLT:
+		case BPF_JSGT:
+		case BPF_JSLT:
+		case BPF_JNE:
+			return 0;
+		default:
+			break;
+		}
+	}
+
 	if (reg_is_pkt_pointer_any(reg1) && reg_is_pkt_pointer_any(reg2) && !is_jmp32)
 		return is_pkt_ptr_branch_taken(reg1, reg2, opcode);
 
@@ -16429,6 +16454,13 @@ static int reg_set_min_max(struct bpf_verifier_env *env,
 	if (false_reg1->type != SCALAR_VALUE || false_reg2->type != SCALAR_VALUE)
 		return 0;
 
+	/* We compute branch direction for same registers in is_branch_taken() and
+	 * is_scalar_branch_taken(). For unknown branch directions (e.g., BPF_JSET)
+	 * on the same registers, we don't need to adjusts the min/max values.
+	 */
+	if (false_reg1 == false_reg2)
+		return 0;
+
 	/* fallthrough (FALSE) branch */
 	regs_refine_cond_op(false_reg1, false_reg2, rev_opcode(opcode), is_jmp32);
 	reg_bounds_sync(false_reg1);
-- 
2.43.0


  reply	other threads:[~2025-10-25  5:31 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-10-25  5:30 [PATCH bpf-next v2 0/2] bpf: Skip bounds adjustment for conditional jumps on same register KaFai Wan
2025-10-25  5:30 ` KaFai Wan [this message]
2025-10-27 20:09   ` [PATCH bpf-next v2 1/2] " Eduard Zingerman
2025-10-28 14:01     ` KaFai Wan
2025-10-25  5:30 ` [PATCH bpf-next v2 2/2] selftests/bpf: Add test for BPF_JGT " KaFai Wan
2025-10-27 19:40   ` Eduard Zingerman
2025-10-28 14:04     ` KaFai Wan

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20251025053017.2308823-2-kafai.wan@linux.dev \
    --to=kafai.wan@linux.dev \
    --cc=M202472210@hust.edu.cn \
    --cc=andrii@kernel.org \
    --cc=ast@kernel.org \
    --cc=bpf@vger.kernel.org \
    --cc=colin.i.king@gmail.com \
    --cc=daniel@iogearbox.net \
    --cc=dddddd@hust.edu.cn \
    --cc=eddyz87@gmail.com \
    --cc=haoluo@google.com \
    --cc=harishankar.vishwanathan@gmail.com \
    --cc=john.fastabend@gmail.com \
    --cc=jolsa@kernel.org \
    --cc=kpsingh@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-kselftest@vger.kernel.org \
    --cc=luis.gerhorst@fau.de \
    --cc=m.shachnai@gmail.com \
    --cc=martin.lau@linux.dev \
    --cc=paul.chaignon@gmail.com \
    --cc=sdf@fomichev.me \
    --cc=shuah@kernel.org \
    --cc=song@kernel.org \
    --cc=yonghong.song@linux.dev \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.