Commit c67cae55 authored by Alexei Starovoitov's avatar Alexei Starovoitov Committed by Andrii Nakryiko

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: fd264ca0 ("bpf: Add a kfunc to type cast from bpf uapi ctx to kernel ctx")
Fixes: 50c6b8a9 ("selftests/bpf: Add a test for btf_type_tag "percpu"")
Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
Signed-off-by: default avatarAndrii Nakryiko <andrii@kernel.org>
Acked-by: default avatarYonghong Song <yhs@fb.com>
Link: https://lore.kernel.org/bpf/20221125220617.26846-1-alexei.starovoitov@gmail.com
parent 996c060e
...@@ -1909,11 +1909,6 @@ static inline bool bpf_allow_uninit_stack(void) ...@@ -1909,11 +1909,6 @@ static inline bool bpf_allow_uninit_stack(void)
return perfmon_capable(); return perfmon_capable();
} }
static inline bool bpf_allow_ptr_to_map_access(void)
{
return perfmon_capable();
}
static inline bool bpf_bypass_spec_v1(void) static inline bool bpf_bypass_spec_v1(void)
{ {
return perfmon_capable(); return perfmon_capable();
......
...@@ -531,7 +531,6 @@ struct bpf_verifier_env { ...@@ -531,7 +531,6 @@ struct bpf_verifier_env {
bool explore_alu_limits; bool explore_alu_limits;
bool allow_ptr_leaks; bool allow_ptr_leaks;
bool allow_uninit_stack; bool allow_uninit_stack;
bool allow_ptr_to_map_access;
bool bpf_capable; bool bpf_capable;
bool bypass_spec_v1; bool bypass_spec_v1;
bool bypass_spec_v4; bool bypass_spec_v4;
......
...@@ -4703,6 +4703,18 @@ static int check_ptr_to_btf_access(struct bpf_verifier_env *env, ...@@ -4703,6 +4703,18 @@ static int check_ptr_to_btf_access(struct bpf_verifier_env *env,
u32 btf_id; u32 btf_id;
int ret; int ret;
if (!env->allow_ptr_leaks) {
verbose(env,
"'struct %s' access is allowed only to CAP_PERFMON and CAP_SYS_ADMIN\n",
tname);
return -EPERM;
}
if (!env->prog->gpl_compatible && btf_is_kernel(reg->btf)) {
verbose(env,
"Cannot access kernel 'struct %s' from non-GPL compatible program\n",
tname);
return -EINVAL;
}
if (off < 0) { if (off < 0) {
verbose(env, verbose(env,
"R%d is ptr_%s invalid negative access: off=%d\n", "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, ...@@ -4823,9 +4835,9 @@ static int check_ptr_to_map_access(struct bpf_verifier_env *env,
t = btf_type_by_id(btf_vmlinux, *map->ops->map_btf_id); t = btf_type_by_id(btf_vmlinux, *map->ops->map_btf_id);
tname = btf_name_by_offset(btf_vmlinux, t->name_off); tname = btf_name_by_offset(btf_vmlinux, t->name_off);
if (!env->allow_ptr_to_map_access) { if (!env->allow_ptr_leaks) {
verbose(env, verbose(env,
"%s access is allowed only to CAP_PERFMON and CAP_SYS_ADMIN\n", "'struct %s' access is allowed only to CAP_PERFMON and CAP_SYS_ADMIN\n",
tname); tname);
return -EPERM; return -EPERM;
} }
...@@ -16679,7 +16691,6 @@ int bpf_check(struct bpf_prog **prog, union bpf_attr *attr, bpfptr_t uattr) ...@@ -16679,7 +16691,6 @@ int bpf_check(struct bpf_prog **prog, union bpf_attr *attr, bpfptr_t uattr)
env->allow_ptr_leaks = bpf_allow_ptr_leaks(); env->allow_ptr_leaks = bpf_allow_ptr_leaks();
env->allow_uninit_stack = bpf_allow_uninit_stack(); env->allow_uninit_stack = bpf_allow_uninit_stack();
env->allow_ptr_to_map_access = bpf_allow_ptr_to_map_access();
env->bypass_spec_v1 = bpf_bypass_spec_v1(); env->bypass_spec_v1 = bpf_bypass_spec_v1();
env->bypass_spec_v4 = bpf_bypass_spec_v4(); env->bypass_spec_v4 = bpf_bypass_spec_v4();
env->bpf_capable = bpf_capable(); env->bpf_capable = bpf_capable();
......
...@@ -64,3 +64,4 @@ int BPF_PROG(test_percpu_helper, struct cgroup *cgrp, const char *path) ...@@ -64,3 +64,4 @@ int BPF_PROG(test_percpu_helper, struct cgroup *cgrp, const char *path)
return 0; return 0;
} }
char _license[] SEC("license") = "GPL";
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
}, },
.fixup_map_array_48b = { 1 }, .fixup_map_array_48b = { 1 },
.result_unpriv = REJECT, .result_unpriv = REJECT,
.errstr_unpriv = "bpf_array access is allowed only to CAP_PERFMON and CAP_SYS_ADMIN", .errstr_unpriv = "access is allowed only to CAP_PERFMON and CAP_SYS_ADMIN",
.result = REJECT, .result = REJECT,
.errstr = "R1 is bpf_array invalid negative access: off=-8", .errstr = "R1 is bpf_array invalid negative access: off=-8",
}, },
...@@ -26,7 +26,7 @@ ...@@ -26,7 +26,7 @@
}, },
.fixup_map_array_48b = { 3 }, .fixup_map_array_48b = { 3 },
.result_unpriv = REJECT, .result_unpriv = REJECT,
.errstr_unpriv = "bpf_array access is allowed only to CAP_PERFMON and CAP_SYS_ADMIN", .errstr_unpriv = "access is allowed only to CAP_PERFMON and CAP_SYS_ADMIN",
.result = REJECT, .result = REJECT,
.errstr = "only read from bpf_array is supported", .errstr = "only read from bpf_array is supported",
}, },
...@@ -41,7 +41,7 @@ ...@@ -41,7 +41,7 @@
}, },
.fixup_map_array_48b = { 1 }, .fixup_map_array_48b = { 1 },
.result_unpriv = REJECT, .result_unpriv = REJECT,
.errstr_unpriv = "bpf_array access is allowed only to CAP_PERFMON and CAP_SYS_ADMIN", .errstr_unpriv = "access is allowed only to CAP_PERFMON and CAP_SYS_ADMIN",
.result = REJECT, .result = REJECT,
.errstr = "cannot access ptr member ops with moff 0 in struct bpf_map with off 1 size 4", .errstr = "cannot access ptr member ops with moff 0 in struct bpf_map with off 1 size 4",
.flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
...@@ -57,7 +57,7 @@ ...@@ -57,7 +57,7 @@
}, },
.fixup_map_array_48b = { 1 }, .fixup_map_array_48b = { 1 },
.result_unpriv = REJECT, .result_unpriv = REJECT,
.errstr_unpriv = "bpf_array access is allowed only to CAP_PERFMON and CAP_SYS_ADMIN", .errstr_unpriv = "access is allowed only to CAP_PERFMON and CAP_SYS_ADMIN",
.result = ACCEPT, .result = ACCEPT,
.retval = 1, .retval = 1,
}, },
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment