• Jesper Dangaard Brouer's avatar
    net: fix divide by zero in tcp algorithm illinois · 8f363b77
    Jesper Dangaard Brouer authored
    Reading TCP stats when using TCP Illinois congestion control algorithm
    can cause a divide by zero kernel oops.
    
    The division by zero occur in tcp_illinois_info() at:
     do_div(t, ca->cnt_rtt);
    where ca->cnt_rtt can become zero (when rtt_reset is called)
    
    Steps to Reproduce:
     1. Register tcp_illinois:
         # sysctl -w net.ipv4.tcp_congestion_control=illinois
     2. Monitor internal TCP information via command "ss -i"
         # watch -d ss -i
     3. Establish new TCP conn to machine
    
    Either it fails at the initial conn, or else it needs to wait
    for a loss or a reset.
    
    This is only related to reading stats.  The function avg_delay() also
    performs the same divide, but is guarded with a (ca->cnt_rtt > 0) at its
    calling point in update_params().  Thus, simply fix tcp_illinois_info().
    
    Function tcp_illinois_info() / get_info() is called without
    socket lock.  Thus, eliminate any race condition on ca->cnt_rtt
    by using a local stack variable.  Simply reuse info.tcpv_rttcnt,
    as its already set to ca->cnt_rtt.
    Function avg_delay() is not affected by this race condition, as
    its called with the socket lock.
    
    Cc: Petr Matousek <pmatouse@redhat.com>
    Signed-off-by: default avatarJesper Dangaard Brouer <brouer@redhat.com>
    Acked-by: default avatarEric Dumazet <edumazet@google.com>
    Acked-by: default avatarStephen Hemminger <shemminger@vyatta.com>
    Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
    8f363b77
tcp_illinois.c 8.19 KB