mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-08-30 14:33:24 -04:00
bpf: Introduce jit_required flag and remove bpf_prog_has_kfunc_call()
Introduce a 'jit_required' bitfield flag in struct bpf_prog to track whether a BPF program strictly requires the JIT compiler to run. This prevents a dangerous runtime fallback to the interpreter for features that are only implemented in the JIT compiler. Currently, bpf_prog_has_kfunc_call() is used only for kernel function calls, replace the kfunc-specific helper with the new 'jit_required' flag. This makes it easy to support other JIT-only BPF features, such as inlined helpers. Suggested-by: Alexei Starovoitov <ast@kernel.org> Suggested-by: KaFai Wan <kafai.wan@linux.dev> Suggested-by: Leon Hwang <leon.hwang@linux.dev> Acked-by: Leon Hwang <leon.hwang@linux.dev> Signed-off-by: Tiezhu Yang <yangtiezhu@loongson.cn> Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
This commit is contained in:
committed by
Eduard Zingerman
parent
47b079e211
commit
9a6df65d5c
@@ -1864,8 +1864,9 @@ struct bpf_prog_aux {
|
||||
|
||||
struct bpf_prog {
|
||||
u16 pages; /* Number of allocated pages */
|
||||
u16 jited:1, /* Is our filter JIT'ed? */
|
||||
u32 jited:1, /* Is our filter JIT'ed? */
|
||||
jit_requested:1,/* archs need to JIT the prog */
|
||||
jit_required:1, /* program strictly requires JIT compiler */
|
||||
gpl_compatible:1, /* Is filter GPL compatible? */
|
||||
cb_access:1, /* Is control block accessed? */
|
||||
dst_needed:1, /* Do we need dst entry? */
|
||||
@@ -3169,7 +3170,6 @@ const struct bpf_func_proto *bpf_base_func_proto(enum bpf_func_id func_id,
|
||||
const struct bpf_prog *prog);
|
||||
void bpf_task_storage_free(struct task_struct *task);
|
||||
void bpf_cgrp_storage_free(struct cgroup *cgroup);
|
||||
bool bpf_prog_has_kfunc_call(const struct bpf_prog *prog);
|
||||
const struct btf_func_model *
|
||||
bpf_jit_find_kfunc_model(const struct bpf_prog *prog,
|
||||
const struct bpf_insn *insn);
|
||||
@@ -3508,11 +3508,6 @@ static inline void bpf_task_storage_free(struct task_struct *task)
|
||||
{
|
||||
}
|
||||
|
||||
static inline bool bpf_prog_has_kfunc_call(const struct bpf_prog *prog)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline const struct btf_func_model *
|
||||
bpf_jit_find_kfunc_model(const struct bpf_prog *prog,
|
||||
const struct bpf_insn *insn)
|
||||
|
||||
@@ -126,6 +126,7 @@ struct bpf_prog *bpf_prog_alloc_no_stats(unsigned int size, gfp_t gfp_extra_flag
|
||||
fp->aux->main_prog_aux = aux;
|
||||
fp->aux->prog = fp;
|
||||
fp->jit_requested = ebpf_jit_enabled();
|
||||
fp->jit_required = IS_ENABLED(CONFIG_BPF_JIT_ALWAYS_ON);
|
||||
fp->blinding_requested = bpf_jit_blinding_enabled(fp);
|
||||
#ifdef CONFIG_CGROUP_BPF
|
||||
aux->cgroup_atype = CGROUP_BPF_ATTACH_TYPE_INVALID;
|
||||
@@ -2670,15 +2671,11 @@ struct bpf_prog *__bpf_prog_select_runtime(struct bpf_verifier_env *env, struct
|
||||
/* In case of BPF to BPF calls, verifier did all the prep
|
||||
* work with regards to JITing, etc.
|
||||
*/
|
||||
bool jit_needed = false;
|
||||
bool jit_needed = fp->jit_required;
|
||||
|
||||
if (fp->bpf_func)
|
||||
goto finalize;
|
||||
|
||||
if (IS_ENABLED(CONFIG_BPF_JIT_ALWAYS_ON) ||
|
||||
bpf_prog_has_kfunc_call(fp))
|
||||
jit_needed = true;
|
||||
|
||||
if (!bpf_prog_select_interpreter(fp))
|
||||
jit_needed = true;
|
||||
|
||||
|
||||
@@ -1378,7 +1378,6 @@ int bpf_fixup_call_args(struct bpf_verifier_env *env)
|
||||
#ifndef CONFIG_BPF_JIT_ALWAYS_ON
|
||||
struct bpf_prog *prog = env->prog;
|
||||
struct bpf_insn *insn = prog->insnsi;
|
||||
bool has_kfunc_call = bpf_prog_has_kfunc_call(prog);
|
||||
int depth;
|
||||
#endif
|
||||
int i, err = 0;
|
||||
@@ -1404,8 +1403,8 @@ int bpf_fixup_call_args(struct bpf_verifier_env *env)
|
||||
return err;
|
||||
}
|
||||
#ifndef CONFIG_BPF_JIT_ALWAYS_ON
|
||||
if (has_kfunc_call) {
|
||||
verbose(env, "calling kernel functions are not allowed in non-JITed programs\n");
|
||||
if (prog->jit_required) {
|
||||
verbose(env, "program requires BPF JIT compiler but it is not available\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
for (i = 0; i < env->subprog_cnt; i++) {
|
||||
|
||||
@@ -2780,6 +2780,8 @@ int bpf_add_kfunc_call(struct bpf_verifier_env *env, u32 func_id, u16 offset)
|
||||
prog_aux->kfunc_tab = tab;
|
||||
}
|
||||
|
||||
env->prog->jit_required = 1;
|
||||
|
||||
/* func_id == 0 is always invalid, but instead of returning an error, be
|
||||
* conservative and wait until the code elimination pass before returning
|
||||
* error, so that invalid calls that get pruned out can be in BPF programs
|
||||
@@ -2834,11 +2836,6 @@ int bpf_add_kfunc_call(struct bpf_verifier_env *env, u32 func_id, u16 offset)
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool bpf_prog_has_kfunc_call(const struct bpf_prog *prog)
|
||||
{
|
||||
return !!prog->aux->kfunc_tab;
|
||||
}
|
||||
|
||||
static int add_subprog_and_kfunc(struct bpf_verifier_env *env)
|
||||
{
|
||||
struct bpf_subprog_info *subprog = env->subprog_info;
|
||||
|
||||
Reference in New Issue
Block a user