[v9,03/12] bpf: allow self-xor operation

Message ID 20210916001416.39998-4-stephen@networkplumber.org (mailing list archive)
State Superseded, archived
Delegated to: Thomas Monjalon
Headers
Series Packet capture framework enhancements |

Checks

Context Check Description
ci/checkpatch success coding style OK

Commit Message

Stephen Hemminger Sept. 16, 2021, 12:14 a.m. UTC
  Some BPF programs may use XOR of a register with itself
as a way to zero register in one instruction.
The BPF filter converter generates this in the prolog
to the generated code.

The BPF validator would not allow this because the value of
register was undefined. But after this operation it always zero.

Fixes: 8021917293d0 ("bpf: add extra validation for input BPF program")
Cc: konstantin.ananyev@intel.com
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
 lib/bpf/bpf_validate.c | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)
  

Comments

Ananyev, Konstantin Sept. 16, 2021, 3:23 p.m. UTC | #1
> Some BPF programs may use XOR of a register with itself
> as a way to zero register in one instruction.
> The BPF filter converter generates this in the prolog
> to the generated code.
> 
> The BPF validator would not allow this because the value of
> register was undefined. But after this operation it always zero.
> 
> Fixes: 8021917293d0 ("bpf: add extra validation for input BPF program")
> Cc: konstantin.ananyev@intel.com
> Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
> ---
>  lib/bpf/bpf_validate.c | 9 ++++++++-
>  1 file changed, 8 insertions(+), 1 deletion(-)
> 
> diff --git a/lib/bpf/bpf_validate.c b/lib/bpf/bpf_validate.c
> index 7b1291b382e9..853279fee557 100644
> --- a/lib/bpf/bpf_validate.c
> +++ b/lib/bpf/bpf_validate.c
> @@ -661,8 +661,15 @@ eval_alu(struct bpf_verifier *bvf, const struct ebpf_insn *ins)
> 
>  	op = BPF_OP(ins->code);
> 
> +	/* Allow self-xor as way to zero register */
> +	if (op == BPF_XOR && BPF_SRC(ins->code) == BPF_X &&
> +	    ins->src_reg == ins->dst_reg) {
> +		eval_fill_imm(&rs, UINT64_MAX, 0);
> +		eval_fill_imm(rd, UINT64_MAX, 0);
> +	}
> +
>  	err = eval_defined((op != EBPF_MOV) ? rd : NULL,
> -			(op != BPF_NEG) ? &rs : NULL);
> +			   (op != BPF_NEG) ? &rs : NULL);
>  	if (err != NULL)
>  		return err;
> 
> --

Acked-by: Konstantin Ananyev <konstantin.ananyev@intel.com>

> 2.30.2
  

Patch

diff --git a/lib/bpf/bpf_validate.c b/lib/bpf/bpf_validate.c
index 7b1291b382e9..853279fee557 100644
--- a/lib/bpf/bpf_validate.c
+++ b/lib/bpf/bpf_validate.c
@@ -661,8 +661,15 @@  eval_alu(struct bpf_verifier *bvf, const struct ebpf_insn *ins)
 
 	op = BPF_OP(ins->code);
 
+	/* Allow self-xor as way to zero register */
+	if (op == BPF_XOR && BPF_SRC(ins->code) == BPF_X &&
+	    ins->src_reg == ins->dst_reg) {
+		eval_fill_imm(&rs, UINT64_MAX, 0);
+		eval_fill_imm(rd, UINT64_MAX, 0);
+	}
+
 	err = eval_defined((op != EBPF_MOV) ? rd : NULL,
-			(op != BPF_NEG) ? &rs : NULL);
+			   (op != BPF_NEG) ? &rs : NULL);
 	if (err != NULL)
 		return err;