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

bpf: Fix check_func_arg_reg_off bug for graph root/node

The commit being fixed introduced a hunk into check_func_arg_reg_off
that bypasses reg->off == 0 enforcement when offset points to a graph
node or root. This might possibly be done for treating bpf_rbtree_remove
and others as KF_RELEASE and then later check correct reg->off in helper
argument checks.

But this is not the case, those helpers are already not KF_RELEASE and
permit non-zero reg->off and verify it later to match the subobject in
BTF type.

However, this logic leads to bpf_obj_drop permitting free of register
arguments with non-zero offset when they point to a graph root or node
within them, which is not ok.

For instance:

struct foo {
	int i;
	int j;
	struct bpf_rb_node node;
};

struct foo *f = bpf_obj_new(typeof(*f));
if (!f) ...
bpf_obj_drop(f); // OK
bpf_obj_drop(&f->i); // still ok from verifier PoV
bpf_obj_drop(&f->node); // Not OK, but permitted right now

Fix this by dropping the whole part of code altogether.

Fixes: 6a3cd331 ("bpf: Migrate release_on_unlock logic to non-owning ref semantics")
Signed-off-by: default avatarKumar Kartikeya Dwivedi <memxor@gmail.com>
Link: https://lore.kernel.org/r/20230822175140.1317749-2-memxor@gmail.comSigned-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
parent fb301594
...@@ -7973,17 +7973,6 @@ int check_func_arg_reg_off(struct bpf_verifier_env *env, ...@@ -7973,17 +7973,6 @@ int check_func_arg_reg_off(struct bpf_verifier_env *env,
if (arg_type_is_dynptr(arg_type) && type == PTR_TO_STACK) if (arg_type_is_dynptr(arg_type) && type == PTR_TO_STACK)
return 0; return 0;
if ((type_is_ptr_alloc_obj(type) || type_is_non_owning_ref(type)) && reg->off) {
if (reg_find_field_offset(reg, reg->off, BPF_GRAPH_NODE_OR_ROOT))
return __check_ptr_off_reg(env, reg, regno, true);
verbose(env, "R%d must have zero offset when passed to release func\n",
regno);
verbose(env, "No graph node or root found at R%d type:%s off:%d\n", regno,
btf_type_name(reg->btf, reg->btf_id), reg->off);
return -EINVAL;
}
/* Doing check_ptr_off_reg check for the offset will catch this /* Doing check_ptr_off_reg check for the offset will catch this
* because fixed_off_ok is false, but checking here allows us * because fixed_off_ok is false, but checking here allows us
* to give the user a better error message. * to give the user a better error message.
......
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