mirror of
https://github.com/torvalds/linux.git
synced 2026-05-28 00:53:34 +02:00
bpf: make makr_btf_ld_reg return error for unexpected reg types
Non-functional change: mark_btf_ld_reg() expects 'reg_type' parameter to be either SCALAR_VALUE or PTR_TO_BTF_ID. Next commit expands this set, so update this function to fail if unexpected type is passed. Also update callers to propagate the error. Acked-by: Kumar Kartikeya Dwivedi <memxor@gmail.com> Signed-off-by: Eduard Zingerman <eddyz87@gmail.com> Link: https://lore.kernel.org/r/20250704230354.1323244-2-eddyz87@gmail.com Signed-off-by: Alexei Starovoitov <ast@kernel.org>
This commit is contained in:
parent
03fe01ddd1
commit
b9d44bc9fd
|
|
@ -2796,22 +2796,28 @@ static void mark_reg_not_init(struct bpf_verifier_env *env,
|
|||
__mark_reg_not_init(env, regs + regno);
|
||||
}
|
||||
|
||||
static void mark_btf_ld_reg(struct bpf_verifier_env *env,
|
||||
struct bpf_reg_state *regs, u32 regno,
|
||||
enum bpf_reg_type reg_type,
|
||||
struct btf *btf, u32 btf_id,
|
||||
enum bpf_type_flag flag)
|
||||
static int mark_btf_ld_reg(struct bpf_verifier_env *env,
|
||||
struct bpf_reg_state *regs, u32 regno,
|
||||
enum bpf_reg_type reg_type,
|
||||
struct btf *btf, u32 btf_id,
|
||||
enum bpf_type_flag flag)
|
||||
{
|
||||
if (reg_type == SCALAR_VALUE) {
|
||||
switch (reg_type) {
|
||||
case SCALAR_VALUE:
|
||||
mark_reg_unknown(env, regs, regno);
|
||||
return;
|
||||
return 0;
|
||||
case PTR_TO_BTF_ID:
|
||||
mark_reg_known_zero(env, regs, regno);
|
||||
regs[regno].type = PTR_TO_BTF_ID | flag;
|
||||
regs[regno].btf = btf;
|
||||
regs[regno].btf_id = btf_id;
|
||||
if (type_may_be_null(flag))
|
||||
regs[regno].id = ++env->id_gen;
|
||||
return 0;
|
||||
default:
|
||||
verifier_bug(env, "unexpected reg_type %d in %s\n", reg_type, __func__);
|
||||
return -EFAULT;
|
||||
}
|
||||
mark_reg_known_zero(env, regs, regno);
|
||||
regs[regno].type = PTR_TO_BTF_ID | flag;
|
||||
regs[regno].btf = btf;
|
||||
regs[regno].btf_id = btf_id;
|
||||
if (type_may_be_null(flag))
|
||||
regs[regno].id = ++env->id_gen;
|
||||
}
|
||||
|
||||
#define DEF_NOT_SUBREG (0)
|
||||
|
|
@ -5965,6 +5971,7 @@ static int check_map_kptr_access(struct bpf_verifier_env *env, u32 regno,
|
|||
struct bpf_insn *insn = &env->prog->insnsi[insn_idx];
|
||||
int class = BPF_CLASS(insn->code);
|
||||
struct bpf_reg_state *val_reg;
|
||||
int ret;
|
||||
|
||||
/* Things we already checked for in check_map_access and caller:
|
||||
* - Reject cases where variable offset may touch kptr
|
||||
|
|
@ -5998,8 +6005,11 @@ static int check_map_kptr_access(struct bpf_verifier_env *env, u32 regno,
|
|||
/* We can simply mark the value_regno receiving the pointer
|
||||
* value from map as PTR_TO_BTF_ID, with the correct type.
|
||||
*/
|
||||
mark_btf_ld_reg(env, cur_regs(env), value_regno, PTR_TO_BTF_ID, kptr_field->kptr.btf,
|
||||
kptr_field->kptr.btf_id, btf_ld_kptr_type(env, kptr_field));
|
||||
ret = mark_btf_ld_reg(env, cur_regs(env), value_regno, PTR_TO_BTF_ID,
|
||||
kptr_field->kptr.btf, kptr_field->kptr.btf_id,
|
||||
btf_ld_kptr_type(env, kptr_field));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
} else if (class == BPF_STX) {
|
||||
val_reg = reg_state(env, value_regno);
|
||||
if (!register_is_null(val_reg) &&
|
||||
|
|
@ -7298,8 +7308,11 @@ static int check_ptr_to_btf_access(struct bpf_verifier_env *env,
|
|||
clear_trusted_flags(&flag);
|
||||
}
|
||||
|
||||
if (atype == BPF_READ && value_regno >= 0)
|
||||
mark_btf_ld_reg(env, regs, value_regno, ret, reg->btf, btf_id, flag);
|
||||
if (atype == BPF_READ && value_regno >= 0) {
|
||||
ret = mark_btf_ld_reg(env, regs, value_regno, ret, reg->btf, btf_id, flag);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -7353,13 +7366,19 @@ static int check_ptr_to_map_access(struct bpf_verifier_env *env,
|
|||
|
||||
/* Simulate access to a PTR_TO_BTF_ID */
|
||||
memset(&map_reg, 0, sizeof(map_reg));
|
||||
mark_btf_ld_reg(env, &map_reg, 0, PTR_TO_BTF_ID, btf_vmlinux, *map->ops->map_btf_id, 0);
|
||||
ret = mark_btf_ld_reg(env, &map_reg, 0, PTR_TO_BTF_ID,
|
||||
btf_vmlinux, *map->ops->map_btf_id, 0);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
ret = btf_struct_access(&env->log, &map_reg, off, size, atype, &btf_id, &flag, NULL);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (value_regno >= 0)
|
||||
mark_btf_ld_reg(env, regs, value_regno, ret, btf_vmlinux, btf_id, flag);
|
||||
if (value_regno >= 0) {
|
||||
ret = mark_btf_ld_reg(env, regs, value_regno, ret, btf_vmlinux, btf_id, flag);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user