[PATCH 1/5] bpf: Clear callee saved regs after updating REG0

David Vernet
2022-08-08T15:54:02Z

In the verifier, we currently reset all of the registers containing caller
saved args before updating the callee's return register (REG0). In a
follow-on patch, we will need to be able to be able to inspect the caller
saved registers when updating REG0 to determine if a dynptr that's passed
to a helper function was allocated by a helper, or allocated by a program.

This patch therefore updates check_helper_call() to clear the caller saved
regs after updating REG0.

Signed-off-by: David Vernet <void@manifault.com>
---
kernel/bpf/verifier.c | 15 ++++++++++-----
1 file changed, 10 insertions(+), 5 deletions(-)

diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index 096fdac70165..938ba1536249 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -7348,11 +7348,9 @@ static int check_helper_call(struct bpf_verifier_env *env, struct bpf_insn *insn
if (err)
return err;

- /* reset caller saved regs */
- for (i = 0; i < CALLER_SAVED_REGS; i++) {
- mark_reg_not_init(env, regs, caller_saved[i]);
- check_reg_arg(env, caller_saved[i], DST_OP_NO_MARK);
- }
+ /* reset return reg */
+ mark_reg_not_init(env, regs, BPF_REG_0);
+ check_reg_arg(env, BPF_REG_0, DST_OP_NO_MARK);

/* helper call returns 64-bit value. */
regs[BPF_REG_0].subreg_def = DEF_NOT_SUBREG;
@@ -7488,6 +7486,13 @@ static int check_helper_call(struct bpf_verifier_env *env, struct bpf_insn *insn
regs[BPF_REG_0].ref_obj_id = dynptr_id;
}

+ /* reset remaining caller saved regs */
+ BUILD_BUG_ON(caller_saved[0] != BPF_REG_0);
+ for (i = 1; i < CALLER_SAVED_REGS; i++) {
+ mark_reg_not_init(env, regs, caller_saved[i]);
+ check_reg_arg(env, caller_saved[i], DST_OP_NO_MARK);
+ }
+
do_refine_retval_range(regs, fn->ret_type, func_id, &meta);

err = check_map_func_compatibility(env, meta.map_ptr, func_id);
--
2.30.2