diff options
author | Rabin Vincent <rabin@rab.in> | 2016-01-05 10:23:07 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2016-01-06 00:43:52 -0500 |
commit | 55795ef5469290f89f04e12e662ded604909e462 (patch) | |
tree | df413e913330af821e7989534a4d36ea621bab56 /arch/sparc/net | |
parent | ff62198553e43cdffa9d539f6165d3e83f8a42bc (diff) |
net: filter: make JITs zero A for SKF_AD_ALU_XOR_X
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>
Diffstat (limited to 'arch/sparc/net')
-rw-r--r-- | arch/sparc/net/bpf_jit_comp.c | 17 |
1 files changed, 2 insertions, 15 deletions
diff --git a/arch/sparc/net/bpf_jit_comp.c b/arch/sparc/net/bpf_jit_comp.c index 22564f5f2364..3e6e05a7c4c2 100644 --- a/arch/sparc/net/bpf_jit_comp.c +++ b/arch/sparc/net/bpf_jit_comp.c | |||
@@ -420,22 +420,9 @@ void bpf_jit_compile(struct bpf_prog *fp) | |||
420 | } | 420 | } |
421 | emit_reg_move(O7, r_saved_O7); | 421 | emit_reg_move(O7, r_saved_O7); |
422 | 422 | ||
423 | switch (filter[0].code) { | 423 | /* Make sure we dont leak kernel information to the user. */ |
424 | case BPF_RET | BPF_K: | 424 | if (bpf_needs_clear_a(&filter[0])) |
425 | case BPF_LD | BPF_W | BPF_LEN: | ||
426 | case BPF_LD | BPF_W | BPF_ABS: | ||
427 | case BPF_LD | BPF_H | BPF_ABS: | ||
428 | case BPF_LD | BPF_B | BPF_ABS: | ||
429 | /* The first instruction sets the A register (or is | ||
430 | * a "RET 'constant'") | ||
431 | */ | ||
432 | break; | ||
433 | default: | ||
434 | /* Make sure we dont leak kernel information to the | ||
435 | * user. | ||
436 | */ | ||
437 | emit_clear(r_A); /* A = 0 */ | 425 | emit_clear(r_A); /* A = 0 */ |
438 | } | ||
439 | 426 | ||
440 | for (i = 0; i < flen; i++) { | 427 | for (i = 0; i < flen; i++) { |
441 | unsigned int K = filter[i].k; | 428 | unsigned int K = filter[i].k; |