Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

bpf: Tighten ptr_to_btf_id checks.

The networking programs typically don't require CAP_PERFMON, but through kfuncs
like bpf_cast_to_kern_ctx() they can access memory through PTR_TO_BTF_ID. In
such case enforce CAP_PERFMON.
Also make sure that only GPL programs can access kernel data structures.
All kfuncs require GPL already.

Also remove allow_ptr_to_map_access. It's the same as allow_ptr_leaks and
different name for the same check only causes confusion.

Fixes: fd264ca02094 ("bpf: Add a kfunc to type cast from bpf uapi ctx to kernel ctx")
Fixes: 50c6b8a9aea2 ("selftests/bpf: Add a test for btf_type_tag "percpu"")
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Acked-by: Yonghong Song <yhs@fb.com>
Link: https://lore.kernel.org/bpf/20221125220617.26846-1-alexei.starovoitov@gmail.com

authored by

Alexei Starovoitov and committed by
Andrii Nakryiko
c67cae55 996c060e

+19 -13
-5
include/linux/bpf.h
··· 1909 1909 return perfmon_capable(); 1910 1910 } 1911 1911 1912 - static inline bool bpf_allow_ptr_to_map_access(void) 1913 - { 1914 - return perfmon_capable(); 1915 - } 1916 - 1917 1912 static inline bool bpf_bypass_spec_v1(void) 1918 1913 { 1919 1914 return perfmon_capable();
-1
include/linux/bpf_verifier.h
··· 531 531 bool explore_alu_limits; 532 532 bool allow_ptr_leaks; 533 533 bool allow_uninit_stack; 534 - bool allow_ptr_to_map_access; 535 534 bool bpf_capable; 536 535 bool bypass_spec_v1; 537 536 bool bypass_spec_v4;
+14 -3
kernel/bpf/verifier.c
··· 4703 4703 u32 btf_id; 4704 4704 int ret; 4705 4705 4706 + if (!env->allow_ptr_leaks) { 4707 + verbose(env, 4708 + "'struct %s' access is allowed only to CAP_PERFMON and CAP_SYS_ADMIN\n", 4709 + tname); 4710 + return -EPERM; 4711 + } 4712 + if (!env->prog->gpl_compatible && btf_is_kernel(reg->btf)) { 4713 + verbose(env, 4714 + "Cannot access kernel 'struct %s' from non-GPL compatible program\n", 4715 + tname); 4716 + return -EINVAL; 4717 + } 4706 4718 if (off < 0) { 4707 4719 verbose(env, 4708 4720 "R%d is ptr_%s invalid negative access: off=%d\n", ··· 4835 4823 t = btf_type_by_id(btf_vmlinux, *map->ops->map_btf_id); 4836 4824 tname = btf_name_by_offset(btf_vmlinux, t->name_off); 4837 4825 4838 - if (!env->allow_ptr_to_map_access) { 4826 + if (!env->allow_ptr_leaks) { 4839 4827 verbose(env, 4840 - "%s access is allowed only to CAP_PERFMON and CAP_SYS_ADMIN\n", 4828 + "'struct %s' access is allowed only to CAP_PERFMON and CAP_SYS_ADMIN\n", 4841 4829 tname); 4842 4830 return -EPERM; 4843 4831 } ··· 16691 16679 16692 16680 env->allow_ptr_leaks = bpf_allow_ptr_leaks(); 16693 16681 env->allow_uninit_stack = bpf_allow_uninit_stack(); 16694 - env->allow_ptr_to_map_access = bpf_allow_ptr_to_map_access(); 16695 16682 env->bypass_spec_v1 = bpf_bypass_spec_v1(); 16696 16683 env->bypass_spec_v4 = bpf_bypass_spec_v4(); 16697 16684 env->bpf_capable = bpf_capable();
+1
tools/testing/selftests/bpf/progs/btf_type_tag_percpu.c
··· 64 64 65 65 return 0; 66 66 } 67 + char _license[] SEC("license") = "GPL";
+4 -4
tools/testing/selftests/bpf/verifier/map_ptr.c
··· 9 9 }, 10 10 .fixup_map_array_48b = { 1 }, 11 11 .result_unpriv = REJECT, 12 - .errstr_unpriv = "bpf_array access is allowed only to CAP_PERFMON and CAP_SYS_ADMIN", 12 + .errstr_unpriv = "access is allowed only to CAP_PERFMON and CAP_SYS_ADMIN", 13 13 .result = REJECT, 14 14 .errstr = "R1 is bpf_array invalid negative access: off=-8", 15 15 }, ··· 26 26 }, 27 27 .fixup_map_array_48b = { 3 }, 28 28 .result_unpriv = REJECT, 29 - .errstr_unpriv = "bpf_array access is allowed only to CAP_PERFMON and CAP_SYS_ADMIN", 29 + .errstr_unpriv = "access is allowed only to CAP_PERFMON and CAP_SYS_ADMIN", 30 30 .result = REJECT, 31 31 .errstr = "only read from bpf_array is supported", 32 32 }, ··· 41 41 }, 42 42 .fixup_map_array_48b = { 1 }, 43 43 .result_unpriv = REJECT, 44 - .errstr_unpriv = "bpf_array access is allowed only to CAP_PERFMON and CAP_SYS_ADMIN", 44 + .errstr_unpriv = "access is allowed only to CAP_PERFMON and CAP_SYS_ADMIN", 45 45 .result = REJECT, 46 46 .errstr = "cannot access ptr member ops with moff 0 in struct bpf_map with off 1 size 4", 47 47 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, ··· 57 57 }, 58 58 .fixup_map_array_48b = { 1 }, 59 59 .result_unpriv = REJECT, 60 - .errstr_unpriv = "bpf_array access is allowed only to CAP_PERFMON and CAP_SYS_ADMIN", 60 + .errstr_unpriv = "access is allowed only to CAP_PERFMON and CAP_SYS_ADMIN", 61 61 .result = ACCEPT, 62 62 .retval = 1, 63 63 },