From: William Tu <hidden> Date: 2017-02-02 19:59:24
When adding a zero value to the packet pointer, the verifer
reports the following error:
R0=imm0,min_value=0,max_value=0 R1=pkt(id=0,off=0,r=4) R2=pkt_end R3=fp-12 R4=imm4,min_value=4,max_value=4 R5=pkt(id=0,off=4,r=4) R6=ctx R7=imm0,min_value=0,max_value=0 R8=inv,min_value=0,max_value=0 R9=inv R10=fp
269: (bf) r2 = r0
270: (77) r2 >>= 3
271: (bf) r4 = r1
272: (0f) r4 += r2
addition of negative constant to packet pointer is not allowed
Signed-off-by: William Tu <redacted>
Cc: Daniel Borkmann <daniel@iogearbox.net>
---
kernel/bpf/verifier.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
@@ -1397,7 +1397,7 @@ static int check_packet_ptr_add(struct bpf_verifier_env *env,imm=insn->imm;add_imm:-if(imm<=0){+if(imm<0){verbose("addition of negative constant to packet pointer is not allowed\n");return-EACCES;}
From: Daniel Borkmann <daniel@iogearbox.net> Date: 2017-02-02 23:46:39
On 02/02/2017 08:59 PM, William Tu wrote:
When adding a zero value to the packet pointer, the verifer
reports the following error:
R0=imm0,min_value=0,max_value=0 R1=pkt(id=0,off=0,r=4) R2=pkt_end R3=fp-12 R4=imm4,min_value=4,max_value=4 R5=pkt(id=0,off=4,r=4) R6=ctx R7=imm0,min_value=0,max_value=0 R8=inv,min_value=0,max_value=0 R9=inv R10=fp
269: (bf) r2 = r0
270: (77) r2 >>= 3
271: (bf) r4 = r1
272: (0f) r4 += r2
addition of negative constant to packet pointer is not allowed
How do we get here? I mean compiler is not optimizing this away
as the reg is populated differently from various branches? Could
you elaborate more on that resp. how we end up with this? Thanks!
quoted hunk
Signed-off-by: William Tu <redacted>
Cc: Daniel Borkmann <daniel@iogearbox.net>
---
kernel/bpf/verifier.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
@@ -1397,7 +1397,7 @@ static int check_packet_ptr_add(struct bpf_verifier_env *env,imm=insn->imm;add_imm:-if(imm<=0){+if(imm<0){verbose("addition of negative constant to packet pointer is not allowed\n");return-EACCES;}
When adding a zero value to the packet pointer, the verifer
reports the following error:
R0=imm0,min_value=0,max_value=0 R1=pkt(id=0,off=0,r=4) R2=pkt_end R3=fp-12
R4=imm4,min_value=4,max_value=4 R5=pkt(id=0,off=4,r=4) R6=ctx
R7=imm0,min_value=0,max_value=0 R8=inv,min_value=0,max_value=0 R9=inv R10=fp
269: (bf) r2 = r0
270: (77) r2 >>= 3
271: (bf) r4 = r1
272: (0f) r4 += r2
addition of negative constant to packet pointer is not allowed
How do we get here? I mean compiler is not optimizing this away
as the reg is populated differently from various branches? Could
you elaborate more on that resp. how we end up with this? Thanks!
quoted
Signed-off-by: William Tu <redacted>
Cc: Daniel Borkmann <daniel@iogearbox.net>
---
kernel/bpf/verifier.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
thanks for sharing.
the C program looks auto-generated? Just curious what did you
use to do it?
The line 272 is r4 += r2
where R4=imm4 and R2=pkt_end
Right now verifier doesn't accept any arithmetic with pkt_end,
since it expects the programs to have cannonical form of
if (ptr > pkt_end)
goto fail;
Even if we add it, I'm not sure what 'pkt_end + 4' suppose to do.
It's a pointer after the valid packet range.
I'm the most puzzled with the diff:
- if (imm <= 0) {
+ if (imm < 0) {
how is it making the program to pass verifier?
PS
gentle reminder to avoid top posting.
thanks for sharing.
the C program looks auto-generated? Just curious what did you
use to do it?
Yes, this is auto-generated. We want to use P4 2016 as front end to
generate ebpf for XDP.
The line 272 is r4 += r2
where R4=imm4 and R2=pkt_end
R2 is no longer pkt_end, it's R2 == R0 == 0
269: (bf) r2 = r0
270: (77) r2 >>= 3
271: (bf) r4 = r1
272: (0f) r4 += r2
So at line 272, it's pkt_ptr = pkt_ptr + 0
thus the following fix works for us.
- if (imm <= 0) {
+ if (imm < 0) {
Right now verifier doesn't accept any arithmetic with pkt_end,
since it expects the programs to have cannonical form of
if (ptr > pkt_end)
goto fail;
Even if we add it, I'm not sure what 'pkt_end + 4' suppose to do.
It's a pointer after the valid packet range.
I'm the most puzzled with the diff:
- if (imm <= 0) {
+ if (imm < 0) {
how is it making the program to pass verifier?
PS
gentle reminder to avoid top posting.
thanks for letting me know we should avoid top posting.
--William
On Thu, Feb 02, 2017 at 09:31:06PM -0800, William Tu wrote:
Yes, this is auto-generated. We want to use P4 2016 as front end to
generate ebpf for XDP.
P4 2016 front-end ? is it public? Is there a 2017 version? ;)
just curious.
quoted
The line 272 is r4 += r2
where R4=imm4 and R2=pkt_end
R2 is no longer pkt_end, it's R2 == R0 == 0
269: (bf) r2 = r0
270: (77) r2 >>= 3
271: (bf) r4 = r1
272: (0f) r4 += r2
So at line 272, it's pkt_ptr = pkt_ptr + 0
thus the following fix works for us.
- if (imm <= 0) {
+ if (imm < 0) {
got it. I forgot that we have:
if (src_reg->type == CONST_IMM) {
/* pkt_ptr += reg where reg is known constant */
imm = src_reg->imm;
goto add_imm;
}
and got confused by if (BPF_SRC(insn->code) == BPF_K) bit.
Thanks for explaining!
Could you respin with the extra test for it in the test_verifier.c ?
Since it's a rare case, would be good to keep it working.