On 06/06/18 23:22, Zvi Effron wrote: > Hi XDPeople! > > I've been having great success with reading data from fixed offsets in > a packet/ethernet frame. But every time I try to read from a dynamic > offset (e.g. read the last byte in the packet by using the packet > length in the IP/UDP headers). It looks like once I add a register to > a packet pointer, the range is reset to 0, and no amount of > comparisons will restore a range. > > Looking through the verifier code, I believe I found where the range > is getting set to 0 > (https://elixir.bootlin.com/linux/latest/source/kernel/bpf/verifier.c#L2695), > and it looks like the risk of overflow > (https://elixir.bootlin.com/linux/latest/source/kernel/bpf/verifier.c#L3267) > is why the range doesn't get updated by later comparisons. > > Is there a way to do a read from a packet at a dynamic offset? If not, > is that something that could potentially be added to the verifier? It > feels like `if (packet_start <= packet_start + offset && packet_end > > packet_start + offset)` is something that should be verifiable as > safe, even with potential overflow in `packet_start + offset`? > > Thank you! > --Zvi I think that to make this work you need to bound the dynamic offset before you add it to the packet pointer. So for instance if you read a packet length from the IP header, that's a u16 (so max. 0xffff), and it's then added to the offset of L4 (probably 14+20=34), giving a max. larger than MAX_PACKET_OFF. So you need to do something like if (offset < 0xffff && packet_start + offset < packet_end) because the verifier isn't smart enough to learn anything from an if (ptr_to_packet <= ptr_to_packet + offset) check. The trouble with the latter is that it's a piece of state that belongs both to the packet-pointer (which in the general case could be variably-offset already) and to the offset, so you'd need n² storage to record which (pointer, offset) pairs had been determined not to overflow. HTH, -Ed