BPF verifier supports direct memory access for BPF_PROG_TYPE_TRACING type of bpf programs, e.g., a->b. If "a" is a pointer pointing to kernel memory, bpf verifier will allow user to write code in C like a->b and the verifier will translate it to a kernel load properly. If "a" is a pointer to user memory, it is expected that bpf developer should be bpf_probe_read_user() helper to get the value a->b. Without utilizing BTF __user tagging information, current verifier will assume that a->b is a kernel memory access and this may generate incorrect result. Now BTF contains __user information, it can check whether the pointer points to a user memory or not. If it is, the verifier can reject the program and force users to use bpf_probe_read_user() helper explicitly. In the future, we can easily extend btf_add_space for other address space tagging, for example, rcu/percpu etc.
Showing the changes to include (2 of 6 files). Show all
Unified · Split
| @@ -332,7 +332,10 @@ enum bpf_type_flag { · 331 unmodified lines | ||
| 332 | 332 | */ |
| 333 | 333 | MEM_ALLOC = BIT(2 + BPF_BASE_TYPE_BITS), |
| 334 | 334 | |
| 335 | − __BPF_TYPE_LAST_FLAG = MEM_ALLOC, | |
| 335 | + /* MEM is in user address space. */ | |
| 336 | + MEM_USER = BIT(3 + BPF_BASE_TYPE_BITS), | |
| 337 | + | |
| 338 | + __BPF_TYPE_LAST_FLAG = MEM_USER, | |
| 336 | 339 | }; |
| 337 | 340 | |
| 338 | 341 | /* Max number of base types. */ |
| @@ -588,7 +591,7 @@ struct bpf_verifier_ops { · 249 unmodified lines | ||
| 588 | 591 | const struct btf *btf, |
| 589 | 592 | const struct btf_type *t, int off, int size, |
| 590 | 593 | enum bpf_access_type atype, |
| 591 | − u32 *next_btf_id); | |
| 594 | + u32 *next_btf_id, enum bpf_type_flag *flag); | |
| 592 | 595 | }; |
| 593 | 596 | |
| 594 | 597 | struct bpf_prog_offload_ops { |
| @@ -1780,7 +1783,7 @@ static inline bool bpf_tracing_btf_ctx_access(int off, int size, · 1185 unmodified lines | ||
| 1780 | 1783 | int btf_struct_access(struct bpf_verifier_log *log, const struct btf *btf, |
| 1781 | 1784 | const struct btf_type *t, int off, int size, |
| 1782 | 1785 | enum bpf_access_type atype, |
| 1783 | − u32 *next_btf_id); | |
| 1786 | + u32 *next_btf_id, enum bpf_type_flag *flag); | |
| 1784 | 1787 | bool btf_struct_ids_match(struct bpf_verifier_log *log, |
| 1785 | 1788 | const struct btf *btf, u32 id, int off, |
| 1786 | 1789 | const struct btf *need_btf, u32 need_type_id); |
| @@ -238,6 +238,11 @@ static inline bool btf_type_is_var(const struct btf_type *t) · 237 unmodified lines | ||
| 238 | 238 | return BTF_INFO_KIND(t->info) == BTF_KIND_VAR; |
| 239 | 239 | } |
| 240 | 240 | |
| 241 | +static inline bool btf_type_is_type_tag(const struct btf_type *t) | |
| 242 | +{ | |
| 243 | + return BTF_INFO_KIND(t->info) == BTF_KIND_TYPE_TAG; | |
| 244 | +} | |
| 245 | + | |
| 241 | 246 | /* union is only a special case of struct: |
| 242 | 247 | * all its offsetof(member) == 0 |
| 243 | 248 | */ |