aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'kernel')
-rw-r--r--kernel/bpf/core.c3
-rw-r--r--kernel/bpf/verifier.c203
2 files changed, 173 insertions, 33 deletions
diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c
index 2a81b8af3748..1e443ba97310 100644
--- a/kernel/bpf/core.c
+++ b/kernel/bpf/core.c
@@ -362,7 +362,8 @@ static int bpf_adj_branches(struct bpf_prog *prog, u32 pos, s32 end_old,
362 insn = prog->insnsi + end_old; 362 insn = prog->insnsi + end_old;
363 } 363 }
364 code = insn->code; 364 code = insn->code;
365 if (BPF_CLASS(code) != BPF_JMP || 365 if ((BPF_CLASS(code) != BPF_JMP &&
366 BPF_CLASS(code) != BPF_JMP32) ||
366 BPF_OP(code) == BPF_EXIT) 367 BPF_OP(code) == BPF_EXIT)
367 continue; 368 continue;
368 /* Adjust offset of jmps if we cross patch boundaries. */ 369 /* Adjust offset of jmps if we cross patch boundaries. */
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index eae6cb1fe653..8c1c21cd50b4 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -1095,7 +1095,7 @@ static int check_subprogs(struct bpf_verifier_env *env)
1095 for (i = 0; i < insn_cnt; i++) { 1095 for (i = 0; i < insn_cnt; i++) {
1096 u8 code = insn[i].code; 1096 u8 code = insn[i].code;
1097 1097
1098 if (BPF_CLASS(code) != BPF_JMP) 1098 if (BPF_CLASS(code) != BPF_JMP && BPF_CLASS(code) != BPF_JMP32)
1099 goto next; 1099 goto next;
1100 if (BPF_OP(code) == BPF_EXIT || BPF_OP(code) == BPF_CALL) 1100 if (BPF_OP(code) == BPF_EXIT || BPF_OP(code) == BPF_CALL)
1101 goto next; 1101 goto next;
@@ -4031,14 +4031,49 @@ static void find_good_pkt_pointers(struct bpf_verifier_state *vstate,
4031 * 0 - branch will not be taken and fall-through to next insn 4031 * 0 - branch will not be taken and fall-through to next insn
4032 * -1 - unknown. Example: "if (reg < 5)" is unknown when register value range [0,10] 4032 * -1 - unknown. Example: "if (reg < 5)" is unknown when register value range [0,10]
4033 */ 4033 */
4034static int is_branch_taken(struct bpf_reg_state *reg, u64 val, u8 opcode) 4034static int is_branch_taken(struct bpf_reg_state *reg, u64 val, u8 opcode,
4035 bool is_jmp32)
4035{ 4036{
4037 struct bpf_reg_state reg_lo;
4036 s64 sval; 4038 s64 sval;
4037 4039
4038 if (__is_pointer_value(false, reg)) 4040 if (__is_pointer_value(false, reg))
4039 return -1; 4041 return -1;
4040 4042
4041 sval = (s64)val; 4043 if (is_jmp32) {
4044 reg_lo = *reg;
4045 reg = &reg_lo;
4046 /* For JMP32, only low 32 bits are compared, coerce_reg_to_size
4047 * could truncate high bits and update umin/umax according to
4048 * information of low bits.
4049 */
4050 coerce_reg_to_size(reg, 4);
4051 /* smin/smax need special handling. For example, after coerce,
4052 * if smin_value is 0x00000000ffffffffLL, the value is -1 when
4053 * used as operand to JMP32. It is a negative number from s32's
4054 * point of view, while it is a positive number when seen as
4055 * s64. The smin/smax are kept as s64, therefore, when used with
4056 * JMP32, they need to be transformed into s32, then sign
4057 * extended back to s64.
4058 *
4059 * Also, smin/smax were copied from umin/umax. If umin/umax has
4060 * different sign bit, then min/max relationship doesn't
4061 * maintain after casting into s32, for this case, set smin/smax
4062 * to safest range.
4063 */
4064 if ((reg->umax_value ^ reg->umin_value) &
4065 (1ULL << 31)) {
4066 reg->smin_value = S32_MIN;
4067 reg->smax_value = S32_MAX;
4068 }
4069 reg->smin_value = (s64)(s32)reg->smin_value;
4070 reg->smax_value = (s64)(s32)reg->smax_value;
4071
4072 val = (u32)val;
4073 sval = (s64)(s32)val;
4074 } else {
4075 sval = (s64)val;
4076 }
4042 4077
4043 switch (opcode) { 4078 switch (opcode) {
4044 case BPF_JEQ: 4079 case BPF_JEQ:
@@ -4108,6 +4143,29 @@ static int is_branch_taken(struct bpf_reg_state *reg, u64 val, u8 opcode)
4108 return -1; 4143 return -1;
4109} 4144}
4110 4145
4146/* Generate min value of the high 32-bit from TNUM info. */
4147static u64 gen_hi_min(struct tnum var)
4148{
4149 return var.value & ~0xffffffffULL;
4150}
4151
4152/* Generate max value of the high 32-bit from TNUM info. */
4153static u64 gen_hi_max(struct tnum var)
4154{
4155 return (var.value | var.mask) & ~0xffffffffULL;
4156}
4157
4158/* Return true if VAL is compared with a s64 sign extended from s32, and they
4159 * are with the same signedness.
4160 */
4161static bool cmp_val_with_extended_s64(s64 sval, struct bpf_reg_state *reg)
4162{
4163 return ((s32)sval >= 0 &&
4164 reg->smin_value >= 0 && reg->smax_value <= S32_MAX) ||
4165 ((s32)sval < 0 &&
4166 reg->smax_value <= 0 && reg->smin_value >= S32_MIN);
4167}
4168
4111/* Adjusts the register min/max values in the case that the dst_reg is the 4169/* Adjusts the register min/max values in the case that the dst_reg is the
4112 * variable register that we are working on, and src_reg is a constant or we're 4170 * variable register that we are working on, and src_reg is a constant or we're
4113 * simply doing a BPF_K check. 4171 * simply doing a BPF_K check.
@@ -4115,7 +4173,7 @@ static int is_branch_taken(struct bpf_reg_state *reg, u64 val, u8 opcode)
4115 */ 4173 */
4116static void reg_set_min_max(struct bpf_reg_state *true_reg, 4174static void reg_set_min_max(struct bpf_reg_state *true_reg,
4117 struct bpf_reg_state *false_reg, u64 val, 4175 struct bpf_reg_state *false_reg, u64 val,
4118 u8 opcode) 4176 u8 opcode, bool is_jmp32)
4119{ 4177{
4120 s64 sval; 4178 s64 sval;
4121 4179
@@ -4128,7 +4186,8 @@ static void reg_set_min_max(struct bpf_reg_state *true_reg,
4128 if (__is_pointer_value(false, false_reg)) 4186 if (__is_pointer_value(false, false_reg))
4129 return; 4187 return;
4130 4188
4131 sval = (s64)val; 4189 val = is_jmp32 ? (u32)val : val;
4190 sval = is_jmp32 ? (s64)(s32)val : (s64)val;
4132 4191
4133 switch (opcode) { 4192 switch (opcode) {
4134 case BPF_JEQ: 4193 case BPF_JEQ:
@@ -4141,7 +4200,15 @@ static void reg_set_min_max(struct bpf_reg_state *true_reg,
4141 * if it is true we know the value for sure. Likewise for 4200 * if it is true we know the value for sure. Likewise for
4142 * BPF_JNE. 4201 * BPF_JNE.
4143 */ 4202 */
4144 __mark_reg_known(reg, val); 4203 if (is_jmp32) {
4204 u64 old_v = reg->var_off.value;
4205 u64 hi_mask = ~0xffffffffULL;
4206
4207 reg->var_off.value = (old_v & hi_mask) | val;
4208 reg->var_off.mask &= hi_mask;
4209 } else {
4210 __mark_reg_known(reg, val);
4211 }
4145 break; 4212 break;
4146 } 4213 }
4147 case BPF_JSET: 4214 case BPF_JSET:
@@ -4157,6 +4224,10 @@ static void reg_set_min_max(struct bpf_reg_state *true_reg,
4157 u64 false_umax = opcode == BPF_JGT ? val : val - 1; 4224 u64 false_umax = opcode == BPF_JGT ? val : val - 1;
4158 u64 true_umin = opcode == BPF_JGT ? val + 1 : val; 4225 u64 true_umin = opcode == BPF_JGT ? val + 1 : val;
4159 4226
4227 if (is_jmp32) {
4228 false_umax += gen_hi_max(false_reg->var_off);
4229 true_umin += gen_hi_min(true_reg->var_off);
4230 }
4160 false_reg->umax_value = min(false_reg->umax_value, false_umax); 4231 false_reg->umax_value = min(false_reg->umax_value, false_umax);
4161 true_reg->umin_value = max(true_reg->umin_value, true_umin); 4232 true_reg->umin_value = max(true_reg->umin_value, true_umin);
4162 break; 4233 break;
@@ -4167,6 +4238,11 @@ static void reg_set_min_max(struct bpf_reg_state *true_reg,
4167 s64 false_smax = opcode == BPF_JSGT ? sval : sval - 1; 4238 s64 false_smax = opcode == BPF_JSGT ? sval : sval - 1;
4168 s64 true_smin = opcode == BPF_JSGT ? sval + 1 : sval; 4239 s64 true_smin = opcode == BPF_JSGT ? sval + 1 : sval;
4169 4240
4241 /* If the full s64 was not sign-extended from s32 then don't
4242 * deduct further info.
4243 */
4244 if (is_jmp32 && !cmp_val_with_extended_s64(sval, false_reg))
4245 break;
4170 false_reg->smax_value = min(false_reg->smax_value, false_smax); 4246 false_reg->smax_value = min(false_reg->smax_value, false_smax);
4171 true_reg->smin_value = max(true_reg->smin_value, true_smin); 4247 true_reg->smin_value = max(true_reg->smin_value, true_smin);
4172 break; 4248 break;
@@ -4177,6 +4253,10 @@ static void reg_set_min_max(struct bpf_reg_state *true_reg,
4177 u64 false_umin = opcode == BPF_JLT ? val : val + 1; 4253 u64 false_umin = opcode == BPF_JLT ? val : val + 1;
4178 u64 true_umax = opcode == BPF_JLT ? val - 1 : val; 4254 u64 true_umax = opcode == BPF_JLT ? val - 1 : val;
4179 4255
4256 if (is_jmp32) {
4257 false_umin += gen_hi_min(false_reg->var_off);
4258 true_umax += gen_hi_max(true_reg->var_off);
4259 }
4180 false_reg->umin_value = max(false_reg->umin_value, false_umin); 4260 false_reg->umin_value = max(false_reg->umin_value, false_umin);
4181 true_reg->umax_value = min(true_reg->umax_value, true_umax); 4261 true_reg->umax_value = min(true_reg->umax_value, true_umax);
4182 break; 4262 break;
@@ -4187,6 +4267,8 @@ static void reg_set_min_max(struct bpf_reg_state *true_reg,
4187 s64 false_smin = opcode == BPF_JSLT ? sval : sval + 1; 4267 s64 false_smin = opcode == BPF_JSLT ? sval : sval + 1;
4188 s64 true_smax = opcode == BPF_JSLT ? sval - 1 : sval; 4268 s64 true_smax = opcode == BPF_JSLT ? sval - 1 : sval;
4189 4269
4270 if (is_jmp32 && !cmp_val_with_extended_s64(sval, false_reg))
4271 break;
4190 false_reg->smin_value = max(false_reg->smin_value, false_smin); 4272 false_reg->smin_value = max(false_reg->smin_value, false_smin);
4191 true_reg->smax_value = min(true_reg->smax_value, true_smax); 4273 true_reg->smax_value = min(true_reg->smax_value, true_smax);
4192 break; 4274 break;
@@ -4213,14 +4295,15 @@ static void reg_set_min_max(struct bpf_reg_state *true_reg,
4213 */ 4295 */
4214static void reg_set_min_max_inv(struct bpf_reg_state *true_reg, 4296static void reg_set_min_max_inv(struct bpf_reg_state *true_reg,
4215 struct bpf_reg_state *false_reg, u64 val, 4297 struct bpf_reg_state *false_reg, u64 val,
4216 u8 opcode) 4298 u8 opcode, bool is_jmp32)
4217{ 4299{
4218 s64 sval; 4300 s64 sval;
4219 4301
4220 if (__is_pointer_value(false, false_reg)) 4302 if (__is_pointer_value(false, false_reg))
4221 return; 4303 return;
4222 4304
4223 sval = (s64)val; 4305 val = is_jmp32 ? (u32)val : val;
4306 sval = is_jmp32 ? (s64)(s32)val : (s64)val;
4224 4307
4225 switch (opcode) { 4308 switch (opcode) {
4226 case BPF_JEQ: 4309 case BPF_JEQ:
@@ -4229,7 +4312,15 @@ static void reg_set_min_max_inv(struct bpf_reg_state *true_reg,
4229 struct bpf_reg_state *reg = 4312 struct bpf_reg_state *reg =
4230 opcode == BPF_JEQ ? true_reg : false_reg; 4313 opcode == BPF_JEQ ? true_reg : false_reg;
4231 4314
4232 __mark_reg_known(reg, val); 4315 if (is_jmp32) {
4316 u64 old_v = reg->var_off.value;
4317 u64 hi_mask = ~0xffffffffULL;
4318
4319 reg->var_off.value = (old_v & hi_mask) | val;
4320 reg->var_off.mask &= hi_mask;
4321 } else {
4322 __mark_reg_known(reg, val);
4323 }
4233 break; 4324 break;
4234 } 4325 }
4235 case BPF_JSET: 4326 case BPF_JSET:
@@ -4245,6 +4336,10 @@ static void reg_set_min_max_inv(struct bpf_reg_state *true_reg,
4245 u64 false_umin = opcode == BPF_JGT ? val : val + 1; 4336 u64 false_umin = opcode == BPF_JGT ? val : val + 1;
4246 u64 true_umax = opcode == BPF_JGT ? val - 1 : val; 4337 u64 true_umax = opcode == BPF_JGT ? val - 1 : val;
4247 4338
4339 if (is_jmp32) {
4340 false_umin += gen_hi_min(false_reg->var_off);
4341 true_umax += gen_hi_max(true_reg->var_off);
4342 }
4248 false_reg->umin_value = max(false_reg->umin_value, false_umin); 4343 false_reg->umin_value = max(false_reg->umin_value, false_umin);
4249 true_reg->umax_value = min(true_reg->umax_value, true_umax); 4344 true_reg->umax_value = min(true_reg->umax_value, true_umax);
4250 break; 4345 break;
@@ -4255,6 +4350,8 @@ static void reg_set_min_max_inv(struct bpf_reg_state *true_reg,
4255 s64 false_smin = opcode == BPF_JSGT ? sval : sval + 1; 4350 s64 false_smin = opcode == BPF_JSGT ? sval : sval + 1;
4256 s64 true_smax = opcode == BPF_JSGT ? sval - 1 : sval; 4351 s64 true_smax = opcode == BPF_JSGT ? sval - 1 : sval;
4257 4352
4353 if (is_jmp32 && !cmp_val_with_extended_s64(sval, false_reg))
4354 break;
4258 false_reg->smin_value = max(false_reg->smin_value, false_smin); 4355 false_reg->smin_value = max(false_reg->smin_value, false_smin);
4259 true_reg->smax_value = min(true_reg->smax_value, true_smax); 4356 true_reg->smax_value = min(true_reg->smax_value, true_smax);
4260 break; 4357 break;
@@ -4265,6 +4362,10 @@ static void reg_set_min_max_inv(struct bpf_reg_state *true_reg,
4265 u64 false_umax = opcode == BPF_JLT ? val : val - 1; 4362 u64 false_umax = opcode == BPF_JLT ? val : val - 1;
4266 u64 true_umin = opcode == BPF_JLT ? val + 1 : val; 4363 u64 true_umin = opcode == BPF_JLT ? val + 1 : val;
4267 4364
4365 if (is_jmp32) {
4366 false_umax += gen_hi_max(false_reg->var_off);
4367 true_umin += gen_hi_min(true_reg->var_off);
4368 }
4268 false_reg->umax_value = min(false_reg->umax_value, false_umax); 4369 false_reg->umax_value = min(false_reg->umax_value, false_umax);
4269 true_reg->umin_value = max(true_reg->umin_value, true_umin); 4370 true_reg->umin_value = max(true_reg->umin_value, true_umin);
4270 break; 4371 break;
@@ -4275,6 +4376,8 @@ static void reg_set_min_max_inv(struct bpf_reg_state *true_reg,
4275 s64 false_smax = opcode == BPF_JSLT ? sval : sval - 1; 4376 s64 false_smax = opcode == BPF_JSLT ? sval : sval - 1;
4276 s64 true_smin = opcode == BPF_JSLT ? sval + 1 : sval; 4377 s64 true_smin = opcode == BPF_JSLT ? sval + 1 : sval;
4277 4378
4379 if (is_jmp32 && !cmp_val_with_extended_s64(sval, false_reg))
4380 break;
4278 false_reg->smax_value = min(false_reg->smax_value, false_smax); 4381 false_reg->smax_value = min(false_reg->smax_value, false_smax);
4279 true_reg->smin_value = max(true_reg->smin_value, true_smin); 4382 true_reg->smin_value = max(true_reg->smin_value, true_smin);
4280 break; 4383 break;
@@ -4416,6 +4519,10 @@ static bool try_match_pkt_pointers(const struct bpf_insn *insn,
4416 if (BPF_SRC(insn->code) != BPF_X) 4519 if (BPF_SRC(insn->code) != BPF_X)
4417 return false; 4520 return false;
4418 4521
4522 /* Pointers are always 64-bit. */
4523 if (BPF_CLASS(insn->code) == BPF_JMP32)
4524 return false;
4525
4419 switch (BPF_OP(insn->code)) { 4526 switch (BPF_OP(insn->code)) {
4420 case BPF_JGT: 4527 case BPF_JGT:
4421 if ((dst_reg->type == PTR_TO_PACKET && 4528 if ((dst_reg->type == PTR_TO_PACKET &&
@@ -4508,16 +4615,18 @@ static int check_cond_jmp_op(struct bpf_verifier_env *env,
4508 struct bpf_reg_state *regs = this_branch->frame[this_branch->curframe]->regs; 4615 struct bpf_reg_state *regs = this_branch->frame[this_branch->curframe]->regs;
4509 struct bpf_reg_state *dst_reg, *other_branch_regs; 4616 struct bpf_reg_state *dst_reg, *other_branch_regs;
4510 u8 opcode = BPF_OP(insn->code); 4617 u8 opcode = BPF_OP(insn->code);
4618 bool is_jmp32;
4511 int err; 4619 int err;
4512 4620
4513 if (opcode > BPF_JSLE) { 4621 /* Only conditional jumps are expected to reach here. */
4514 verbose(env, "invalid BPF_JMP opcode %x\n", opcode); 4622 if (opcode == BPF_JA || opcode > BPF_JSLE) {
4623 verbose(env, "invalid BPF_JMP/JMP32 opcode %x\n", opcode);
4515 return -EINVAL; 4624 return -EINVAL;
4516 } 4625 }
4517 4626
4518 if (BPF_SRC(insn->code) == BPF_X) { 4627 if (BPF_SRC(insn->code) == BPF_X) {
4519 if (insn->imm != 0) { 4628 if (insn->imm != 0) {
4520 verbose(env, "BPF_JMP uses reserved fields\n"); 4629 verbose(env, "BPF_JMP/JMP32 uses reserved fields\n");
4521 return -EINVAL; 4630 return -EINVAL;
4522 } 4631 }
4523 4632
@@ -4533,7 +4642,7 @@ static int check_cond_jmp_op(struct bpf_verifier_env *env,
4533 } 4642 }
4534 } else { 4643 } else {
4535 if (insn->src_reg != BPF_REG_0) { 4644 if (insn->src_reg != BPF_REG_0) {
4536 verbose(env, "BPF_JMP uses reserved fields\n"); 4645 verbose(env, "BPF_JMP/JMP32 uses reserved fields\n");
4537 return -EINVAL; 4646 return -EINVAL;
4538 } 4647 }
4539 } 4648 }
@@ -4544,9 +4653,11 @@ static int check_cond_jmp_op(struct bpf_verifier_env *env,
4544 return err; 4653 return err;
4545 4654
4546 dst_reg = &regs[insn->dst_reg]; 4655 dst_reg = &regs[insn->dst_reg];
4656 is_jmp32 = BPF_CLASS(insn->code) == BPF_JMP32;
4547 4657
4548 if (BPF_SRC(insn->code) == BPF_K) { 4658 if (BPF_SRC(insn->code) == BPF_K) {
4549 int pred = is_branch_taken(dst_reg, insn->imm, opcode); 4659 int pred = is_branch_taken(dst_reg, insn->imm, opcode,
4660 is_jmp32);
4550 4661
4551 if (pred == 1) { 4662 if (pred == 1) {
4552 /* only follow the goto, ignore fall-through */ 4663 /* only follow the goto, ignore fall-through */
@@ -4574,30 +4685,51 @@ static int check_cond_jmp_op(struct bpf_verifier_env *env,
4574 * comparable. 4685 * comparable.
4575 */ 4686 */
4576 if (BPF_SRC(insn->code) == BPF_X) { 4687 if (BPF_SRC(insn->code) == BPF_X) {
4688 struct bpf_reg_state *src_reg = &regs[insn->src_reg];
4689 struct bpf_reg_state lo_reg0 = *dst_reg;
4690 struct bpf_reg_state lo_reg1 = *src_reg;
4691 struct bpf_reg_state *src_lo, *dst_lo;
4692
4693 dst_lo = &lo_reg0;
4694 src_lo = &lo_reg1;
4695 coerce_reg_to_size(dst_lo, 4);
4696 coerce_reg_to_size(src_lo, 4);
4697
4577 if (dst_reg->type == SCALAR_VALUE && 4698 if (dst_reg->type == SCALAR_VALUE &&
4578 regs[insn->src_reg].type == SCALAR_VALUE) { 4699 src_reg->type == SCALAR_VALUE) {
4579 if (tnum_is_const(regs[insn->src_reg].var_off)) 4700 if (tnum_is_const(src_reg->var_off) ||
4701 (is_jmp32 && tnum_is_const(src_lo->var_off)))
4580 reg_set_min_max(&other_branch_regs[insn->dst_reg], 4702 reg_set_min_max(&other_branch_regs[insn->dst_reg],
4581 dst_reg, regs[insn->src_reg].var_off.value, 4703 dst_reg,
4582 opcode); 4704 is_jmp32
4583 else if (tnum_is_const(dst_reg->var_off)) 4705 ? src_lo->var_off.value
4706 : src_reg->var_off.value,
4707 opcode, is_jmp32);
4708 else if (tnum_is_const(dst_reg->var_off) ||
4709 (is_jmp32 && tnum_is_const(dst_lo->var_off)))
4584 reg_set_min_max_inv(&other_branch_regs[insn->src_reg], 4710 reg_set_min_max_inv(&other_branch_regs[insn->src_reg],
4585 &regs[insn->src_reg], 4711 src_reg,
4586 dst_reg->var_off.value, opcode); 4712 is_jmp32
4587 else if (opcode == BPF_JEQ || opcode == BPF_JNE) 4713 ? dst_lo->var_off.value
4714 : dst_reg->var_off.value,
4715 opcode, is_jmp32);
4716 else if (!is_jmp32 &&
4717 (opcode == BPF_JEQ || opcode == BPF_JNE))
4588 /* Comparing for equality, we can combine knowledge */ 4718 /* Comparing for equality, we can combine knowledge */
4589 reg_combine_min_max(&other_branch_regs[insn->src_reg], 4719 reg_combine_min_max(&other_branch_regs[insn->src_reg],
4590 &other_branch_regs[insn->dst_reg], 4720 &other_branch_regs[insn->dst_reg],
4591 &regs[insn->src_reg], 4721 src_reg, dst_reg, opcode);
4592 &regs[insn->dst_reg], opcode);
4593 } 4722 }
4594 } else if (dst_reg->type == SCALAR_VALUE) { 4723 } else if (dst_reg->type == SCALAR_VALUE) {
4595 reg_set_min_max(&other_branch_regs[insn->dst_reg], 4724 reg_set_min_max(&other_branch_regs[insn->dst_reg],
4596 dst_reg, insn->imm, opcode); 4725 dst_reg, insn->imm, opcode, is_jmp32);
4597 } 4726 }
4598 4727
4599 /* detect if R == 0 where R is returned from bpf_map_lookup_elem() */ 4728 /* detect if R == 0 where R is returned from bpf_map_lookup_elem().
4600 if (BPF_SRC(insn->code) == BPF_K && 4729 * NOTE: these optimizations below are related with pointer comparison
4730 * which will never be JMP32.
4731 */
4732 if (!is_jmp32 && BPF_SRC(insn->code) == BPF_K &&
4601 insn->imm == 0 && (opcode == BPF_JEQ || opcode == BPF_JNE) && 4733 insn->imm == 0 && (opcode == BPF_JEQ || opcode == BPF_JNE) &&
4602 reg_type_may_be_null(dst_reg->type)) { 4734 reg_type_may_be_null(dst_reg->type)) {
4603 /* Mark all identical registers in each branch as either 4735 /* Mark all identical registers in each branch as either
@@ -4926,7 +5058,8 @@ peek_stack:
4926 goto check_state; 5058 goto check_state;
4927 t = insn_stack[cur_stack - 1]; 5059 t = insn_stack[cur_stack - 1];
4928 5060
4929 if (BPF_CLASS(insns[t].code) == BPF_JMP) { 5061 if (BPF_CLASS(insns[t].code) == BPF_JMP ||
5062 BPF_CLASS(insns[t].code) == BPF_JMP32) {
4930 u8 opcode = BPF_OP(insns[t].code); 5063 u8 opcode = BPF_OP(insns[t].code);
4931 5064
4932 if (opcode == BPF_EXIT) { 5065 if (opcode == BPF_EXIT) {
@@ -6082,7 +6215,7 @@ static int do_check(struct bpf_verifier_env *env)
6082 if (err) 6215 if (err)
6083 return err; 6216 return err;
6084 6217
6085 } else if (class == BPF_JMP) { 6218 } else if (class == BPF_JMP || class == BPF_JMP32) {
6086 u8 opcode = BPF_OP(insn->code); 6219 u8 opcode = BPF_OP(insn->code);
6087 6220
6088 if (opcode == BPF_CALL) { 6221 if (opcode == BPF_CALL) {
@@ -6090,7 +6223,8 @@ static int do_check(struct bpf_verifier_env *env)
6090 insn->off != 0 || 6223 insn->off != 0 ||
6091 (insn->src_reg != BPF_REG_0 && 6224 (insn->src_reg != BPF_REG_0 &&
6092 insn->src_reg != BPF_PSEUDO_CALL) || 6225 insn->src_reg != BPF_PSEUDO_CALL) ||
6093 insn->dst_reg != BPF_REG_0) { 6226 insn->dst_reg != BPF_REG_0 ||
6227 class == BPF_JMP32) {
6094 verbose(env, "BPF_CALL uses reserved fields\n"); 6228 verbose(env, "BPF_CALL uses reserved fields\n");
6095 return -EINVAL; 6229 return -EINVAL;
6096 } 6230 }
@@ -6106,7 +6240,8 @@ static int do_check(struct bpf_verifier_env *env)
6106 if (BPF_SRC(insn->code) != BPF_K || 6240 if (BPF_SRC(insn->code) != BPF_K ||
6107 insn->imm != 0 || 6241 insn->imm != 0 ||
6108 insn->src_reg != BPF_REG_0 || 6242 insn->src_reg != BPF_REG_0 ||
6109 insn->dst_reg != BPF_REG_0) { 6243 insn->dst_reg != BPF_REG_0 ||
6244 class == BPF_JMP32) {
6110 verbose(env, "BPF_JA uses reserved fields\n"); 6245 verbose(env, "BPF_JA uses reserved fields\n");
6111 return -EINVAL; 6246 return -EINVAL;
6112 } 6247 }
@@ -6118,7 +6253,8 @@ static int do_check(struct bpf_verifier_env *env)
6118 if (BPF_SRC(insn->code) != BPF_K || 6253 if (BPF_SRC(insn->code) != BPF_K ||
6119 insn->imm != 0 || 6254 insn->imm != 0 ||
6120 insn->src_reg != BPF_REG_0 || 6255 insn->src_reg != BPF_REG_0 ||
6121 insn->dst_reg != BPF_REG_0) { 6256 insn->dst_reg != BPF_REG_0 ||
6257 class == BPF_JMP32) {
6122 verbose(env, "BPF_EXIT uses reserved fields\n"); 6258 verbose(env, "BPF_EXIT uses reserved fields\n");
6123 return -EINVAL; 6259 return -EINVAL;
6124 } 6260 }
@@ -6635,6 +6771,9 @@ static bool insn_is_cond_jump(u8 code)
6635{ 6771{
6636 u8 op; 6772 u8 op;
6637 6773
6774 if (BPF_CLASS(code) == BPF_JMP32)
6775 return true;
6776
6638 if (BPF_CLASS(code) != BPF_JMP) 6777 if (BPF_CLASS(code) != BPF_JMP)
6639 return false; 6778 return false;
6640 6779