Commit dbd8d228 authored by Kumar Kartikeya Dwivedi's avatar Kumar Kartikeya Dwivedi Committed by Alexei Starovoitov

bpf: Wrap register invalidation with a helper

Typically, verifier should use env->allow_ptr_leaks when invaliding
registers for users that don't have CAP_PERFMON or CAP_SYS_ADMIN to
avoid leaking the pointer value. This is similar in spirit to
c67cae55 ("bpf: Tighten ptr_to_btf_id checks."). In a lot of the
existing checks, we know the capabilities are present, hence we don't do
the check.

Instead of being inconsistent in the application of the check, wrap the
action of invalidating a register into a helper named 'mark_invalid_reg'
and use it in a uniform fashion to replace open coded invalidation
operations, so that the check is always made regardless of the call site
and we don't have to remember whether it needs to be done or not for
each case.
Signed-off-by: default avatarKumar Kartikeya Dwivedi <memxor@gmail.com>
Link: https://lore.kernel.org/r/20230221200646.2500777-7-memxor@gmail.comSigned-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
parent da03e43a
...@@ -895,6 +895,14 @@ static int unmark_stack_slots_dynptr(struct bpf_verifier_env *env, struct bpf_re ...@@ -895,6 +895,14 @@ static int unmark_stack_slots_dynptr(struct bpf_verifier_env *env, struct bpf_re
static void __mark_reg_unknown(const struct bpf_verifier_env *env, static void __mark_reg_unknown(const struct bpf_verifier_env *env,
struct bpf_reg_state *reg); struct bpf_reg_state *reg);
static void mark_reg_invalid(const struct bpf_verifier_env *env, struct bpf_reg_state *reg)
{
if (!env->allow_ptr_leaks)
__mark_reg_not_init(env, reg);
else
__mark_reg_unknown(env, reg);
}
static int destroy_if_dynptr_stack_slot(struct bpf_verifier_env *env, static int destroy_if_dynptr_stack_slot(struct bpf_verifier_env *env,
struct bpf_func_state *state, int spi) struct bpf_func_state *state, int spi)
{ {
...@@ -934,12 +942,8 @@ static int destroy_if_dynptr_stack_slot(struct bpf_verifier_env *env, ...@@ -934,12 +942,8 @@ static int destroy_if_dynptr_stack_slot(struct bpf_verifier_env *env,
/* Dynptr slices are only PTR_TO_MEM_OR_NULL and PTR_TO_MEM */ /* Dynptr slices are only PTR_TO_MEM_OR_NULL and PTR_TO_MEM */
if (dreg->type != (PTR_TO_MEM | PTR_MAYBE_NULL) && dreg->type != PTR_TO_MEM) if (dreg->type != (PTR_TO_MEM | PTR_MAYBE_NULL) && dreg->type != PTR_TO_MEM)
continue; continue;
if (dreg->dynptr_id == dynptr_id) { if (dreg->dynptr_id == dynptr_id)
if (!env->allow_ptr_leaks) mark_reg_invalid(env, dreg);
__mark_reg_not_init(env, dreg);
else
__mark_reg_unknown(env, dreg);
}
})); }));
/* Do not release reference state, we are destroying dynptr on stack, /* Do not release reference state, we are destroying dynptr on stack,
...@@ -7384,7 +7388,7 @@ static void clear_all_pkt_pointers(struct bpf_verifier_env *env) ...@@ -7384,7 +7388,7 @@ static void clear_all_pkt_pointers(struct bpf_verifier_env *env)
bpf_for_each_reg_in_vstate(env->cur_state, state, reg, ({ bpf_for_each_reg_in_vstate(env->cur_state, state, reg, ({
if (reg_is_pkt_pointer_any(reg)) if (reg_is_pkt_pointer_any(reg))
__mark_reg_unknown(env, reg); mark_reg_invalid(env, reg);
})); }));
} }
...@@ -7429,12 +7433,8 @@ static int release_reference(struct bpf_verifier_env *env, ...@@ -7429,12 +7433,8 @@ static int release_reference(struct bpf_verifier_env *env,
return err; return err;
bpf_for_each_reg_in_vstate(env->cur_state, state, reg, ({ bpf_for_each_reg_in_vstate(env->cur_state, state, reg, ({
if (reg->ref_obj_id == ref_obj_id) { if (reg->ref_obj_id == ref_obj_id)
if (!env->allow_ptr_leaks) mark_reg_invalid(env, reg);
__mark_reg_not_init(env, reg);
else
__mark_reg_unknown(env, reg);
}
})); }));
return 0; return 0;
...@@ -7447,7 +7447,7 @@ static void invalidate_non_owning_refs(struct bpf_verifier_env *env) ...@@ -7447,7 +7447,7 @@ static void invalidate_non_owning_refs(struct bpf_verifier_env *env)
bpf_for_each_reg_in_vstate(env->cur_state, unused, reg, ({ bpf_for_each_reg_in_vstate(env->cur_state, unused, reg, ({
if (type_is_non_owning_ref(reg->type)) if (type_is_non_owning_ref(reg->type))
__mark_reg_unknown(env, reg); mark_reg_invalid(env, reg);
})); }));
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment