The interpreter is unable to handle the user BPF_ADDR_SPACE_CAST insn,
whose '->off' is 1:

static u64 ___bpf_prog_run(u64 *regs, const struct bpf_insn *insn)
{
        ALU64_MOV_X:
                switch (OFF) {
                case 0:
                        DST = SRC;
                        break;
                case 8:
                        DST = (s8) SRC;
                        break;
                case 16:
                        DST = (s16) SRC;
                        break;
                case 32:
                        DST = (s32) SRC;
                        break;
                }
                CONT;
}

On the fallback path from JIT in __bpf_prog_select_runtime(), reject
the insn to avoid being ignored by interpreter.

Fixes: 142fd4d2dcf5 ("bpf: Add x86-64 JIT support for bpf_addr_space_cast 
instruction.")
Signed-off-by: Leon Hwang <[email protected]>
---
 kernel/bpf/core.c | 29 +++++++++++++++++++++++------
 1 file changed, 23 insertions(+), 6 deletions(-)

diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c
index 0db6e55bad52..e92eb8b7f945 100644
--- a/kernel/bpf/core.c
+++ b/kernel/bpf/core.c
@@ -2608,23 +2608,37 @@ static struct bpf_prog *bpf_prog_jit_compile(struct 
bpf_verifier_env *env, struc
        return prog;
 }
 
+static bool bpf_insn_requires_jit(struct bpf_insn *insn)
+{
+       if (insn_is_cast_user(insn))
+               return true;
+
+       return false;
+}
+
 /* Fix up helper call offsets on JIT fallback path. */
-static void bpf_fixup_fallback_helpers(struct bpf_verifier_env *env, struct 
bpf_prog *fp)
+static int bpf_fixup_fallback_helpers(struct bpf_verifier_env *env, struct 
bpf_prog *fp)
 {
        struct bpf_insn *insn = fp->insnsi;
        const struct bpf_func_proto *fn;
        int i;
 
-       if (!env || !env->ops->get_func_proto)
-               return;
+       if (!env)
+               return 0;
 
        for (i = 0; i < fp->len; i++, insn++) {
-               if (bpf_helper_call(insn) && 
bpf_jit_inlines_helper_call(insn->imm)) {
+               if (env->ops->get_func_proto && bpf_helper_call(insn) &&
+                   bpf_jit_inlines_helper_call(insn->imm)) {
                        fn = env->ops->get_func_proto(insn->imm, env->prog);
                        if (fn && fn->func)
                                insn->imm = fn->func - __bpf_call_base;
                }
+
+               if (bpf_insn_requires_jit(insn))
+                       return -EOPNOTSUPP;
        }
+
+       return 0;
 }
 
 struct bpf_prog *__bpf_prog_select_runtime(struct bpf_verifier_env *env, 
struct bpf_prog *fp,
@@ -2663,8 +2677,11 @@ struct bpf_prog *__bpf_prog_select_runtime(struct 
bpf_verifier_env *env, struct
                        return fp;
                }
 
-               if (!fp->jited)
-                       bpf_fixup_fallback_helpers(env, fp);
+               if (!fp->jited) {
+                       *err = bpf_fixup_fallback_helpers(env, fp);
+                       if (*err)
+                               return fp;
+               }
        } else {
                *err = bpf_prog_offload_compile(fp);
                if (*err)
-- 
2.54.0


Reply via email to