mirror of
https://github.com/torvalds/linux.git
synced 2026-06-03 20:14:06 +02:00
bpf: rdonly_untrusted_mem for btf id walk pointer leafs
When processing a load from a PTR_TO_BTF_ID, the verifier calculates
the type of the loaded structure field based on the load offset.
For example, given the following types:
struct foo {
struct foo *a;
int *b;
} *p;
The verifier would calculate the type of `p->a` as a pointer to
`struct foo`. However, the type of `p->b` is currently calculated as a
SCALAR_VALUE.
This commit updates the logic for processing PTR_TO_BTF_ID to instead
calculate the type of p->b as PTR_TO_MEM|MEM_RDONLY|PTR_UNTRUSTED.
This change allows further dereferencing of such pointers (using probe
memory instructions).
Suggested-by: Alexei Starovoitov <alexei.starovoitov@gmail.com>
Acked-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
Link: https://lore.kernel.org/r/20250704230354.1323244-3-eddyz87@gmail.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
This commit is contained in:
parent
b9d44bc9fd
commit
2d5c91e1cc
|
|
@ -6915,6 +6915,7 @@ enum bpf_struct_walk_result {
|
|||
/* < 0 error */
|
||||
WALK_SCALAR = 0,
|
||||
WALK_PTR,
|
||||
WALK_PTR_UNTRUSTED,
|
||||
WALK_STRUCT,
|
||||
};
|
||||
|
||||
|
|
@ -7156,6 +7157,8 @@ static int btf_struct_walk(struct bpf_verifier_log *log, const struct btf *btf,
|
|||
*field_name = mname;
|
||||
return WALK_PTR;
|
||||
}
|
||||
|
||||
return WALK_PTR_UNTRUSTED;
|
||||
}
|
||||
|
||||
/* Allow more flexible access within an int as long as
|
||||
|
|
@ -7228,6 +7231,9 @@ int btf_struct_access(struct bpf_verifier_log *log,
|
|||
*next_btf_id = id;
|
||||
*flag = tmp_flag;
|
||||
return PTR_TO_BTF_ID;
|
||||
case WALK_PTR_UNTRUSTED:
|
||||
*flag = MEM_RDONLY | PTR_UNTRUSTED;
|
||||
return PTR_TO_MEM;
|
||||
case WALK_SCALAR:
|
||||
return SCALAR_VALUE;
|
||||
case WALK_STRUCT:
|
||||
|
|
|
|||
|
|
@ -2814,6 +2814,11 @@ static int mark_btf_ld_reg(struct bpf_verifier_env *env,
|
|||
if (type_may_be_null(flag))
|
||||
regs[regno].id = ++env->id_gen;
|
||||
return 0;
|
||||
case PTR_TO_MEM:
|
||||
mark_reg_known_zero(env, regs, regno);
|
||||
regs[regno].type = PTR_TO_MEM | flag;
|
||||
regs[regno].mem_size = 0;
|
||||
return 0;
|
||||
default:
|
||||
verifier_bug(env, "unexpected reg_type %d in %s\n", reg_type, __func__);
|
||||
return -EFAULT;
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ static struct {
|
|||
{ "new_null_ret", "R0 invalid mem access 'ptr_or_null_'" },
|
||||
{ "obj_new_acq", "Unreleased reference id=" },
|
||||
{ "use_after_drop", "invalid mem access 'scalar'" },
|
||||
{ "ptr_walk_scalar", "type=scalar expected=percpu_ptr_" },
|
||||
{ "ptr_walk_scalar", "type=rdonly_untrusted_mem expected=percpu_ptr_" },
|
||||
{ "direct_read_lock", "direct access to bpf_spin_lock is disallowed" },
|
||||
{ "direct_write_lock", "direct access to bpf_spin_lock is disallowed" },
|
||||
{ "direct_read_head", "direct access to bpf_list_head is disallowed" },
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user