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 | MEM_ALLOC = BIT(2 + BPF_BASE_TYPE_BITS), | 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 | /* Max number of base types. */ | 341 | /* Max number of base types. */ |
| @@ -588,7 +591,7 @@ struct bpf_verifier_ops { · 249 unmodified lines | |||
| 588 | const struct btf *btf, | 591 | const struct btf *btf, |
| 589 | const struct btf_type *t, int off, int size, | 592 | const struct btf_type *t, int off, int size, |
| 590 | enum bpf_access_type atype, | 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 | struct bpf_prog_offload_ops { | 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 | int btf_struct_access(struct bpf_verifier_log *log, const struct btf *btf, | 1783 | int btf_struct_access(struct bpf_verifier_log *log, const struct btf *btf, |
| 1781 | const struct btf_type *t, int off, int size, | 1784 | const struct btf_type *t, int off, int size, |
| 1782 | enum bpf_access_type atype, | 1785 | enum bpf_access_type atype, |
| 1783 | u32 *next_btf_id); | 1786 | u32 *next_btf_id, enum bpf_type_flag *flag); |
| 1784 | bool btf_struct_ids_match(struct bpf_verifier_log *log, | 1787 | bool btf_struct_ids_match(struct bpf_verifier_log *log, |
| 1785 | const struct btf *btf, u32 id, int off, | 1788 | const struct btf *btf, u32 id, int off, |
| 1786 | const struct btf *need_btf, u32 need_type_id); | 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 | return BTF_INFO_KIND(t->info) == BTF_KIND_VAR; | 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 | /* union is only a special case of struct: | 246 | /* union is only a special case of struct: |
| 242 | * all its offsetof(member) == 0 | 247 | * all its offsetof(member) == 0 |
| 243 | */ | 248 | */ |