Skip to content

Commit 7a2d070

Browse files
committed
Merge branch 'bpf-global-funcs'
Alexei Starovoitov says: ==================== Introduce static vs global functions and function by function verification. This is another step toward dynamic re-linking (or replacement) of global functions. See patch 2 for details. v2->v3: - cleaned up a check spotted by Song. - rebased and dropped patch 2 that was trying to improve BTF based on ELF. - added one more unit test for scalar return value from global func. v1->v2: - addressed review comments from Song, Andrii, Yonghong - fixed memory leak in error path - added modified ctx check - added more tests in patch 7 ==================== Signed-off-by: Daniel Borkmann <[email protected]>
2 parents f41aa38 + 360301a commit 7a2d070

22 files changed

+746
-89
lines changed

include/linux/bpf.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -566,6 +566,7 @@ static inline void bpf_dispatcher_change_prog(struct bpf_dispatcher *d,
566566
#endif
567567

568568
struct bpf_func_info_aux {
569+
u16 linkage;
569570
bool unreliable;
570571
};
571572

@@ -1081,7 +1082,11 @@ int btf_distill_func_proto(struct bpf_verifier_log *log,
10811082
const char *func_name,
10821083
struct btf_func_model *m);
10831084

1084-
int btf_check_func_arg_match(struct bpf_verifier_env *env, int subprog);
1085+
struct bpf_reg_state;
1086+
int btf_check_func_arg_match(struct bpf_verifier_env *env, int subprog,
1087+
struct bpf_reg_state *regs);
1088+
int btf_prepare_func_args(struct bpf_verifier_env *env, int subprog,
1089+
struct bpf_reg_state *reg);
10851090

10861091
struct bpf_prog *bpf_prog_by_id(u32 id);
10871092

include/linux/bpf_verifier.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -304,11 +304,13 @@ struct bpf_insn_aux_data {
304304
u64 map_key_state; /* constant (32 bit) key tracking for maps */
305305
int ctx_field_size; /* the ctx field size for load insn, maybe 0 */
306306
int sanitize_stack_off; /* stack slot to be cleared */
307-
bool seen; /* this insn was processed by the verifier */
307+
u32 seen; /* this insn was processed by the verifier at env->pass_cnt */
308308
bool zext_dst; /* this insn zero extends dst reg */
309309
u8 alu_state; /* used in combination with alu_limit */
310-
bool prune_point;
310+
311+
/* below fields are initialized once */
311312
unsigned int orig_idx; /* original instruction index */
313+
bool prune_point;
312314
};
313315

314316
#define MAX_USED_MAPS 64 /* max number of maps accessed by one eBPF program */
@@ -379,6 +381,7 @@ struct bpf_verifier_env {
379381
int *insn_stack;
380382
int cur_stack;
381383
} cfg;
384+
u32 pass_cnt; /* number of times do_check() was called */
382385
u32 subprog_cnt;
383386
/* number of instructions analyzed by the verifier */
384387
u32 prev_insn_processed, insn_processed;
@@ -428,4 +431,7 @@ bpf_prog_offload_replace_insn(struct bpf_verifier_env *env, u32 off,
428431
void
429432
bpf_prog_offload_remove_insns(struct bpf_verifier_env *env, u32 off, u32 cnt);
430433

434+
int check_ctx_reg(struct bpf_verifier_env *env,
435+
const struct bpf_reg_state *reg, int regno);
436+
431437
#endif /* _LINUX_BPF_VERIFIER_H */

include/uapi/linux/btf.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,12 @@ enum {
146146
BTF_VAR_GLOBAL_EXTERN = 2,
147147
};
148148

149+
enum btf_func_linkage {
150+
BTF_FUNC_STATIC = 0,
151+
BTF_FUNC_GLOBAL = 1,
152+
BTF_FUNC_EXTERN = 2,
153+
};
154+
149155
/* BTF_KIND_VAR is followed by a single "struct btf_var" to describe
150156
* additional information related to the variable such as its linkage.
151157
*/

kernel/bpf/btf.c

Lines changed: 144 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -2651,8 +2651,8 @@ static s32 btf_func_check_meta(struct btf_verifier_env *env,
26512651
return -EINVAL;
26522652
}
26532653

2654-
if (btf_type_vlen(t)) {
2655-
btf_verifier_log_type(env, t, "vlen != 0");
2654+
if (btf_type_vlen(t) > BTF_FUNC_GLOBAL) {
2655+
btf_verifier_log_type(env, t, "Invalid func linkage");
26562656
return -EINVAL;
26572657
}
26582658

@@ -3506,7 +3506,8 @@ static u8 bpf_ctx_convert_map[] = {
35063506

35073507
static const struct btf_member *
35083508
btf_get_prog_ctx_type(struct bpf_verifier_log *log, struct btf *btf,
3509-
const struct btf_type *t, enum bpf_prog_type prog_type)
3509+
const struct btf_type *t, enum bpf_prog_type prog_type,
3510+
int arg)
35103511
{
35113512
const struct btf_type *conv_struct;
35123513
const struct btf_type *ctx_struct;
@@ -3527,12 +3528,13 @@ btf_get_prog_ctx_type(struct bpf_verifier_log *log, struct btf *btf,
35273528
* is not supported yet.
35283529
* BPF_PROG_TYPE_RAW_TRACEPOINT is fine.
35293530
*/
3530-
bpf_log(log, "BPF program ctx type is not a struct\n");
3531+
if (log->level & BPF_LOG_LEVEL)
3532+
bpf_log(log, "arg#%d type is not a struct\n", arg);
35313533
return NULL;
35323534
}
35333535
tname = btf_name_by_offset(btf, t->name_off);
35343536
if (!tname) {
3535-
bpf_log(log, "BPF program ctx struct doesn't have a name\n");
3537+
bpf_log(log, "arg#%d struct doesn't have a name\n", arg);
35363538
return NULL;
35373539
}
35383540
/* prog_type is valid bpf program type. No need for bounds check. */
@@ -3565,11 +3567,12 @@ btf_get_prog_ctx_type(struct bpf_verifier_log *log, struct btf *btf,
35653567
static int btf_translate_to_vmlinux(struct bpf_verifier_log *log,
35663568
struct btf *btf,
35673569
const struct btf_type *t,
3568-
enum bpf_prog_type prog_type)
3570+
enum bpf_prog_type prog_type,
3571+
int arg)
35693572
{
35703573
const struct btf_member *prog_ctx_type, *kern_ctx_type;
35713574

3572-
prog_ctx_type = btf_get_prog_ctx_type(log, btf, t, prog_type);
3575+
prog_ctx_type = btf_get_prog_ctx_type(log, btf, t, prog_type, arg);
35733576
if (!prog_ctx_type)
35743577
return -ENOENT;
35753578
kern_ctx_type = prog_ctx_type + 1;
@@ -3731,7 +3734,7 @@ bool btf_ctx_access(int off, int size, enum bpf_access_type type,
37313734
info->reg_type = PTR_TO_BTF_ID;
37323735

37333736
if (tgt_prog) {
3734-
ret = btf_translate_to_vmlinux(log, btf, t, tgt_prog->type);
3737+
ret = btf_translate_to_vmlinux(log, btf, t, tgt_prog->type, arg);
37353738
if (ret > 0) {
37363739
info->btf_id = ret;
37373740
return true;
@@ -4112,11 +4115,16 @@ int btf_distill_func_proto(struct bpf_verifier_log *log,
41124115
return 0;
41134116
}
41144117

4115-
int btf_check_func_arg_match(struct bpf_verifier_env *env, int subprog)
4118+
/* Compare BTF of a function with given bpf_reg_state.
4119+
* Returns:
4120+
* EFAULT - there is a verifier bug. Abort verification.
4121+
* EINVAL - there is a type mismatch or BTF is not available.
4122+
* 0 - BTF matches with what bpf_reg_state expects.
4123+
* Only PTR_TO_CTX and SCALAR_VALUE states are recognized.
4124+
*/
4125+
int btf_check_func_arg_match(struct bpf_verifier_env *env, int subprog,
4126+
struct bpf_reg_state *reg)
41164127
{
4117-
struct bpf_verifier_state *st = env->cur_state;
4118-
struct bpf_func_state *func = st->frame[st->curframe];
4119-
struct bpf_reg_state *reg = func->regs;
41204128
struct bpf_verifier_log *log = &env->log;
41214129
struct bpf_prog *prog = env->prog;
41224130
struct btf *btf = prog->aux->btf;
@@ -4126,27 +4134,30 @@ int btf_check_func_arg_match(struct bpf_verifier_env *env, int subprog)
41264134
const char *tname;
41274135

41284136
if (!prog->aux->func_info)
4129-
return 0;
4137+
return -EINVAL;
41304138

41314139
btf_id = prog->aux->func_info[subprog].type_id;
41324140
if (!btf_id)
4133-
return 0;
4141+
return -EFAULT;
41344142

41354143
if (prog->aux->func_info_aux[subprog].unreliable)
4136-
return 0;
4144+
return -EINVAL;
41374145

41384146
t = btf_type_by_id(btf, btf_id);
41394147
if (!t || !btf_type_is_func(t)) {
4140-
bpf_log(log, "BTF of subprog %d doesn't point to KIND_FUNC\n",
4148+
/* These checks were already done by the verifier while loading
4149+
* struct bpf_func_info
4150+
*/
4151+
bpf_log(log, "BTF of func#%d doesn't point to KIND_FUNC\n",
41414152
subprog);
4142-
return -EINVAL;
4153+
return -EFAULT;
41434154
}
41444155
tname = btf_name_by_offset(btf, t->name_off);
41454156

41464157
t = btf_type_by_id(btf, t->type);
41474158
if (!t || !btf_type_is_func_proto(t)) {
4148-
bpf_log(log, "Invalid type of func %s\n", tname);
4149-
return -EINVAL;
4159+
bpf_log(log, "Invalid BTF of func %s\n", tname);
4160+
return -EFAULT;
41504161
}
41514162
args = (const struct btf_param *)(t + 1);
41524163
nargs = btf_type_vlen(t);
@@ -4172,25 +4183,127 @@ int btf_check_func_arg_match(struct bpf_verifier_env *env, int subprog)
41724183
bpf_log(log, "R%d is not a pointer\n", i + 1);
41734184
goto out;
41744185
}
4175-
/* If program is passing PTR_TO_CTX into subprogram
4176-
* check that BTF type matches.
4186+
/* If function expects ctx type in BTF check that caller
4187+
* is passing PTR_TO_CTX.
41774188
*/
4178-
if (reg[i + 1].type == PTR_TO_CTX &&
4179-
!btf_get_prog_ctx_type(log, btf, t, prog->type))
4180-
goto out;
4181-
/* All other pointers are ok */
4182-
continue;
4189+
if (btf_get_prog_ctx_type(log, btf, t, prog->type, i)) {
4190+
if (reg[i + 1].type != PTR_TO_CTX) {
4191+
bpf_log(log,
4192+
"arg#%d expected pointer to ctx, but got %s\n",
4193+
i, btf_kind_str[BTF_INFO_KIND(t->info)]);
4194+
goto out;
4195+
}
4196+
if (check_ctx_reg(env, &reg[i + 1], i + 1))
4197+
goto out;
4198+
continue;
4199+
}
41834200
}
4184-
bpf_log(log, "Unrecognized argument type %s\n",
4185-
btf_kind_str[BTF_INFO_KIND(t->info)]);
4201+
bpf_log(log, "Unrecognized arg#%d type %s\n",
4202+
i, btf_kind_str[BTF_INFO_KIND(t->info)]);
41864203
goto out;
41874204
}
41884205
return 0;
41894206
out:
4190-
/* LLVM optimizations can remove arguments from static functions. */
4191-
bpf_log(log,
4192-
"Type info disagrees with actual arguments due to compiler optimizations\n");
4207+
/* Compiler optimizations can remove arguments from static functions
4208+
* or mismatched type can be passed into a global function.
4209+
* In such cases mark the function as unreliable from BTF point of view.
4210+
*/
41934211
prog->aux->func_info_aux[subprog].unreliable = true;
4212+
return -EINVAL;
4213+
}
4214+
4215+
/* Convert BTF of a function into bpf_reg_state if possible
4216+
* Returns:
4217+
* EFAULT - there is a verifier bug. Abort verification.
4218+
* EINVAL - cannot convert BTF.
4219+
* 0 - Successfully converted BTF into bpf_reg_state
4220+
* (either PTR_TO_CTX or SCALAR_VALUE).
4221+
*/
4222+
int btf_prepare_func_args(struct bpf_verifier_env *env, int subprog,
4223+
struct bpf_reg_state *reg)
4224+
{
4225+
struct bpf_verifier_log *log = &env->log;
4226+
struct bpf_prog *prog = env->prog;
4227+
struct btf *btf = prog->aux->btf;
4228+
const struct btf_param *args;
4229+
const struct btf_type *t;
4230+
u32 i, nargs, btf_id;
4231+
const char *tname;
4232+
4233+
if (!prog->aux->func_info ||
4234+
prog->aux->func_info_aux[subprog].linkage != BTF_FUNC_GLOBAL) {
4235+
bpf_log(log, "Verifier bug\n");
4236+
return -EFAULT;
4237+
}
4238+
4239+
btf_id = prog->aux->func_info[subprog].type_id;
4240+
if (!btf_id) {
4241+
bpf_log(log, "Global functions need valid BTF\n");
4242+
return -EFAULT;
4243+
}
4244+
4245+
t = btf_type_by_id(btf, btf_id);
4246+
if (!t || !btf_type_is_func(t)) {
4247+
/* These checks were already done by the verifier while loading
4248+
* struct bpf_func_info
4249+
*/
4250+
bpf_log(log, "BTF of func#%d doesn't point to KIND_FUNC\n",
4251+
subprog);
4252+
return -EFAULT;
4253+
}
4254+
tname = btf_name_by_offset(btf, t->name_off);
4255+
4256+
if (log->level & BPF_LOG_LEVEL)
4257+
bpf_log(log, "Validating %s() func#%d...\n",
4258+
tname, subprog);
4259+
4260+
if (prog->aux->func_info_aux[subprog].unreliable) {
4261+
bpf_log(log, "Verifier bug in function %s()\n", tname);
4262+
return -EFAULT;
4263+
}
4264+
4265+
t = btf_type_by_id(btf, t->type);
4266+
if (!t || !btf_type_is_func_proto(t)) {
4267+
bpf_log(log, "Invalid type of function %s()\n", tname);
4268+
return -EFAULT;
4269+
}
4270+
args = (const struct btf_param *)(t + 1);
4271+
nargs = btf_type_vlen(t);
4272+
if (nargs > 5) {
4273+
bpf_log(log, "Global function %s() with %d > 5 args. Buggy compiler.\n",
4274+
tname, nargs);
4275+
return -EINVAL;
4276+
}
4277+
/* check that function returns int */
4278+
t = btf_type_by_id(btf, t->type);
4279+
while (btf_type_is_modifier(t))
4280+
t = btf_type_by_id(btf, t->type);
4281+
if (!btf_type_is_int(t) && !btf_type_is_enum(t)) {
4282+
bpf_log(log,
4283+
"Global function %s() doesn't return scalar. Only those are supported.\n",
4284+
tname);
4285+
return -EINVAL;
4286+
}
4287+
/* Convert BTF function arguments into verifier types.
4288+
* Only PTR_TO_CTX and SCALAR are supported atm.
4289+
*/
4290+
for (i = 0; i < nargs; i++) {
4291+
t = btf_type_by_id(btf, args[i].type);
4292+
while (btf_type_is_modifier(t))
4293+
t = btf_type_by_id(btf, t->type);
4294+
if (btf_type_is_int(t) || btf_type_is_enum(t)) {
4295+
reg[i + 1].type = SCALAR_VALUE;
4296+
continue;
4297+
}
4298+
if (btf_type_is_ptr(t) &&
4299+
btf_get_prog_ctx_type(log, btf, t, prog->type, i)) {
4300+
reg[i + 1].type = PTR_TO_CTX;
4301+
continue;
4302+
}
4303+
bpf_log(log, "Arg#%d type %s in %s() is not supported yet.\n",
4304+
i, btf_kind_str[BTF_INFO_KIND(t->info)], tname);
4305+
return -EINVAL;
4306+
}
41944307
return 0;
41954308
}
41964309

0 commit comments

Comments
 (0)