| @@ -1792,6 +1792,17 @@ static const int caller_saved[CALLER_SAVED_REGS] = { · 1791 unmodified lines |
| 1792 | 1792 | BPF_REG_0, BPF_REG_1, BPF_REG_2, BPF_REG_3, BPF_REG_4, BPF_REG_5 |
| 1793 | 1793 | }; |
| 1794 | 1794 | |
| 1795 | +static void bpf_diag_record_caller_saved(struct bpf_verifier_env *env, |
| 1796 | + struct bpf_reg_state *regs) |
| 1797 | +{ |
| 1798 | + int i; |
| 1799 | + |
| 1800 | + for (i = 1; i < CALLER_SAVED_REGS; i++) { |
| 1801 | + bpf_diag_record_scrub(env, ®s[caller_saved[i]], |
| 1802 | + BPF_DIAG_MOD_CALLER_SAVED); |
| 1803 | + } |
| 1804 | +} |
| 1805 | + |
| 1795 | 1806 | /* This helper doesn't clear reg->id */ |
| 1796 | 1807 | static void ___mark_reg_known(struct bpf_reg_state *reg, u64 imm) |
| 1797 | 1808 | { |
| @@ -2245,6 +2256,7 @@ static void init_func_state(struct bpf_verifier_env *env, · 447 unmodified lines |
| 2245 | 2256 | { |
| 2246 | 2257 | state->callsite = callsite; |
| 2247 | 2258 | state->frameno = frameno; |
| 2259 | + bpf_diag_init_frame(env, state); |
| 2248 | 2260 | state->subprogno = subprogno; |
| 2249 | 2261 | state->callback_ret_range = retval_range(0, 0); |
| 2250 | 2262 | init_reg_state(env, state); |
| @@ -3362,6 +3374,7 @@ static void save_register_state(struct bpf_verifier_env *env, · 1111 unmodified lines |
| 3362 | 3374 | { |
| 3363 | 3375 | int i; |
| 3364 | 3376 | |
| 3377 | + bpf_diag_mod_begin(env, &state->stack[spi].spilled_ptr, reg, BPF_DIAG_MOD_SPILL); |
| 3365 | 3378 | state->stack[spi].spilled_ptr = *reg; |
| 3366 | 3379 | |
| 3367 | 3380 | for (i = BPF_REG_SIZE; i > BPF_REG_SIZE - size; i--) |
| @@ -3370,6 +3383,8 @@ static void save_register_state(struct bpf_verifier_env *env, · 2 unmodified lines |
| 3370 | 3383 | /* size < 8 bytes spill */ |
| 3371 | 3384 | for (; i; i--) |
| 3372 | 3385 | mark_stack_slot_misc(env, &state->stack[spi].slot_type[i - 1]); |
| 3386 | + |
| 3387 | + bpf_diag_mod_end(env); |
| 3373 | 3388 | } |
| 3374 | 3389 | |
| 3375 | 3390 | static bool is_bpf_st_mem(struct bpf_insn *insn) |
| @@ -3506,6 +3521,9 @@ static int check_stack_write_fixed_off(struct bpf_verifier_env *env, · 130 unmodified lines |
| 3506 | 3521 | } else { |
| 3507 | 3522 | u8 type = STACK_MISC; |
| 3508 | 3523 | |
| 3524 | + if (bpf_is_spilled_reg(&state->stack[spi])) |
| 3525 | + bpf_diag_record_scrub(env, &state->stack[spi].spilled_ptr, |
| 3526 | + BPF_DIAG_MOD_WRITE); |
| 3509 | 3527 | scrub_special_slot(state, spi); |
| 3510 | 3528 | |
| 3511 | 3529 | /* when we zero initialize stack slots mark them as such */ |
| @@ -3666,6 +3684,8 @@ static int check_stack_write_var_off(struct bpf_verifier_env *env, · 154 unmodified lines |
| 3666 | 3684 | if (err) |
| 3667 | 3685 | return err; |
| 3668 | 3686 | } |
| 3687 | + bpf_diag_record_scrub_stack(env, state, min_off, max_off, |
| 3688 | + BPF_DIAG_MOD_VAR_WRITE); |
| 3669 | 3689 | return 0; |
| 3670 | 3690 | } |
| 3671 | 3691 | |
| @@ -3758,6 +3778,12 @@ static int check_stack_read_fixed_off(struct bpf_verifier_env *env, · 86 unmodified lines |
| 3758 | 3778 | mark_stack_slot_scratched(env, spi); |
| 3759 | 3779 | check_fastcall_stack_contract(env, state, env->insn_idx, off); |
| 3760 | 3780 | |
| 3781 | + /* |
| 3782 | + * Refine the in-progress load record's origin to the source stack slot. |
| 3783 | + */ |
| 3784 | + if (dst_regno >= 0) |
| 3785 | + bpf_diag_mod_begin(env, &state->regs[dst_regno], reg, BPF_DIAG_MOD_WRITE); |
| 3786 | + |
| 3761 | 3787 | if (bpf_is_spilled_reg(®_state->stack[spi])) { |
| 3762 | 3788 | u8 spill_size = 1; |
| 3763 | 3789 | |
| @@ -4051,14 +4077,17 @@ static int check_stack_arg_write(struct bpf_verifier_env *env, struct bpf_func_s · 287 unmodified lines |
| 4051 | 4077 | if (spi + 1 > subprog->max_out_stack_arg_cnt) |
| 4052 | 4078 | subprog->max_out_stack_arg_cnt = spi + 1; |
| 4053 | 4079 | |
| 4080 | + arg = &state->stack_arg_regs[spi]; |
| 4081 | + bpf_diag_mod_begin(env, arg, value_reg, BPF_DIAG_MOD_WRITE); |
| 4082 | + |
| 4054 | 4083 | if (value_reg) { |
| 4055 | 4084 | state->stack_arg_regs[spi] = *value_reg; |
| 4056 | 4085 | } else { |
| 4057 | 4086 | /* BPF_ST: store immediate, treat as scalar */ |
| 4058 | | − arg = &state->stack_arg_regs[spi]; |
| 4059 | 4087 | arg->type = SCALAR_VALUE; |
| 4060 | 4088 | __mark_reg_known(arg, env->prog->insnsi[env->insn_idx].imm); |
| 4061 | 4089 | } |
| 4090 | + bpf_diag_mod_end(env); |
| 4062 | 4091 | state->no_stack_arg_load = true; |
| 4063 | 4092 | return bpf_push_jmp_history(env, env->cur_state, |
| 4064 | 4093 | INSN_F_STACK_ARG_ACCESS, spi, 0, 0); |
| @@ -4091,7 +4120,9 @@ static int check_stack_arg_read(struct bpf_verifier_env *env, struct bpf_func_st · 26 unmodified lines |
| 4091 | 4120 | caller = vstate->frame[vstate->curframe - 1]; |
| 4092 | 4121 | arg = &caller->stack_arg_regs[spi]; |
| 4093 | 4122 | cur = vstate->frame[vstate->curframe]; |
| 4123 | + bpf_diag_mod_begin(env, &cur->regs[dst_regno], arg, BPF_DIAG_MOD_WRITE); |
| 4094 | 4124 | cur->regs[dst_regno] = *arg; |
| 4125 | + bpf_diag_mod_end(env); |
| 4095 | 4126 | return bpf_push_jmp_history(env, env->cur_state, |
| 4096 | 4127 | INSN_F_STACK_ARG_ACCESS, spi, 0, 0); |
| 4097 | 4128 | } |
| @@ -6426,15 +6457,19 @@ static int check_load_mem(struct bpf_verifier_env *env, struct bpf_insn *insn, · 2328 unmodified lines |
| 6426 | 6457 | |
| 6427 | 6458 | src_reg_type = regs[insn->src_reg].type; |
| 6428 | 6459 | |
| 6429 | | − /* Check if (src_reg + off) is readable. The state of dst_reg will be |
| 6430 | | − * updated by this call. |
| 6460 | + /* |
| 6461 | + * check_stack_read_fixed_off() may refine the modification's origin to |
| 6462 | + * the source stack slot. |
| 6431 | 6463 | */ |
| 6464 | + bpf_diag_mod_begin(env, ®s[insn->dst_reg], NULL, BPF_DIAG_MOD_WRITE); |
| 6432 | 6465 | err = check_mem_access(env, env->insn_idx, regs + insn->src_reg, argno_from_reg(insn->src_reg), insn->off, |
| 6433 | 6466 | BPF_SIZE(insn->code), BPF_READ, insn->dst_reg, |
| 6434 | 6467 | strict_alignment_once, is_ldsx); |
| 6435 | 6468 | err = err ?: save_aux_ptr_type(env, src_reg_type, |
| 6436 | 6469 | allow_trust_mismatch); |
| 6437 | 6470 | err = err ?: reg_bounds_sanity_check(env, ®s[insn->dst_reg], ctx); |
| 6471 | + if (!err) |
| 6472 | + bpf_diag_mod_end(env); |
| 6438 | 6473 | |
| 6439 | 6474 | return err; |
| 6440 | 6475 | } |
| @@ -6540,10 +6575,14 @@ static int check_atomic_rmw(struct bpf_verifier_env *env, · 99 unmodified lines |
| 6540 | 6575 | */ |
| 6541 | 6576 | err = check_mem_access(env, env->insn_idx, dst_reg, argno_from_reg(insn->dst_reg), insn->off, |
| 6542 | 6577 | BPF_SIZE(insn->code), BPF_READ, -1, true, false); |
| 6543 | | − if (!err && load_reg >= 0) |
| 6578 | + if (!err && load_reg >= 0) { |
| 6579 | + bpf_diag_mod_begin(env, cur_regs(env) + load_reg, NULL, BPF_DIAG_MOD_WRITE); |
| 6544 | 6580 | err = check_mem_access(env, env->insn_idx, dst_reg, argno_from_reg(insn->dst_reg), |
| 6545 | 6581 | insn->off, BPF_SIZE(insn->code), |
| 6546 | 6582 | BPF_READ, load_reg, true, false); |
| 6583 | + if (!err) |
| 6584 | + bpf_diag_mod_end(env); |
| 6585 | + } |
| 6547 | 6586 | if (err) |
| 6548 | 6587 | return err; |
| 6549 | 6588 | |
| @@ -8945,8 +8984,10 @@ static void clear_all_pkt_pointers(struct bpf_verifier_env *env) · 2395 unmodified lines |
| 8945 | 8984 | struct bpf_reg_state *reg; |
| 8946 | 8985 | |
| 8947 | 8986 | bpf_for_each_reg_in_vstate(env->cur_state, state, reg, ({ |
| 8948 | | − if (reg_is_pkt_pointer_any(reg) || reg_is_dynptr_slice_pkt(reg)) |
| 8987 | + if (reg_is_pkt_pointer_any(reg) || reg_is_dynptr_slice_pkt(reg)) { |
| 8988 | + bpf_diag_record_scrub(env, reg, BPF_DIAG_MOD_PKT_DATA_CHANGE); |
| 8949 | 8989 | mark_reg_invalid(env, reg); |
| 8990 | + } |
| 8950 | 8991 | })); |
| 8951 | 8992 | } |
| 8952 | 8993 | |
| @@ -9062,10 +9103,25 @@ static int release_reference(struct bpf_verifier_env *env, int id) · 109 unmodified lines |
| 9062 | 9103 | return err; |
| 9063 | 9104 | } |
| 9064 | 9105 | |
| 9106 | + /* |
| 9107 | + * A dynptr occupies two stack slots that invalidate_dynptr() |
| 9108 | + * clears together. Record both scrubs before invalidating it. |
| 9109 | + */ |
| 9110 | + if (stack && stack->slot_type[BPF_REG_SIZE - 1] == STACK_DYNPTR) { |
| 9111 | + struct bpf_stack_state *dyn_stack = stack; |
| 9112 | + |
| 9113 | + if (reg->dynptr.first_slot) |
| 9114 | + dyn_stack--; |
| 9115 | + bpf_diag_record_scrub(env, &dyn_stack[0].spilled_ptr, |
| 9116 | + BPF_DIAG_MOD_REF_RELEASE); |
| 9117 | + bpf_diag_record_scrub(env, &dyn_stack[1].spilled_ptr, |
| 9118 | + BPF_DIAG_MOD_REF_RELEASE); |
| 9119 | + invalidate_dynptr(env, dyn_stack); |
| 9120 | + continue; |
| 9121 | + } |
| 9122 | + bpf_diag_record_scrub(env, reg, BPF_DIAG_MOD_REF_RELEASE); |
| 9065 | 9123 | if (!stack || stack->slot_type[BPF_REG_SIZE - 1] == STACK_SPILL) |
| 9066 | 9124 | mark_reg_invalid(env, reg); |
| 9067 | | − else if (stack->slot_type[BPF_REG_SIZE - 1] == STACK_DYNPTR) |
| 9068 | | − invalidate_dynptr(env, stack); |
| 9069 | 9125 | })); |
| 9070 | 9126 | } |
| 9071 | 9127 | |
| @@ -9078,8 +9134,10 @@ static void invalidate_non_owning_refs(struct bpf_verifier_env *env) · 6 unmodified lines |
| 9078 | 9134 | struct bpf_reg_state *reg; |
| 9079 | 9135 | |
| 9080 | 9136 | bpf_for_each_reg_in_vstate(env->cur_state, unused, reg, ({ |
| 9081 | | − if (type_is_non_owning_ref(reg->type)) |
| 9137 | + if (type_is_non_owning_ref(reg->type)) { |
| 9138 | + bpf_diag_record_scrub(env, reg, BPF_DIAG_MOD_NON_OWN_REF); |
| 9082 | 9139 | mark_reg_invalid(env, reg); |
| 9140 | + } |
| 9083 | 9141 | })); |
| 9084 | 9142 | } |
| 9085 | 9143 | |
| @@ -9092,8 +9150,10 @@ static void invalidate_rcu_protected_refs(struct bpf_verifier_env *env) · 6 unmodified lines |
| 9092 | 9150 | |
| 9093 | 9151 | bpf_for_each_reg_in_vstate_mask(env->cur_state, state, reg, stack, clear_mask, ({ |
| 9094 | 9152 | if (reg->type & MEM_RCU) { |
| 9153 | + bpf_diag_mod_begin(env, reg, NULL, BPF_DIAG_MOD_WRITE); |
| 9095 | 9154 | reg->type &= ~(MEM_RCU | PTR_MAYBE_NULL); |
| 9096 | 9155 | reg->type |= PTR_UNTRUSTED; |
| 9156 | + bpf_diag_mod_end(env); |
| 9097 | 9157 | } |
| 9098 | 9158 | })); |
| 9099 | 9159 | } |
| @@ -9110,9 +9170,11 @@ static int ref_convert_alloc_rcu_protected(struct bpf_verifier_env *env, u32 id) · 10 unmodified lines |
| 9110 | 9170 | if (reg->id != id) |
| 9111 | 9171 | continue; |
| 9112 | 9172 | if ((reg->type & MEM_ALLOC) && (reg->type & MEM_PERCPU)) { |
| 9173 | + bpf_diag_mod_begin(env, reg, NULL, BPF_DIAG_MOD_WRITE); |
| 9113 | 9174 | reg->id = 0; |
| 9114 | 9175 | reg->type &= ~MEM_ALLOC; |
| 9115 | 9176 | reg->type |= MEM_RCU; |
| 9177 | + bpf_diag_mod_end(env); |
| 9116 | 9178 | } |
| 9117 | 9179 | })); |
| 9118 | 9180 | |
| @@ -9124,6 +9186,8 @@ static void clear_caller_saved_regs(struct bpf_verifier_env *env, · 5 unmodified lines |
| 9124 | 9186 | { |
| 9125 | 9187 | int i; |
| 9126 | 9188 | |
| 9189 | + bpf_diag_record_caller_saved(env, regs); |
| 9190 | + |
| 9127 | 9191 | /* after the call registers r0 - r5 were scratched */ |
| 9128 | 9192 | for (i = 0; i < CALLER_SAVED_REGS; i++) { |
| 9129 | 9193 | bpf_mark_reg_not_init(env, ®s[caller_saved[i]]); |
| @@ -9131,13 +9195,15 @@ static void clear_caller_saved_regs(struct bpf_verifier_env *env, · 1 unmodified line |
| 9131 | 9195 | } |
| 9132 | 9196 | } |
| 9133 | 9197 | |
| 9134 | | −static void invalidate_outgoing_stack_args(const struct bpf_verifier_env *env, |
| 9198 | +static void invalidate_outgoing_stack_args(struct bpf_verifier_env *env, |
| 9135 | 9199 | struct bpf_func_state *state) |
| 9136 | 9200 | { |
| 9137 | 9201 | int i, nslots = state->out_stack_arg_cnt; |
| 9138 | 9202 | |
| 9139 | | − for (i = 0; i < nslots; i++) |
| 9203 | + for (i = 0; i < nslots; i++) { |
| 9204 | + bpf_diag_record_scrub(env, &state->stack_arg_regs[i], BPF_DIAG_MOD_CALLER_SAVED); |
| 9140 | 9205 | bpf_mark_reg_not_init(env, &state->stack_arg_regs[i]); |
| 9206 | + } |
| 9141 | 9207 | } |
| 9142 | 9208 | |
| 9143 | 9209 | typedef int (*set_callee_state_fn)(struct bpf_verifier_env *env, |
| @@ -9436,6 +9502,7 @@ static int check_func_call(struct bpf_verifier_env *env, struct bpf_insn *insn, · 292 unmodified lines |
| 9436 | 9502 | return err; |
| 9437 | 9503 | if (bpf_subprog_is_global(env, subprog)) { |
| 9438 | 9504 | const char *sub_name = bpf_subprog_name(env, subprog); |
| 9505 | + bool returns_void; |
| 9439 | 9506 | |
| 9440 | 9507 | if (env->cur_state->active_locks) { |
| 9441 | 9508 | verbose(env, "global function calls are not allowed while holding a lock,\n" |
| @@ -9458,16 +9525,22 @@ static int check_func_call(struct bpf_verifier_env *env, struct bpf_insn *insn, · 16 unmodified lines |
| 9458 | 9525 | if (env->log.level & BPF_LOG_LEVEL) |
| 9459 | 9526 | verbose(env, "Func#%d ('%s') is global and assumed valid.\n", |
| 9460 | 9527 | subprog, sub_name); |
| 9528 | + returns_void = subprog_returns_void(env, subprog); |
| 9461 | 9529 | if (env->subprog_info[subprog].changes_pkt_data) |
| 9462 | 9530 | clear_all_pkt_pointers(env); |
| 9463 | 9531 | /* mark global subprog for verifying after main prog */ |
| 9464 | 9532 | subprog_aux(env, subprog)->called = true; |
| 9533 | + if (returns_void) |
| 9534 | + bpf_diag_record_scrub(env, &caller->regs[BPF_REG_0], BPF_DIAG_MOD_CALLER_SAVED); |
| 9535 | + else |
| 9536 | + bpf_diag_mod_begin(env, &caller->regs[BPF_REG_0], NULL, BPF_DIAG_MOD_WRITE); |
| 9465 | 9537 | clear_caller_saved_regs(env, caller->regs); |
| 9466 | 9538 | invalidate_outgoing_stack_args(env, cur_func(env)); |
| 9467 | 9539 | |
| 9468 | 9540 | /* All non-void global functions return a 64-bit SCALAR_VALUE. */ |
| 9469 | | − if (!subprog_returns_void(env, subprog)) { |
| 9541 | + if (!returns_void) { |
| 9470 | 9542 | mark_reg_unknown(env, caller->regs, BPF_REG_0); |
| 9543 | + bpf_diag_mod_end(env); |
| 9471 | 9544 | } |
| 9472 | 9545 | |
| 9473 | 9546 | if (env->subprog_info[subprog].might_throw) { |
| @@ -9502,6 +9575,7 @@ static int check_func_call(struct bpf_verifier_env *env, struct bpf_insn *insn, · 28 unmodified lines |
| 9502 | 9575 | if (err) |
| 9503 | 9576 | return err; |
| 9504 | 9577 | |
| 9578 | + bpf_diag_record_scrub(env, &caller->regs[BPF_REG_0], BPF_DIAG_MOD_CALLER_SAVED); |
| 9505 | 9579 | clear_caller_saved_regs(env, caller->regs); |
| 9506 | 9580 | |
| 9507 | 9581 | /* and go analyze first insn of the callee */ |
| @@ -9865,7 +9939,9 @@ static int prepare_func_exit(struct bpf_verifier_env *env, int *insn_idx) · 357 unmodified lines |
| 9865 | 9939 | } |
| 9866 | 9940 | } else { |
| 9867 | 9941 | /* return to the caller whatever r0 had in the callee */ |
| 9942 | + bpf_diag_mod_begin(env, &caller->regs[BPF_REG_0], r0, BPF_DIAG_MOD_WRITE); |
| 9868 | 9943 | caller->regs[BPF_REG_0] = *r0; |
| 9944 | + bpf_diag_mod_end(env); |
| 9869 | 9945 | } |
| 9870 | 9946 | |
| 9871 | 9947 | /* for callbacks like bpf_loop or bpf_for_each_map_elem go back to callsite, |
| @@ -10518,12 +10594,14 @@ static int check_helper_call(struct bpf_verifier_env *env, struct bpf_insn *insn · 646 unmodified lines |
| 10518 | 10594 | return err; |
| 10519 | 10595 | |
| 10520 | 10596 | /* reset caller saved regs */ |
| 10597 | + bpf_diag_record_caller_saved(env, regs); |
| 10521 | 10598 | for (i = 0; i < CALLER_SAVED_REGS; i++) { |
| 10522 | 10599 | bpf_mark_reg_not_init(env, ®s[caller_saved[i]]); |
| 10523 | 10600 | check_reg_arg(env, caller_saved[i], DST_OP_NO_MARK); |
| 10524 | 10601 | } |
| 10525 | 10602 | invalidate_outgoing_stack_args(env, cur_func(env)); |
| 10526 | 10603 | |
| 10604 | + bpf_diag_mod_begin(env, ®s[BPF_REG_0], NULL, BPF_DIAG_MOD_WRITE); |
| 10527 | 10605 | /* update return register (already marked as written above) */ |
| 10528 | 10606 | ret_type = fn->ret_type; |
| 10529 | 10607 | ret_flag = type_flag(ret_type); |
| @@ -10672,6 +10750,8 @@ static int check_helper_call(struct bpf_verifier_env *env, struct bpf_insn *insn · 142 unmodified lines |
| 10672 | 10750 | if (err) |
| 10673 | 10751 | return err; |
| 10674 | 10752 | |
| 10753 | + bpf_diag_mod_end(env); |
| 10754 | + |
| 10675 | 10755 | /* |
| 10676 | 10756 | * In order for a release of any of the original or cast pointers |
| 10677 | 10757 | * to invalidate all other pointers, reuse the same reference id for |
| @@ -10688,6 +10768,7 @@ static int check_helper_call(struct bpf_verifier_env *env, struct bpf_insn *insn · 10 unmodified lines |
| 10688 | 10768 | __mark_reg_known_zero(r0); |
| 10689 | 10769 | r0->type = SCALAR_VALUE; |
| 10690 | 10770 | |
| 10771 | + bpf_diag_mod_begin(env, ®s[BPF_REG_0], NULL, BPF_DIAG_MOD_WRITE); |
| 10691 | 10772 | regs[BPF_REG_0].type &= ~PTR_MAYBE_NULL; |
| 10692 | 10773 | regs[BPF_REG_0].id = meta.ref_obj.id; |
| 10693 | 10774 | } else if (is_acquire_function(func_id, meta.map.ptr)) { |
| @@ -10706,6 +10787,8 @@ static int check_helper_call(struct bpf_verifier_env *env, struct bpf_insn *insn · 12 unmodified lines |
| 10706 | 10787 | if (err) |
| 10707 | 10788 | return err; |
| 10708 | 10789 | |
| 10790 | + bpf_diag_mod_end(env); |
| 10791 | + |
| 10709 | 10792 | err = check_map_func_compatibility(env, meta.map.ptr, func_id); |
| 10710 | 10793 | if (err) |
| 10711 | 10794 | return err; |
| @@ -13211,6 +13294,8 @@ static int check_kfunc_call(struct bpf_verifier_env *env, struct bpf_insn *insn, · 2499 unmodified lines |
| 13211 | 13294 | } |
| 13212 | 13295 | } |
| 13213 | 13296 | |
| 13297 | + bpf_diag_record_caller_saved(env, regs); |
| 13298 | + bpf_diag_mod_begin(env, ®s[BPF_REG_0], NULL, BPF_DIAG_MOD_WRITE); |
| 13214 | 13299 | for (i = 0; i < CALLER_SAVED_REGS; i++) { |
| 13215 | 13300 | u32 regno = caller_saved[i]; |
| 13216 | 13301 | |
| @@ -13362,6 +13447,12 @@ static int check_kfunc_call(struct bpf_verifier_env *env, struct bpf_insn *insn, · 145 unmodified lines |
| 13362 | 13447 | caller_info->stack_arg_cnt = stack_arg_cnt; |
| 13363 | 13448 | } |
| 13364 | 13449 | |
| 13450 | + /* |
| 13451 | + * Record R0 before process_iter_next_call() snapshots the alternate |
| 13452 | + * iterator path's diagnostic position. |
| 13453 | + */ |
| 13454 | + bpf_diag_mod_end(env); |
| 13455 | + |
| 13365 | 13456 | if (bpf_is_iter_next_kfunc(&meta)) { |
| 13366 | 13457 | err = process_iter_next_call(env, insn_idx, &meta); |
| 13367 | 13458 | if (err) |
| @@ -15004,6 +15095,8 @@ static int check_alu_op(struct bpf_verifier_env *env, struct bpf_insn *insn) · 1636 unmodified lines |
| 15004 | 15095 | u8 opcode = BPF_OP(insn->code); |
| 15005 | 15096 | int err; |
| 15006 | 15097 | |
| 15098 | + bpf_diag_mod_begin(env, ®s[insn->dst_reg], NULL, BPF_DIAG_MOD_WRITE); |
| 15099 | + |
| 15007 | 15100 | if (opcode == BPF_END || opcode == BPF_NEG) { |
| 15008 | 15101 | /* check src operand */ |
| 15009 | 15102 | err = check_reg_arg(env, insn->dst_reg, SRC_OP); |
| @@ -15177,7 +15270,12 @@ static int check_alu_op(struct bpf_verifier_env *env, struct bpf_insn *insn) · 167 unmodified lines |
| 15177 | 15270 | return err; |
| 15178 | 15271 | } |
| 15179 | 15272 | |
| 15180 | | − return reg_bounds_sanity_check(env, ®s[insn->dst_reg], "alu"); |
| 15273 | + err = reg_bounds_sanity_check(env, ®s[insn->dst_reg], "alu"); |
| 15274 | + if (err) |
| 15275 | + return err; |
| 15276 | + |
| 15277 | + bpf_diag_mod_end(env); |
| 15278 | + return 0; |
| 15181 | 15279 | } |
| 15182 | 15280 | |
| 15183 | 15281 | static void find_good_pkt_pointers(struct bpf_verifier_state *vstate, |
| @@ -16271,11 +16369,13 @@ static int check_ld_imm(struct bpf_verifier_env *env, struct bpf_insn *insn) · 1087 unmodified lines |
| 16271 | 16369 | return err; |
| 16272 | 16370 | |
| 16273 | 16371 | dst_reg = ®s[insn->dst_reg]; |
| 16372 | + bpf_diag_mod_begin(env, dst_reg, NULL, BPF_DIAG_MOD_WRITE); |
| 16274 | 16373 | if (insn->src_reg == 0) { |
| 16275 | 16374 | u64 imm = ((u64)(insn + 1)->imm << 32) | (u32)insn->imm; |
| 16276 | 16375 | |
| 16277 | 16376 | dst_reg->type = SCALAR_VALUE; |
| 16278 | 16377 | __mark_reg_known(®s[insn->dst_reg], imm); |
| 16378 | + bpf_diag_mod_end(env); |
| 16279 | 16379 | return 0; |
| 16280 | 16380 | } |
| 16281 | 16381 | |
| @@ -16299,6 +16399,7 @@ static int check_ld_imm(struct bpf_verifier_env *env, struct bpf_insn *insn) · 17 unmodified lines |
| 16299 | 16399 | verifier_bug(env, "pseudo btf id: unexpected dst reg type"); |
| 16300 | 16400 | return -EFAULT; |
| 16301 | 16401 | } |
| 16402 | + bpf_diag_mod_end(env); |
| 16302 | 16403 | return 0; |
| 16303 | 16404 | } |
| 16304 | 16405 | |
| @@ -16318,6 +16419,7 @@ static int check_ld_imm(struct bpf_verifier_env *env, struct bpf_insn *insn) · 13 unmodified lines |
| 16318 | 16419 | |
| 16319 | 16420 | dst_reg->type = PTR_TO_FUNC; |
| 16320 | 16421 | dst_reg->subprogno = subprogno; |
| 16422 | + bpf_diag_mod_end(env); |
| 16321 | 16423 | return 0; |
| 16322 | 16424 | } |
| 16323 | 16425 | |
| @@ -16328,6 +16430,7 @@ static int check_ld_imm(struct bpf_verifier_env *env, struct bpf_insn *insn) · 4 unmodified lines |
| 16328 | 16430 | if (map->map_type == BPF_MAP_TYPE_ARENA) { |
| 16329 | 16431 | __mark_reg_unknown(env, dst_reg); |
| 16330 | 16432 | dst_reg->map_ptr = map; |
| 16433 | + bpf_diag_mod_end(env); |
| 16331 | 16434 | return 0; |
| 16332 | 16435 | } |
| 16333 | 16436 | __mark_reg_known(dst_reg, aux->map_off); |
| @@ -16345,6 +16448,7 @@ static int check_ld_imm(struct bpf_verifier_env *env, struct bpf_insn *insn) · 11 unmodified lines |
| 16345 | 16448 | return -EFAULT; |
| 16346 | 16449 | } |
| 16347 | 16450 | |
| 16451 | + bpf_diag_mod_end(env); |
| 16348 | 16452 | return 0; |
| 16349 | 16453 | } |
| 16350 | 16454 | |
| @@ -16423,6 +16527,8 @@ static int check_ld_abs(struct bpf_verifier_env *env, struct bpf_insn *insn) · 72 unmodified lines |
| 16423 | 16527 | return err; |
| 16424 | 16528 | |
| 16425 | 16529 | /* reset caller saved regs to unreadable */ |
| 16530 | + bpf_diag_record_caller_saved(env, regs); |
| 16531 | + bpf_diag_mod_begin(env, ®s[BPF_REG_0], NULL, BPF_DIAG_MOD_WRITE); |
| 16426 | 16532 | for (i = 0; i < CALLER_SAVED_REGS; i++) { |
| 16427 | 16533 | bpf_mark_reg_not_init(env, ®s[caller_saved[i]]); |
| 16428 | 16534 | check_reg_arg(env, caller_saved[i], DST_OP_NO_MARK); |
| @@ -16433,6 +16539,7 @@ static int check_ld_abs(struct bpf_verifier_env *env, struct bpf_insn *insn) · 4 unmodified lines |
| 16433 | 16539 | * Already marked as written above. |
| 16434 | 16540 | */ |
| 16435 | 16541 | mark_reg_unknown(env, regs, BPF_REG_0); |
| 16542 | + bpf_diag_mod_end(env); |
| 16436 | 16543 | /* |
| 16437 | 16544 | * See bpf_gen_ld_abs() which emits a hidden BPF_EXIT with r0=0 |
| 16438 | 16545 | * which must be explored by the verifier when in a subprog. |