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

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
64 }64 }
65}65}
66 66
67/* This function is supposed to be used by the zero extension optimization67/*
68 * code only. It returns TRUE if the source or destination register operates68 * For use only in combination with insn_def_regno() >= 0.
69 * on 64-bit, otherwise return FALSE.69 * Returns TRUE if the destination register operates on 64-bit,
70 * otherwise return FALSE.
70 */71 */
71static bool bpf_is_reg64(struct bpf_prog *prog, struct bpf_insn *insn,72static 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)
73{73{
74 u8 code, class, op;74 u8 class = BPF_CLASS(insn->code);
75 75 u8 mode = BPF_MODE(insn->code);
76 code = insn->code;76 u8 size = BPF_SIZE(insn->code);
77 class = BPF_CLASS(code);77 u8 op = BPF_OP(insn->code);
78 op = BPF_OP(code);78 bool mode_mem;
79 if (class == BPF_JMP) {79
80 /* BPF_EXIT for "main" will reach here. Return TRUE80 /* subregister endiness swap */
81 * conservatively.81 if ((class == BPF_ALU || class == BPF_ALU64) && op == BPF_END && insn->imm != 64)
82 */82 return false;
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 }
102 83
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)
104 return false;86 return false;
105 87
106 /* address space casts converted to BPF_ALU, see bpf_do_misc_fixups() */88 /* address space casts converted to BPF_ALU, see bpf_do_misc_fixups() */
107 if (is_addr_space_cast32(prog, insn))89 if (is_addr_space_cast32(prog, insn))
108 return false;90 return false;
109 91
110 if (class == BPF_ALU64 || class == BPF_JMP ||92 /* non 64-bit, non signed extended loads */
111 (class == BPF_ALU && op == BPF_END && insn->imm == 64))93 mode_mem = mode == BPF_MEM || mode == BPF_PROBE_MEM || mode == BPF_PROBE_MEM32;
112 return true;94 if (class == BPF_LDX && mode_mem && size != BPF_DW)
113
114 if (class == BPF_ALU || class == BPF_JMP32)
115 return false;95 return false;
116 96
117 if (class == BPF_LDX) {97 /* atomics, see insn_def_regno() */
118 if (t != SRC_OP)98 if (class == BPF_STX && size != BPF_DW)
119 return BPF_SIZE(code) == BPF_DW || BPF_MODE(code) == BPF_MEMSX;99 return false;
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 }
152 100
153 if (class == BPF_ST)101 /* both LD_IND and LD_ABS return 32-bit data. */
154 /* The only source register for BPF_ST is a ptr. */102 if (class == BPF_LD && (mode == BPF_IND || mode == BPF_ABS))
155 return true;103 return false;
156 104
157 /* Conservatively return true at default. */105 /* Conservatively return true at default. */
158 return true;106 return true;
@@ -166,7 +114,7 @@ int bpf_insn_def32(struct bpf_prog *prog, struct bpf_insn *insn) · 7 unmodified lines
166{114{
167 int dst_reg = insn_def_regno(insn);115 int dst_reg = insn_def_regno(insn);
168 116
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))
170 return -1;118 return -1;
171 119
172 return dst_reg;120 return dst_reg;
@@ -733,11 +681,7 @@ int bpf_opt_subreg_zext_lo32_rnd_hi32(struct bpf_verifier_env *env, · 560 unmodified lines
733 if (load_reg == -1)681 if (load_reg == -1)
734 continue;682 continue;
735 683
736 /* NOTE: arg "reg" (the fourth one) is only used for684 if (bpf_is_reg64(env->prog, &insn)) {
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)) {
741 if (class == BPF_LD &&685 if (class == BPF_LD &&
742 BPF_MODE(code) == BPF_IMM)686 BPF_MODE(code) == BPF_IMM)
743 i++;687 i++;