patch 'bpf/validate: fix BPF_OR min calculations' has been queued to stable release 24.11.7
luca.boccassi at gmail.com
luca.boccassi at gmail.com
Mon Jul 6 12:21:10 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/31d70fb2c3d7eb5898784e89006f7239500893d9
Thanks.
Luca Boccassi
---
>From 31d70fb2c3d7eb5898784e89006f7239500893d9 Mon Sep 17 00:00:00 2001
From: Marat Khalili <marat.khalili at huawei.com>
Date: Wed, 24 Jun 2026 13:17:53 +0100
Subject: [PATCH] bpf/validate: fix BPF_OR min calculations
[ upstream commit 9b4781582e5cbbc13be095219a14ca91d00f2330 ]
This commit fixes two different problems in signed and unsigned minimum
calculations within `eval_or`. Passing tests requires both problems to
be fixed which is why the changes are squashed in one commit.
1) Function `eval_or` calculated result signed minimum as bitwise OR
between corresponding minimums as long as any of them is non-negative,
which is incorrect since values within the range can have zeroes where
the minimums don't, including the sign bit.
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, #0x5, L8
3: jgt r2, #0x6, L8
4: jslt r2, #0x5, L8
5: jsgt r2, #0x6, L8
6: or r2, #0xfffffffe ; tested instruction
7: mov r0, #0x1
8: exit
Pre-state:
r2: 5..6
Post-state:
r2: -1
After the tested instruction validator considers r2 to always equal -1,
however if 6 was loaded on step 1 it is possible for it to be -2:
0x6 & 0xfffffffffffffffe == 0xfffffffffffffffe = -2
Set signed range to full if any of the operands can be negative,
otherwise use the maximum of both minimums as a new signed minimum
following the idea that result of bitwise OR cannot be smaller than its
operands. Add test.
2) Function `eval_or` calculated result unsigned minimum as bitwise OR
between corresponding minimums, which is incorrect since values within
the range can have zeroes the minimums don't.
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, #0x5, L8
3: jgt r2, #0x6, L8
4: jslt r2, #0x5, L8
5: jsgt r2, #0x6, L8
6: or r2, #0x2 ; tested instruction
7: mov r0, #0x1
8: exit
Pre-state:
r2: 5..6
Post-state:
r2: 7
After the tested instruction validator considers r2 to always equal 7,
however if 6 was loaded on step 1 it is possible for it to be 6:
0x6 & 0x2 == 0x6
Use the maximum of both minimums as a new unsigned minimum following the
idea that result of bitwise OR cannot be smaller than its operands. Add
test.
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 | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/lib/bpf/bpf_validate.c b/lib/bpf/bpf_validate.c
index 9206122812..63f710cf28 100644
--- a/lib/bpf/bpf_validate.c
+++ b/lib/bpf/bpf_validate.c
@@ -455,7 +455,7 @@ eval_or(struct bpf_reg_val *rd, const struct bpf_reg_val *rs, size_t opsz,
rd->u.max |= rs->u.max;
} else {
rd->u.max = eval_uor_max(rd->u.max, rs->u.max, opsz);
- rd->u.min |= rs->u.min;
+ rd->u.min = RTE_MAX(rd->u.min, rs->u.min);
}
/* both operands are constants */
@@ -464,9 +464,9 @@ eval_or(struct bpf_reg_val *rd, const struct bpf_reg_val *rs, size_t opsz,
rd->s.max |= rs->s.max;
/* both operands are non-negative */
- } else if (rd->s.min >= 0 || rs->s.min >= 0) {
+ } else if (rd->s.min >= 0 && rs->s.min >= 0) {
rd->s.max = eval_uor_max(rd->s.max, rs->s.max, opsz);
- rd->s.min |= rs->s.min;
+ rd->s.min = RTE_MAX(rd->s.min, rs->s.min);
} else
eval_smax_bound(rd, msk);
}
--
2.47.3
---
Diff of the applied patch vs upstream commit (please double-check if non-empty:
---
--- - 2026-07-03 12:55:49.636419290 +0100
+++ 0078-bpf-validate-fix-BPF_OR-min-calculations.patch 2026-07-03 12:55:46.730575555 +0100
@@ -1 +1 @@
-From 9b4781582e5cbbc13be095219a14ca91d00f2330 Mon Sep 17 00:00:00 2001
+From 31d70fb2c3d7eb5898784e89006f7239500893d9 Mon Sep 17 00:00:00 2001
@@ -5,0 +6,2 @@
+[ upstream commit 9b4781582e5cbbc13be095219a14ca91d00f2330 ]
+
@@ -73 +74,0 @@
-Cc: stable at dpdk.org
@@ -79,49 +80,3 @@
- app/test/test_bpf_validate.c | 34 ++++++++++++++++++++++++++++++++++
- lib/bpf/bpf_validate.c | 6 +++---
- 2 files changed, 37 insertions(+), 3 deletions(-)
-
-diff --git a/app/test/test_bpf_validate.c b/app/test/test_bpf_validate.c
-index 55a2f383bd..dfcf49ccb9 100644
---- a/app/test/test_bpf_validate.c
-+++ b/app/test/test_bpf_validate.c
-@@ -1713,6 +1713,40 @@ test_alu64_neg_zero_last(void)
- REGISTER_FAST_TEST(bpf_validate_alu64_neg_zero_last_autotest, NOHUGE_OK, ASAN_OK,
- test_alu64_neg_zero_last);
-
-+/* 64-bit bitwise OR between a positive scalar range and negative immediate. */
-+static int
-+test_alu64_or_k_negative(void)
-+{
-+ return verify_instruction((struct verify_instruction_param){
-+ .tested_instruction = {
-+ .code = (EBPF_ALU64 | BPF_OR | BPF_K),
-+ .imm = -2,
-+ },
-+ .pre.dst = make_signed_domain(5, 6),
-+ .post.dst = make_signed_domain(-2, -1),
-+ });
-+}
-+
-+REGISTER_FAST_TEST(bpf_validate_alu64_or_k_negative_autotest, NOHUGE_OK, ASAN_OK,
-+ test_alu64_or_k_negative);
-+
-+/* 64-bit bitwise OR between a positive scalar range and positive immediate. */
-+static int
-+test_alu64_or_k_positive(void)
-+{
-+ return verify_instruction((struct verify_instruction_param){
-+ .tested_instruction = {
-+ .code = (EBPF_ALU64 | BPF_OR | BPF_K),
-+ .imm = 2,
-+ },
-+ .pre.dst = make_signed_domain(5, 6),
-+ .post.dst = make_signed_domain(5, 7),
-+ });
-+}
-+
-+REGISTER_FAST_TEST(bpf_validate_alu64_or_k_positive_autotest, NOHUGE_OK, ASAN_OK,
-+ test_alu64_or_k_positive);
-+
- /* Jump if greater than immediate. */
- static int
- test_jmp64_jeq_k(void)
+ lib/bpf/bpf_validate.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
@@ -129 +84 @@
-index 4e4c0ddeb2..abb39cfd32 100644
+index 9206122812..63f710cf28 100644
@@ -132 +87 @@
-@@ -875,7 +875,7 @@ eval_or(struct bpf_reg_val *rd, const struct bpf_reg_val *rs, size_t opsz,
+@@ -455,7 +455,7 @@ eval_or(struct bpf_reg_val *rd, const struct bpf_reg_val *rs, size_t opsz,
@@ -141 +96 @@
-@@ -884,9 +884,9 @@ eval_or(struct bpf_reg_val *rd, const struct bpf_reg_val *rs, size_t opsz,
+@@ -464,9 +464,9 @@ eval_or(struct bpf_reg_val *rd, const struct bpf_reg_val *rs, size_t opsz,
More information about the stable
mailing list