lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite for Android: free password hash cracker in your pocket
[<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

Powered by Openwall GNU/*/Linux Powered by OpenVZ