Skip to content

Commit 07236ea

Browse files
anakryikoAlexei Starovoitov
authored andcommitted
bpf: factor out fetching basic kfunc metadata
Factor out logic to fetch basic kfunc metadata based on struct bpf_insn. This is not exactly short or trivial code to just copy/paste and this information is sometimes necessary in other parts of the verifier logic. Subsequent patches will rely on this to determine if an instruction is a kfunc call to iterator next method. No functional changes intended, including that verbose() warning behavior when kfunc is not allowed for a particular program type. Signed-off-by: Andrii Nakryiko <andrii@kernel.org> Link: https://lore.kernel.org/r/20230308184121.1165081-2-andrii@kernel.org Signed-off-by: Alexei Starovoitov <ast@kernel.org>
1 parent ed69e06 commit 07236ea

File tree

1 file changed

+59
-33
lines changed

1 file changed

+59
-33
lines changed

kernel/bpf/verifier.c

Lines changed: 59 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -10079,24 +10079,21 @@ static int check_kfunc_args(struct bpf_verifier_env *env, struct bpf_kfunc_call_
1007910079
return 0;
1008010080
}
1008110081

10082-
static int check_kfunc_call(struct bpf_verifier_env *env, struct bpf_insn *insn,
10083-
int *insn_idx_p)
10082+
static int fetch_kfunc_meta(struct bpf_verifier_env *env,
10083+
struct bpf_insn *insn,
10084+
struct bpf_kfunc_call_arg_meta *meta,
10085+
const char **kfunc_name)
1008410086
{
10085-
const struct btf_type *t, *func, *func_proto, *ptr_type;
10086-
u32 i, nargs, func_id, ptr_type_id, release_ref_obj_id;
10087-
struct bpf_reg_state *regs = cur_regs(env);
10088-
const char *func_name, *ptr_type_name;
10089-
bool sleepable, rcu_lock, rcu_unlock;
10090-
struct bpf_kfunc_call_arg_meta meta;
10091-
int err, insn_idx = *insn_idx_p;
10092-
const struct btf_param *args;
10093-
const struct btf_type *ret_t;
10087+
const struct btf_type *func, *func_proto;
10088+
u32 func_id, *kfunc_flags;
10089+
const char *func_name;
1009410090
struct btf *desc_btf;
10095-
u32 *kfunc_flags;
1009610091

10097-
/* skip for now, but return error when we find this in fixup_kfunc_call */
10092+
if (kfunc_name)
10093+
*kfunc_name = NULL;
10094+
1009810095
if (!insn->imm)
10099-
return 0;
10096+
return -EINVAL;
1010010097

1010110098
desc_btf = find_kfunc_desc_btf(env, insn->off);
1010210099
if (IS_ERR(desc_btf))
@@ -10105,22 +10102,51 @@ static int check_kfunc_call(struct bpf_verifier_env *env, struct bpf_insn *insn,
1010510102
func_id = insn->imm;
1010610103
func = btf_type_by_id(desc_btf, func_id);
1010710104
func_name = btf_name_by_offset(desc_btf, func->name_off);
10105+
if (kfunc_name)
10106+
*kfunc_name = func_name;
1010810107
func_proto = btf_type_by_id(desc_btf, func->type);
1010910108

1011010109
kfunc_flags = btf_kfunc_id_set_contains(desc_btf, resolve_prog_type(env->prog), func_id);
1011110110
if (!kfunc_flags) {
10112-
verbose(env, "calling kernel function %s is not allowed\n",
10113-
func_name);
1011410111
return -EACCES;
1011510112
}
1011610113

10117-
/* Prepare kfunc call metadata */
10118-
memset(&meta, 0, sizeof(meta));
10119-
meta.btf = desc_btf;
10120-
meta.func_id = func_id;
10121-
meta.kfunc_flags = *kfunc_flags;
10122-
meta.func_proto = func_proto;
10123-
meta.func_name = func_name;
10114+
memset(meta, 0, sizeof(*meta));
10115+
meta->btf = desc_btf;
10116+
meta->func_id = func_id;
10117+
meta->kfunc_flags = *kfunc_flags;
10118+
meta->func_proto = func_proto;
10119+
meta->func_name = func_name;
10120+
10121+
return 0;
10122+
}
10123+
10124+
static int check_kfunc_call(struct bpf_verifier_env *env, struct bpf_insn *insn,
10125+
int *insn_idx_p)
10126+
{
10127+
const struct btf_type *t, *ptr_type;
10128+
u32 i, nargs, ptr_type_id, release_ref_obj_id;
10129+
struct bpf_reg_state *regs = cur_regs(env);
10130+
const char *func_name, *ptr_type_name;
10131+
bool sleepable, rcu_lock, rcu_unlock;
10132+
struct bpf_kfunc_call_arg_meta meta;
10133+
struct bpf_insn_aux_data *insn_aux;
10134+
int err, insn_idx = *insn_idx_p;
10135+
const struct btf_param *args;
10136+
const struct btf_type *ret_t;
10137+
struct btf *desc_btf;
10138+
10139+
/* skip for now, but return error when we find this in fixup_kfunc_call */
10140+
if (!insn->imm)
10141+
return 0;
10142+
10143+
err = fetch_kfunc_meta(env, insn, &meta, &func_name);
10144+
if (err == -EACCES && func_name)
10145+
verbose(env, "calling kernel function %s is not allowed\n", func_name);
10146+
if (err)
10147+
return err;
10148+
desc_btf = meta.btf;
10149+
insn_aux = &env->insn_aux_data[insn_idx];
1012410150

1012510151
if (is_kfunc_destructive(&meta) && !capable(CAP_SYS_BOOT)) {
1012610152
verbose(env, "destructive kfunc calls require CAP_SYS_BOOT capability\n");
@@ -10173,7 +10199,7 @@ static int check_kfunc_call(struct bpf_verifier_env *env, struct bpf_insn *insn,
1017310199
err = release_reference(env, regs[meta.release_regno].ref_obj_id);
1017410200
if (err) {
1017510201
verbose(env, "kfunc %s#%d reference has not been acquired before\n",
10176-
func_name, func_id);
10202+
func_name, meta.func_id);
1017710203
return err;
1017810204
}
1017910205
}
@@ -10185,14 +10211,14 @@ static int check_kfunc_call(struct bpf_verifier_env *env, struct bpf_insn *insn,
1018510211
err = ref_convert_owning_non_owning(env, release_ref_obj_id);
1018610212
if (err) {
1018710213
verbose(env, "kfunc %s#%d conversion of owning ref to non-owning failed\n",
10188-
func_name, func_id);
10214+
func_name, meta.func_id);
1018910215
return err;
1019010216
}
1019110217

1019210218
err = release_reference(env, release_ref_obj_id);
1019310219
if (err) {
1019410220
verbose(env, "kfunc %s#%d reference has not been acquired before\n",
10195-
func_name, func_id);
10221+
func_name, meta.func_id);
1019610222
return err;
1019710223
}
1019810224
}
@@ -10202,7 +10228,7 @@ static int check_kfunc_call(struct bpf_verifier_env *env, struct bpf_insn *insn,
1020210228
set_rbtree_add_callback_state);
1020310229
if (err) {
1020410230
verbose(env, "kfunc %s#%d failed callback verification\n",
10205-
func_name, func_id);
10231+
func_name, meta.func_id);
1020610232
return err;
1020710233
}
1020810234
}
@@ -10211,7 +10237,7 @@ static int check_kfunc_call(struct bpf_verifier_env *env, struct bpf_insn *insn,
1021110237
mark_reg_not_init(env, regs, caller_saved[i]);
1021210238

1021310239
/* Check return type */
10214-
t = btf_type_skip_modifiers(desc_btf, func_proto->type, NULL);
10240+
t = btf_type_skip_modifiers(desc_btf, meta.func_proto->type, NULL);
1021510241

1021610242
if (is_kfunc_acquire(&meta) && !btf_type_is_struct_ptr(meta.btf, t)) {
1021710243
/* Only exception is bpf_obj_new_impl */
@@ -10260,11 +10286,11 @@ static int check_kfunc_call(struct bpf_verifier_env *env, struct bpf_insn *insn,
1026010286
regs[BPF_REG_0].btf = ret_btf;
1026110287
regs[BPF_REG_0].btf_id = ret_btf_id;
1026210288

10263-
env->insn_aux_data[insn_idx].obj_new_size = ret_t->size;
10264-
env->insn_aux_data[insn_idx].kptr_struct_meta =
10289+
insn_aux->obj_new_size = ret_t->size;
10290+
insn_aux->kptr_struct_meta =
1026510291
btf_find_struct_meta(ret_btf, ret_btf_id);
1026610292
} else if (meta.func_id == special_kfunc_list[KF_bpf_obj_drop_impl]) {
10267-
env->insn_aux_data[insn_idx].kptr_struct_meta =
10293+
insn_aux->kptr_struct_meta =
1026810294
btf_find_struct_meta(meta.arg_obj_drop.btf,
1026910295
meta.arg_obj_drop.btf_id);
1027010296
} else if (meta.func_id == special_kfunc_list[KF_bpf_list_pop_front] ||
@@ -10397,8 +10423,8 @@ static int check_kfunc_call(struct bpf_verifier_env *env, struct bpf_insn *insn,
1039710423
regs[BPF_REG_0].id = ++env->id_gen;
1039810424
} /* else { add_kfunc_call() ensures it is btf_type_is_void(t) } */
1039910425

10400-
nargs = btf_type_vlen(func_proto);
10401-
args = (const struct btf_param *)(func_proto + 1);
10426+
nargs = btf_type_vlen(meta.func_proto);
10427+
args = (const struct btf_param *)(meta.func_proto + 1);
1040210428
for (i = 0; i < nargs; i++) {
1040310429
u32 regno = i + 1;
1040410430

0 commit comments

Comments
 (0)