• J
    net: do not process device backlog during unregistration · e9e4dd32
    Julian Anastasov 提交于
    commit 381c759d ("ipv4: Avoid crashing in ip_error")
    fixes a problem where processed packet comes from device
    with destroyed inetdev (dev->ip_ptr). This is not expected
    because inetdev_destroy is called in NETDEV_UNREGISTER
    phase and packets should not be processed after
    dev_close_many() and synchronize_net(). Above fix is still
    required because inetdev_destroy can be called for other
    reasons. But it shows the real problem: backlog can keep
    packets for long time and they do not hold reference to
    device. Such packets are then delivered to upper levels
    at the same time when device is unregistered.
    Calling flush_backlog after NETDEV_UNREGISTER_FINAL still
    accounts all packets from backlog but before that some packets
    continue to be delivered to upper levels long after the
    synchronize_net call which is supposed to wait the last
    ones. Also, as Eric pointed out, processed packets, mostly
    from other devices, can continue to add new packets to backlog.
    
    Fix the problem by moving flush_backlog early, after the
    device driver is stopped and before the synchronize_net() call.
    Then use netif_running check to make sure we do not add more
    packets to backlog. We have to do it in enqueue_to_backlog
    context when the local IRQ is disabled. As result, after the
    flush_backlog and synchronize_net sequence all packets
    should be accounted.
    
    Thanks to Eric W. Biederman for the test script and his
    valuable feedback!
    Reported-by: NVittorio Gambaletta <linuxbugs@vittgam.net>
    Fixes: 6e583ce5 ("net: eliminate refcounting in backlog queue")
    Cc: Eric W. Biederman <ebiederm@xmission.com>
    Cc: Stephen Hemminger <stephen@networkplumber.org>
    Signed-off-by: NJulian Anastasov <ja@ssi.bg>
    Signed-off-by: NDavid S. Miller <davem@davemloft.net>
    e9e4dd32
dev.c 189.4 KB