mirror of
https://github.com/torvalds/linux.git
synced 2024-11-17 09:31:50 +00:00
bpf: fix pattern matches for direct packet access
Alexander had a test program with direct packet access, where
the access test was in the form of data + X > data_end. In an
unrelated change to the program LLVM decided to swap the branches
and emitted code for the test in form of data + X <= data_end.
We hadn't seen these being generated previously, thus verifier
would reject the program. Therefore, fix up the verifier to
detect all test cases, so we don't run into such issues in the
future.
Fixes: b4e432f100
("bpf: enable BPF_J{LT, LE, SLT, SLE} opcodes in verifier")
Reported-by: Alexander Alemayhu <alexander@alemayhu.com>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Acked-by: Alexei Starovoitov <ast@kernel.org>
Acked-by: John Fastabend <john.fastabend@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
fb2a311a31
commit
0fd4759c55
@ -2874,18 +2874,42 @@ static int check_cond_jmp_op(struct bpf_verifier_env *env,
|
||||
} else if (BPF_SRC(insn->code) == BPF_X && opcode == BPF_JGT &&
|
||||
dst_reg->type == PTR_TO_PACKET &&
|
||||
regs[insn->src_reg].type == PTR_TO_PACKET_END) {
|
||||
/* pkt_data' > pkt_end */
|
||||
find_good_pkt_pointers(this_branch, dst_reg, false);
|
||||
} else if (BPF_SRC(insn->code) == BPF_X && opcode == BPF_JGT &&
|
||||
dst_reg->type == PTR_TO_PACKET_END &&
|
||||
regs[insn->src_reg].type == PTR_TO_PACKET) {
|
||||
/* pkt_end > pkt_data' */
|
||||
find_good_pkt_pointers(other_branch, ®s[insn->src_reg], true);
|
||||
} else if (BPF_SRC(insn->code) == BPF_X && opcode == BPF_JLT &&
|
||||
dst_reg->type == PTR_TO_PACKET &&
|
||||
regs[insn->src_reg].type == PTR_TO_PACKET_END) {
|
||||
/* pkt_data' < pkt_end */
|
||||
find_good_pkt_pointers(other_branch, dst_reg, true);
|
||||
} else if (BPF_SRC(insn->code) == BPF_X && opcode == BPF_JLT &&
|
||||
dst_reg->type == PTR_TO_PACKET_END &&
|
||||
regs[insn->src_reg].type == PTR_TO_PACKET) {
|
||||
/* pkt_end < pkt_data' */
|
||||
find_good_pkt_pointers(this_branch, ®s[insn->src_reg], false);
|
||||
} else if (BPF_SRC(insn->code) == BPF_X && opcode == BPF_JGE &&
|
||||
dst_reg->type == PTR_TO_PACKET &&
|
||||
regs[insn->src_reg].type == PTR_TO_PACKET_END) {
|
||||
/* pkt_data' >= pkt_end */
|
||||
find_good_pkt_pointers(this_branch, dst_reg, true);
|
||||
} else if (BPF_SRC(insn->code) == BPF_X && opcode == BPF_JGE &&
|
||||
dst_reg->type == PTR_TO_PACKET_END &&
|
||||
regs[insn->src_reg].type == PTR_TO_PACKET) {
|
||||
/* pkt_end >= pkt_data' */
|
||||
find_good_pkt_pointers(other_branch, ®s[insn->src_reg], false);
|
||||
} else if (BPF_SRC(insn->code) == BPF_X && opcode == BPF_JLE &&
|
||||
dst_reg->type == PTR_TO_PACKET &&
|
||||
regs[insn->src_reg].type == PTR_TO_PACKET_END) {
|
||||
/* pkt_data' <= pkt_end */
|
||||
find_good_pkt_pointers(other_branch, dst_reg, false);
|
||||
} else if (BPF_SRC(insn->code) == BPF_X && opcode == BPF_JLE &&
|
||||
dst_reg->type == PTR_TO_PACKET_END &&
|
||||
regs[insn->src_reg].type == PTR_TO_PACKET) {
|
||||
/* pkt_end <= pkt_data' */
|
||||
find_good_pkt_pointers(this_branch, ®s[insn->src_reg], true);
|
||||
} else if (is_pointer_value(env, insn->dst_reg)) {
|
||||
verbose("R%d pointer comparison prohibited\n", insn->dst_reg);
|
||||
|
Loading…
Reference in New Issue
Block a user