On 01/12/2017 07:50 PM, William Tu via iovisor-dev wrote:
Hi,

I observed that for direct packet access, we have to use this data and
data_end checking pattern:

int xdp_prog1(struct xdp_md *ctx)
{
     void *data_end = (void *)(long)ctx->data_end;
     void *data = (void *)(long)ctx->data;
     struct ethhdr *eth = data;
     ...
     nh_off = sizeof(*eth);
     if (nh_off + data > data_end)
         return rc;
---
if writing in another way like
---
     if ((long)nh_off > data_end - data)
        return rc;
---
then verifier isn't able to record the packet's range (r=0):
0: (61) r2 = *(u32 *)(r1 +0)
1: (61) r1 = *(u32 *)(r1 +4)
2: (bf) r4 = r1
3: (1f) r4 -= r2
4: (b7) r3 = 14
5: (6d) if r3 s> r4 goto pc+54
  R1=pkt_end R2=pkt(id=0,off=0,r=0) R3=imm14,min_value=14,max_value=14
R4=inv,min_value=14 R10=fp
6: (71) r5 = *(u8 *)(r2 +12)
invalid access to packet, off=12 size=1, R2(id=0,off=0,r=0)

Is this the expected behavior?

Yes, effectively in 3) you're doing data_end -= data and that
will result in marking the register as unknown value by the
verifier, since it doesn't pattern match alu ops with data_end
as dst reg. So that carried onwards in the conditional cannot
type match the pkt test, and thus access range won't get updated,
so verifier correctly complains here. Hm, not sure if that's
worth the extra complexity ... I'd assume for getting it to work
you would need to make that result a new internal reg type and
then add pattern matches against that one.
_______________________________________________
iovisor-dev mailing list
[email protected]
https://lists.iovisor.org/mailman/listinfo/iovisor-dev

Reply via email to