diff options
author | Daniel Borkmann <daniel@iogearbox.net> | 2018-01-26 23:33:38 +0100 |
---|---|---|
committer | Alexei Starovoitov <ast@kernel.org> | 2018-01-26 16:42:05 -0800 |
commit | 5e581dad4fec0e6d062740dc35b8dc248b39d224 (patch) | |
tree | 534845527ccef6977576db77a02f96956f329b7f /include/linux/filter.h | |
parent | 2a5418a13fcfbb1f13a847eedb9a8e30a9ead765 (diff) | |
download | lwn-5e581dad4fec0e6d062740dc35b8dc248b39d224.tar.gz lwn-5e581dad4fec0e6d062740dc35b8dc248b39d224.zip |
bpf: make unknown opcode handling more robust
Recent findings by syzcaller fixed in 7891a87efc71 ("bpf: arsh is
not supported in 32 bit alu thus reject it") triggered a warning
in the interpreter due to unknown opcode not being rejected by
the verifier. The 'return 0' for an unknown opcode is really not
optimal, since with BPF to BPF calls, this would go untracked by
the verifier.
Do two things here to improve the situation: i) perform basic insn
sanity check early on in the verification phase and reject every
non-uapi insn right there. The bpf_opcode_in_insntable() table
reuses the same mapping as the jumptable in ___bpf_prog_run() sans
the non-public mappings. And ii) in ___bpf_prog_run() we do need
to BUG in the case where the verifier would ever create an unknown
opcode due to some rewrites.
Note that JITs do not have such issues since they would punt to
interpreter in these situations. Moreover, the BPF_JIT_ALWAYS_ON
would also help to avoid such unknown opcodes in the first place.
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Acked-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Diffstat (limited to 'include/linux/filter.h')
-rw-r--r-- | include/linux/filter.h | 2 |
1 files changed, 2 insertions, 0 deletions
diff --git a/include/linux/filter.h b/include/linux/filter.h index 20384c4bed25..276932d75975 100644 --- a/include/linux/filter.h +++ b/include/linux/filter.h @@ -688,6 +688,8 @@ static inline int sk_filter(struct sock *sk, struct sk_buff *skb) struct bpf_prog *bpf_prog_select_runtime(struct bpf_prog *fp, int *err); void bpf_prog_free(struct bpf_prog *fp); +bool bpf_opcode_in_insntable(u8 code); + struct bpf_prog *bpf_prog_alloc(unsigned int size, gfp_t gfp_extra_flags); struct bpf_prog *bpf_prog_realloc(struct bpf_prog *fp_old, unsigned int size, gfp_t gfp_extra_flags); |