This patch puts all BPF oracle logic behind a new BPF_ORACLE kernel config. At the moment, this config requires CONFIG_BPF_JIT_ALWAYS_ON to be disabled as the oracle only runs in the interpreter. Signed-off-by: Paul Chaignon --- kernel/bpf/Kconfig | 14 ++++++++++++++ kernel/bpf/Makefile | 3 ++- kernel/bpf/core.c | 2 ++ kernel/bpf/verifier.c | 6 ++++++ 4 files changed, 24 insertions(+), 1 deletion(-) diff --git a/kernel/bpf/Kconfig b/kernel/bpf/Kconfig index eb3de35734f0..390db0bcca3d 100644 --- a/kernel/bpf/Kconfig +++ b/kernel/bpf/Kconfig @@ -101,4 +101,18 @@ config BPF_LSM If you are unsure how to answer this question, answer N. +config BPF_ORACLE + bool "Enable BPF test oracle" + depends on BPF_SYSCALL + depends on DEBUG_KERNEL + depends on !BPF_JIT_ALWAYS_ON + default n + help + Enable the BPF test oracle to compare concrete runtime values of + registers with their verification-time bounds. This will throw a kernel + warning if the runtime values don't match the expected bounds from the + verifier. + + If you are unsure how to answer this question, answer N. + endmenu # "BPF subsystem" diff --git a/kernel/bpf/Makefile b/kernel/bpf/Makefile index b94c9af3288a..647ff7cb86b9 100644 --- a/kernel/bpf/Makefile +++ b/kernel/bpf/Makefile @@ -6,7 +6,7 @@ cflags-nogcse-$(CONFIG_X86)$(CONFIG_CC_IS_GCC) := -fno-gcse endif CFLAGS_core.o += -Wno-override-init $(cflags-nogcse-yy) -obj-$(CONFIG_BPF_SYSCALL) += syscall.o verifier.o inode.o helpers.o tnum.o oracle.o log.o token.o liveness.o +obj-$(CONFIG_BPF_SYSCALL) += syscall.o verifier.o inode.o helpers.o tnum.o log.o token.o liveness.o obj-$(CONFIG_BPF_SYSCALL) += bpf_iter.o map_iter.o task_iter.o prog_iter.o link_iter.o obj-$(CONFIG_BPF_SYSCALL) += hashtab.o arraymap.o percpu_freelist.o bpf_lru_list.o lpm_trie.o map_in_map.o bloom_filter.o obj-$(CONFIG_BPF_SYSCALL) += local_storage.o queue_stack_maps.o ringbuf.o bpf_insn_array.o @@ -56,6 +56,7 @@ obj-$(CONFIG_BPF_SYSCALL) += kmem_cache_iter.o ifeq ($(CONFIG_DMA_SHARED_BUFFER),y) obj-$(CONFIG_BPF_SYSCALL) += dmabuf_iter.o endif +obj-$(CONFIG_BPF_ORACLE) += oracle.o CFLAGS_REMOVE_percpu_freelist.o = $(CC_FLAGS_FTRACE) CFLAGS_REMOVE_bpf_lru_list.o = $(CC_FLAGS_FTRACE) diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c index fe251f1ff703..f89fdde66348 100644 --- a/kernel/bpf/core.c +++ b/kernel/bpf/core.c @@ -1851,11 +1851,13 @@ static u64 ___bpf_prog_run(u64 *regs, const struct bpf_insn *insn) LD_IMM_DW: { u64 address = (u64)(u32)insn[0].imm | ((u64)(u32)insn[1].imm) << 32; +#ifdef CONFIG_BPF_ORACLE if (insn[0].src_reg == BPF_PSEUDO_MAP_ORACLE) { oracle_test((struct bpf_map *)address, regs); insn++; CONT; } +#endif DST = address; insn++; CONT; diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index 9b39bc2ca7f1..32c0146b9add 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -20505,9 +20505,11 @@ static int do_check(struct bpf_verifier_env *env) state->insn_idx = env->insn_idx; if (is_prune_point(env, env->insn_idx)) { +#ifdef CONFIG_BPF_ORACLE err = save_state_in_oracle(env, env->insn_idx); if (err < 0) return err; +#endif err = is_state_visited(env, env->insn_idx); if (err < 0) @@ -22641,6 +22643,7 @@ static int do_misc_fixups(struct bpf_verifier_env *env) } for (i = 0; i < insn_cnt;) { +#ifdef CONFIG_BPF_ORACLE if (is_prune_point(env, i + delta)) { new_prog = patch_oracle_check_insn(env, insn, i + delta, &cnt); if (IS_ERR(new_prog)) @@ -22650,6 +22653,7 @@ static int do_misc_fixups(struct bpf_verifier_env *env) env->prog = prog = new_prog; insn = new_prog->insnsi + i + delta; } +#endif if (insn->code == (BPF_ALU64 | BPF_MOV | BPF_X) && insn->imm) { if ((insn->off == BPF_ADDR_SPACE_CAST && insn->imm == 1) || @@ -25303,8 +25307,10 @@ int bpf_check(struct bpf_prog **prog, union bpf_attr *attr, bpfptr_t uattr, __u3 if (ret == 0) ret = do_misc_fixups(env); +#ifdef CONFIG_BPF_ORACLE if (ret == 0) ret = create_and_populate_oracle_map(env); +#endif /* do 32-bit optimization after insn patching has done so those patched * insns could be handled correctly. -- 2.43.0