Thread (19 messages) 19 messages, 4 authors, 2018-08-07

Re: AW: AW: PROBLEM: Kernel Oops in UDP stack

From: Eric Dumazet <hidden>
Date: 2018-08-01 11:25:24
Also in: netdev
Subsystem: netfilter, networking [general], the rest · Maintainers: Pablo Neira Ayuso, Florian Westphal, "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Linus Torvalds


On 08/01/2018 03:49 AM, Eric Dumazet wrote:

On 08/01/2018 03:44 AM, Paolo Abeni wrote:
quoted
On Wed, 2018-08-01 at 10:35 +0000, Marcel Hellwig wrote:
quoted
quoted
quoted
[<c0228adc>] (udp_recvmsg+0x284/0x33c) from [<c02306e0>] (inet_recvmsg+0x38/0x4c): net/ipv4/udp.c:1234
             sin->sin_addr.s_addr = ip_hdr(skb)->saddr;

Unaligned access trap (virtual address c14fe63a), so either sin or ip_hdr(skb) are not on a 32bit alignment

Can you produce the disassembly of the trapping instruction ?
https://gist.github.com/hellow554/6b11c6c0827d5db80a7e66f71f5636ff#file-net_uipv4_udp-lst-L1892-L1895

		sin->sin_addr.s_addr = ip_hdr(skb)->saddr;
c0228ad8:	e5943080 	ldr	r3, [r4, #128]	; 0x80
c0228adc:	e593300c 	ldr	r3, [r3, #12]
c0228ae0: 	e5823004	str	r3, [r2, #4]
I *think* pskb_trim_rcsum() in __udp4_lib_rcv() can copy the ipv4
header to an unaligned address, for cloned skbs. If I understood
correctly the relevant socket is a mcast one, so cloned skbs can land
there.
kmalloc() should return aligned pointer.

pskb_expand_head() should allocate aligned skb->head

So pskb_expand_head() should keep whatever offset was provided in the source skb 

( Driver called skb_reserve() or similar function)
I suspect the following patch my need to be backported, please Marcel git it a try.

Another way to spot the problem would be to add a check in pskb_expand_head()

commit 5e2afba4ecd7931ea06e6fa116ab28e6943dbd42
Author: Paul Guo [off-list ref]
Date:   Mon Nov 14 19:00:54 2011 +0800

    netfilter: possible unaligned packet header in ip_route_me_harder
    
    This patch tries to fix the following issue in netfilter:
    In ip_route_me_harder(), we invoke pskb_expand_head() that
    rellocates new header with additional head room which can break
    the alignment of the original packet header.
    
    In one of my NAT test case, the NIC port for internal hosts is
    configured with vlan and the port for external hosts is with
    general configuration. If we ping an external "unknown" hosts from an
    internal host, an icmp packet will be sent. We find that in
    icmp_send()->...->ip_route_me_harder()->pskb_expand_head(), hh_len=18
    and current headroom (skb_headroom(skb)) of the packet is 16. After
    calling pskb_expand_head() the packet header becomes to be unaligned
    and then our system (arch/tile) panics immediately.
    
    Signed-off-by: Paul Guo [off-list ref]
    Acked-by: Eric Dumazet [off-list ref]
    Signed-off-by: Pablo Neira Ayuso [off-list ref]
diff --git a/net/ipv4/netfilter.c b/net/ipv4/netfilter.c
index 9899619ab9b8db0f9d8d02c8005c0e6bb01fda94..4f47e064e262c2f24e7cb13eacfcebff0fad86a3 100644
--- a/net/ipv4/netfilter.c
+++ b/net/ipv4/netfilter.c
@@ -64,7 +64,8 @@ int ip_route_me_harder(struct sk_buff *skb, unsigned addr_type)
        /* Change in oif may mean change in hh_len. */
        hh_len = skb_dst(skb)->dev->hard_header_len;
        if (skb_headroom(skb) < hh_len &&
-           pskb_expand_head(skb, hh_len - skb_headroom(skb), 0, GFP_ATOMIC))
+           pskb_expand_head(skb, HH_DATA_ALIGN(hh_len - skb_headroom(skb)),
+                               0, GFP_ATOMIC))
                return -1;
 
        return 0;
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help