diff options
author | Rabin Vincent <rabin@rab.in> | 2016-01-05 18:23:07 +0300 |
---|---|---|
committer | Sasha Levin <sasha.levin@oracle.com> | 2016-02-15 23:42:43 +0300 |
commit | 03a115644c4a6dd0f7efec7e9b28b2dbebd7c018 (patch) | |
tree | 5bd1f74fcc5736fc23f638033bb30020499fe285 /arch/arm | |
parent | 7e95dfd637e49b49f3e3383fc28db48004103184 (diff) | |
download | linux-03a115644c4a6dd0f7efec7e9b28b2dbebd7c018.tar.xz |
net: filter: make JITs zero A for SKF_AD_ALU_XOR_X
[ Upstream commit 55795ef5469290f89f04e12e662ded604909e462 ]
The SKF_AD_ALU_XOR_X ancillary is not like the other ancillary data
instructions since it XORs A with X while all the others replace A with
some loaded value. All the BPF JITs fail to clear A if this is used as
the first instruction in a filter. This was found using american fuzzy
lop.
Add a helper to determine if A needs to be cleared given the first
instruction in a filter, and use this in the JITs. Except for ARM, the
rest have only been compile-tested.
Fixes: 3480593131e0 ("net: filter: get rid of BPF_S_* enum")
Signed-off-by: Rabin Vincent <rabin@rab.in>
Acked-by: Daniel Borkmann <daniel@iogearbox.net>
Acked-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Sasha Levin <sasha.levin@oracle.com>
Diffstat (limited to 'arch/arm')
-rw-r--r-- | arch/arm/net/bpf_jit_32.c | 16 |
1 files changed, 1 insertions, 15 deletions
diff --git a/arch/arm/net/bpf_jit_32.c b/arch/arm/net/bpf_jit_32.c index f412b53ed268..ace4dc1e24ba 100644 --- a/arch/arm/net/bpf_jit_32.c +++ b/arch/arm/net/bpf_jit_32.c @@ -161,19 +161,6 @@ static inline int mem_words_used(struct jit_ctx *ctx) return fls(ctx->seen & SEEN_MEM); } -static inline bool is_load_to_a(u16 inst) -{ - switch (inst) { - case BPF_LD | BPF_W | BPF_LEN: - case BPF_LD | BPF_W | BPF_ABS: - case BPF_LD | BPF_H | BPF_ABS: - case BPF_LD | BPF_B | BPF_ABS: - return true; - default: - return false; - } -} - static void jit_fill_hole(void *area, unsigned int size) { u32 *ptr; @@ -185,7 +172,6 @@ static void jit_fill_hole(void *area, unsigned int size) static void build_prologue(struct jit_ctx *ctx) { u16 reg_set = saved_regs(ctx); - u16 first_inst = ctx->skf->insns[0].code; u16 off; #ifdef CONFIG_FRAME_POINTER @@ -215,7 +201,7 @@ static void build_prologue(struct jit_ctx *ctx) emit(ARM_MOV_I(r_X, 0), ctx); /* do not leak kernel data to userspace */ - if ((first_inst != (BPF_RET | BPF_K)) && !(is_load_to_a(first_inst))) + if (bpf_needs_clear_a(&ctx->skf->insns[0])) emit(ARM_MOV_I(r_A, 0), ctx); /* stack space for the BPF_MEM words */ |