Skip to content

Commit f782e2c

Browse files
ubiqueAlexei Starovoitov
authored andcommitted
bpf: Relax return code check for subprograms
Currently verifier enforces return code checks for subprograms in the same manner as it does for program entry points. This prevents returning arbitrary scalar values from subprograms. Scalar type of returned values is checked by btf_prepare_func_args() and hence it should be safe to allow only scalars for now. Relax return code checks for subprograms and allow any correct scalar values. Fixes: 51c39bb (bpf: Introduce function-by-function verification) Signed-off-by: Dmitrii Banshchikov <[email protected]> Signed-off-by: Alexei Starovoitov <[email protected]> Acked-by: Andrii Nakryiko <[email protected]> Link: https://lore.kernel.org/bpf/[email protected]
1 parent 50431b4 commit f782e2c

File tree

3 files changed

+33
-2
lines changed

3 files changed

+33
-2
lines changed

kernel/bpf/verifier.c

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7786,9 +7786,11 @@ static int check_return_code(struct bpf_verifier_env *env)
77867786
struct tnum range = tnum_range(0, 1);
77877787
enum bpf_prog_type prog_type = resolve_prog_type(env->prog);
77887788
int err;
7789+
const bool is_subprog = env->cur_state->frame[0]->subprogno;
77897790

77907791
/* LSM and struct_ops func-ptr's return type could be "void" */
7791-
if ((prog_type == BPF_PROG_TYPE_STRUCT_OPS ||
7792+
if (!is_subprog &&
7793+
(prog_type == BPF_PROG_TYPE_STRUCT_OPS ||
77927794
prog_type == BPF_PROG_TYPE_LSM) &&
77937795
!prog->aux->attach_func_proto->type)
77947796
return 0;
@@ -7808,6 +7810,16 @@ static int check_return_code(struct bpf_verifier_env *env)
78087810
return -EACCES;
78097811
}
78107812

7813+
reg = cur_regs(env) + BPF_REG_0;
7814+
if (is_subprog) {
7815+
if (reg->type != SCALAR_VALUE) {
7816+
verbose(env, "At subprogram exit the register R0 is not a scalar value (%s)\n",
7817+
reg_type_str[reg->type]);
7818+
return -EINVAL;
7819+
}
7820+
return 0;
7821+
}
7822+
78117823
switch (prog_type) {
78127824
case BPF_PROG_TYPE_CGROUP_SOCK_ADDR:
78137825
if (env->prog->expected_attach_type == BPF_CGROUP_UDP4_RECVMSG ||
@@ -7861,7 +7873,6 @@ static int check_return_code(struct bpf_verifier_env *env)
78617873
return 0;
78627874
}
78637875

7864-
reg = cur_regs(env) + BPF_REG_0;
78657876
if (reg->type != SCALAR_VALUE) {
78667877
verbose(env, "At program exit the register R0 is not a known value (%s)\n",
78677878
reg_type_str[reg->type]);

tools/testing/selftests/bpf/prog_tests/test_global_funcs.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ void test_test_global_funcs(void)
6060
{ "test_global_func5.o" , "expected pointer to ctx, but got PTR" },
6161
{ "test_global_func6.o" , "modified ctx ptr R2" },
6262
{ "test_global_func7.o" , "foo() doesn't return scalar" },
63+
{ "test_global_func8.o" },
6364
};
6465
libbpf_print_fn_t old_print_fn = NULL;
6566
int err, i, duration = 0;
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// SPDX-License-Identifier: GPL-2.0-only
2+
/* Copyright (c) 2020 Facebook */
3+
#include <stddef.h>
4+
#include <linux/bpf.h>
5+
#include <bpf/bpf_helpers.h>
6+
7+
__noinline int foo(struct __sk_buff *skb)
8+
{
9+
return bpf_get_prandom_u32();
10+
}
11+
12+
SEC("cgroup_skb/ingress")
13+
int test_cls(struct __sk_buff *skb)
14+
{
15+
if (!foo(skb))
16+
return 0;
17+
18+
return 1;
19+
}

0 commit comments

Comments
 (0)