netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH net-next 0/2] bpf: verifier fixes
@ 2016-05-20  1:17 Alexei Starovoitov
  2016-05-20  1:17 ` [PATCH net-next 1/2] bpf: support decreasing order in direct packet access Alexei Starovoitov
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Alexei Starovoitov @ 2016-05-20  1:17 UTC (permalink / raw)
  To: David S . Miller; +Cc: Daniel Borkmann, netdev, kernel-team

Further testing of 'direct packet access' uncovered
several usability issues. Fix them.

Alexei Starovoitov (2):
  bpf: support decreasing order in direct packet access
  bpf: teach verifier to recognize imm += ptr pattern

 kernel/bpf/verifier.c | 30 +++++++++++++++++++++---------
 1 file changed, 21 insertions(+), 9 deletions(-)

-- 
2.8.0

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH net-next 1/2] bpf: support decreasing order in direct packet access
  2016-05-20  1:17 [PATCH net-next 0/2] bpf: verifier fixes Alexei Starovoitov
@ 2016-05-20  1:17 ` Alexei Starovoitov
  2016-05-20  1:17 ` [PATCH net-next 2/2] bpf: teach verifier to recognize imm += ptr pattern Alexei Starovoitov
  2016-05-20 23:53 ` [PATCH net-next 0/2] bpf: verifier fixes David Miller
  2 siblings, 0 replies; 4+ messages in thread
From: Alexei Starovoitov @ 2016-05-20  1:17 UTC (permalink / raw)
  To: David S . Miller; +Cc: Daniel Borkmann, netdev, kernel-team

when packet headers are accessed in 'decreasing' order (like TCP port
may be fetched before the program reads IP src) the llvm may generate
the following code:
[...]                // R7=pkt(id=0,off=22,r=70)
r2 = *(u32 *)(r7 +0) // good access
[...]
r7 += 40             // R7=pkt(id=0,off=62,r=70)
r8 = *(u32 *)(r7 +0) // good access
[...]
r1 = *(u32 *)(r7 -20) // this one will fail though it's within a safe range
                      // it's doing *(u32*)(skb->data + 42)
Fix verifier to recognize such code pattern

Alos turned out that 'off > range' condition is not a verifier bug.
It's a buggy program that may do something like:
if (ptr + 50 > data_end)
  return 0;
ptr += 60;
*(u32*)ptr;
in such case emit
"invalid access to packet, off=0 size=4, R1(id=0,off=60,r=50)" error message,
so all information is available for the program author to fix the program.

Fixes: 969bf05eb3ce ("bpf: direct packet access")
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Acked-by: Daniel Borkmann <daniel@iogearbox.net>
---
 kernel/bpf/verifier.c | 12 ++++--------
 1 file changed, 4 insertions(+), 8 deletions(-)

diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index a08d66215245..d54e34874579 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -683,15 +683,11 @@ static int check_packet_access(struct verifier_env *env, u32 regno, int off,
 {
 	struct reg_state *regs = env->cur_state.regs;
 	struct reg_state *reg = &regs[regno];
-	int linear_size = (int) reg->range - (int) reg->off;
 
-	if (linear_size < 0 || linear_size >= MAX_PACKET_OFF) {
-		verbose("verifier bug\n");
-		return -EFAULT;
-	}
-	if (off < 0 || off + size > linear_size) {
-		verbose("invalid access to packet, off=%d size=%d, allowed=%d\n",
-			off, size, linear_size);
+	off += reg->off;
+	if (off < 0 || off + size > reg->range) {
+		verbose("invalid access to packet, off=%d size=%d, R%d(id=%d,off=%d,r=%d)\n",
+			off, size, regno, reg->id, reg->off, reg->range);
 		return -EACCES;
 	}
 	return 0;
-- 
2.8.0

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH net-next 2/2] bpf: teach verifier to recognize imm += ptr pattern
  2016-05-20  1:17 [PATCH net-next 0/2] bpf: verifier fixes Alexei Starovoitov
  2016-05-20  1:17 ` [PATCH net-next 1/2] bpf: support decreasing order in direct packet access Alexei Starovoitov
@ 2016-05-20  1:17 ` Alexei Starovoitov
  2016-05-20 23:53 ` [PATCH net-next 0/2] bpf: verifier fixes David Miller
  2 siblings, 0 replies; 4+ messages in thread
From: Alexei Starovoitov @ 2016-05-20  1:17 UTC (permalink / raw)
  To: David S . Miller; +Cc: Daniel Borkmann, netdev, kernel-team

Humans don't write C code like:
  u8 *ptr = skb->data;
  int imm = 4;
  imm += ptr;
but from llvm backend point of view 'imm' and 'ptr' are registers and
imm += ptr may be preferred vs ptr += imm depending which register value
will be used further in the code, while verifier can only recognize ptr += imm.
That caused small unrelated changes in the C code of the bpf program to
trigger rejection by the verifier. Therefore teach the verifier to recognize
both ptr += imm and imm += ptr.
For example:
when R6=pkt(id=0,off=0,r=62) R7=imm22
after r7 += r6 instruction
will be R6=pkt(id=0,off=0,r=62) R7=pkt(id=0,off=22,r=62)

Fixes: 969bf05eb3ce ("bpf: direct packet access")
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Acked-by: Daniel Borkmann <daniel@iogearbox.net>
---
 kernel/bpf/verifier.c | 18 +++++++++++++++++-
 1 file changed, 17 insertions(+), 1 deletion(-)

diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index d54e34874579..668e07903c8f 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -1245,6 +1245,7 @@ static int check_packet_ptr_add(struct verifier_env *env, struct bpf_insn *insn)
 	struct reg_state *regs = env->cur_state.regs;
 	struct reg_state *dst_reg = &regs[insn->dst_reg];
 	struct reg_state *src_reg = &regs[insn->src_reg];
+	struct reg_state tmp_reg;
 	s32 imm;
 
 	if (BPF_SRC(insn->code) == BPF_K) {
@@ -1267,6 +1268,19 @@ add_imm:
 		 */
 		dst_reg->off += imm;
 	} else {
+		if (src_reg->type == PTR_TO_PACKET) {
+			/* R6=pkt(id=0,off=0,r=62) R7=imm22; r7 += r6 */
+			tmp_reg = *dst_reg;  /* save r7 state */
+			*dst_reg = *src_reg; /* copy pkt_ptr state r6 into r7 */
+			src_reg = &tmp_reg;  /* pretend it's src_reg state */
+			/* if the checks below reject it, the copy won't matter,
+			 * since we're rejecting the whole program. If all ok,
+			 * then imm22 state will be added to r7
+			 * and r7 will be pkt(id=0,off=22,r=62) while
+			 * r6 will stay as pkt(id=0,off=0,r=62)
+			 */
+		}
+
 		if (src_reg->type == CONST_IMM) {
 			/* pkt_ptr += reg where reg is known constant */
 			imm = src_reg->imm;
@@ -1565,7 +1579,9 @@ static int check_alu_op(struct verifier_env *env, struct bpf_insn *insn)
 			return 0;
 		} else if (opcode == BPF_ADD &&
 			   BPF_CLASS(insn->code) == BPF_ALU64 &&
-			   dst_reg->type == PTR_TO_PACKET) {
+			   (dst_reg->type == PTR_TO_PACKET ||
+			    (BPF_SRC(insn->code) == BPF_X &&
+			     regs[insn->src_reg].type == PTR_TO_PACKET))) {
 			/* ptr_to_packet += K|X */
 			return check_packet_ptr_add(env, insn);
 		} else if (BPF_CLASS(insn->code) == BPF_ALU64 &&
-- 
2.8.0

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH net-next 0/2] bpf: verifier fixes
  2016-05-20  1:17 [PATCH net-next 0/2] bpf: verifier fixes Alexei Starovoitov
  2016-05-20  1:17 ` [PATCH net-next 1/2] bpf: support decreasing order in direct packet access Alexei Starovoitov
  2016-05-20  1:17 ` [PATCH net-next 2/2] bpf: teach verifier to recognize imm += ptr pattern Alexei Starovoitov
@ 2016-05-20 23:53 ` David Miller
  2 siblings, 0 replies; 4+ messages in thread
From: David Miller @ 2016-05-20 23:53 UTC (permalink / raw)
  To: ast; +Cc: daniel, netdev, kernel-team

From: Alexei Starovoitov <ast@fb.com>
Date: Thu, 19 May 2016 18:17:12 -0700

> Further testing of 'direct packet access' uncovered
> several usability issues. Fix them.

Series applied, thanks Alexei.

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2016-05-20 23:53 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-05-20  1:17 [PATCH net-next 0/2] bpf: verifier fixes Alexei Starovoitov
2016-05-20  1:17 ` [PATCH net-next 1/2] bpf: support decreasing order in direct packet access Alexei Starovoitov
2016-05-20  1:17 ` [PATCH net-next 2/2] bpf: teach verifier to recognize imm += ptr pattern Alexei Starovoitov
2016-05-20 23:53 ` [PATCH net-next 0/2] bpf: verifier fixes David Miller

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).