patch 'bpf/validate: fix BPF_JGT/EBPF_JSGT no-jump max' has been queued to stable release 24.11.7

luca.boccassi at gmail.com luca.boccassi at gmail.com
Mon Jul 6 12:21:06 CEST 2026


Hi,

FYI, your patch has been queued to stable release 24.11.7

Note it hasn't been pushed to http://dpdk.org/browse/dpdk-stable yet.
It will be pushed if I get no objections before 07/05/26. So please
shout if anyone has objections.

Also note that after the patch there's a diff of the upstream commit vs the
patch applied to the branch. This will indicate if there was any rebasing
needed to apply to the stable branch. If there were code changes for rebasing
(ie: not only metadata diffs), please double check that the rebase was
correctly done.

Queued patches are on a temporary branch at:
https://github.com/bluca/dpdk-stable

This queued commit can be viewed at:
https://github.com/bluca/dpdk-stable/commit/c871bb442cc6ea7f4ebfeed32e856e77577f9ada

Thanks.

Luca Boccassi

---
>From c871bb442cc6ea7f4ebfeed32e856e77577f9ada Mon Sep 17 00:00:00 2001
From: Marat Khalili <marat.khalili at huawei.com>
Date: Wed, 24 Jun 2026 13:17:48 +0100
Subject: [PATCH] bpf/validate: fix BPF_JGT/EBPF_JSGT no-jump max

[ upstream commit 199179c89bfa6dd4bd5e024044ce3fe843667b4d ]

Functions `eval_jgt_jle` and `eval_jsgt_jsle` reduced range maximum for
BPF_JGT and EBPF_JSGT instructions in the no-jump case to the minimum of
src register instead of the maximum, producing more conservative
estimate that could cause false positives.

E.g. consider the following program with the current validation code:

    Tested program:
        0:  mov r0, #0x0
        1:  ldxdw r2, [r1 + 0]
        2:  jlt r2, #0x14, L15
        3:  jgt r2, #0x3c, L15
        4:  jslt r2, #0x14, L15
        5:  jsgt r2, #0x3c, L15
        6:  ldxdw r3, [r1 + 8]
        7:  jlt r3, #0x1e, L15
        8:  jgt r3, #0x32, L15
        9:  jslt r3, #0x1e, L15
       10:  jsgt r3, #0x32, L15
       11:  jgt r2, r3, L14  ; tested instruction
       12:  mov r0, #0x1
       13:  exit
       14:  mov r0, #0x2
       15:  exit
    Pre-state:
       r2:  20..60
       r3:  30..50
    Post-state:
       r2:  20..60 INTERSECT 0x14..0x1e (!)

Immediately after the tested instruction on step 12 validator expects r2
to contain values up to 60, for example 55, however for this value jump
condition r2 > r3 on step 11 would be always satisfied since r3 is known
to not exceed 50, and thus execution will always jump to step 14 instead
of continuing to step 12.

Fix range calculation, add tests for cases where range of src register
values is a strict subset of dst. Other cases will be covered in the
subsequent commits.

Fixes: 8021917293d0 ("bpf: add extra validation for input BPF program")

Reported-by: Claudia Cauli <claudiacauli at gmail.com>
Signed-off-by: Marat Khalili <marat.khalili at huawei.com>
Acked-by: Konstantin Ananyev <konstantin.ananyev at huawei.com>
---
 lib/bpf/bpf_validate.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/lib/bpf/bpf_validate.c b/lib/bpf/bpf_validate.c
index 20428393d9..917c1a78ad 100644
--- a/lib/bpf/bpf_validate.c
+++ b/lib/bpf/bpf_validate.c
@@ -1095,7 +1095,7 @@ static void
 eval_jgt_jle(struct bpf_reg_val *trd, struct bpf_reg_val *trs,
 	struct bpf_reg_val *frd, struct bpf_reg_val *frs)
 {
-	frd->u.max = RTE_MIN(frd->u.max, frs->u.min);
+	frd->u.max = RTE_MIN(frd->u.max, frs->u.max);
 	trd->u.min = RTE_MAX(trd->u.min, trs->u.min + 1);
 }
 
@@ -1111,7 +1111,7 @@ static void
 eval_jsgt_jsle(struct bpf_reg_val *trd, struct bpf_reg_val *trs,
 	struct bpf_reg_val *frd, struct bpf_reg_val *frs)
 {
-	frd->s.max = RTE_MIN(frd->s.max, frs->s.min);
+	frd->s.max = RTE_MIN(frd->s.max, frs->s.max);
 	trd->s.min = RTE_MAX(trd->s.min, trs->s.min + 1);
 }
 
-- 
2.47.3

---
  Diff of the applied patch vs upstream commit (please double-check if non-empty:
---
--- -	2026-07-03 12:55:49.487372739 +0100
+++ 0074-bpf-validate-fix-BPF_JGT-EBPF_JSGT-no-jump-max.patch	2026-07-03 12:55:46.726575450 +0100
@@ -1 +1 @@
-From 199179c89bfa6dd4bd5e024044ce3fe843667b4d Mon Sep 17 00:00:00 2001
+From c871bb442cc6ea7f4ebfeed32e856e77577f9ada Mon Sep 17 00:00:00 2001
@@ -5,0 +6,2 @@
+[ upstream commit 199179c89bfa6dd4bd5e024044ce3fe843667b4d ]
+
@@ -47 +48,0 @@
-Cc: stable at dpdk.org
@@ -53,105 +54,3 @@
- app/test/test_bpf_validate.c | 90 ++++++++++++++++++++++++++++++++++++
- lib/bpf/bpf_validate.c       |  4 +-
- 2 files changed, 92 insertions(+), 2 deletions(-)
-
-diff --git a/app/test/test_bpf_validate.c b/app/test/test_bpf_validate.c
-index ae28e85a29..1dc45602f3 100644
---- a/app/test/test_bpf_validate.c
-+++ b/app/test/test_bpf_validate.c
-@@ -1485,6 +1485,96 @@ test_jmp64_jslt_x(void)
- REGISTER_FAST_TEST(bpf_validate_jmp64_jslt_x_autotest, NOHUGE_OK, ASAN_OK,
- 	test_jmp64_jslt_x);
- 
-+/* Jump on ordering relationship with narrower range. */
-+static int
-+test_jmp64_jxx_x_ordering_narrower(void)
-+{
-+	TEST_ASSERT_SUCCESS(verify_instruction((struct verify_instruction_param){
-+		.tested_instruction = {
-+			.code = (BPF_JMP | BPF_JGT | BPF_X),
-+		},
-+		.pre.dst = make_signed_domain(20, 60),
-+		.pre.src = make_signed_domain(30, 50),
-+		.post.dst = make_signed_domain(20, 50),
-+		.jump.dst = make_signed_domain(31, 60),
-+	}), "(BPF_JMP | BPF_JGT | BPF_X) check");
-+
-+	TEST_ASSERT_SUCCESS(verify_instruction((struct verify_instruction_param){
-+		.tested_instruction = {
-+			.code = (BPF_JMP | BPF_JGE | BPF_X),
-+		},
-+		.pre.dst = make_signed_domain(20, 60),
-+		.pre.src = make_signed_domain(30, 50),
-+		.post.dst = make_signed_domain(20, 49),
-+		.jump.dst = make_signed_domain(30, 60),
-+	}), "(BPF_JMP | BPF_JGE | BPF_X) check");
-+
-+	TEST_ASSERT_SUCCESS(verify_instruction((struct verify_instruction_param){
-+		.tested_instruction = {
-+			.code = (BPF_JMP | EBPF_JLT | BPF_X),
-+		},
-+		.pre.dst = make_signed_domain(20, 60),
-+		.pre.src = make_signed_domain(30, 50),
-+		.post.dst = make_signed_domain(30, 60),
-+		.jump.dst = make_signed_domain(20, 49),
-+	}), "(BPF_JMP | EBPF_JLT | BPF_X) check");
-+
-+	TEST_ASSERT_SUCCESS(verify_instruction((struct verify_instruction_param){
-+		.tested_instruction = {
-+			.code = (BPF_JMP | EBPF_JLE | BPF_X),
-+		},
-+		.pre.dst = make_signed_domain(20, 60),
-+		.pre.src = make_signed_domain(30, 50),
-+		.post.dst = make_signed_domain(31, 60),
-+		.jump.dst = make_signed_domain(20, 50),
-+	}), "(BPF_JMP | EBPF_JLE | BPF_X) check");
-+
-+	TEST_ASSERT_SUCCESS(verify_instruction((struct verify_instruction_param){
-+		.tested_instruction = {
-+			.code = (BPF_JMP | EBPF_JSGT | BPF_X),
-+		},
-+		.pre.dst = make_signed_domain(20, 60),
-+		.pre.src = make_signed_domain(30, 50),
-+		.post.dst = make_signed_domain(20, 50),
-+		.jump.dst = make_signed_domain(31, 60),
-+	}), "(BPF_JMP | EBPF_JSGT | BPF_X) check");
-+
-+	TEST_ASSERT_SUCCESS(verify_instruction((struct verify_instruction_param){
-+		.tested_instruction = {
-+			.code = (BPF_JMP | EBPF_JSGE | BPF_X),
-+		},
-+		.pre.dst = make_signed_domain(20, 60),
-+		.pre.src = make_signed_domain(30, 50),
-+		.post.dst = make_signed_domain(20, 49),
-+		.jump.dst = make_signed_domain(30, 60),
-+	}), "(BPF_JMP | EBPF_JSGE | BPF_X) check");
-+
-+	TEST_ASSERT_SUCCESS(verify_instruction((struct verify_instruction_param){
-+		.tested_instruction = {
-+			.code = (BPF_JMP | EBPF_JSLT | BPF_X),
-+		},
-+		.pre.dst = make_signed_domain(20, 60),
-+		.pre.src = make_signed_domain(30, 50),
-+		.post.dst = make_signed_domain(30, 60),
-+		.jump.dst = make_signed_domain(20, 49),
-+	}), "(BPF_JMP | EBPF_JSLT | BPF_X) check");
-+
-+	TEST_ASSERT_SUCCESS(verify_instruction((struct verify_instruction_param){
-+		.tested_instruction = {
-+			.code = (BPF_JMP | EBPF_JSLE | BPF_X),
-+		},
-+		.pre.dst = make_signed_domain(20, 60),
-+		.pre.src = make_signed_domain(30, 50),
-+		.post.dst = make_signed_domain(31, 60),
-+		.jump.dst = make_signed_domain(20, 50),
-+	}), "(BPF_JMP | EBPF_JSLE | BPF_X) check");
-+
-+	return TEST_SUCCESS;
-+}
-+
-+REGISTER_FAST_TEST(bpf_validate_jmp64_jxx_x_ordering_narrower_autotest, NOHUGE_OK, ASAN_OK,
-+	test_jmp64_jxx_x_ordering_narrower);
-+
- /* 64-bit load from heap (should be set to unknown). */
- static int
- test_mem_ldx_dw_heap(void)
+ lib/bpf/bpf_validate.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
@@ -159 +58 @@
-index 2b73e36288..0578029dcc 100644
+index 20428393d9..917c1a78ad 100644
@@ -162 +61 @@
-@@ -1521,7 +1521,7 @@ static void
+@@ -1095,7 +1095,7 @@ static void
@@ -171 +70 @@
-@@ -1537,7 +1537,7 @@ static void
+@@ -1111,7 +1111,7 @@ static void


More information about the stable mailing list