Skip to content

Commit

Permalink
bpf: fix net.core.bpf_jit_enable race
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
4ast authored and borkmann committed Dec 17, 2017
1 parent 1ea47e0 commit 60b58af
Show file tree
Hide file tree
Showing 10 changed files with 13 additions and 11 deletions.
2 changes: 1 addition & 1 deletion arch/arm/net/bpf_jit_32.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion arch/arm64/net/bpf_jit_comp.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion arch/mips/net/ebpf_jit.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion arch/powerpc/net/bpf_jit_comp64.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion arch/s390/net/bpf_jit_comp.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion arch/sparc/net/bpf_jit_comp_64.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion arch/x86/net/bpf_jit_comp.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
5 changes: 3 additions & 2 deletions include/linux/filter.h
Original file line number Diff line number Diff line change
Expand Up @@ -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? */
Expand Down Expand Up @@ -804,15 +805,15 @@ 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
* bail out.
*/
if (!bpf_jit_is_ebpf())
return false;
if (!bpf_jit_enable)
if (!prog->jit_requested)
return false;
if (!bpf_jit_harden)
return false;
Expand Down
3 changes: 2 additions & 1 deletion kernel/bpf/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion kernel/bpf/verifier.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 ||
Expand Down

0 comments on commit 60b58af

Please sign in to comment.