[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-ID: <418e872d-54ec-b27d-d0fb-28ac0c05f86e@iogearbox.net>
Date: Thu, 23 Aug 2018 09:17:20 +0200
From: Daniel Borkmann <daniel@...earbox.net>
To: IMBRIUS AGER <imbrius.ager@...il.com>, netdev@...r.kernel.org
Subject: Re: Failed to call bpf_l3_csum_replace() twice for IPIP tunnel
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
>
Powered by blists - more mailing lists