All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH bpf-next v2 0/2] bpf: Fix tnum_overlap to check for zero mask intersection
@ 2025-10-28 15:19 KaFai Wan
  2025-10-28 15:19 ` [PATCH bpf-next v2 1/2] " KaFai Wan
  2025-10-28 15:19 ` [PATCH bpf-next v2 2/2] selftests/bpf: Range analysis test case for JEQ KaFai Wan
  0 siblings, 2 replies; 5+ messages in thread
From: KaFai Wan @ 2025-10-28 15:19 UTC (permalink / raw)
  To: ast, daniel, john.fastabend, andrii, martin.lau, eddyz87, song,
	yonghong.song, kpsingh, sdf, haoluo, jolsa, shuah, paul.chaignon,
	m.shachnai, kafai.wan, harishankar.vishwanathan, colin.i.king,
	luis.gerhorst, shung-hsi.yu, bpf, linux-kernel, linux-kselftest

This small patchset is about avoid verifier bug warning when tnum_overlap()
is called with zero mask intersection.

v2:
 - fix runtime error

v1:
 https://lore.kernel.org/all/20251026163806.3300636-1-kafai.wan@linux.dev/
---
KaFai Wan (2):
  bpf: Fix tnum_overlap to check for zero mask intersection
  selftests/bpf: Range analysis test case for JEQ

 kernel/bpf/tnum.c                             |  2 ++
 .../selftests/bpf/progs/verifier_bounds.c     | 23 +++++++++++++++++++
 2 files changed, 25 insertions(+)

-- 
2.43.0


^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH bpf-next v2 1/2] bpf: Fix tnum_overlap to check for zero mask intersection
  2025-10-28 15:19 [PATCH bpf-next v2 0/2] bpf: Fix tnum_overlap to check for zero mask intersection KaFai Wan
@ 2025-10-28 15:19 ` KaFai Wan
  2025-10-28 15:45   ` bot+bpf-ci
  2025-10-28 15:19 ` [PATCH bpf-next v2 2/2] selftests/bpf: Range analysis test case for JEQ KaFai Wan
  1 sibling, 1 reply; 5+ messages in thread
From: KaFai Wan @ 2025-10-28 15:19 UTC (permalink / raw)
  To: ast, daniel, john.fastabend, andrii, martin.lau, eddyz87, song,
	yonghong.song, kpsingh, sdf, haoluo, jolsa, shuah, paul.chaignon,
	m.shachnai, kafai.wan, harishankar.vishwanathan, colin.i.king,
	luis.gerhorst, shung-hsi.yu, bpf, linux-kernel, linux-kselftest
  Cc: syzbot+c950cc277150935cc0b5

Syzbot reported a kernel warning due to a range invariant violation in
the BPF verifier. The issue occurs when tnum_overlap() fails to detect
that two tnums don't have any overlapping bits.

The problematic BPF program:
   0: call bpf_get_prandom_u32
   1: r6 = r0
   2: r6 &= 0xFFFFFFFFFFFFFFF0
   3: r7 = r0
   4: r7 &= 0x07
   5: r7 -= 0xFF
   6: if r6 == r7 goto <exit>

After instruction 5, R7 has the range:
   R7: u64=[0xffffffffffffff01, 0xffffffffffffff08] var_off=(0xffffffffffffff00; 0xf)

R6 and R7 don't overlap since they have no agreeing bits. However,
is_branch_taken() fails to recognize this, causing the verifier to
refine register bounds and trigger range bounds violation:

   6: if r6 == r7 goto <exit>
   true_reg1: u64=[0xffffffffffffff01, 0xffffffffffffff00] var_off=(0xffffffffffffff00, 0x0)
   true_reg2: u64=[0xffffffffffffff01, 0xffffffffffffff00] var_off=(0xffffffffffffff00, 0x0)

The root cause is that tnum_overlap() doesn't properly handle the case
where the masks have no overlapping bits.

Fix this by adding an early check for zero mask intersection in tnum_overlap().

Reported-by: syzbot+c950cc277150935cc0b5@syzkaller.appspotmail.com
Fixes: f41345f47fb2 ("bpf: Use tnums for JEQ/JNE is_branch_taken logic")
Signed-off-by: KaFai Wan <kafai.wan@linux.dev>
---
 kernel/bpf/tnum.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/kernel/bpf/tnum.c b/kernel/bpf/tnum.c
index f8e70e9c3998..1a75b7c9a73a 100644
--- a/kernel/bpf/tnum.c
+++ b/kernel/bpf/tnum.c
@@ -163,6 +163,8 @@ bool tnum_overlap(struct tnum a, struct tnum b)
 {
 	u64 mu;
 
+	if (a.mask && b.mask && !(a.mask & b.mask))
+		return false;
 	mu = ~a.mask & ~b.mask;
 	return (a.value & mu) == (b.value & mu);
 }
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH bpf-next v2 2/2] selftests/bpf: Range analysis test case for JEQ
  2025-10-28 15:19 [PATCH bpf-next v2 0/2] bpf: Fix tnum_overlap to check for zero mask intersection KaFai Wan
  2025-10-28 15:19 ` [PATCH bpf-next v2 1/2] " KaFai Wan
@ 2025-10-28 15:19 ` KaFai Wan
  1 sibling, 0 replies; 5+ messages in thread
From: KaFai Wan @ 2025-10-28 15:19 UTC (permalink / raw)
  To: ast, daniel, john.fastabend, andrii, martin.lau, eddyz87, song,
	yonghong.song, kpsingh, sdf, haoluo, jolsa, shuah, paul.chaignon,
	m.shachnai, kafai.wan, harishankar.vishwanathan, colin.i.king,
	luis.gerhorst, shung-hsi.yu, bpf, linux-kernel, linux-kselftest

This patch adds coverage for the warning detected by syzkaller and fixed
in the previous patch. Without the previous patch, this test fails with:

  verifier bug: REG INVARIANTS VIOLATION (true_reg1): range bounds
  violation u64=[0xffffffffffffff01, 0xffffffffffffff00]
  s64=[0xffffffffffffff01, 0xffffffffffffff00]
  u32=[0xffffff01, 0xffffff00] s32=[0xffffff00, 0xffffff00]
  var_off=(0xffffffffffffff00, 0x0)
  verifier bug: REG INVARIANTS VIOLATION (true_reg2): range bounds
  violation u64=[0xffffffffffffff01, 0xffffffffffffff00]
  s64=[0xffffffffffffff01, 0xffffffffffffff00]
  u32=[0xffffff01, 0xffffff00] s32=[0xffffff01, 0xffffff00]
  var_off=(0xffffffffffffff00, 0x0)

Signed-off-by: KaFai Wan <kafai.wan@linux.dev>
---
 .../selftests/bpf/progs/verifier_bounds.c     | 23 +++++++++++++++++++
 1 file changed, 23 insertions(+)

diff --git a/tools/testing/selftests/bpf/progs/verifier_bounds.c b/tools/testing/selftests/bpf/progs/verifier_bounds.c
index 0a72e0228ea9..304ab5a07a3b 100644
--- a/tools/testing/selftests/bpf/progs/verifier_bounds.c
+++ b/tools/testing/selftests/bpf/progs/verifier_bounds.c
@@ -1550,6 +1550,29 @@ l0_%=:	r0 = 0;				\
 	: __clobber_all);
 }
 
+SEC("socket")
+__description("dead branch on jeq, does not result in invariants violation error")
+__success __log_level(2)
+__retval(0) __flag(BPF_F_TEST_REG_INVARIANTS)
+__naked void jeq_range_analysis(void)
+{
+	asm volatile ("			\
+	call %[bpf_get_prandom_u32];	\
+	r6 = r0;			\
+	r6 &= 0xFFFFFFFFFFFFFFF0;	\
+	r7 = r0;			\
+	r7 &= 0x07;			\
+	r7 -= 0xFF;			\
+	if r6 == r7 goto l1_%=;		\
+l0_%=:  r0 = 0;				\
+	exit;				\
+l1_%=:  r0 = 1;				\
+	exit;				\
+"	:
+	: __imm(bpf_get_prandom_u32)
+	: __clobber_all);
+}
+
 /* This test covers the bounds deduction on 64bits when the s64 and u64 ranges
  * overlap on the negative side. At instruction 7, the ranges look as follows:
  *
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH bpf-next v2 1/2] bpf: Fix tnum_overlap to check for zero mask intersection
  2025-10-28 15:19 ` [PATCH bpf-next v2 1/2] " KaFai Wan
@ 2025-10-28 15:45   ` bot+bpf-ci
  2025-10-28 17:18     ` Eduard Zingerman
  0 siblings, 1 reply; 5+ messages in thread
From: bot+bpf-ci @ 2025-10-28 15:45 UTC (permalink / raw)
  To: kafai.wan, ast, daniel, john.fastabend, andrii, martin.lau,
	eddyz87, song, yonghong.song, kpsingh, sdf, haoluo, jolsa, shuah,
	paul.chaignon, m.shachnai, kafai.wan, harishankar.vishwanathan,
	colin.i.king, luis.gerhorst, shung-hsi.yu, bpf, linux-kernel,
	linux-kselftest
  Cc: syzbot+c950cc277150935cc0b5, ast, andrii, daniel, martin.lau,
	eddyz87, yonghong.song, clm, ihor.solodrai

[-- Attachment #1: Type: text/plain, Size: 1887 bytes --]


```
commit 16cbc4520eb13d2065d145c76b97fb93035d81e8
Author: KaFai Wan <kafai.wan@linux.dev>

bpf: Fix tnum_overlap to check for zero mask intersection

This patch adds an early return check in tnum_overlap() to detect
non-overlapping tnums when their masks have no overlapping bits. The
fix addresses a syzbot report where the verifier failed to recognize
that two tnums couldn't represent the same value.

Reported-by: syzbot+c950cc277150935cc0b5@syzkaller.appspotmail.com

> diff --git a/kernel/bpf/tnum.c b/kernel/bpf/tnum.c
> index f8e70e9c3..1a75b7c9a 100644
> --- a/kernel/bpf/tnum.c
> +++ b/kernel/bpf/tnum.c
> @@ -163,6 +163,8 @@ bool tnum_overlap(struct tnum a, struct tnum b)
>  {
>  	u64 mu;
>
> +	if (a.mask && b.mask && !(a.mask & b.mask))
> +		return false;
                              ^^^^^

Does this logic correctly detect non-overlapping tnums? Consider this
counter-example:

  a = (value=0x5, mask=0xA)  // binary: value=0101, mask=1010
  b = (value=0xA, mask=0x5)  // binary: value=1010, mask=0101

The masks are disjoint: (0xA & 0x5) == 0, so the new check returns
false (no overlap).

However, these tnums actually represent overlapping sets:
  a represents: {5, 7, 13, 15}  // 0b0101, 0b0111, 0b1101, 0b1111
  b represents: {10, 11, 14, 15} // 0b1010, 0b1011, 0b1110, 0b1111

Both sets contain 15, so they do overlap. Can this cause incorrect
verifier behavior when is_branch_taken() calls tnum_overlap() to
determine if JEQ/JNE branches are reachable?

>  	mu = ~a.mask & ~b.mask;
>  	return (a.value & mu) == (b.value & mu);
>  }


```

---
AI reviewed your patch. Please fix the bug or email reply why it's not a bug.
See: https://github.com/kernel-patches/vmtest/blob/master/ci/claude/README.md

In-Reply-To-Subject: `bpf: Fix tnum_overlap to check for zero mask intersection`
CI run summary: https://github.com/kernel-patches/bpf/actions/runs/18880108453

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH bpf-next v2 1/2] bpf: Fix tnum_overlap to check for zero mask intersection
  2025-10-28 15:45   ` bot+bpf-ci
@ 2025-10-28 17:18     ` Eduard Zingerman
  0 siblings, 0 replies; 5+ messages in thread
From: Eduard Zingerman @ 2025-10-28 17:18 UTC (permalink / raw)
  To: bot+bpf-ci, kafai.wan, ast, daniel, john.fastabend, andrii,
	martin.lau, song, yonghong.song, kpsingh, sdf, haoluo, jolsa,
	shuah, paul.chaignon, m.shachnai, harishankar.vishwanathan,
	colin.i.king, luis.gerhorst, shung-hsi.yu, bpf, linux-kernel,
	linux-kselftest
  Cc: syzbot+c950cc277150935cc0b5, martin.lau, clm, ihor.solodrai

On Tue, 2025-10-28 at 15:45 +0000, bot+bpf-ci@kernel.org wrote:
> ```
> commit 16cbc4520eb13d2065d145c76b97fb93035d81e8
> Author: KaFai Wan <kafai.wan@linux.dev>
> 
> bpf: Fix tnum_overlap to check for zero mask intersection
> 
> This patch adds an early return check in tnum_overlap() to detect
> non-overlapping tnums when their masks have no overlapping bits. The
> fix addresses a syzbot report where the verifier failed to recognize
> that two tnums couldn't represent the same value.
> 
> Reported-by: syzbot+c950cc277150935cc0b5@syzkaller.appspotmail.com
> 
> > diff --git a/kernel/bpf/tnum.c b/kernel/bpf/tnum.c
> > index f8e70e9c3..1a75b7c9a 100644
> > --- a/kernel/bpf/tnum.c
> > +++ b/kernel/bpf/tnum.c
> > @@ -163,6 +163,8 @@ bool tnum_overlap(struct tnum a, struct tnum b)
> >  {
> >  	u64 mu;
> > 
> > +	if (a.mask && b.mask && !(a.mask & b.mask))
> > +		return false;
>                               ^^^^^
> 
> Does this logic correctly detect non-overlapping tnums? Consider this
> counter-example:
> 
>   a = (value=0x5, mask=0xA)  // binary: value=0101, mask=1010
>   b = (value=0xA, mask=0x5)  // binary: value=1010, mask=0101
> 
> The masks are disjoint: (0xA & 0x5) == 0, so the new check returns
> false (no overlap).
> 
> However, these tnums actually represent overlapping sets:
>   a represents: {5, 7, 13, 15}  // 0b0101, 0b0111, 0b1101, 0b1111
>   b represents: {10, 11, 14, 15} // 0b1010, 0b1011, 0b1110, 0b1111
> 
> Both sets contain 15, so they do overlap. Can this cause incorrect
> verifier behavior when is_branch_taken() calls tnum_overlap() to
> determine if JEQ/JNE branches are reachable?

This is a legit bug, please address.

> >  	mu = ~a.mask & ~b.mask;
> >  	return (a.value & mu) == (b.value & mu);
> >  }
> 
> 
> ```
> 
> ---
> AI reviewed your patch. Please fix the bug or email reply why it's not a bug.
> See: https://github.com/kernel-patches/vmtest/blob/master/ci/claude/README.md
> 
> In-Reply-To-Subject: `bpf: Fix tnum_overlap to check for zero mask intersection`
> CI run summary: https://github.com/kernel-patches/bpf/actions/runs/18880108453

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2025-10-28 17:18 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-10-28 15:19 [PATCH bpf-next v2 0/2] bpf: Fix tnum_overlap to check for zero mask intersection KaFai Wan
2025-10-28 15:19 ` [PATCH bpf-next v2 1/2] " KaFai Wan
2025-10-28 15:45   ` bot+bpf-ci
2025-10-28 17:18     ` Eduard Zingerman
2025-10-28 15:19 ` [PATCH bpf-next v2 2/2] selftests/bpf: Range analysis test case for JEQ KaFai Wan

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.