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.
Unified · Split
| @@ -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 optimization | 67 | /* |
| 68 | * code only. It returns TRUE if the source or destination register operates | 68 | * 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 | */ |
| 71 | static bool bpf_is_reg64(struct bpf_prog *prog, struct bpf_insn *insn, | 72 | 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) | ||
| 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 TRUE | 80 | /* 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 for | 684 | 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++; |