bpf: Mark PTR_TO_FUNC register initially with zero offset
authorDaniel Borkmann <daniel@iogearbox.net>
Fri, 14 Jan 2022 13:58:36 +0000 (13:58 +0000)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 27 Jan 2022 11:02:54 +0000 (12:02 +0100)
commit d400a6cf1c8a57cdf10f35220ead3284320d85ff upstream.

Similar as with other pointer types where we use ldimm64, clear the register
content to zero first, and then populate the PTR_TO_FUNC type and subprogno
number. Currently this is not done, and leads to reuse of stale register
tracking data.

Given for special ldimm64 cases we always clear the register offset, make it
common for all cases, so it won't be forgotten in future.

Fixes: 69c087ba6225 ("bpf: Add bpf_for_each_map_elem() helper")
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Acked-by: John Fastabend <john.fastabend@gmail.com>
Acked-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
kernel/bpf/verifier.c

index d48000b90eb8a1486e75b55ceaf12a5d040630d4..6b987407752ab0d137da8ca5f4af5c4ee98bc9ef 100644 (file)
@@ -9389,9 +9389,13 @@ static int check_ld_imm(struct bpf_verifier_env *env, struct bpf_insn *insn)
                return 0;
        }
 
-       if (insn->src_reg == BPF_PSEUDO_BTF_ID) {
-               mark_reg_known_zero(env, regs, insn->dst_reg);
+       /* All special src_reg cases are listed below. From this point onwards
+        * we either succeed and assign a corresponding dst_reg->type after
+        * zeroing the offset, or fail and reject the program.
+        */
+       mark_reg_known_zero(env, regs, insn->dst_reg);
 
+       if (insn->src_reg == BPF_PSEUDO_BTF_ID) {
                dst_reg->type = aux->btf_var.reg_type;
                switch (dst_reg->type) {
                case PTR_TO_MEM:
@@ -9429,7 +9433,6 @@ static int check_ld_imm(struct bpf_verifier_env *env, struct bpf_insn *insn)
        }
 
        map = env->used_maps[aux->map_index];
-       mark_reg_known_zero(env, regs, insn->dst_reg);
        dst_reg->map_ptr = map;
 
        if (insn->src_reg == BPF_PSEUDO_MAP_VALUE ||