Skip to content

Commit 2d5c91e

Browse files
eddyz87Alexei Starovoitov
authored andcommitted
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 <[email protected]> Acked-by: Kumar Kartikeya Dwivedi <[email protected]> Signed-off-by: Eduard Zingerman <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Alexei Starovoitov <[email protected]>
1 parent b9d44bc commit 2d5c91e

File tree

3 files changed

+12
-1
lines changed

3 files changed

+12
-1
lines changed

kernel/bpf/btf.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6915,6 +6915,7 @@ enum bpf_struct_walk_result {
69156915
/* < 0 error */
69166916
WALK_SCALAR = 0,
69176917
WALK_PTR,
6918+
WALK_PTR_UNTRUSTED,
69186919
WALK_STRUCT,
69196920
};
69206921

@@ -7156,6 +7157,8 @@ static int btf_struct_walk(struct bpf_verifier_log *log, const struct btf *btf,
71567157
*field_name = mname;
71577158
return WALK_PTR;
71587159
}
7160+
7161+
return WALK_PTR_UNTRUSTED;
71597162
}
71607163

71617164
/* Allow more flexible access within an int as long as
@@ -7228,6 +7231,9 @@ int btf_struct_access(struct bpf_verifier_log *log,
72287231
*next_btf_id = id;
72297232
*flag = tmp_flag;
72307233
return PTR_TO_BTF_ID;
7234+
case WALK_PTR_UNTRUSTED:
7235+
*flag = MEM_RDONLY | PTR_UNTRUSTED;
7236+
return PTR_TO_MEM;
72317237
case WALK_SCALAR:
72327238
return SCALAR_VALUE;
72337239
case WALK_STRUCT:

kernel/bpf/verifier.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2814,6 +2814,11 @@ static int mark_btf_ld_reg(struct bpf_verifier_env *env,
28142814
if (type_may_be_null(flag))
28152815
regs[regno].id = ++env->id_gen;
28162816
return 0;
2817+
case PTR_TO_MEM:
2818+
mark_reg_known_zero(env, regs, regno);
2819+
regs[regno].type = PTR_TO_MEM | flag;
2820+
regs[regno].mem_size = 0;
2821+
return 0;
28172822
default:
28182823
verifier_bug(env, "unexpected reg_type %d in %s\n", reg_type, __func__);
28192824
return -EFAULT;

tools/testing/selftests/bpf/prog_tests/linked_list.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ static struct {
7272
{ "new_null_ret", "R0 invalid mem access 'ptr_or_null_'" },
7373
{ "obj_new_acq", "Unreleased reference id=" },
7474
{ "use_after_drop", "invalid mem access 'scalar'" },
75-
{ "ptr_walk_scalar", "type=scalar expected=percpu_ptr_" },
75+
{ "ptr_walk_scalar", "type=rdonly_untrusted_mem expected=percpu_ptr_" },
7676
{ "direct_read_lock", "direct access to bpf_spin_lock is disallowed" },
7777
{ "direct_write_lock", "direct access to bpf_spin_lock is disallowed" },
7878
{ "direct_read_head", "direct access to bpf_list_head is disallowed" },

0 commit comments

Comments
 (0)