• Florian Westphal's avatar
    net: ip: always refragment ip defragmented packets · bb4cc1a1
    Florian Westphal authored
    Conntrack reassembly records the largest fragment size seen in IPCB.
    However, when this gets forwarded/transmitted, fragmentation will only
    be forced if one of the fragmented packets had the DF bit set.
    
    In that case, a flag in IPCB will force fragmentation even if the
    MTU is large enough.
    
    This should work fine, but this breaks with ip tunnels.
    Consider client that sends a UDP datagram of size X to another host.
    
    The client fragments the datagram, so two packets, of size y and z, are
    sent. DF bit is not set on any of these packets.
    
    Middlebox netfilter reassembles those packets back to single size-X
    packet, before routing decision.
    
    packet-size-vs-mtu checks in ip_forward are irrelevant, because DF bit
    isn't set.  At output time, ip refragmentation is skipped as well
    because x is still smaller than the mtu of the output device.
    
    If ttransmit device is an ip tunnel, the packet size increases to
    x+overhead.
    
    Also, tunnel might be configured to force DF bit on outer header.
    
    In this case, packet will be dropped (exceeds MTU) and an ICMP error is
    generated back to sender.
    
    But sender already respects the announced MTU, all the packets that
    it sent did fit the announced mtu.
    
    Force refragmentation as per original sizes unconditionally so ip tunnel
    will encapsulate the fragments instead.
    
    The only other solution I see is to place ip refragmentation in
    the ip_tunnel code to handle this case.
    
    Fixes: d6b915e2 ("ip_fragment: don't forward defragmented DF packet")
    Reported-by: default avatarChristian Perle <christian.perle@secunet.com>
    Signed-off-by: default avatarFlorian Westphal <fw@strlen.de>
    Acked-by: default avatarPablo Neira Ayuso <pablo@netfilter.org>
    Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
    bb4cc1a1
ip_output.c 43 KB