[PATCH bpf-next v4 6/7] bpf: simplify the bpf_is_reg64()
Eduard Zingerman <[email protected]>
| Newsgroups | org.kernel.vger.bpf |
|---|---|
| Message-ID | <[email protected]> |
After the previous commit bpf_is_reg64() is only used in a context
where destination register's property is queried, and only for
instructions for which insn_def_regno() >= 0.
Hence, simplify the function by:
- removing unused parameters;
- removing code paths considering BPF_JMP{,32} instructions;
- streamlining the condition expressions.
Signed-off-by: Eduard Zingerman <[email protected]>
---
kernel/bpf/fixups.c | 110 +++++++++++++---------------------------------------
1 file changed, 27 insertions(+), 83 deletions(-)
diff --git a/kernel/bpf/fixups.c b/kernel/bpf/fixups.c
index 447c54828cb9..661e2d13a604 100644
--- a/kernel/bpf/fixups.c
+++ b/kernel/bpf/fixups.c
@@ -64,95 +64,43 @@ static int insn_def_regno(const struct bpf_insn *insn)
}
}
-/* This function is supposed to be used by the zero extension optimization
- * code only. It returns TRUE if the source or destination register operates
- * on 64-bit, otherwise return FALSE.
+/*
+ * For use only in combination with insn_def_regno() >= 0.
+ * Returns TRUE if the destination register operates on 64-bit,
+ * otherwise return FALSE.
*/
-static bool bpf_is_reg64(struct bpf_prog *prog, struct bpf_insn *insn,
- u32 regno, struct bpf_reg_state *reg, enum bpf_reg_arg_type t)
+static bool bpf_is_reg64(struct bpf_prog *prog, struct bpf_insn *insn)
{
- u8 code, class, op;
-
- code = insn->code;
- class = BPF_CLASS(code);
- op = BPF_OP(code);
- if (class == BPF_JMP) {
- /* BPF_EXIT for "main" will reach here. Return TRUE
- * conservatively.
- */
- if (op == BPF_EXIT)
- return true;
- if (op == BPF_CALL) {
- /* BPF to BPF call will reach here because of marking
- * caller saved clobber with DST_OP_NO_MARK for which we
- * don't care the register def because they are anyway
- * marked as NOT_INIT already.
- */
- if (insn->src_reg == BPF_PSEUDO_CALL)
- return false;
- /* Helper call will reach here because of arg type
- * check, conservatively return TRUE.
- */
- if (t == SRC_OP)
- return true;
-
- return false;
- }
- }
+ u8 class = BPF_CLASS(insn->code);
+ u8 mode = BPF_MODE(insn->code);
+ u8 size = BPF_SIZE(insn->code);
+ u8 op = BPF_OP(insn->code);
+ bool mode_mem;
+
+ /* subregister endiness swap */
+ if ((class == BPF_ALU || class == BPF_ALU64) && op == BPF_END && insn->imm != 64)
+ return false;
- if (class == BPF_ALU64 && op == BPF_END && (insn->imm == 16 || insn->imm == 32))
+ /* w0 += 1 */
+ if (class == BPF_ALU && op != BPF_END)
return false;
/* address space casts converted to BPF_ALU, see bpf_do_misc_fixups() */
if (is_addr_space_cast32(prog, insn))
return false;
- if (class == BPF_ALU64 || class == BPF_JMP ||
- (class == BPF_ALU && op == BPF_END && insn->imm == 64))
- return true;
-
- if (class == BPF_ALU || class == BPF_JMP32)
+ /* non 64-bit, non signed extended loads */
+ mode_mem = mode == BPF_MEM || mode == BPF_PROBE_MEM || mode == BPF_PROBE_MEM32;
+ if (class == BPF_LDX && mode_mem && size != BPF_DW)
return false;
- if (class == BPF_LDX) {
- if (t != SRC_OP)
- return BPF_SIZE(code) == BPF_DW || BPF_MODE(code) == BPF_MEMSX;
- /* LDX source must be ptr. */
- return true;
- }
-
- if (class == BPF_STX) {
- /* BPF_STX (including atomic variants) has one or more source
- * operands, one of which is a ptr. Check whether the caller is
- * asking about it.
- */
- if (t == SRC_OP && reg->type != SCALAR_VALUE)
- return true;
- return BPF_SIZE(code) == BPF_DW;
- }
-
- if (class == BPF_LD) {
- u8 mode = BPF_MODE(code);
-
- /* LD_IMM64 */
- if (mode == BPF_IMM)
- return true;
-
- /* Both LD_IND and LD_ABS return 32-bit data. */
- if (t != SRC_OP)
- return false;
-
- /* Implicit ctx ptr. */
- if (regno == BPF_REG_6)
- return true;
-
- /* Explicit source could be any width. */
- return true;
- }
+ /* atomics, see insn_def_regno() */
+ if (class == BPF_STX && size != BPF_DW)
+ return false;
- if (class == BPF_ST)
- /* The only source register for BPF_ST is a ptr. */
- return true;
+ /* both LD_IND and LD_ABS return 32-bit data. */
+ if (class == BPF_LD && (mode == BPF_IND || mode == BPF_ABS))
+ return false;
/* Conservatively return true at default. */
return true;
@@ -166,7 +114,7 @@ int bpf_insn_def32(struct bpf_prog *prog, struct bpf_insn *insn)
{
int dst_reg = insn_def_regno(insn);
- if (dst_reg < 0 || bpf_is_reg64(prog, insn, dst_reg, NULL, DST_OP))
+ if (dst_reg < 0 || bpf_is_reg64(prog, insn))
return -1;
return dst_reg;
@@ -733,11 +681,7 @@ int bpf_opt_subreg_zext_lo32_rnd_hi32(struct bpf_verifier_env *env,
if (load_reg == -1)
continue;
- /* NOTE: arg "reg" (the fourth one) is only used for
- * BPF_STX + SRC_OP, so it is safe to pass NULL
- * here.
- */
- if (bpf_is_reg64(env->prog, &insn, load_reg, NULL, DST_OP)) {
+ if (bpf_is_reg64(env->prog, &insn)) {
if (class == BPF_LD &&
BPF_MODE(code) == BPF_IMM)
i++;
--
2.55.0