History

bpf: reject program if a __user tagged memory accessed in kernel way

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.

Yonghong Song committed 4 years ago

Commit c6f1bfe1 parent 7472d5a6 files · +71 −24Browse files

Showing the changes to include (2 of 6 files). Show all

Unified · Split

2 files
  1. include/linux/bpf.h +6 −3
  2. include/linux/btf.h +5 −0
include/linux/bpf.h+6−3
@@ -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
594struct bpf_prog_offload_ops {597struct bpf_prog_offload_ops {
@@ -1780,7 +1783,7 @@ static inline bool bpf_tracing_btf_ctx_access(int off, int size, · 1185 unmodified lines
1780int btf_struct_access(struct bpf_verifier_log *log, const struct btf *btf,1783int 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);
1784bool btf_struct_ids_match(struct bpf_verifier_log *log,1787bool 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);
include/linux/btf.h+5−0
@@ -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
241static 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) == 0247 * all its offsetof(member) == 0
243 */248 */

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t