[PATCH bpf-next v2 6/8] bpf: Refactor ALU instruction variant validation
tangyazhou at zju.edu.cn
tangyazhou at zju.edu.cn
Wed Oct 21 01:23:58 PDT 2026
From: Yazhou Tang <tangyazhou518 at outlook.com>
check_alu_fields() currently validates insn->off together with the
source-specific reserved fields. This duplicates the DIV and MOD
variant rules between register and immediate forms and makes the valid
instruction variants difficult to identify.
Move the opcode-specific insn->off validation into is_valid_alu_variant().
The helper permits off == 1 for DIV and MOD and requires off == 0 for all
other ALU operations. Validate the variant once, then separately check the
reserved immediate field for register sources and src_reg for immediate sources.
This is a pure refactoring and does not change which instruction encodings
the verifier accepts.
Signed-off-by: Yazhou Tang <tangyazhou518 at outlook.com>
Co-developed-by: Tianci Cao <ziye at zju.edu.cn>
Signed-off-by: Tianci Cao <ziye at zju.edu.cn>
Co-developed-by: Shenghao Yuan <shenghaoyuan0928 at 163.com>
Signed-off-by: Shenghao Yuan <shenghaoyuan0928 at 163.com>
---
kernel/bpf/verifier.c | 24 +++++++++++++++---------
1 file changed, 15 insertions(+), 9 deletions(-)
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index 5601d2056218..4f9d7b3de442 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -21194,6 +21194,18 @@ static int fd_array_get_map_idx(struct bpf_verifier_env *env, u32 idx)
return -EPROTO;
}
+static bool is_valid_alu_variant(const struct bpf_insn *insn)
+{
+ switch (BPF_OP(insn->code)) {
+ case BPF_DIV:
+ case BPF_MOD:
+ /* off == 1 selects SDIV/SMOD. */
+ return insn->off == 0 || insn->off == 1;
+ default:
+ return insn->off == 0;
+ }
+}
+
static int check_alu_fields(struct bpf_verifier_env *env, struct bpf_insn *insn)
{
u8 class = BPF_CLASS(insn->code);
@@ -21249,15 +21261,9 @@ static int check_alu_fields(struct bpf_verifier_env *env, struct bpf_insn *insn)
case BPF_MUL:
case BPF_DIV:
case BPF_MOD:
- if (BPF_SRC(insn->code) == BPF_X) {
- if (insn->imm != 0 || (insn->off != 0 && insn->off != 1) ||
- (insn->off == 1 && opcode != BPF_MOD && opcode != BPF_DIV)) {
- verbose(env, "BPF_ALU uses reserved fields\n");
- return -EINVAL;
- }
- } else if (insn->src_reg != BPF_REG_0 ||
- (insn->off != 0 && insn->off != 1) ||
- (insn->off == 1 && opcode != BPF_MOD && opcode != BPF_DIV)) {
+ if (!is_valid_alu_variant(insn) ||
+ (BPF_SRC(insn->code) == BPF_X && insn->imm != 0) ||
+ (BPF_SRC(insn->code) == BPF_K && insn->src_reg != BPF_REG_0)) {
verbose(env, "BPF_ALU uses reserved fields\n");
return -EINVAL;
}
--
2.56.0
More information about the linux-riscv
mailing list