History

bpf: Simplify the bpf_is_reg64()

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.

Eduard Zingerman committed 3 months ago

Commit be4f8d61 parent 7ce090a1 file · +27 −83Browse files

Showing the changes to kernel (1 of 1 file). Show all

Unified · Split

kernel/bpf/fixups.c+27−83
@@ -64,95 +64,43 @@ static int insn_def_regno(const struct bpf_insn *insn) · 63 unmodified lines
6464 }
6565 }
6666
67−/* This function is supposed to be used by the zero extension optimization
68− * code only. It returns TRUE if the source or destination register operates
69− * on 64-bit, otherwise return FALSE.
67+/*
68+ * For use only in combination with insn_def_regno() >= 0.
69+ * Returns TRUE if the destination register operates on 64-bit,
70+ * otherwise return FALSE.
7071 */
71−static bool bpf_is_reg64(struct bpf_prog *prog, struct bpf_insn *insn,
72− u32 regno, struct bpf_reg_state *reg, enum bpf_reg_arg_type t)
72+static bool bpf_is_reg64(struct bpf_prog *prog, struct bpf_insn *insn)
7373 {
74− u8 code, class, op;
75−
76− code = insn->code;
77− class = BPF_CLASS(code);
78− op = BPF_OP(code);
79− if (class == BPF_JMP) {
80− /* BPF_EXIT for "main" will reach here. Return TRUE
81− * conservatively.
82− */
83− if (op == BPF_EXIT)
84− return true;
85− if (op == BPF_CALL) {
86− /* BPF to BPF call will reach here because of marking
87− * caller saved clobber with DST_OP_NO_MARK for which we
88− * don't care the register def because they are anyway
89− * marked as NOT_INIT already.
90− */
91− if (insn->src_reg == BPF_PSEUDO_CALL)
92− return false;
93− /* Helper call will reach here because of arg type
94− * check, conservatively return TRUE.
95− */
96− if (t == SRC_OP)
97− return true;
98−
99− return false;
100− }
101− }
74+ u8 class = BPF_CLASS(insn->code);
75+ u8 mode = BPF_MODE(insn->code);
76+ u8 size = BPF_SIZE(insn->code);
77+ u8 op = BPF_OP(insn->code);
78+ bool mode_mem;
79+
80+ /* subregister endiness swap */
81+ if ((class == BPF_ALU || class == BPF_ALU64) && op == BPF_END && insn->imm != 64)
82+ return false;
10283
103− if (class == BPF_ALU64 && op == BPF_END && (insn->imm == 16 || insn->imm == 32))
84+ /* w0 += 1 */
85+ if (class == BPF_ALU && op != BPF_END)
10486 return false;
10587
10688 /* address space casts converted to BPF_ALU, see bpf_do_misc_fixups() */
10789 if (is_addr_space_cast32(prog, insn))
10890 return false;
10991
110− if (class == BPF_ALU64 || class == BPF_JMP ||
111− (class == BPF_ALU && op == BPF_END && insn->imm == 64))
112− return true;
113−
114− if (class == BPF_ALU || class == BPF_JMP32)
92+ /* non 64-bit, non signed extended loads */
93+ mode_mem = mode == BPF_MEM || mode == BPF_PROBE_MEM || mode == BPF_PROBE_MEM32;
94+ if (class == BPF_LDX && mode_mem && size != BPF_DW)
11595 return false;
11696
117− if (class == BPF_LDX) {
118− if (t != SRC_OP)
119− return BPF_SIZE(code) == BPF_DW || BPF_MODE(code) == BPF_MEMSX;
120− /* LDX source must be ptr. */
121− return true;
122− }
123−
124− if (class == BPF_STX) {
125− /* BPF_STX (including atomic variants) has one or more source
126− * operands, one of which is a ptr. Check whether the caller is
127− * asking about it.
128− */
129− if (t == SRC_OP && reg->type != SCALAR_VALUE)
130− return true;
131− return BPF_SIZE(code) == BPF_DW;
132− }
133−
134− if (class == BPF_LD) {
135− u8 mode = BPF_MODE(code);
136−
137− /* LD_IMM64 */
138− if (mode == BPF_IMM)
139− return true;
140−
141− /* Both LD_IND and LD_ABS return 32-bit data. */
142− if (t != SRC_OP)
143− return false;
144−
145− /* Implicit ctx ptr. */
146− if (regno == BPF_REG_6)
147− return true;
148−
149− /* Explicit source could be any width. */
150− return true;
151− }
97+ /* atomics, see insn_def_regno() */
98+ if (class == BPF_STX && size != BPF_DW)
99+ return false;
152100
153− if (class == BPF_ST)
154− /* The only source register for BPF_ST is a ptr. */
155− return true;
101+ /* both LD_IND and LD_ABS return 32-bit data. */
102+ if (class == BPF_LD && (mode == BPF_IND || mode == BPF_ABS))
103+ return false;
156104
157105 /* Conservatively return true at default. */
158106 return true;
@@ -166,7 +114,7 @@ int bpf_insn_def32(struct bpf_prog *prog, struct bpf_insn *insn) · 7 unmodified lines
166114 {
167115 int dst_reg = insn_def_regno(insn);
168116
169− if (dst_reg < 0 || bpf_is_reg64(prog, insn, dst_reg, NULL, DST_OP))
117+ if (dst_reg < 0 || bpf_is_reg64(prog, insn))
170118 return -1;
171119
172120 return dst_reg;
@@ -733,11 +681,7 @@ int bpf_opt_subreg_zext_lo32_rnd_hi32(struct bpf_verifier_env *env, · 560 unmodified lines
733681 if (load_reg == -1)
734682 continue;
735683
736− /* NOTE: arg "reg" (the fourth one) is only used for
737− * BPF_STX + SRC_OP, so it is safe to pass NULL
738− * here.
739− */
740− if (bpf_is_reg64(env->prog, &insn, load_reg, NULL, DST_OP)) {
684+ if (bpf_is_reg64(env->prog, &insn)) {
741685 if (class == BPF_LD &&
742686 BPF_MODE(code) == BPF_IMM)
743687 i++;