[PATCH 06/25] bpf/validate: fix BPF_ADD of pointer to a scalar

Marat Khalili marat.khalili at huawei.com
Wed May 6 19:38:24 CEST 2026


Function `eval_add` preserved type of the destination register even when
a pointer was added to it. If it contained scalar, it remained a scalar,
and if it contained pointer, it remained a pointer.

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

    Tested program:
        0:  mov r0, #0x0
        1:  mov r3, #0x0
        2:  add r3, r1  ; tested instruction
        3:  ldxdw r2, [r3 + 16]
        4:  mov r0, #0x1
        5:  exit

After the tested instruction validator considers r3 to be scalar and
fails validation with the error:

    BPF: evaluate(): destination is not a pointer at pc: 3

However, this code is valid as long as program argument points to a
valid memory area at least 24 bytes long which we read at offset 16.

When adding pointer to a scalar set type of the result to pointer of
the same type. When adding pointer to a pointer set type of the result
to scalar and value to unknown.

The test will be added in subsequent commits since it depends on other
fixes.

Fixes: 8021917293d0 ("bpf: add extra validation for input BPF program")
Cc: stable at dpdk.org

Signed-off-by: Marat Khalili <marat.khalili at huawei.com>
---
 lib/bpf/bpf_validate.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/lib/bpf/bpf_validate.c b/lib/bpf/bpf_validate.c
index 8dac908c394f..41dca2fb7673 100644
--- a/lib/bpf/bpf_validate.c
+++ b/lib/bpf/bpf_validate.c
@@ -647,8 +647,20 @@ eval_apply_mask(struct bpf_reg_val *rv, uint64_t mask)
 static void
 eval_add(struct bpf_reg_val *rd, const struct bpf_reg_val *rs, uint64_t msk)
 {
+	struct bpf_reg_val rs_buf;
 	struct bpf_reg_val rv;
 
+	if (RTE_BPF_ARG_PTR_TYPE(rs->v.type) != 0) {
+		if (RTE_BPF_ARG_PTR_TYPE(rd->v.type) != 0) {
+			/* treat sum of pointers as sum of two unknown scalars */
+			eval_fill_max_bound(&rs_buf, msk);
+			*rd = rs_buf;
+			rs = &rs_buf;
+		} else
+			/* scalar + pointer is a pointer of the same type */
+			rd->v = rs->v;
+	}
+
 	rv.u.min = (rd->u.min + rs->u.min) & msk;
 	rv.u.max = (rd->u.max + rs->u.max) & msk;
 	rv.s.min = ((uint64_t)rd->s.min + (uint64_t)rs->s.min) & msk;
-- 
2.43.0



More information about the dev mailing list