diff options
author | Zi Shen Lim <zlim.lnx@gmail.com> | 2016-01-14 02:33:22 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2016-01-17 19:15:26 -0500 |
commit | 42ff712bc0c3d7cd60d29b319aecd2d2c8cc75d4 (patch) | |
tree | 41722ff39391f428b5ee48ce461b32329be4fda4 | |
parent | c94ae4f7c5ec6b6fddde1c08809d5e32a963d7f3 (diff) |
arm64: bpf: add extra pass to handle faulty codegen
Code generation functions in arch/arm64/kernel/insn.c previously
BUG_ON invalid parameters. Following change of that behavior, now we
need to handle the error case where AARCH64_BREAK_FAULT is returned.
Instead of error-handling on every emit() in JIT, we add a new
validation pass at the end of JIT compilation. There's no point in
running JITed code at run-time only to trap due to AARCH64_BREAK_FAULT.
Instead, we drop this failed JIT compilation and allow the system to
gracefully fallback on the BPF interpreter.
Signed-off-by: Zi Shen Lim <zlim.lnx@gmail.com>
Suggested-by: Alexei Starovoitov <ast@kernel.org>
Acked-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | arch/arm64/net/bpf_jit_comp.c | 22 |
1 files changed, 21 insertions, 1 deletions
diff --git a/arch/arm64/net/bpf_jit_comp.c b/arch/arm64/net/bpf_jit_comp.c index 7658612d915c..a34420a5df9a 100644 --- a/arch/arm64/net/bpf_jit_comp.c +++ b/arch/arm64/net/bpf_jit_comp.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * BPF JIT compiler for ARM64 | 2 | * BPF JIT compiler for ARM64 |
3 | * | 3 | * |
4 | * Copyright (C) 2014-2015 Zi Shen Lim <zlim.lnx@gmail.com> | 4 | * Copyright (C) 2014-2016 Zi Shen Lim <zlim.lnx@gmail.com> |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
7 | * it under the terms of the GNU General Public License version 2 as | 7 | * it under the terms of the GNU General Public License version 2 as |
@@ -737,6 +737,20 @@ static int build_body(struct jit_ctx *ctx) | |||
737 | return 0; | 737 | return 0; |
738 | } | 738 | } |
739 | 739 | ||
740 | static int validate_code(struct jit_ctx *ctx) | ||
741 | { | ||
742 | int i; | ||
743 | |||
744 | for (i = 0; i < ctx->idx; i++) { | ||
745 | u32 a64_insn = le32_to_cpu(ctx->image[i]); | ||
746 | |||
747 | if (a64_insn == AARCH64_BREAK_FAULT) | ||
748 | return -1; | ||
749 | } | ||
750 | |||
751 | return 0; | ||
752 | } | ||
753 | |||
740 | static inline void bpf_flush_icache(void *start, void *end) | 754 | static inline void bpf_flush_icache(void *start, void *end) |
741 | { | 755 | { |
742 | flush_icache_range((unsigned long)start, (unsigned long)end); | 756 | flush_icache_range((unsigned long)start, (unsigned long)end); |
@@ -799,6 +813,12 @@ void bpf_int_jit_compile(struct bpf_prog *prog) | |||
799 | 813 | ||
800 | build_epilogue(&ctx); | 814 | build_epilogue(&ctx); |
801 | 815 | ||
816 | /* 3. Extra pass to validate JITed code. */ | ||
817 | if (validate_code(&ctx)) { | ||
818 | bpf_jit_binary_free(header); | ||
819 | goto out; | ||
820 | } | ||
821 | |||
802 | /* And we're done. */ | 822 | /* And we're done. */ |
803 | if (bpf_jit_enable > 1) | 823 | if (bpf_jit_enable > 1) |
804 | bpf_jit_dump(prog->len, image_size, 2, ctx.image); | 824 | bpf_jit_dump(prog->len, image_size, 2, ctx.image); |