bpf: Fix net.core.bpf_jit_harden race
authorHou Tao <houtao1@huawei.com>
Wed, 9 Mar 2022 12:33:20 +0000 (20:33 +0800)
committerAlexei Starovoitov <ast@kernel.org>
Wed, 16 Mar 2022 22:13:36 +0000 (15:13 -0700)
It is the bpf_jit_harden counterpart to commit 60b58afc96c9 ("bpf: fix
net.core.bpf_jit_enable race"). bpf_jit_harden will be tested twice
for each subprog if there are subprogs in bpf program and constant
blinding may increase the length of program, so when running
"./test_progs -t subprogs" and toggling bpf_jit_harden between 0 and 2,
jit_subprogs may fail because constant blinding increases the length
of subprog instructions during extra passs.

So cache the value of bpf_jit_blinding_enabled() during program
allocation, and use the cached value during constant blinding, subprog
JITing and args tracking of tail call.

Signed-off-by: Hou Tao <houtao1@huawei.com>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Link: https://lore.kernel.org/bpf/20220309123321.2400262-4-houtao1@huawei.com
include/linux/filter.h
kernel/bpf/core.c
kernel/bpf/verifier.c

index 05ed9bd31b451ee77ab0ee44c6f3ad4100bb03fc..ed0c0ff42ad5b5bc0b0cb5ec2f41712a4b9400c6 100644 (file)
@@ -566,6 +566,7 @@ struct bpf_prog {
                                gpl_compatible:1, /* Is filter GPL compatible? */
                                cb_access:1,    /* Is control block accessed? */
                                dst_needed:1,   /* Do we need dst entry? */
+                               blinding_requested:1, /* needs constant blinding */
                                blinded:1,      /* Was blinded */
                                is_func:1,      /* program is a bpf function */
                                kprobe_override:1, /* Do we override a kprobe? */
index ab630f773ec1dd2cbb9e76994513488f1ee615e8..1324f9523e7c520c6a45440fda9dae5f4ed74343 100644 (file)
@@ -105,6 +105,7 @@ struct bpf_prog *bpf_prog_alloc_no_stats(unsigned int size, gfp_t gfp_extra_flag
        fp->aux = aux;
        fp->aux->prog = fp;
        fp->jit_requested = ebpf_jit_enabled();
+       fp->blinding_requested = bpf_jit_blinding_enabled(fp);
 
        INIT_LIST_HEAD_RCU(&fp->aux->ksym.lnode);
        mutex_init(&fp->aux->used_maps_mutex);
@@ -1382,7 +1383,7 @@ struct bpf_prog *bpf_jit_blind_constants(struct bpf_prog *prog)
        struct bpf_insn *insn;
        int i, rewritten;
 
-       if (!bpf_jit_blinding_enabled(prog) || prog->blinded)
+       if (!prog->blinding_requested || prog->blinded)
                return prog;
 
        clone = bpf_prog_clone_create(prog, GFP_USER);
index 0db6cd8dcb3599d1ea7da5058dd947d62df4ec56..cf92f9c01556f337748f39aa1cb0ad085e18c5f7 100644 (file)
@@ -13023,6 +13023,7 @@ static int jit_subprogs(struct bpf_verifier_env *env)
                func[i]->aux->name[0] = 'F';
                func[i]->aux->stack_depth = env->subprog_info[i].stack_depth;
                func[i]->jit_requested = 1;
+               func[i]->blinding_requested = prog->blinding_requested;
                func[i]->aux->kfunc_tab = prog->aux->kfunc_tab;
                func[i]->aux->kfunc_btf_tab = prog->aux->kfunc_btf_tab;
                func[i]->aux->linfo = prog->aux->linfo;
@@ -13146,6 +13147,7 @@ out_free:
 out_undo_insn:
        /* cleanup main prog to be interpreted */
        prog->jit_requested = 0;
+       prog->blinding_requested = 0;
        for (i = 0, insn = prog->insnsi; i < prog->len; i++, insn++) {
                if (!bpf_pseudo_call(insn))
                        continue;
@@ -13239,7 +13241,6 @@ static int do_misc_fixups(struct bpf_verifier_env *env)
 {
        struct bpf_prog *prog = env->prog;
        enum bpf_attach_type eatype = prog->expected_attach_type;
-       bool expect_blinding = bpf_jit_blinding_enabled(prog);
        enum bpf_prog_type prog_type = resolve_prog_type(prog);
        struct bpf_insn *insn = prog->insnsi;
        const struct bpf_func_proto *fn;
@@ -13403,7 +13404,7 @@ static int do_misc_fixups(struct bpf_verifier_env *env)
                        insn->code = BPF_JMP | BPF_TAIL_CALL;
 
                        aux = &env->insn_aux_data[i + delta];
-                       if (env->bpf_capable && !expect_blinding &&
+                       if (env->bpf_capable && !prog->blinding_requested &&
                            prog->jit_requested &&
                            !bpf_map_key_poisoned(aux) &&
                            !bpf_map_ptr_poisoned(aux) &&