]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
bpf: fix net.core.bpf_jit_enable race
authorAlexei Starovoitov <ast@fb.com>
Fri, 15 Dec 2017 01:55:14 +0000 (17:55 -0800)
committerDaniel Borkmann <daniel@iogearbox.net>
Sun, 17 Dec 2017 19:34:36 +0000 (20:34 +0100)
global bpf_jit_enable variable is tested multiple times in JITs,
blinding and verifier core. The malicious root can try to toggle
it while loading the programs. This race condition was accounted
for and there should be no issues, but it's safer to avoid
this race condition.

Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Acked-by: Daniel Borkmann <daniel@iogearbox.net>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
arch/arm/net/bpf_jit_32.c
arch/arm64/net/bpf_jit_comp.c
arch/mips/net/ebpf_jit.c
arch/powerpc/net/bpf_jit_comp64.c
arch/s390/net/bpf_jit_comp.c
arch/sparc/net/bpf_jit_comp_64.c
arch/x86/net/bpf_jit_comp.c
include/linux/filter.h
kernel/bpf/core.c
kernel/bpf/verifier.c

index c199990e12b620fe40f34215abf2d577e6f90c70..4425189bb24c42ab43057f3070cf79cb0110ce28 100644 (file)
@@ -1824,7 +1824,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
        /* If BPF JIT was not enabled then we must fall back to
         * the interpreter.
         */
-       if (!bpf_jit_enable)
+       if (!prog->jit_requested)
                return orig_prog;
 
        /* If constant blinding was enabled and we failed during blinding
index ba38d403abb2fc92d8ea6ae9a6c3c38e70979062..288137cb08711af97c342e9bf9f839e575418f84 100644 (file)
@@ -844,7 +844,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
        int image_size;
        u8 *image_ptr;
 
-       if (!bpf_jit_enable)
+       if (!prog->jit_requested)
                return orig_prog;
 
        tmp = bpf_jit_blind_constants(prog);
index 962b0259b4b6eb86443f88134fa90d044af08cc1..97069a1b6f43f365da217f695d73e54131058b12 100644 (file)
@@ -1869,7 +1869,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
        unsigned int image_size;
        u8 *image_ptr;
 
-       if (!bpf_jit_enable || !cpu_has_mips64r2)
+       if (!prog->jit_requested || !cpu_has_mips64r2)
                return prog;
 
        tmp = bpf_jit_blind_constants(prog);
index 46d74e81aff1b4caad4769e7686fa0a800695cd4..d5a5bc43cf8f96f1d648457a432d04afa200712b 100644 (file)
@@ -993,7 +993,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp)
        struct bpf_prog *tmp_fp;
        bool bpf_blinded = false;
 
-       if (!bpf_jit_enable)
+       if (!fp->jit_requested)
                return org_fp;
 
        tmp_fp = bpf_jit_blind_constants(org_fp);
index e81c16838b90f1bc9a5418bc1b4e5365e9cb0aef..f4baa8c514d345913a1be161df51d3ccd529c340 100644 (file)
@@ -1300,7 +1300,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp)
        struct bpf_jit jit;
        int pass;
 
-       if (!bpf_jit_enable)
+       if (!fp->jit_requested)
                return orig_fp;
 
        tmp = bpf_jit_blind_constants(fp);
index 5765e7e711f78248d2bff70f9c57ca48a4514355..a2f1b5e774a716eb437322de036bec8371b51f88 100644 (file)
@@ -1517,7 +1517,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
        u8 *image_ptr;
        int pass;
 
-       if (!bpf_jit_enable)
+       if (!prog->jit_requested)
                return orig_prog;
 
        tmp = bpf_jit_blind_constants(prog);
index 0554e8aef4d54522393f78b8b7973f8dfac4750c..68859b58ab8415e6d13d66dc25a33dcdd8bf08a7 100644 (file)
@@ -1121,7 +1121,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
        int pass;
        int i;
 
-       if (!bpf_jit_enable)
+       if (!prog->jit_requested)
                return orig_prog;
 
        tmp = bpf_jit_blind_constants(prog);
index f26e6da1007b4b8452b418a3b6aebd78ed6bcee9..3d6edc34932c6c95393f05b4b3d69ce69413c1e5 100644 (file)
@@ -458,6 +458,7 @@ struct bpf_binary_header {
 struct bpf_prog {
        u16                     pages;          /* Number of allocated pages */
        u16                     jited:1,        /* Is our filter JIT'ed? */
+                               jit_requested:1,/* archs need to JIT the prog */
                                locked:1,       /* Program image locked? */
                                gpl_compatible:1, /* Is filter GPL compatible? */
                                cb_access:1,    /* Is control block accessed? */
@@ -804,7 +805,7 @@ static inline bool bpf_prog_ebpf_jited(const struct bpf_prog *fp)
        return fp->jited && bpf_jit_is_ebpf();
 }
 
-static inline bool bpf_jit_blinding_enabled(void)
+static inline bool bpf_jit_blinding_enabled(struct bpf_prog *prog)
 {
        /* These are the prerequisites, should someone ever have the
         * idea to call blinding outside of them, we make sure to
@@ -812,7 +813,7 @@ static inline bool bpf_jit_blinding_enabled(void)
         */
        if (!bpf_jit_is_ebpf())
                return false;
-       if (!bpf_jit_enable)
+       if (!prog->jit_requested)
                return false;
        if (!bpf_jit_harden)
                return false;
index dc12c4fd006e41617188acf70c855637b5025eac..bda911644b1cba4fe6b05033df9593886ff89f1f 100644 (file)
@@ -94,6 +94,7 @@ struct bpf_prog *bpf_prog_alloc(unsigned int size, gfp_t gfp_extra_flags)
        fp->pages = size / PAGE_SIZE;
        fp->aux = aux;
        fp->aux->prog = fp;
+       fp->jit_requested = ebpf_jit_enabled();
 
        INIT_LIST_HEAD_RCU(&fp->aux->ksym_lnode);
 
@@ -721,7 +722,7 @@ struct bpf_prog *bpf_jit_blind_constants(struct bpf_prog *prog)
        struct bpf_insn *insn;
        int i, rewritten;
 
-       if (!bpf_jit_blinding_enabled())
+       if (!bpf_jit_blinding_enabled(prog))
                return prog;
 
        clone = bpf_prog_clone_create(prog, GFP_USER);
index cdc1f043c69b3ef3fb6067df3a444f72425bb4d1..8e0e4cd0d5e459e4827c4e69ac70d77c1b9575d6 100644 (file)
@@ -5080,7 +5080,7 @@ static int fixup_bpf_calls(struct bpf_verifier_env *env)
                /* BPF_EMIT_CALL() assumptions in some of the map_gen_lookup
                 * handlers are currently limited to 64 bit only.
                 */
-               if (ebpf_jit_enabled() && BITS_PER_LONG == 64 &&
+               if (prog->jit_requested && BITS_PER_LONG == 64 &&
                    insn->imm == BPF_FUNC_map_lookup_elem) {
                        map_ptr = env->insn_aux_data[i + delta].map_ptr;
                        if (map_ptr == BPF_MAP_PTR_POISON ||