Skip to content

Commit f97566e

Browse files
puranjaymohanKernel Patches Daemon
authored andcommitted
bpf: verifier: initialize imm in kfunc_tab in add_kfunc_call()
Metadata about a kfunc call is added to the kfunc_tab in add_kfunc_call() but the call instruction itself could get removed by opt_remove_dead_code() later if it is not reachable. If the call instruction is removed, specialize_kfunc() is never called for it and the desc->imm in the kfunc_tab is never initialized for this kfunc call. In this case, sort_kfunc_descs_by_imm_off(env->prog); in do_misc_fixups() doesn't sort the table correctly. This is a problem from s390 as its JIT uses this table to find the addresses for kfuncs, and if this table is not sorted properly, JIT can fail to find addresses for valid kfunc calls. This was exposed by: commit d869d56 ("bpf: verifier: refactor kfunc specialization") as before this commit, desc->imm was initialised in add_kfunc_call(). Initialize desc->imm in add_kfunc_call(), it will be overwritten with new imm in specialize_kfunc() if the instruction is not removed. Signed-off-by: Puranjay Mohan <[email protected]> Acked-by: Kumar Kartikeya Dwivedi <[email protected]>
1 parent b1af442 commit f97566e

File tree

1 file changed

+15
-5
lines changed

1 file changed

+15
-5
lines changed

kernel/bpf/verifier.c

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3273,7 +3273,7 @@ static int add_kfunc_call(struct bpf_verifier_env *env, u32 func_id, s16 offset)
32733273
struct bpf_kfunc_desc *desc;
32743274
const char *func_name;
32753275
struct btf *desc_btf;
3276-
unsigned long addr;
3276+
unsigned long addr, call_imm;
32773277
int err;
32783278

32793279
prog_aux = env->prog->aux;
@@ -3369,8 +3369,20 @@ static int add_kfunc_call(struct bpf_verifier_env *env, u32 func_id, s16 offset)
33693369
if (err)
33703370
return err;
33713371

3372+
if (bpf_jit_supports_far_kfunc_call()) {
3373+
call_imm = func_id;
3374+
} else {
3375+
call_imm = BPF_CALL_IMM(addr);
3376+
/* Check whether the relative offset overflows desc->imm */
3377+
if ((unsigned long)(s32)call_imm != call_imm) {
3378+
verbose(env, "address of kernel func_id %u is out of range\n", func_id);
3379+
return -EINVAL;
3380+
}
3381+
}
3382+
33723383
desc = &tab->descs[tab->nr_descs++];
33733384
desc->func_id = func_id;
3385+
desc->imm = call_imm;
33743386
desc->offset = offset;
33753387
desc->addr = addr;
33763388
desc->func_model = func_model;
@@ -22353,17 +22365,15 @@ static int specialize_kfunc(struct bpf_verifier_env *env, struct bpf_kfunc_desc
2235322365
}
2235422366

2235522367
set_imm:
22356-
if (bpf_jit_supports_far_kfunc_call()) {
22357-
call_imm = func_id;
22358-
} else {
22368+
if (!bpf_jit_supports_far_kfunc_call()) {
2235922369
call_imm = BPF_CALL_IMM(addr);
2236022370
/* Check whether the relative offset overflows desc->imm */
2236122371
if ((unsigned long)(s32)call_imm != call_imm) {
2236222372
verbose(env, "address of kernel func_id %u is out of range\n", func_id);
2236322373
return -EINVAL;
2236422374
}
22375+
desc->imm = call_imm;
2236522376
}
22366-
desc->imm = call_imm;
2236722377
desc->addr = addr;
2236822378
return 0;
2236922379
}

0 commit comments

Comments
 (0)