Skip to content

Commit c67cae5

Browse files
Alexei Starovoitovanakryiko
authored andcommitted
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: fd264ca ("bpf: Add a kfunc to type cast from bpf uapi ctx to kernel ctx") Fixes: 50c6b8a ("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
1 parent 996c060 commit c67cae5

File tree

5 files changed

+19
-13
lines changed

5 files changed

+19
-13
lines changed

include/linux/bpf.h

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1909,11 +1909,6 @@ static inline bool bpf_allow_uninit_stack(void)
19091909
return perfmon_capable();
19101910
}
19111911

1912-
static inline bool bpf_allow_ptr_to_map_access(void)
1913-
{
1914-
return perfmon_capable();
1915-
}
1916-
19171912
static inline bool bpf_bypass_spec_v1(void)
19181913
{
19191914
return perfmon_capable();

include/linux/bpf_verifier.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -531,7 +531,6 @@ struct bpf_verifier_env {
531531
bool explore_alu_limits;
532532
bool allow_ptr_leaks;
533533
bool allow_uninit_stack;
534-
bool allow_ptr_to_map_access;
535534
bool bpf_capable;
536535
bool bypass_spec_v1;
537536
bool bypass_spec_v4;

kernel/bpf/verifier.c

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4703,6 +4703,18 @@ static int check_ptr_to_btf_access(struct bpf_verifier_env *env,
47034703
u32 btf_id;
47044704
int ret;
47054705

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+
}
47064718
if (off < 0) {
47074719
verbose(env,
47084720
"R%d is ptr_%s invalid negative access: off=%d\n",
@@ -4823,9 +4835,9 @@ static int check_ptr_to_map_access(struct bpf_verifier_env *env,
48234835
t = btf_type_by_id(btf_vmlinux, *map->ops->map_btf_id);
48244836
tname = btf_name_by_offset(btf_vmlinux, t->name_off);
48254837

4826-
if (!env->allow_ptr_to_map_access) {
4838+
if (!env->allow_ptr_leaks) {
48274839
verbose(env,
4828-
"%s access is allowed only to CAP_PERFMON and CAP_SYS_ADMIN\n",
4840+
"'struct %s' access is allowed only to CAP_PERFMON and CAP_SYS_ADMIN\n",
48294841
tname);
48304842
return -EPERM;
48314843
}
@@ -16679,7 +16691,6 @@ int bpf_check(struct bpf_prog **prog, union bpf_attr *attr, bpfptr_t uattr)
1667916691

1668016692
env->allow_ptr_leaks = bpf_allow_ptr_leaks();
1668116693
env->allow_uninit_stack = bpf_allow_uninit_stack();
16682-
env->allow_ptr_to_map_access = bpf_allow_ptr_to_map_access();
1668316694
env->bypass_spec_v1 = bpf_bypass_spec_v1();
1668416695
env->bypass_spec_v4 = bpf_bypass_spec_v4();
1668516696
env->bpf_capable = bpf_capable();

tools/testing/selftests/bpf/progs/btf_type_tag_percpu.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,3 +64,4 @@ int BPF_PROG(test_percpu_helper, struct cgroup *cgrp, const char *path)
6464

6565
return 0;
6666
}
67+
char _license[] SEC("license") = "GPL";

tools/testing/selftests/bpf/verifier/map_ptr.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
},
1010
.fixup_map_array_48b = { 1 },
1111
.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",
1313
.result = REJECT,
1414
.errstr = "R1 is bpf_array invalid negative access: off=-8",
1515
},
@@ -26,7 +26,7 @@
2626
},
2727
.fixup_map_array_48b = { 3 },
2828
.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",
3030
.result = REJECT,
3131
.errstr = "only read from bpf_array is supported",
3232
},
@@ -41,7 +41,7 @@
4141
},
4242
.fixup_map_array_48b = { 1 },
4343
.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",
4545
.result = REJECT,
4646
.errstr = "cannot access ptr member ops with moff 0 in struct bpf_map with off 1 size 4",
4747
.flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
@@ -57,7 +57,7 @@
5757
},
5858
.fixup_map_array_48b = { 1 },
5959
.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",
6161
.result = ACCEPT,
6262
.retval = 1,
6363
},

0 commit comments

Comments
 (0)