On 08/23/2018 08:39 AM, IMBRIUS AGER wrote: > hello, I am trying to modify the src addr (both inner and outer) of IPIP > tunnel. > > this is the testing code: > > ======================================= > > void *data = (void *)(long)skb->data; > void *data_end = (void *)(long)skb->data_end; > > struct ethhdr *eth = data; > struct iphdr *ip_outer = (void *)(eth + 1); > > if (ip_outer->ihl != 5 || ip_outer + 1 > data_end) > return; > > struct iphdr *ip_inner = (void *)(ip4_outer + 1); > > if (ip_inner->ihl != 5 || ip_inner + 1 > data_end) > return; > > src = 0x11111111; > > /* First I modify the inner ip */ > bpf_l3_csum_replace(skb, IP4_CSUM_OFF + sizeof(struct iphdr), > ip_inner->saddr, src, sizeof(src)); > bpf_skb_store_bytes(skb, IP4_SRC_OFF + sizeof(struct iphdr), &src, > sizeof(src), 0); > > /* Second I modify the outer ip */ > bpf_l3_csum_replace(skb, IP4_CSUM_OFF, ip_outer->saddr, src, sizeof(src)); > bpf_skb_store_bytes(skb, IP4_SRC_OFF, &src, sizeof(src), 0);
You need to reload skb->data pointer as otherwise the first l3_csum_replace could have uncloned the skb and then ip_outer->saddr would point to invalid mem. Other, better option is to use the bpf_csum_diff() helper and calc the diff which then only needs to be fed into bpf_l3_csum_replace() once. > ======================================== > > I found that I could only modify one of the src addr (inner or outer). > If both, the kernel always rejected the code at the first > bpf_l3_csum_replace(): > > ======================================== > > Prog section '__xxxxx' rejected: Permission denied (13)! > - Type: 3 > - Instructions: 171 (0 over limit) > - License: GPL > > ..... > > 96: (85) call bpf_l3_csum_replace#10 > 97: (61) r4 = *(u32 *)(r7 +0) > R0=inv(id=0) R6=ctx(id=0,off=0,imm=0) > R7=map_value(id=0,off=0,ks=4,vs=4,imm=0) R8=inv(id=0) R9=inv(id=0) > R10=fp0 > 98: (61) r3 = *(u32 *)(r9 +26) > R9 invalid mem access 'inv' > > Error fetching program/map! > Unable to load program > > ======================================== > > I tried to validate the pointer again before the second modification. > But nothing good has happened. > > if (ip_outer->ihl != 5 || ip_outer + 1 > data_end) > return; > /* Second I modify the outer ip */ > bpf_l3_csum_replace(skb, IP4_CSUM_OFF, ip_outer->saddr, src, sizeof(src)); > bpf_skb_store_bytes(skb, IP4_SRC_OFF, &src, sizeof(src), 0); > > > Any idea? > Thanks very much >